Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

276 lines
7.1 KiB

//+-------------------------------------------------------------------------
//
// 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);
}