3 《Undocumented Windows 2000 Secrets》翻译 --- 第四章( 三 )


l dCode 指定了 IOCTL 编码,以确定 Spy 设备需要执行的命令 。一个 IOCTL 编码是一个 32 位整数,它包含 4 个位域,如 图 4-6 所示 。
l pInput 指向一个输入缓冲区,用于给 IOCTL 提供输入数据 。
l dInput 输入缓冲区的大小 。
l pOutput 指向用来接收 IOCTL 输出数据的输出缓冲区 。
l dOutput 输出缓冲区的大小
l pdInfo 指向一个 DWORD 变量,该变量保存写入输出缓冲区中的字节数 。
图 4-6. 设备 I/O 控制编码的结构
根据所用的 IOCTL 使用的传输模式,输入 / 输出缓冲区会以不同的方式从系统传递给驱动程序 。Spy 设备使用已缓存的 I/O ( buffered I/O ),系统将输入数据复制到一个安全的缓冲区(此缓冲区由系统自动分配)中,在返回时,将指定数目的数据从同样的系统缓冲区中复制到调用者提供的输出缓冲区中 。一定要牢记:在这种情况下,输入和输出缓冲区是重叠的,因此 IOCTL 的处理代码必须在向输出缓冲区中写入任何数据之前,保存所有它稍后可能需要使用的输入数据 。系统 I/O 缓冲区的指针保存在 IRP 结构中的 SystemBuffer 成员中(参见 ntddk.h ) 。输入 / 输出缓冲区的大小保存在一个不同的地方,它们是 IRP 的参数成员 DeviceIoControl 的一部分,分别为 InputBufferLength 和 OutputBufferLength。DeviceIoControl 子结构还通过其 IoControlCode 成员提供了 IOCTL 编码 。有关 Windows NT/2000 的 IOCTL 的传输模式的信息以及它们如何传入 / 传出数据,请参考我在 Windows Developer"s Journal(Schreiber 1997) 发表的文章“ A Spy Filter Driver for Windows NT ” 。
NTSTATUS SpyDispatcher (PDEVICE_CONTEXT pDeviceContext,
DWORD dCode,
PVOID pInput,
DWORD dInput,
PVOID pOutput,
DWORD dOutput,
PDWORD pdInfo)
{
SPY_MEMORY_BLOCK smb;
SPY_PAGE_ENTRY spe;
SPY_CALL_INPUT sci;
PHYSICAL_ADDRESS pa;
DWORD dValue, dCount;
BOOL fReset, fPause, fFilter, fLine;
PVOID pAddress;
PBYTE pbName;
HANDLE hObject;
NTSTATUS ns = STATUS_INVALID_PARAMETER;
MUTEX_WAIT (pDeviceContext->kmDispatch);
*pdInfo = 0;
switch (dCode)
{
case SPY_IO_VERSION_INFO:
{
ns = SpyOutputVersionInfo (pOutput, dOutput, pdInfo);
break;
}
case SPY_IO_OS_INFO:
{
ns = SpyOutputOsInfo (pOutput, dOutput, pdInfo);
break;
}
case SPY_IO_SEGMENT:
{
if ((ns = SpyInputDword (&dValue,
pInput, dInput))
== STATUS_SUCCESS)
{
ns = SpyOutputSegment (dValue,
pOutput, dOutput, pdInfo);
}
break;
}
case SPY_IO_INTERRUPT:
{
if ((ns = SpyInputDword (&dValue,
pInput, dInput))
== STATUS_SUCCESS)
{
ns = SpyOutputInterrupt (dValue,
pOutput, dOutput, pdInfo);
}
break;
}
case SPY_IO_PHYSICAL:
{
if ((ns = SpyInputPointer (&pAddress,
pInput, dInput))
== STATUS_SUCCESS)
{
pa = MmGetPhysicalAddress (pAddress);
ns = SpyOutputBinary (&pa, PHYSICAL_ADDRESS_,
pOutput, dOutput, pdInfo);
}
break;
}
case SPY_IO_CPU_INFO:
{
ns = SpyOutputCpuInfo (pOutput, dOutput, pdInfo);
break;
}
case SPY_IO_PDE_ARRAY:
{
ns = SpyOutputBinary (X86_PDE_ARRAY, SPY_PDE_ARRAY_,
pOutput, dOutput, pdInfo);
break;
}
case SPY_IO_PAGE_ENTRY:
{
if ((ns = SpyInputPointer (&pAddress,
pInput, dInput))
== STATUS_SUCCESS)
{
SpyMemoryPageEntry (pAddress, &spe);
ns = SpyOutputBinary (&spe, SPY_PAGE_ENTRY_,
pOutput, dOutput, pdInfo);
}
break;
}
case SPY_IO_MEMORY_DATA:
{
if ((ns = SpyInputMemory (&smb,
pInput, dInput))

推荐阅读