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.

988 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. ptdrvcom.c
  5. Abstract:
  6. Code for the RDP remote port driver which is common to the mouse and keyboard
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. 02/12/99 - Initial Revision based on pnpi8042 driver
  11. --*/
  12. #include <precomp.h>
  13. #pragma hdrstop
  14. #include <poclass.h>
  15. #include "ptdrvcom.h"
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, PtCreate)
  18. #pragma alloc_text(PAGE, PtDeviceControl)
  19. #pragma alloc_text(INIT, PtEntry)
  20. #pragma alloc_text(PAGE, PtUnload)
  21. #if PTDRV_VERBOSE
  22. #pragma alloc_text(INIT, PtServiceParameters)
  23. #endif
  24. #endif // ALLOC_PRAGMA
  25. GLOBALS Globals;
  26. NTSTATUS
  27. PtCreate (
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN PIRP Irp
  30. )
  31. /*++
  32. Routine Description:
  33. This is the dispatch routine for create/open requests.
  34. Arguments:
  35. DeviceObject - Pointer to the device object.
  36. Irp - Pointer to the request packet.
  37. Return Value:
  38. NT status code.
  39. --*/
  40. {
  41. NTSTATUS status = STATUS_SUCCESS;
  42. PCOMMON_DATA commonData = NULL;
  43. Print(DBG_IOCTL_TRACE, ("Create enter\n"));
  44. PAGED_CODE();
  45. commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
  46. if (NULL == commonData->ConnectData.ClassService) {
  47. //
  48. // No Connection yet. How can we be enabled?
  49. //
  50. Print(DBG_IOCTL_ERROR,
  51. ("ERROR: enable before connect!\n"));
  52. status = STATUS_INVALID_DEVICE_STATE;
  53. }
  54. else if (commonData->ManuallyRemoved) {
  55. status = STATUS_NO_SUCH_DEVICE;
  56. }
  57. else if (1 >= InterlockedIncrement(&commonData->EnableCount)) {
  58. Print(DBG_IOCTL_INFO,
  59. ("Enabling %s (%d)\n",
  60. commonData->IsKeyboard ? "Keyboard" : "Mouse",
  61. commonData->EnableCount
  62. ));
  63. }
  64. //
  65. // No need to call the lower driver (the root bus) because it only handles
  66. // Power and PnP Irps
  67. //
  68. Irp->IoStatus.Status = status;
  69. Irp->IoStatus.Information = 0;
  70. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  71. Print(DBG_IOCTL_TRACE, ("Create (%x)\n", status));
  72. return status;
  73. }
  74. NTSTATUS
  75. PtClose (
  76. IN PDEVICE_OBJECT DeviceObject,
  77. IN PIRP Irp
  78. )
  79. /*++
  80. Routine Description:
  81. This is the dispatch routine for close requests. This request
  82. completes successfully.
  83. Arguments:
  84. DeviceObject - Pointer to the device object.
  85. Irp - Pointer to the request packet.
  86. Return Value:
  87. NT status code.
  88. --*/
  89. {
  90. PCOMMON_DATA commonData;
  91. PAGED_CODE();
  92. Print(DBG_IOCTL_TRACE, ("Close\n"));
  93. commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
  94. ASSERT(0 < commonData->EnableCount);
  95. if (0 >= InterlockedDecrement(&commonData->EnableCount)) {
  96. Print(DBG_IOCTL_INFO,
  97. ("Disabling %s (%d)\n",
  98. commonData->IsKeyboard ? "Keyboard" : "Mouse",
  99. commonData->EnableCount
  100. ));
  101. }
  102. Irp->IoStatus.Status = STATUS_SUCCESS;
  103. Irp->IoStatus.Information = 0;
  104. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  105. return STATUS_SUCCESS;
  106. }
  107. NTSTATUS
  108. PtDeviceControl(
  109. IN PDEVICE_OBJECT DeviceObject,
  110. IN PIRP Irp
  111. )
  112. {
  113. PPORT_KEYBOARD_EXTENSION kbExtension;
  114. PIO_STACK_LOCATION stack;
  115. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  116. PAGED_CODE();
  117. //
  118. // Get a pointer to the device extension.
  119. //
  120. kbExtension = (PPORT_KEYBOARD_EXTENSION) DeviceObject->DeviceExtension;
  121. if (!kbExtension->Started || !kbExtension->IsKeyboard ||
  122. kbExtension->ManuallyRemoved) {
  123. status = STATUS_INVALID_DEVICE_REQUEST;
  124. }
  125. else {
  126. stack = IoGetCurrentIrpStackLocation(Irp);
  127. switch (stack->Parameters.DeviceIoControl.IoControlCode) {
  128. case IOCTL_GET_SYS_BUTTON_CAPS:
  129. //
  130. // We don't support any system buttons
  131. //
  132. if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
  133. Print(DBG_IOCTL_ERROR, ("get caps, buffer too small\n"));
  134. status = STATUS_INVALID_BUFFER_SIZE;
  135. }
  136. else {
  137. Print(DBG_IOCTL_INFO, ("Returned sys btn caps of 0x0\n"));
  138. *(PULONG) Irp->AssociatedIrp.SystemBuffer = 0x0;
  139. status = STATUS_SUCCESS;
  140. }
  141. Irp->IoStatus.Information = sizeof(ULONG);
  142. break;
  143. default:
  144. Print(DBG_IOCTL_ERROR, ("Invalid request 0x%x\n",
  145. stack->Parameters.DeviceIoControl.IoControlCode));
  146. status = STATUS_INVALID_DEVICE_REQUEST;
  147. break;
  148. }
  149. }
  150. Irp->IoStatus.Status = status;
  151. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  152. return status;
  153. }
  154. NTSTATUS
  155. PtInternalDeviceControl(
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PIRP Irp
  158. )
  159. /*++
  160. Routine Description:
  161. This routine is the dispatch routine for internal device control requests.
  162. This routine cannot be paged because the class drivers send down internal
  163. IOCTLs at DISPATCH_LEVEL.
  164. Arguments:
  165. DeviceObject - Pointer to the device object.
  166. Irp - Pointer to the request packet.
  167. Return Value:
  168. Status is returned.
  169. --*/
  170. {
  171. PIO_STACK_LOCATION irpSp;
  172. PPORT_MOUSE_EXTENSION mouseExtension = DeviceObject->DeviceExtension;
  173. PPORT_KEYBOARD_EXTENSION kbExtension = DeviceObject->DeviceExtension;
  174. NTSTATUS status;
  175. ULONG sizeOfTranslation;
  176. PDEVICE_OBJECT topOfStack;
  177. Print(DBG_IOCTL_TRACE, ("IOCTL: enter\n"));
  178. Irp->IoStatus.Information = 0;
  179. irpSp = IoGetCurrentIrpStackLocation(Irp);
  180. //
  181. // Case on the device control subfunction that is being performed by the
  182. // requestor.
  183. //
  184. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  185. //
  186. // Connect a keyboard class device driver to the port driver.
  187. //
  188. case IOCTL_INTERNAL_KEYBOARD_CONNECT:
  189. //
  190. // This really isn't something to worry about overall, but it is worthy
  191. // enough to be noted and recorded. The multiple starts will be handled in
  192. // PtPnp and PtKeyboardStartDevice routines
  193. //
  194. if (KEYBOARD_PRESENT()) {
  195. Print(DBG_ALWAYS, ("Received 1+ kb connects!\n"));
  196. SET_HW_FLAGS(DUP_KEYBOARD_HARDWARE_PRESENT);
  197. }
  198. InterlockedIncrement(&Globals.AddedKeyboards);
  199. kbExtension->IsKeyboard = TRUE;
  200. SET_HW_FLAGS(KEYBOARD_HARDWARE_PRESENT);
  201. Print(DBG_IOCTL_INFO, ("IOCTL: keyboard connect\n"));
  202. //
  203. // Save away the keyboard device object - we'll need it later
  204. //
  205. KbdDeviceObject = DeviceObject;
  206. //
  207. // Only allow a connection if the keyboard hardware is present.
  208. // Also, only allow one connection.
  209. //
  210. if (kbExtension->ConnectData.ClassService != NULL) {
  211. Print(DBG_IOCTL_ERROR, ("IOCTL: error - already connected\n"));
  212. status = STATUS_SHARING_VIOLATION;
  213. break;
  214. }
  215. else if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  216. sizeof(CONNECT_DATA)) {
  217. Print(DBG_IOCTL_ERROR, ("IOCTL: error - invalid buffer length\n"));
  218. status = STATUS_INVALID_PARAMETER;
  219. break;
  220. }
  221. //
  222. // Copy the connection parameters to the device extension.
  223. //
  224. kbExtension->ConnectData =
  225. *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
  226. status = STATUS_SUCCESS;
  227. break;
  228. //
  229. // Disconnect a keyboard class device driver from the port driver.
  230. //
  231. // NOTE: Not implemented.
  232. //
  233. case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
  234. Print(DBG_IOCTL_INFO, ("IOCTL: keyboard disconnect\n"));
  235. status = STATUS_NOT_IMPLEMENTED;
  236. break;
  237. //
  238. // Connect a mouse class device driver to the port driver.
  239. //
  240. case IOCTL_INTERNAL_MOUSE_CONNECT:
  241. //
  242. // This really isn't something to worry about overall, but it is worthy
  243. // enough to be noted and recorded. The multiple starts will be handled in
  244. // PtPnp and PtMouseStartDevice routines
  245. //
  246. if (MOUSE_PRESENT()) {
  247. Print(DBG_ALWAYS, ("Received 1+ mouse connects!\n"));
  248. SET_HW_FLAGS(DUP_MOUSE_HARDWARE_PRESENT);
  249. }
  250. InterlockedIncrement(&Globals.AddedMice);
  251. mouseExtension->IsKeyboard = FALSE;
  252. SET_HW_FLAGS(MOUSE_HARDWARE_PRESENT);
  253. Print(DBG_IOCTL_INFO, ("IOCTL: mouse connect\n"));
  254. //
  255. // Save away the mouse device object - we'll need it later
  256. //
  257. MouDeviceObject = DeviceObject;
  258. //
  259. // Only allow a connection if the mouse hardware is present.
  260. // Also, only allow one connection.
  261. //
  262. if (mouseExtension->ConnectData.ClassService != NULL) {
  263. Print(DBG_IOCTL_ERROR, ("IOCTL: error - already connected\n"));
  264. status = STATUS_SHARING_VIOLATION;
  265. break;
  266. }
  267. else if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  268. sizeof(CONNECT_DATA)) {
  269. Print(DBG_IOCTL_ERROR, ("IOCTL: error - invalid buffer length\n"));
  270. status = STATUS_INVALID_PARAMETER;
  271. break;
  272. }
  273. //
  274. // Copy the connection parameters to the device extension.
  275. //
  276. mouseExtension->ConnectData =
  277. *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
  278. status = STATUS_SUCCESS;
  279. break;
  280. //
  281. // Disconnect a mouse class device driver from the port driver.
  282. //
  283. // NOTE: Not implemented.
  284. //
  285. case IOCTL_INTERNAL_MOUSE_DISCONNECT:
  286. Print(DBG_IOCTL_INFO, ("IOCTL: mouse disconnect\n"));
  287. status = STATUS_NOT_IMPLEMENTED;
  288. break;
  289. //
  290. // Query the keyboard attributes. First check for adequate buffer
  291. // length. Then, copy the keyboard attributes from the device
  292. // extension to the output buffer.
  293. //
  294. case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
  295. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard query attributes\n"));
  296. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  297. sizeof(KEYBOARD_ATTRIBUTES)) {
  298. status = STATUS_BUFFER_TOO_SMALL;
  299. }
  300. else {
  301. //
  302. // Copy the attributes from the DeviceExtension to the
  303. // buffer.
  304. //
  305. PKEYBOARD_ATTRIBUTES pKBA =
  306. (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
  307. pKBA->KeyboardIdentifier.Type = 0x51;
  308. pKBA->KeyboardIdentifier.Subtype = 0;
  309. pKBA->KeyboardMode = 1;
  310. pKBA->NumberOfFunctionKeys = KEYBOARD_NUM_FUNCTION_KEYS;
  311. pKBA->NumberOfIndicators = KEYBOARD_NUM_INDICATORS;
  312. pKBA->NumberOfKeysTotal = KEYBOARD_NUM_KEYS_TOTAL;
  313. pKBA->InputDataQueueLength = 100;
  314. pKBA->KeyRepeatMinimum.UnitId = 0;
  315. pKBA->KeyRepeatMinimum.Rate = 2;
  316. pKBA->KeyRepeatMinimum.Delay = 250;
  317. pKBA->KeyRepeatMaximum.UnitId = 0;
  318. pKBA->KeyRepeatMaximum.Rate = 30;
  319. pKBA->KeyRepeatMaximum.Delay = 1000;
  320. Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES);
  321. status = STATUS_SUCCESS;
  322. }
  323. break;
  324. //
  325. // Query the scan code to indicator-light mapping. Validate the
  326. // parameters, and copy the indicator mapping information from
  327. // the port device extension to the SystemBuffer.
  328. //
  329. case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: {
  330. PKEYBOARD_INDICATOR_TRANSLATION translation;
  331. ASSERT(kbExtension->IsKeyboard);
  332. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard query indicator translation\n"));
  333. sizeOfTranslation = sizeof(KEYBOARD_INDICATOR_TRANSLATION)
  334. + (sizeof(INDICATOR_LIST)
  335. * (KEYBOARD_NUM_INDICATORS - 1));
  336. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  337. sizeOfTranslation) {
  338. status = STATUS_BUFFER_TOO_SMALL;
  339. }
  340. else {
  341. //
  342. // Copy the indicator mapping information to the system
  343. // buffer.
  344. //
  345. translation = (PKEYBOARD_INDICATOR_TRANSLATION)
  346. Irp->AssociatedIrp.SystemBuffer;
  347. translation->NumberOfIndicatorKeys = KEYBOARD_NUM_INDICATORS;
  348. RtlMoveMemory(
  349. translation->IndicatorList,
  350. (PCHAR) IndicatorList,
  351. sizeof(INDICATOR_LIST) * translation->NumberOfIndicatorKeys
  352. );
  353. Irp->IoStatus.Information = sizeOfTranslation;
  354. status = STATUS_SUCCESS;
  355. }
  356. break;
  357. }
  358. //
  359. // Query the keyboard indicators. Validate the parameters, and
  360. // copy the indicator information from the port device extension to
  361. // the SystemBuffer.
  362. //
  363. case IOCTL_KEYBOARD_QUERY_INDICATORS:
  364. ASSERT(kbExtension->IsKeyboard);
  365. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard query indicators\n"));
  366. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  367. sizeof(KEYBOARD_INDICATOR_PARAMETERS)) {
  368. status = STATUS_BUFFER_TOO_SMALL;
  369. }
  370. else {
  371. //
  372. // Just say they're all off
  373. //
  374. ((PKEYBOARD_INDICATOR_PARAMETERS)Irp->AssociatedIrp.SystemBuffer)->LedFlags = 0;
  375. Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
  376. status = STATUS_SUCCESS;
  377. }
  378. break;
  379. //
  380. // Set the keyboard indicators
  381. //
  382. case IOCTL_KEYBOARD_SET_INDICATORS:
  383. // Just return success
  384. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard set indicators\n"));
  385. status = STATUS_SUCCESS;
  386. break;
  387. //
  388. // Query the current keyboard typematic rate and delay. Validate
  389. // the parameters, and copy the typematic information from the port
  390. // device extension to the SystemBuffer.
  391. //
  392. case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
  393. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard query typematic\n"));
  394. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  395. sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
  396. status = STATUS_BUFFER_TOO_SMALL;
  397. }
  398. else {
  399. //
  400. // just return our default info
  401. //
  402. PKEYBOARD_TYPEMATIC_PARAMETERS pKTP =
  403. (PKEYBOARD_TYPEMATIC_PARAMETERS) Irp->AssociatedIrp.SystemBuffer;
  404. pKTP->Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
  405. pKTP->Delay = KEYBOARD_TYPEMATIC_DELAY_DEFAULT;
  406. Irp->IoStatus.Information = sizeof(KEYBOARD_TYPEMATIC_PARAMETERS);
  407. status = STATUS_SUCCESS;
  408. }
  409. break;
  410. //
  411. // Sets the keyboard typematic rate and delay
  412. // We just say 'fine'
  413. //
  414. case IOCTL_KEYBOARD_SET_TYPEMATIC:
  415. {
  416. status = STATUS_SUCCESS;
  417. }
  418. break;
  419. case IOCTL_KEYBOARD_SET_IME_STATUS:
  420. Print(DBG_IOCTL_NOISE, ("IOCTL: keyboard set ime status\n"));
  421. status = STATUS_INVALID_DEVICE_REQUEST;
  422. break;
  423. //
  424. // Query the mouse attributes. First check for adequate buffer
  425. // length. Then, copy the mouse attributes from the device
  426. // extension to the output buffer.
  427. //
  428. case IOCTL_MOUSE_QUERY_ATTRIBUTES:
  429. Print(DBG_IOCTL_NOISE, ("IOCTL: mouse query attributes\n"));
  430. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  431. sizeof(MOUSE_ATTRIBUTES)) {
  432. status = STATUS_BUFFER_TOO_SMALL;
  433. }
  434. else {
  435. //
  436. // Copy the attributes from the DeviceExtension to the
  437. // buffer.
  438. //
  439. PMOUSE_ATTRIBUTES pMA = (PMOUSE_ATTRIBUTES)
  440. Irp->AssociatedIrp.SystemBuffer;
  441. pMA->MouseIdentifier = MOUSE_IDENTIFIER;
  442. pMA->NumberOfButtons = MOUSE_NUM_BUTTONS;
  443. pMA->SampleRate = MOUSE_SAMPLE_RATE;
  444. pMA->InputDataQueueLength = MOUSE_INPUT_QLEN;
  445. Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
  446. status = STATUS_SUCCESS;
  447. }
  448. break;
  449. case IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER:
  450. case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER:
  451. Print(DBG_IOCTL_NOISE, ("IOCTL: mouse send buffer\n"));
  452. status = STATUS_INVALID_DEVICE_REQUEST;
  453. break;
  454. case IOCTL_INTERNAL_I8042_CONTROLLER_WRITE_BUFFER:
  455. status = STATUS_NOT_SUPPORTED;
  456. break;
  457. default:
  458. Print(DBG_IOCTL_ERROR, ("IOCTL: INVALID REQUEST\n"));
  459. status = STATUS_INVALID_DEVICE_REQUEST;
  460. break;
  461. }
  462. Irp->IoStatus.Status = status;
  463. if (status == STATUS_PENDING) {
  464. IoMarkIrpPending(Irp);
  465. IoStartPacket(DeviceObject,
  466. Irp,
  467. (PULONG) NULL,
  468. NULL
  469. );
  470. }
  471. else {
  472. IoCompleteRequest(Irp,
  473. IO_NO_INCREMENT
  474. );
  475. }
  476. Print(DBG_IOCTL_TRACE, ("IOCTL: exit (0x%x)\n", status));
  477. return status;
  478. }
  479. VOID
  480. PtStartIo(
  481. IN PDEVICE_OBJECT DeviceObject,
  482. IN PIRP Irp
  483. )
  484. /*++
  485. Routine Description:
  486. This routine starts an I/O operation for the device which is further
  487. controlled by the controller object
  488. Arguments:
  489. DeviceObject - Pointer to the device object.
  490. Irp - Pointer to the request packet.
  491. Return Value:
  492. None.
  493. --*/
  494. {
  495. KIRQL cancelIrql;
  496. PIO_STACK_LOCATION irpSp;
  497. Print(DBG_IOCTL_TRACE, ("PtStartIo: enter\n"));
  498. irpSp = IoGetCurrentIrpStackLocation(Irp);
  499. switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
  500. case IOCTL_KEYBOARD_SET_INDICATORS:
  501. case IOCTL_KEYBOARD_SET_TYPEMATIC:
  502. case IOCTL_KEYBOARD_SET_IME_STATUS:
  503. case IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER:
  504. case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER:
  505. case IOCTL_INTERNAL_MOUSE_RESET:
  506. default:
  507. Print(DBG_IOCTL_ERROR, ("PtStartIo: INVALID REQUEST\n"));
  508. IoAcquireCancelSpinLock(&cancelIrql);
  509. IoSetCancelRoutine(Irp, NULL);
  510. IoReleaseCancelSpinLock(cancelIrql);
  511. Irp->IoStatus.Information = 0;
  512. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  513. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  514. IoStartNextPacket(DeviceObject, FALSE);
  515. }
  516. Print(DBG_IOCTL_TRACE, ("PtStartIo: exit\n"));
  517. }
  518. NTSTATUS
  519. PtEntry(
  520. IN PDRIVER_OBJECT DriverObject,
  521. IN PUNICODE_STRING RegistryPath
  522. )
  523. {
  524. NTSTATUS status = STATUS_SUCCESS;
  525. UNICODE_STRING parametersPath;
  526. PWSTR path;
  527. UNICODE_STRING deviceName;
  528. PDEVICE_OBJECT newDeviceObject;
  529. RtlZeroMemory(&Globals,
  530. sizeof(GLOBALS)
  531. );
  532. Globals.ControllerData = (PCONTROLLER_DATA) ExAllocatePool(
  533. NonPagedPool,
  534. sizeof(CONTROLLER_DATA)
  535. );
  536. if (!Globals.ControllerData) {
  537. status = STATUS_INSUFFICIENT_RESOURCES;
  538. goto DriverEntryError;
  539. }
  540. RtlZeroMemory(Globals.ControllerData,
  541. sizeof(CONTROLLER_DATA)
  542. );
  543. Globals.ControllerData->ControllerObject = IoCreateController(0);
  544. if (!Globals.ControllerData->ControllerObject) {
  545. status = STATUS_INSUFFICIENT_RESOURCES;
  546. goto DriverEntryError;
  547. }
  548. Globals.RegistryPath.MaximumLength = RegistryPath->Length +
  549. sizeof(UNICODE_NULL);
  550. Globals.RegistryPath.Length = RegistryPath->Length;
  551. Globals.RegistryPath.Buffer = ExAllocatePool(
  552. NonPagedPool,
  553. Globals.RegistryPath.MaximumLength
  554. );
  555. if (!Globals.RegistryPath.Buffer) {
  556. Print (DBG_SS_ERROR,
  557. ("Initialize: Couldn't allocate pool for registry path."));
  558. status = STATUS_INSUFFICIENT_RESOURCES;
  559. goto DriverEntryError;
  560. }
  561. RtlZeroMemory (Globals.RegistryPath.Buffer,
  562. Globals.RegistryPath.MaximumLength);
  563. RtlMoveMemory (Globals.RegistryPath.Buffer,
  564. RegistryPath->Buffer,
  565. RegistryPath->Length);
  566. #if PTDRV_VERBOSE
  567. PtServiceParameters(RegistryPath);
  568. #endif
  569. ExInitializeFastMutex(&Globals.DispatchMutex);
  570. KeInitializeSpinLock(&Globals.ControllerData->PowerUpSpinLock);
  571. Print(DBG_SS_TRACE, ("PortDriverEntry (0x%x) \n", status));
  572. return status;
  573. DriverEntryError:
  574. //
  575. // Clean after something has gone wrong
  576. //
  577. if (Globals.ControllerData) {
  578. if (Globals.ControllerData->ControllerObject) {
  579. IoDeleteController(Globals.ControllerData->ControllerObject);
  580. }
  581. ExFreePool(Globals.ControllerData);
  582. }
  583. if (Globals.RegistryPath.Buffer) {
  584. ExFreePool(Globals.RegistryPath.Buffer);
  585. }
  586. Print(DBG_SS_ERROR, ("PortDriverEntry (0x%x) \n", status));
  587. return status;
  588. }
  589. VOID
  590. PtUnload(
  591. IN PDRIVER_OBJECT Driver
  592. )
  593. /*++
  594. Routine Description:
  595. Free all the allocated resources associated with this driver.
  596. Arguments:
  597. DriverObject - Pointer to the driver object.
  598. Return Value:
  599. None.
  600. --*/
  601. {
  602. ULONG i;
  603. PAGED_CODE();
  604. ASSERT(NULL == Driver->DeviceObject);
  605. Print(DBG_SS_TRACE, ("Unload \n"));
  606. //
  607. // Free resources in Globals
  608. //
  609. ExFreePool(Globals.RegistryPath.Buffer);
  610. if (Globals.ControllerData->ControllerObject) {
  611. IoDeleteController(Globals.ControllerData->ControllerObject);
  612. }
  613. ExFreePool(Globals.ControllerData);
  614. return;
  615. }
  616. #if PTDRV_VERBOSE
  617. VOID
  618. PtServiceParameters(
  619. IN PUNICODE_STRING RegistryPath
  620. )
  621. /*++
  622. Routine Description:
  623. This routine retrieves this driver's service parameters information
  624. from the registry.
  625. Arguments:
  626. RegistryPath - Pointer to the null-terminated Unicode name of the
  627. registry path for this driver.
  628. Return Value:
  629. None. As a side-effect, sets fields in DeviceExtension->Configuration.
  630. --*/
  631. {
  632. NTSTATUS status = STATUS_SUCCESS;
  633. PI8042_CONFIGURATION_INFORMATION configuration;
  634. PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
  635. PWSTR path = NULL;
  636. ULONG defaultDebugFlags = DEFAULT_DEBUG_FLAGS;
  637. ULONG i = 0;
  638. UNICODE_STRING parametersPath;
  639. USHORT queries = 2;
  640. configuration = &(Globals.ControllerData->Configuration);
  641. parametersPath.Buffer = NULL;
  642. Globals.DebugFlags = DEFAULT_DEBUG_FLAGS;
  643. //
  644. // Registry path is already null-terminated, so just use it.
  645. //
  646. path = RegistryPath->Buffer;
  647. if (NT_SUCCESS(status)) {
  648. //
  649. // Allocate the Rtl query table.
  650. //
  651. parameters = ExAllocatePool(
  652. PagedPool,
  653. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  654. );
  655. if (!parameters) {
  656. Print(DBG_SS_ERROR,
  657. ("%s: couldn't allocate table for Rtl query to %ws for %ws\n",
  658. pFncServiceParameters,
  659. pwParameters,
  660. path
  661. ));
  662. status = STATUS_UNSUCCESSFUL;
  663. } else {
  664. RtlZeroMemory(
  665. parameters,
  666. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  667. );
  668. //
  669. // Form a path to this driver's Parameters subkey.
  670. //
  671. RtlInitUnicodeString( &parametersPath, NULL );
  672. parametersPath.MaximumLength = RegistryPath->Length +
  673. (wcslen(pwParameters) * sizeof(WCHAR) ) + sizeof(UNICODE_NULL);
  674. parametersPath.Buffer = ExAllocatePool(
  675. PagedPool,
  676. parametersPath.MaximumLength
  677. );
  678. if (!parametersPath.Buffer) {
  679. Print(DBG_SS_ERROR,
  680. ("%s: Couldn't allocate string for path to %ws for %ws\n",
  681. pFncServiceParameters,
  682. pwParameters,
  683. path
  684. ));
  685. status = STATUS_UNSUCCESSFUL;
  686. }
  687. }
  688. }
  689. if (NT_SUCCESS(status)) {
  690. //
  691. // Form the parameters path.
  692. //
  693. RtlZeroMemory(
  694. parametersPath.Buffer,
  695. parametersPath.MaximumLength
  696. );
  697. RtlAppendUnicodeToString(
  698. &parametersPath,
  699. path
  700. );
  701. RtlAppendUnicodeToString(
  702. &parametersPath,
  703. pwParameters
  704. );
  705. Print(DBG_SS_INFO,
  706. ("%s: %ws path is %ws\n",
  707. pFncServiceParameters,
  708. pwParameters,
  709. parametersPath.Buffer
  710. ));
  711. parameters[i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  712. parameters[i].Name = pwDebugFlags;
  713. parameters[i].EntryContext = &Globals.DebugFlags;
  714. parameters[i].DefaultType = REG_DWORD;
  715. parameters[i].DefaultData = &defaultDebugFlags;
  716. parameters[i].DefaultLength = sizeof(ULONG);
  717. status = RtlQueryRegistryValues(
  718. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  719. parametersPath.Buffer,
  720. parameters,
  721. NULL,
  722. NULL
  723. );
  724. if (!NT_SUCCESS(status)) {
  725. Print(DBG_SS_INFO,
  726. ("%s: RtlQueryRegistryValues failed with 0x%x\n",
  727. pFncServiceParameters,
  728. status
  729. ));
  730. }
  731. }
  732. Print(DBG_SS_NOISE, ("PtServiceParameters results..\n"));
  733. Print(DBG_SS_NOISE,
  734. ("\tDebug flags are 0x%x\n",
  735. Globals.DebugFlags
  736. ));
  737. //
  738. // Free the allocated memory before returning.
  739. //
  740. if (parametersPath.Buffer)
  741. ExFreePool(parametersPath.Buffer);
  742. if (parameters)
  743. ExFreePool(parameters);
  744. }
  745. #endif // PTDRV_VERBOSE