|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1998
//
// File: test.c
//
//--------------------------------------------------------------------------
//
// This file contains functions that are used for testing the ParClass driver.
//
// This file differs from debug.c in that these functions may
// also be available in a fre build
//
#include "pch.h"
#include "test.h"
NTSTATUS MfSendPnpIrp( IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION Location, OUT PULONG_PTR Information OPTIONAL )
/*++
Routine Description:
This builds and send a pnp irp to a device. Arguments:
DeviceObject - The a device in the device stack the irp is to be sent to - the top of the device stack is always found and the irp sent there first. Location - The initial stack location to use - contains the IRP minor code and any parameters Information - If provided contains the final value of the irps information field.
Return Value:
The final status of the completed irp or an error if the irp couldn't be sent --*/
{
NTSTATUS status; PIRP irp = NULL; PIO_STACK_LOCATION irpStack; PDEVICE_OBJECT targetDevice = NULL; KEVENT irpCompleted; IO_STATUS_BLOCK statusBlock; ASSERT(Location->MajorFunction == IRP_MJ_PNP);
//
// Find out where we are sending the irp
//
targetDevice = IoGetAttachedDeviceReference(DeviceObject);
//
// Get an IRP
//
KeInitializeEvent(&irpCompleted, SynchronizationEvent, FALSE);
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, targetDevice, NULL, // Buffer
0, // Length
0, // StartingOffset
&irpCompleted, &statusBlock ); if (!irp) { goto cleanup; } irp->IoStatus.Status = STATUS_NOT_SUPPORTED; irp->IoStatus.Information = 0; //
// Initialize the stack location
//
irpStack = IoGetNextIrpStackLocation(irp); ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
irpStack->MinorFunction = Location->MinorFunction; irpStack->Parameters = Location->Parameters; //
// Call the driver and wait for completion
//
status = IoCallDriver(targetDevice, irp);
if (status == STATUS_PENDING) { KeWaitForSingleObject(&irpCompleted, Executive, KernelMode, FALSE, NULL); status = statusBlock.Status; }
if (!NT_SUCCESS(status)) { goto cleanup; }
//
// Return the information
//
if (ARGUMENT_PRESENT(Information)) { *Information = statusBlock.Information; }
ObDereferenceObject(targetDevice); ASSERT(status == STATUS_PENDING || status == statusBlock.Status);
return statusBlock.Status;
cleanup:
if (targetDevice) { ObDereferenceObject(targetDevice); }
return status; }
VOID regTst(PDEVICE_OBJECT PortDeviceObject) { NTSTATUS status; PIRP irp; PDEVICE_OBJECT pdo; IO_STACK_LOCATION request; IO_STATUS_BLOCK ioStatus; ULONG_PTR info; HANDLE handle; PKEY_VALUE_FULL_INFORMATION buffer; ULONG bufferLength; ULONG resultLength; PWSTR valueNameWstr; UNICODE_STRING valueName; PWSTR portName;
///
// RtlZeroMemory(&request, sizeof(IO_STACK_LOCATION));
request.MajorFunction = IRP_MJ_PNP; request.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; request.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
status = MfSendPnpIrp(PortDeviceObject, &request, &info); if( !NT_SUCCESS(status) ) { return; }
pdo = ((PDEVICE_RELATIONS)info)->Objects[0]; ExFreePool((PVOID)info);
if( !pdo ) { // NULL pdo?, bail out
return; }
status = IoOpenDeviceRegistryKey(pdo, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &handle);
if( !NT_SUCCESS(status) ) { // unable to open key, bail out
return; }
//
// we have a handle to the registry key
//
// loop trying to read registry value until either we succeed or
// we get a hard failure, grow the result buffer as needed
//
bufferLength = 0; // we will ask how large a buffer we need
buffer = NULL; valueNameWstr = L"PortName"; RtlInitUnicodeString(&valueName, valueNameWstr); status = STATUS_BUFFER_TOO_SMALL;
while(status == STATUS_BUFFER_TOO_SMALL) {
status = ZwQueryValueKey(handle, &valueName, KeyValueFullInformation, buffer, bufferLength, &resultLength);
if(status == STATUS_BUFFER_TOO_SMALL) { //
// buffer too small, free it and allocate a larger buffer
//
if(buffer) ExFreePool(buffer); buffer = ExAllocatePool(PagedPool, resultLength); bufferLength = resultLength; if(!buffer) { // unable to allocate pool, clean up and exit
ZwClose(handle); return; } }
} // end while BUFFER_TOO_SMALL
//
// query is complete
//
// write something new as a test
{ UNICODE_STRING unicodeName; ULONG data=0x0fa305ff; RtlInitUnicodeString(&unicodeName, L"TestNameOKtoDelete"); status = ZwSetValueKey(handle, &unicodeName, 0, REG_DWORD, &data, sizeof(ULONG)); // ParDumpV( ("ZwSetValueKey returned status=%x\n", status) );
}
// no longer need the handle so close it
ZwClose(handle);
// check the status of our query
if( !NT_SUCCESS(status) ) { if(buffer) ExFreePool(buffer); return; }
// sanity check our result
if( (buffer->Type != REG_SZ) || (!buffer->DataLength) ) { // ParDumpV( (" - either bogus PortName data type or zero length\n", status) );
ExFreePool(buffer); // query succeeded, so we know we have a buffer
return; }
//
// result looks ok, copy PortName to its own allocation of the proper size
// and return a pointer to it
//
portName = ExAllocatePool(PagedPool, buffer->DataLength); if(!portName) { // unable to allocate pool, clean up and exit
// ParDumpV( (" - unable to allocate pool to hold PortName(SymbolicLinkName)\n") );
ExFreePool(buffer); return; }
RtlCopyMemory(portName, (PUCHAR)buffer + buffer->DataOffset, buffer->DataLength);
// ParDumpV( ("fred: PortName== <%S>\n",portName) );
ExFreePool(portName); ExFreePool(buffer); }
|