261 lines
6.9 KiB
C++
261 lines
6.9 KiB
C++
|
/////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 2001 Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
// tdiquery
|
||
|
//
|
||
|
// Abstract:
|
||
|
// This module contains code which deals with tdi queries
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
#include "sysvars.h"
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// private constants, types, and prototypes
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
|
||
|
const PCHAR strFunc1 = "TSQueryInfo";
|
||
|
const PCHAR strFuncP1 = "TSQueryComplete";
|
||
|
|
||
|
|
||
|
//
|
||
|
// completion context
|
||
|
//
|
||
|
struct QUERY_CONTEXT
|
||
|
{
|
||
|
PIRP pUpperIrp; // irp from dll to complete
|
||
|
PMDL pLowerMdl; // mdl from lower irp
|
||
|
PUCHAR pucLowerBuffer; // data buffer from lower irp
|
||
|
};
|
||
|
typedef QUERY_CONTEXT *PQUERY_CONTEXT;
|
||
|
|
||
|
//
|
||
|
// completion function
|
||
|
//
|
||
|
TDI_STATUS
|
||
|
TSQueryComplete(
|
||
|
PDEVICE_OBJECT DeviceObject,
|
||
|
PIRP Irp,
|
||
|
PVOID Context
|
||
|
);
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// public functions
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------
|
||
|
//
|
||
|
// Function: TSQueryInfo
|
||
|
//
|
||
|
// Arguments: pGenericHeader -- handle of appropriate type
|
||
|
// pSendBuffer -- arguments from user dll
|
||
|
// pIrp -- completion information
|
||
|
//
|
||
|
// Returns: NTSTATUS (normally pending)
|
||
|
//
|
||
|
// Descript: This function queries the appropriate object for some information
|
||
|
//
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
TSQueryInfo(PGENERIC_HEADER pGenericHeader,
|
||
|
PSEND_BUFFER pSendBuffer,
|
||
|
PIRP pUpperIrp)
|
||
|
{
|
||
|
ULONG ulQueryId = pSendBuffer->COMMAND_ARGS.ulQueryId;
|
||
|
|
||
|
//
|
||
|
// show debug, if it is turned on
|
||
|
//
|
||
|
if (ulDebugLevel & ulDebugShowCommand)
|
||
|
{
|
||
|
DebugPrint2("\nCommand = ulQUERYINFO\n"
|
||
|
"FileObject = %p\n"
|
||
|
"QueryId = 0x%08x\n",
|
||
|
pGenericHeader,
|
||
|
ulQueryId);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// allocate all the necessary structures
|
||
|
//
|
||
|
PQUERY_CONTEXT pQueryContext = NULL;
|
||
|
PUCHAR pucBuffer = NULL;
|
||
|
PMDL pQueryMdl = NULL;
|
||
|
|
||
|
|
||
|
// first, our context
|
||
|
//
|
||
|
if ((TSAllocateMemory((PVOID *)&pQueryContext,
|
||
|
sizeof(QUERY_CONTEXT),
|
||
|
strFunc1,
|
||
|
"QueryContext")) != STATUS_SUCCESS)
|
||
|
{
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// next the data buffer (for the mdl)
|
||
|
//
|
||
|
if ((TSAllocateMemory((PVOID *)&pucBuffer,
|
||
|
ulMAX_BUFFER_LENGTH,
|
||
|
strFunc1,
|
||
|
"pucBuffer")) != STATUS_SUCCESS)
|
||
|
{
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// then the actual mdl
|
||
|
//
|
||
|
pQueryMdl = TSAllocateBuffer(pucBuffer,
|
||
|
ulMAX_BUFFER_LENGTH);
|
||
|
|
||
|
if (pQueryMdl)
|
||
|
{
|
||
|
pQueryContext->pUpperIrp = pUpperIrp;
|
||
|
pQueryContext->pLowerMdl = pQueryMdl;
|
||
|
pQueryContext->pucLowerBuffer = pucBuffer;
|
||
|
|
||
|
//
|
||
|
// finally, the irp itself
|
||
|
//
|
||
|
PIRP pLowerIrp = TSAllocateIrp(pGenericHeader->pDeviceObject,
|
||
|
NULL);
|
||
|
|
||
|
if (pLowerIrp)
|
||
|
{
|
||
|
//
|
||
|
// if made it to here, everything is correctly allocated
|
||
|
// set up irp and call the tdi provider
|
||
|
//
|
||
|
|
||
|
#pragma warning(disable: CONSTANT_CONDITIONAL)
|
||
|
|
||
|
TdiBuildQueryInformation(pLowerIrp,
|
||
|
pGenericHeader->pDeviceObject,
|
||
|
pGenericHeader->pFileObject,
|
||
|
TSQueryComplete,
|
||
|
pQueryContext,
|
||
|
ulQueryId,
|
||
|
pQueryMdl);
|
||
|
|
||
|
#pragma warning(default: CONSTANT_CONDITIONAL)
|
||
|
|
||
|
//
|
||
|
// make the call to the tdi provider
|
||
|
//
|
||
|
pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
|
||
|
|
||
|
NTSTATUS lStatus = IoCallDriver(pGenericHeader->pDeviceObject,
|
||
|
pLowerIrp);
|
||
|
|
||
|
if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
|
||
|
{
|
||
|
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
|
||
|
strFunc1,
|
||
|
lStatus);
|
||
|
}
|
||
|
return STATUS_PENDING;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// get to here if there was an error
|
||
|
//
|
||
|
cleanup:
|
||
|
if (pQueryContext)
|
||
|
{
|
||
|
TSFreeMemory(pQueryContext);
|
||
|
}
|
||
|
if (pucBuffer)
|
||
|
{
|
||
|
TSFreeMemory(pucBuffer);
|
||
|
}
|
||
|
if (pQueryMdl)
|
||
|
{
|
||
|
TSFreeBuffer(pQueryMdl);
|
||
|
}
|
||
|
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////
|
||
|
// private functions
|
||
|
/////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// ---------------------------------------------------------
|
||
|
//
|
||
|
// Function: TSQueryComplete
|
||
|
//
|
||
|
// Arguments: pDeviceObject -- device object that called tdiquery
|
||
|
// pIrp -- IRP used in the call
|
||
|
// pContext -- context used for the call
|
||
|
//
|
||
|
// Returns: status of operation (STATUS_MORE_PROCESSING_REQUIRED)
|
||
|
//
|
||
|
// Descript: Gets the result of the query, stuffs results into
|
||
|
// receive buffer, completes the IRP from the dll, and
|
||
|
// cleans up the Irp and associated data from the query
|
||
|
//
|
||
|
// ---------------------------------------------------------
|
||
|
|
||
|
#pragma warning(disable: UNREFERENCED_PARAM)
|
||
|
|
||
|
TDI_STATUS
|
||
|
TSQueryComplete(PDEVICE_OBJECT pDeviceObject,
|
||
|
PIRP pLowerIrp,
|
||
|
PVOID pvContext)
|
||
|
|
||
|
|
||
|
{
|
||
|
PQUERY_CONTEXT pQueryContext = (PQUERY_CONTEXT)pvContext;
|
||
|
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
|
||
|
ULONG_PTR ulCopyLength = pLowerIrp->IoStatus.Information;
|
||
|
PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pQueryContext->pUpperIrp);
|
||
|
|
||
|
pReceiveBuffer->lStatus = lStatus;
|
||
|
|
||
|
if (NT_SUCCESS(lStatus))
|
||
|
{
|
||
|
pReceiveBuffer->RESULTS.QueryRet.ulBufferLength = (ULONG)ulCopyLength;
|
||
|
if (ulCopyLength)
|
||
|
{
|
||
|
RtlCopyMemory(pReceiveBuffer->RESULTS.QueryRet.pucDataBuffer,
|
||
|
pQueryContext->pucLowerBuffer,
|
||
|
ulCopyLength);
|
||
|
}
|
||
|
}
|
||
|
else if (ulDebugLevel & ulDebugShowCommand)
|
||
|
{
|
||
|
DebugPrint2("%s: Completed with status 0x%08x\n",
|
||
|
strFuncP1,
|
||
|
lStatus);
|
||
|
}
|
||
|
TSCompleteIrp(pQueryContext->pUpperIrp);
|
||
|
|
||
|
//
|
||
|
// now cleanup
|
||
|
//
|
||
|
TSFreeBuffer(pQueryContext->pLowerMdl);
|
||
|
TSFreeMemory(pQueryContext->pucLowerBuffer);
|
||
|
TSFreeMemory(pQueryContext);
|
||
|
|
||
|
TSFreeIrp(pLowerIrp, NULL);
|
||
|
return TDI_MORE_PROCESSING;
|
||
|
}
|
||
|
|
||
|
#pragma warning(default: UNREFERENCED_PARAM)
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// end of file tdiquery.cpp
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|