Click here to Skip to main content
15,886,622 members
Articles / Web Development / HTML

A simple demo for WDM Driver development

Rate me:
Please Sign up or sign in to vote.
4.95/5 (131 votes)
25 Oct 2004CPOL7 min read 423.1K   10.9K   319  
WDM Driver programming introduction with three Pseudo Drivers.
/*************************************************************************
/*
/*      Copyright 2004/02/08
/*      Author : Meng-Jer Tsai(Taiwan R.O.C)
/*      Email : mjtsai87@ms31.hinet.net
/*      Declaration and Agreement Statements:
/*      [1]This Program is free for redistribution with
/*         or without any modify of the source code containing
/*         in this source file on conditions that the Declaration
/*         and Agreement Statements is included.
/*      [2]If any damanage done to your computer system due to the 
/*         execution of the source code in this file, no responsibility
/*         will be taken by the Author.
/*      [3]Any commercial binary executable product developed based on 
/*         this source code must have the Copyright and all items in 
/*         this Declaration and Agreement Statements in its User License
/*         Agreement, or will be regarded as inappropriate occupy of 
/*         software creativity.
/*
/*************************************************************************/

/*************************************************************************
/*
/*       This file is implemented for the common and default handle for
/*       PnP-Related tasks, such as Start Device, Stop Device, Device
/*       Capabilities.
/*
/*************************************************************************/

#include <wdm.h>
#include "..\Basic\WDMDefault.h"
#include "PnP.h"

extern PDEVICE_POWER_INFORMATION Global_PowerInfo_Ptr;

NTSTATUS
  PsdoDispatchPnP(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp
    )
{
	PIO_STACK_LOCATION p_IO_STK;
	PDEVICE_EXTENSION p_DVCEXT;
	ULONG IRP_MN_Code;
	NTSTATUS Status = STATUS_SUCCESS;

	DbgPrint("IRP_MJ_PNP Received : Begin\r\n");

	p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
	p_DVCEXT = DeviceObject->DeviceExtension;
	IoAcquireRemoveLock(
		&p_DVCEXT->RemoveLock, 
		Irp);
	IRP_MN_Code = p_IO_STK->MinorFunction ;

	switch(IRP_MN_Code)
	{
	case IRP_MN_START_DEVICE :
		DbgPrint("IRP_MN_START_DEVICE Received : Begin\r\n");
		Status = StartDevice(
			DeviceObject,
			Irp
		);
		DbgPrint("IRP_MN_START_DEVICE Received : End\r\n");
		break;
	case IRP_MN_STOP_DEVICE :
		DbgPrint("IRP_MN_STOP_DEVICE Received : Begin\r\n");
		Status = StopDevice(
			DeviceObject,
			Irp
		);
		DbgPrint("IRP_MN_STOP_DEVICE Received : End\r\n");
		break;
	case IRP_MN_REMOVE_DEVICE :
		DbgPrint("IRP_MN_REMOVE_DEVICE Received : Begin\r\n");
		Status = RemoveDevice(
			DeviceObject,
			Irp
		);
		DbgPrint("IRP_MN_REMOVE_DEVICE Received : End\r\n");
		break;
	case IRP_MN_QUERY_CAPABILITIES :
		DbgPrint("IRP_MN_QUERY_CAPABILITIES Received : Begin\r\n");
		Status = QueryCapability(
			DeviceObject,
			Irp
		);
		DbgPrint("IRP_MN_QUERY_CAPABILITIES Received : End\r\n");
		break;
	default:
		break;
	}
	IoReleaseRemoveLock(
		&p_DVCEXT->RemoveLock, 
		Irp);
	
	if (NT_SUCCESS(Status))
	  CompleteRequest(
		Irp, 
		STATUS_SUCCESS, 
		0);

	DbgPrint("IRP_MJ_PNP Received : End\r\n");

	return Status;
}

NTSTATUS
  StartDevice(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp
    )
{
	DbgPrint("Start Device....\r\n");
	return STATUS_SUCCESS;
}

NTSTATUS
  StopDevice(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp
    )
{
	DbgPrint("Stop Device....\r\n");
	return STATUS_SUCCESS;
}

NTSTATUS
  RemoveDevice(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp
    )
{
	PDEVICE_EXTENSION p_DVCEXT;

	DbgPrint("Remove Device....\r\n");
#if 0
	p_DVCEXT = DeviceObject->DeviceExtension;
	IoDetachDevice(
		p_DVCEXT->DeviceObject);
	IoDeleteDevice(
		p_DVCEXT->NextDeviceObject);
#endif
	return STATUS_SUCCESS;
}

NTSTATUS
  QueryCapability(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp
    )
{
#if 1
	//It is OKAY Version
	PIO_STACK_LOCATION p_IO_STK;
	PDEVICE_EXTENSION p_DVCEXT;
	NTSTATUS Status;
	KEVENT event;
	ULONG IdxPwrState;

	DbgPrint("Query Device Capability....\r\n");
	DbgPrint("Ready to pass IRP down\r\n");
	
	p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
	p_DVCEXT = DeviceObject->DeviceExtension;

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	IoCopyCurrentIrpStackLocationToNext(Irp);

	IoSetCompletionRoutine(
		Irp,
		(PIO_COMPLETION_ROUTINE)CompletionQueryCapability,
		(PVOID)&event,//p_DVCEXT,
		TRUE,
		TRUE,
		TRUE);

	Status = IoCallDriver(
				p_DVCEXT->NextDeviceObject,
				Irp);

	KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

	if (NT_SUCCESS(Irp->IoStatus.Status)) {
		p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
		p_DVCEXT = DeviceObject->DeviceExtension;
		p_DVCEXT->pdc = *p_IO_STK->
			Parameters.DeviceCapabilities.Capabilities;
#if 1
		Global_PowerInfo_Ptr->SupportQueryCapability = TRUE;
		Global_PowerInfo_Ptr->DeviceD1 = p_DVCEXT->pdc.DeviceD1;
		Global_PowerInfo_Ptr->DeviceD2 = p_DVCEXT->pdc.DeviceD1;
		Global_PowerInfo_Ptr->WakeFromD0 = p_DVCEXT->pdc.WakeFromD0;
		Global_PowerInfo_Ptr->WakeFromD1 = p_DVCEXT->pdc.WakeFromD1;
		Global_PowerInfo_Ptr->WakeFromD2 = p_DVCEXT->pdc.WakeFromD2;
		Global_PowerInfo_Ptr->WakeFromD3 = p_DVCEXT->pdc.WakeFromD3;
		Global_PowerInfo_Ptr->DeviceWake = p_DVCEXT->pdc.SystemWake;
		Global_PowerInfo_Ptr->SystemWake = p_DVCEXT->pdc.DeviceWake;
		for (IdxPwrState = 0; 
			IdxPwrState < PowerSystemMaximum;
			IdxPwrState++)
		{
			Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 
				p_DVCEXT->pdc.DeviceState[IdxPwrState];
		}
#else
		//Display Related Device Power State
		DbgPrint("WakeFromD0 : %d\r\n", p_DVCEXT->pdc.WakeFromD0);
		DbgPrint("WakeFromD1 : %d\r\n", p_DVCEXT->pdc.WakeFromD1);
		DbgPrint("WakeFromD2 : %d\r\n", p_DVCEXT->pdc.WakeFromD2);
		DbgPrint("WakeFromD3 : %d\r\n", p_DVCEXT->pdc.WakeFromD3);
		DbgPrint("SystemWake : %d\r\n", p_DVCEXT->pdc.SystemWake);
		DbgPrint("DeviceWake : %d\r\n", p_DVCEXT->pdc.DeviceWake);
		for (IdxPwrState = 0; 
			IdxPwrState < PowerSystemMaximum;
			IdxPwrState++)
		{
			DbgPrint("DeviceState[%d] : %d\r\n", 
				IdxPwrState, 
				p_DVCEXT->pdc.DeviceState[IdxPwrState]);
		}
#endif
	} else {
		DbgPrint("Failed to handle IRP_MN_QUERY_CAPABILITIES");
	}
	return Irp->IoStatus.Status;
#else
	PIO_STACK_LOCATION p_IO_STK;
	PDEVICE_EXTENSION p_DVCEXT;
	NTSTATUS Status;

	DbgPrint("Query Device Capability....\r\n");
	DbgPrint("Ready to pass IRP down\r\n");
	
	p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
	p_DVCEXT = DeviceObject->DeviceExtension;
	IoCopyCurrentIrpStackLocationToNext(Irp);

	IoSetCompletionRoutine(
		Irp,
		(PIO_COMPLETION_ROUTINE)CompletionQueryCapability,
		p_DVCEXT,
		TRUE,
		TRUE,
		TRUE);

	return IoCallDriver(
				p_DVCEXT->NextDeviceObject,
				Irp);
/*
	if (Status == STATUS_PENDING)
	{
		DbgPrint("IRP_MN_QUERY_CAPABILITIES requires more preocessing...\r\n");
		return STATUS_PENDING;
	}
	else
	{
		DbgPrint("IoCallDriver return status :%d\r\n", Status);
		return Status;
	}
*/
#endif
}

NTSTATUS
  CompletionQueryCapability(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp,
    IN PVOID  Context
    )
{
#if 1
	//It is Okay Version
	PIO_STACK_LOCATION p_IO_STK;
	PDEVICE_EXTENSION p_DVCEXT;
	NTSTATUS Status = STATUS_SUCCESS;
	PIO_STATUS_BLOCK p_IO_Status;
	ULONG IdxPwrState;
	PKEVENT pev;

	DbgPrint("In Completion Routine for IRP_MN_QUERY_CAPABILITIES....\r\n");
	p_IO_STK = IoGetCurrentIrpStackLocation(Irp);

	pev = (PKEVENT)Context;
	KeSetEvent(pev, 0, FALSE);
	DbgPrint("return from IoCompletion Routine for IRP_MN_QUERY_CAPABILITIES\r\n");
	return STATUS_MORE_PROCESSING_REQUIRED;
#else
	PIO_STACK_LOCATION p_IO_STK;
	PDEVICE_EXTENSION p_DVCEXT;
	NTSTATUS Status = STATUS_SUCCESS;
	PIO_STATUS_BLOCK p_IO_Status;
	ULONG IdxPwrState;

	DbgPrint("In Completion Routine for IRP_MN_QUERY_CAPABILITIES....\r\n");
	p_IO_STK = IoGetCurrentIrpStackLocation(Irp);

	//Check if IRP is completed by lower-layered driver 
	if (NT_SUCCESS(Irp->IoStatus.Status))
	{
		DbgPrint("IRP_MN_QUERY_CAPABILITIES completed by lower-layered driver\r\n");
		p_DVCEXT = DeviceObject->DeviceExtension;
		p_DVCEXT->pdc = *p_IO_STK->
			Parameters.DeviceCapabilities.Capabilities;
		//Display Related Device Power State
		DbgPrint("WakeFromD0 : %d\r\n", p_DVCEXT->pdc.WakeFromD0);
		DbgPrint("WakeFromD1 : %d\r\n", p_DVCEXT->pdc.WakeFromD1);
		DbgPrint("WakeFromD2 : %d\r\n", p_DVCEXT->pdc.WakeFromD2);
		DbgPrint("WakeFromD3 : %d\r\n", p_DVCEXT->pdc.WakeFromD3);
		DbgPrint("SystemWake : %d\r\n", p_DVCEXT->pdc.SystemWake);
		DbgPrint("DeviceWake : %d\r\n", p_DVCEXT->pdc.DeviceWake);
		for (IdxPwrState = 0; 
			IdxPwrState < PowerSystemMaximum;
			IdxPwrState++)
		{
			DbgPrint("DeviceState[%d] : %d\r\n", 
				IdxPwrState, 
				p_DVCEXT->pdc.DeviceState[IdxPwrState]);
		}
		if (Irp->PendingReturned)
		{
			IoMarkIrpPending(Irp);
			Status =  STATUS_PENDING;
		} else {
			Status = STATUS_SUCCESS;
		}
	} 
	else if (NT_ERROR(Irp->IoStatus.Status))
	{
		DbgPrint("error occur while lower-layered driver handle IRP_MN_QUERY_CAPABILITIES\r\n");
		Status = Irp->IoStatus.Status;
	}
	else {
		//Check if IRP is canceled by lower-layered driver
		if (Irp->Cancel) 
		{
			DbgPrint("IRP_MN_QUERY_CAPABILITIES canceled by lower-layered driver\r\n");
			Status = Irp->IoStatus.Status;
		}
	}
	//CompleteRequest(Irp, Status, 0);
	DbgPrint("return from IoCompletion Routine for IRP_MN_QUERY_CAPABILITIES\r\n");
	return Status;
#endif
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Taiwan Taiwan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions