?? pnpdev.cpp
字號:
//****************************************************************************
// File PNPDEV.CPP
//
// PnP device object
//
// Copyright (c) APSoft, 1998-2002.
// All rights reserved.
//
//****************************************************************************
extern "C"
{
#include <ntddk.h> // Main DDK's include
}
#include <pnpdev.h> // Device class
#include <utils.h> // Utils methods
///////////////////////////////////////////////////////////////////////////////
// --- IRP Dispatch --- //
///////////////////////////////////////////////////////////////////////////////
typedef BOOLEAN (CPnpDevice::* PFNMJHANDLER)(PIRP pIrp, NTSTATUS & ntStatus);
static PFNMJHANDLER MjDispatch[] =
{
CPnpDevice::OnIrpCreate, // IRP_MJ_CREATE 0x00
CPnpDevice::OnIrpCreateNamedPipe, // IRP_MJ_CREATE_NAMED_PIPE 0x01
CPnpDevice::OnIrpClose, // IRP_MJ_CLOSE 0x02
CPnpDevice::OnIrpRead, // IRP_MJ_READ 0x03
CPnpDevice::OnIrpWrite, // IRP_MJ_WRITE 0x04
CPnpDevice::OnIrpQueryInfo, // IRP_MJ_QUERY_INFORMATION 0x05
CPnpDevice::OnIrpSetInfo, // IRP_MJ_SET_INFORMATION 0x06
CPnpDevice::OnIrpQueryEA, // IRP_MJ_QUERY_EA 0x07
CPnpDevice::OnIrpSetEA, // IRP_MJ_SET_EA 0x08
CPnpDevice::OnIrpFlushBuffers, // IRP_MJ_FLUSH_BUFFERS 0x09
CPnpDevice::OnIrpQueryVolInfo, // IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
CPnpDevice::OnIrpSetVolInfo, // IRP_MJ_SET_VOLUME_INFORMATION 0x0b
CPnpDevice::OnIrpDirCtrl, // IRP_MJ_DIRECTORY_CONTROL 0x0c
CPnpDevice::OnIrpFSCtrl, // IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
CPnpDevice::OnIrpDevCtrl, // IRP_MJ_DEVICE_CONTROL 0x0e
CPnpDevice::OnIrpIntDevCtrl, // IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
CPnpDevice::OnIrpShutDown, // IRP_MJ_SHUTDOWN 0x10
CPnpDevice::OnIrpLockCtrl, // IRP_MJ_LOCK_CONTROL 0x11
CPnpDevice::OnIrpCleanUp, // IRP_MJ_CLEANUP 0x12
CPnpDevice::OnIrpCreateMailSlot, // IRP_MJ_CREATE_MAILSLOT 0x13
CPnpDevice::OnIrpQuerySec, // IRP_MJ_QUERY_SECURITY 0x14
CPnpDevice::OnIrpSetSec, // IRP_MJ_SET_SECURITY 0x15
CPnpDevice::OnIrpPower, // IRP_MJ_POWER 0x16
CPnpDevice::OnIrpSysControl, // IRP_MJ_SYSTEM_CONTROL 0x17
CPnpDevice::OnIrpDevChange, // IRP_MJ_DEVICE_CHANGE 0x18
CPnpDevice::OnIrpQueryQuota, // IRP_MJ_QUERY_QUOTA 0x19
CPnpDevice::OnIrpSetQuota, // IRP_MJ_SET_QUOTA 0x1a
CPnpDevice::OnIrpPnP, // IRP_MJ_PNP 0x1b
};
///////////////////////////////////////////////////////////////////////////////
// --- Class CPnpDevice --- //
///////////////////////////////////////////////////////////////////////////////
//****************************************************************************
// --- CPnpDevice::CPnpDevice ---
//
// Purpose: CPnpDevice object constructor
// Input: PDEVICE_OBJECT pDevObject - Address of assotiated device object
// PDEVICE_OBJECT pPdo - Physical device object
// PWSTR pLnkName - Name of symbolic link or NULL
// Output: none
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
CPnpDevice::CPnpDevice(PDEVICE_OBJECT pDevObject, PDEVICE_OBJECT pPdo, PWSTR pLnkName)
{
//----------------------------- Save members ---------------------------------
m_pPdo = pPdo;
m_pNextStackDevice = NULL;
m_uPnpState = PNP_DEVICE_FAILED;
m_pDevObject = pDevObject;
//----------------------- Init. symbolic link name ---------------------------
RtlZeroMemory(&m_usLnkName, sizeof(m_usLnkName));
if (pLnkName != NULL)
AllocateUnicodeString(&m_usLnkName, pLnkName);
//------------------------- Init. remove members -----------------------------
m_fInUse = 1; // Locked until RemoveDevice
m_fRemoving = FALSE;
KeInitializeEvent(&m_evRemove, NotificationEvent, FALSE);
//---------------------- Attach to next stack device -------------------------
if (pPdo != NULL)
m_pNextStackDevice = IoAttachDeviceToDeviceStack(pDevObject, pPdo);
}
//****************************************************************************
// --- CPnpDevice::~CPnpDevice ---
//
// Purpose: CPnpDevice object destructor
// Input: none
// Output: none
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
CPnpDevice::~CPnpDevice(void)
{
//--------------------- Detach from next stack device ------------------------
if (m_pNextStackDevice != NULL)
IoDetachDevice(m_pNextStackDevice);
//------------------------- Delete symbolic link -----------------------------
if (m_usLnkName.Length != 0)
{
IoDeleteSymbolicLink(&m_usLnkName);
RtlFreeUnicodeString(&m_usLnkName);
} // if (m_usLnkName.Length != 0)
}
//****************************************************************************
// --- CPnpDevice::LockDevice ---
//
// Purpose: Lock device
// Input: none
// Output: BOOLEAN - TRUE or FALSE
// Written: by Anton V. Krivenko 4/18/2002
//****************************************************************************
BOOLEAN CPnpDevice::LockDevice(void)
{
LONG fInUse = InterlockedIncrement(&m_fInUse);
if (m_fRemoving)
{
if (!InterlockedDecrement(&m_fInUse))
KeSetEvent(&m_evRemove, 0, FALSE);
return FALSE;
} // if (m_fRemoving)
return TRUE;
}
//****************************************************************************
// --- CPnpDevice::UnlockDevice ---
//
// Purpose: Unlock device
// Input: none
// Output: none
// Written: by Anton V. Krivenko 4/18/2002
//****************************************************************************
void CPnpDevice::UnlockDevice(void)
{
LONG fInUse = InterlockedDecrement(&m_fInUse);
if (!fInUse)
KeSetEvent(&m_evRemove, 0, FALSE);
}
//****************************************************************************
// --- CPnpDevice::OnCreate ---
//
// Purpose: Create device
// Input: PDRIVER_OBJECT pDrvObject - Driver object
// PDEVICE_OBJECT * ppDevObject - Address of variable to be set to
// the address of created device
// ULONG uDevExtSize - Size of device extension
// PWSTR pDevName - Name of device
// PWSTR pLnkName - Name of symbolic link (Optional)
// DEVICE_TYPE DevType - Type of device to create
// Output: NTSTATUS - Operation status
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
NTSTATUS CPnpDevice::OnCreate(PDRIVER_OBJECT pDrvObject,
PDEVICE_OBJECT * ppDevObject,
ULONG uDevExtSize,
PWSTR pDevName,
PWSTR pLnkName,
DEVICE_TYPE DevType)
{
STRACE_PNPDRV(">> CPnpDevice::OnCreate()\n");
//----------------------------- Create device --------------------------------
UNICODE_STRING usDevName;
PUNICODE_STRING pusDevName = NULL; // Device name
if (pDevName != NULL)
{
RtlInitUnicodeString(&usDevName, pDevName);
pusDevName = &usDevName;
} // if (pDevName != NULL)
NTSTATUS ntStatus = IoCreateDevice(pDrvObject, uDevExtSize,
pusDevName, DevType, 0,
FALSE, ppDevObject);
ASSERTS_PNPDRV(NT_SUCCESS(ntStatus));
if (NT_SUCCESS(ntStatus))
{
//---------------------- Initialize device extension -------------------------
PVOID pExtension = (*ppDevObject)->DeviceExtension;
RtlZeroMemory(pExtension, uDevExtSize);
//------------------------- Create symbolic link -----------------------------
if (pLnkName != NULL)
{
UNICODE_STRING usLnkName; // Link name
RtlInitUnicodeString(&usLnkName, pLnkName);
ntStatus = IoCreateSymbolicLink(&usLnkName, pusDevName);
ASSERTS_PNPDRV(NT_SUCCESS(ntStatus));
if (!NT_SUCCESS(ntStatus))
{
STRACE_PNPDRV(" Failed to create symbolic link\n");
IoDeleteDevice(*ppDevObject);
*ppDevObject = NULL;
} // if (!NT_SUCCESS(ntStatus))
} // if (pLnkName != NULL)
} // if (NT_SUCCESS(ntStatus))
else
{
STRACE_PNPDRV(" Failed to create device\n");
*ppDevObject = NULL;
} // else
STRACE_PNPDRV("<< CPnpDevice::OnCreate()- ntStatus=%08X\n", ntStatus);
return ntStatus;
}
//****************************************************************************
// --- CPnpDevice::operator new ---
//
// Purpose: Operator NEW
// Input: size_t nSize - Size of object
// PDEVICE_OBJECT pDevObject - Storage
// Output: void * - Device extension address
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
void * CPnpDevice::operator new(size_t nSize, PDEVICE_OBJECT pDevObject)
{
STRACE_PNPDRV("CPnpDevice::operator new()\n");
return pDevObject->DeviceExtension;
}
//****************************************************************************
// --- CPnpDevice::operator delete ---
//
// Purpose: Operator DELETE
// Input: void * This - Device extension
// Output: none
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
void CPnpDevice::operator delete(void * pThis)
{
STRACE_PNPDRV("CPnpDevice::operator delete()\n");
CPnpDevice * pObject = (CPnpDevice *)pThis;
PDEVICE_OBJECT pDevObject = pObject->m_pDevObject;
RtlZeroMemory(pObject, sizeof(CPnpDevice));
IoDeleteDevice(pDevObject);
}
//****************************************************************************
// --- CallDriverSyncCompletion ---
//
// Purpose: Completion routine
// Input: PDEVICE_OBJECT p - Device object pointer
// PIRP pIrp - I/O request package to complete
// PVOID pContext - Context pointer (Address of KEVENT struct)
// Output: NTSTATUS - STATUS_MORE_PROCESSING_REQUIRED
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
static NTSTATUS CallDriverSyncCompletion(PDEVICE_OBJECT p, PIRP pIrp, PVOID pContext)
{
PKEVENT pkEvent = (PKEVENT)pContext;
KeSetEvent(pkEvent, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//****************************************************************************
// --- CPnpDevice::CallDriverSync ---
//
// Purpose: Call driver and wait for result
// Input: PDEVICE_OBJECT pDevice - Target device
// PIRP pIrp - Request to send
// Output: NTSTATUS - Operation status
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
NTSTATUS CPnpDevice::CallDriverSync(PDEVICE_OBJECT pDevice, PIRP pIrp)
{
KEVENT kEvent;
KeInitializeEvent(&kEvent, NotificationEvent, FALSE);
IoSetCompletionRoutine( pIrp, CallDriverSyncCompletion,
&kEvent, TRUE, TRUE, TRUE);
NTSTATUS ntStatus = IoCallDriver(pDevice, pIrp);
if (ntStatus == STATUS_PENDING || NT_SUCCESS(ntStatus))
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
ntStatus = pIrp->IoStatus.Status;
} // if (ntStatus == STATUS_PENDING ...
return ntStatus;
}
//****************************************************************************
// --- CPnpDevice::ForwardAndWait ---
//
// Purpose: Forward IRP to next device and wait for completion
// Input: PDEVICE_OBJECT pDevice - Next device object
// PIRP pIrp - I/O request package
// Output: NTSTATUS - Operation status
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
NTSTATUS CPnpDevice::ForwardAndWait(PDEVICE_OBJECT pDevice, PIRP pIrp)
{
IoCopyCurrentIrpStackLocationToNext(pIrp);
return CallDriverSync(pDevice, pIrp);
}
//****************************************************************************
// --- CPnpDevice::DispatchMjRequest ---
//
// Purpose: Dispatch IRP_MJ_ request
// Input: PIRP pIrp - I/O request package
// NTSTATUS & ntStatus - Operation status
// Output: BOOLEAN - TRUE if request was completed
// Written: by Anton V. Krivenko 4/9/2002
//****************************************************************************
BOOLEAN CPnpDevice::DispatchMjRequest(PIRP pIrp, NTSTATUS & ntStatus)
{
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
ULONG uFunction = pIoStack->MajorFunction;
BOOLEAN fCompleted = FALSE;
ASSERTS_PNPDRV(uFunction < sizeof(MjDispatch) / sizeof(MjDispatch[0]));
if (uFunction < sizeof(MjDispatch) / sizeof(MjDispatch[0]))
{
PFNMJHANDLER p = MjDispatch[uFunction];
fCompleted = (this->*p)(pIrp, ntStatus);
} // if (uFunction < sizeof(...
return fCompleted;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -