windows-nt/Source/XPSP1/NT/net/tdi/sample/sys/tdiquery.cpp
2020-09-26 16:20:57 +08:00

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
///////////////////////////////////////////////////////////////////////////////