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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1998
  6. //
  7. // File: test.c
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // This file contains functions that are used for testing the ParClass driver.
  12. //
  13. // This file differs from debug.c in that these functions may
  14. // also be available in a fre build
  15. //
  16. #include "pch.h"
  17. #include "test.h"
  18. NTSTATUS
  19. MfSendPnpIrp(
  20. IN PDEVICE_OBJECT DeviceObject,
  21. IN PIO_STACK_LOCATION Location,
  22. OUT PULONG_PTR Information OPTIONAL
  23. )
  24. /*++
  25. Routine Description:
  26. This builds and send a pnp irp to a device.
  27. Arguments:
  28. DeviceObject - The a device in the device stack the irp is to be sent to -
  29. the top of the device stack is always found and the irp sent there first.
  30. Location - The initial stack location to use - contains the IRP minor code
  31. and any parameters
  32. Information - If provided contains the final value of the irps information
  33. field.
  34. Return Value:
  35. The final status of the completed irp or an error if the irp couldn't be sent
  36. --*/
  37. {
  38. NTSTATUS status;
  39. PIRP irp = NULL;
  40. PIO_STACK_LOCATION irpStack;
  41. PDEVICE_OBJECT targetDevice = NULL;
  42. KEVENT irpCompleted;
  43. IO_STATUS_BLOCK statusBlock;
  44. ASSERT(Location->MajorFunction == IRP_MJ_PNP);
  45. //
  46. // Find out where we are sending the irp
  47. //
  48. targetDevice = IoGetAttachedDeviceReference(DeviceObject);
  49. //
  50. // Get an IRP
  51. //
  52. KeInitializeEvent(&irpCompleted, SynchronizationEvent, FALSE);
  53. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
  54. targetDevice,
  55. NULL, // Buffer
  56. 0, // Length
  57. 0, // StartingOffset
  58. &irpCompleted,
  59. &statusBlock
  60. );
  61. if (!irp) {
  62. goto cleanup;
  63. }
  64. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  65. irp->IoStatus.Information = 0;
  66. //
  67. // Initialize the stack location
  68. //
  69. irpStack = IoGetNextIrpStackLocation(irp);
  70. ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  71. irpStack->MinorFunction = Location->MinorFunction;
  72. irpStack->Parameters = Location->Parameters;
  73. //
  74. // Call the driver and wait for completion
  75. //
  76. status = IoCallDriver(targetDevice, irp);
  77. if (status == STATUS_PENDING) {
  78. KeWaitForSingleObject(&irpCompleted, Executive, KernelMode, FALSE, NULL);
  79. status = statusBlock.Status;
  80. }
  81. if (!NT_SUCCESS(status)) {
  82. goto cleanup;
  83. }
  84. //
  85. // Return the information
  86. //
  87. if (ARGUMENT_PRESENT(Information)) {
  88. *Information = statusBlock.Information;
  89. }
  90. ObDereferenceObject(targetDevice);
  91. ASSERT(status == STATUS_PENDING || status == statusBlock.Status);
  92. return statusBlock.Status;
  93. cleanup:
  94. if (targetDevice) {
  95. ObDereferenceObject(targetDevice);
  96. }
  97. return status;
  98. }
  99. VOID
  100. regTst(PDEVICE_OBJECT PortDeviceObject) {
  101. NTSTATUS status;
  102. PIRP irp;
  103. PDEVICE_OBJECT pdo;
  104. IO_STACK_LOCATION request;
  105. IO_STATUS_BLOCK ioStatus;
  106. ULONG_PTR info;
  107. HANDLE handle;
  108. PKEY_VALUE_FULL_INFORMATION buffer;
  109. ULONG bufferLength;
  110. ULONG resultLength;
  111. PWSTR valueNameWstr;
  112. UNICODE_STRING valueName;
  113. PWSTR portName;
  114. ///
  115. // RtlZeroMemory(&request, sizeof(IO_STACK_LOCATION));
  116. request.MajorFunction = IRP_MJ_PNP;
  117. request.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
  118. request.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
  119. status = MfSendPnpIrp(PortDeviceObject, &request, &info);
  120. if( !NT_SUCCESS(status) ) {
  121. return;
  122. }
  123. pdo = ((PDEVICE_RELATIONS)info)->Objects[0];
  124. ExFreePool((PVOID)info);
  125. if( !pdo ) {
  126. // NULL pdo?, bail out
  127. return;
  128. }
  129. status = IoOpenDeviceRegistryKey(pdo, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &handle);
  130. if( !NT_SUCCESS(status) ) {
  131. // unable to open key, bail out
  132. return;
  133. }
  134. //
  135. // we have a handle to the registry key
  136. //
  137. // loop trying to read registry value until either we succeed or
  138. // we get a hard failure, grow the result buffer as needed
  139. //
  140. bufferLength = 0; // we will ask how large a buffer we need
  141. buffer = NULL;
  142. valueNameWstr = L"PortName";
  143. RtlInitUnicodeString(&valueName, valueNameWstr);
  144. status = STATUS_BUFFER_TOO_SMALL;
  145. while(status == STATUS_BUFFER_TOO_SMALL) {
  146. status = ZwQueryValueKey(handle,
  147. &valueName,
  148. KeyValueFullInformation,
  149. buffer,
  150. bufferLength,
  151. &resultLength);
  152. if(status == STATUS_BUFFER_TOO_SMALL) {
  153. //
  154. // buffer too small, free it and allocate a larger buffer
  155. //
  156. if(buffer) ExFreePool(buffer);
  157. buffer = ExAllocatePool(PagedPool, resultLength);
  158. bufferLength = resultLength;
  159. if(!buffer) {
  160. // unable to allocate pool, clean up and exit
  161. ZwClose(handle);
  162. return;
  163. }
  164. }
  165. } // end while BUFFER_TOO_SMALL
  166. //
  167. // query is complete
  168. //
  169. // write something new as a test
  170. {
  171. UNICODE_STRING unicodeName;
  172. ULONG data=0x0fa305ff;
  173. RtlInitUnicodeString(&unicodeName, L"TestNameOKtoDelete");
  174. status = ZwSetValueKey(handle, &unicodeName, 0, REG_DWORD, &data, sizeof(ULONG));
  175. // ParDumpV( ("ZwSetValueKey returned status=%x\n", status) );
  176. }
  177. // no longer need the handle so close it
  178. ZwClose(handle);
  179. // check the status of our query
  180. if( !NT_SUCCESS(status) ) {
  181. if(buffer) ExFreePool(buffer);
  182. return;
  183. }
  184. // sanity check our result
  185. if( (buffer->Type != REG_SZ) || (!buffer->DataLength) ) {
  186. // ParDumpV( (" - either bogus PortName data type or zero length\n", status) );
  187. ExFreePool(buffer); // query succeeded, so we know we have a buffer
  188. return;
  189. }
  190. //
  191. // result looks ok, copy PortName to its own allocation of the proper size
  192. // and return a pointer to it
  193. //
  194. portName = ExAllocatePool(PagedPool, buffer->DataLength);
  195. if(!portName) {
  196. // unable to allocate pool, clean up and exit
  197. // ParDumpV( (" - unable to allocate pool to hold PortName(SymbolicLinkName)\n") );
  198. ExFreePool(buffer);
  199. return;
  200. }
  201. RtlCopyMemory(portName, (PUCHAR)buffer + buffer->DataOffset, buffer->DataLength);
  202. // ParDumpV( ("fred: PortName== <%S>\n",portName) );
  203. ExFreePool(portName);
  204. ExFreePool(buffer);
  205. }