Leaked source code of windows server 2003
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.

1004 lines
27 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. RtlZeroMemory(&Globals,
  526. sizeof(GLOBALS)
  527. );
  528. Globals.ControllerData = (PCONTROLLER_DATA) ExAllocatePool(
  529. NonPagedPool,
  530. sizeof(CONTROLLER_DATA)
  531. );
  532. if (!Globals.ControllerData) {
  533. status = STATUS_INSUFFICIENT_RESOURCES;
  534. goto DriverEntryError;
  535. }
  536. RtlZeroMemory(Globals.ControllerData,
  537. sizeof(CONTROLLER_DATA)
  538. );
  539. Globals.ControllerData->ControllerObject = IoCreateController(0);
  540. if (!Globals.ControllerData->ControllerObject) {
  541. status = STATUS_INSUFFICIENT_RESOURCES;
  542. goto DriverEntryError;
  543. }
  544. Globals.RegistryPath.MaximumLength = RegistryPath->Length +
  545. sizeof(UNICODE_NULL);
  546. Globals.RegistryPath.Length = RegistryPath->Length;
  547. Globals.RegistryPath.Buffer = ExAllocatePool(
  548. NonPagedPool,
  549. Globals.RegistryPath.MaximumLength
  550. );
  551. if (!Globals.RegistryPath.Buffer) {
  552. Print (DBG_SS_ERROR,
  553. ("Initialize: Couldn't allocate pool for registry path."));
  554. status = STATUS_INSUFFICIENT_RESOURCES;
  555. goto DriverEntryError;
  556. }
  557. RtlZeroMemory (Globals.RegistryPath.Buffer,
  558. Globals.RegistryPath.MaximumLength);
  559. RtlMoveMemory (Globals.RegistryPath.Buffer,
  560. RegistryPath->Buffer,
  561. RegistryPath->Length);
  562. #if PTDRV_VERBOSE
  563. PtServiceParameters(RegistryPath);
  564. #endif
  565. ExInitializeFastMutex(&Globals.DispatchMutex);
  566. KeInitializeSpinLock(&Globals.ControllerData->PowerUpSpinLock);
  567. Print(DBG_SS_TRACE, ("PortDriverEntry (0x%x) \n", status));
  568. return status;
  569. DriverEntryError:
  570. //
  571. // Clean after something has gone wrong
  572. // and set pointers to NULL for PtUnload
  573. //
  574. if (Globals.ControllerData) {
  575. if (Globals.ControllerData->ControllerObject) {
  576. IoDeleteController(Globals.ControllerData->ControllerObject);
  577. }
  578. ExFreePool(Globals.ControllerData);
  579. Globals.ControllerData = NULL;
  580. }
  581. if (Globals.RegistryPath.Buffer) {
  582. ExFreePool(Globals.RegistryPath.Buffer);
  583. Globals.RegistryPath.Buffer = NULL;
  584. Globals.RegistryPath.Length = 0;
  585. Globals.RegistryPath.MaximumLength = 0;
  586. }
  587. Print(DBG_SS_ERROR, ("PortDriverEntry (0x%x) \n", status));
  588. return status;
  589. }
  590. VOID
  591. PtUnload(
  592. IN PDRIVER_OBJECT Driver
  593. )
  594. /*++
  595. Routine Description:
  596. Free all the allocated resources associated with this driver.
  597. Arguments:
  598. DriverObject - Pointer to the driver object.
  599. Return Value:
  600. None.
  601. --*/
  602. {
  603. ULONG i;
  604. PAGED_CODE();
  605. ASSERT(NULL == Driver->DeviceObject);
  606. Print(DBG_SS_TRACE, ("Unload \n"));
  607. //
  608. // Free resources in Globals
  609. //
  610. // test for all pointers in case they were not allocated
  611. if (Globals.ControllerData) {
  612. if (Globals.ControllerData->ControllerObject) {
  613. IoDeleteController(Globals.ControllerData->ControllerObject);
  614. }
  615. ExFreePool(Globals.ControllerData);
  616. Globals.ControllerData = NULL;
  617. }
  618. if (Globals.RegistryPath.Buffer) {
  619. ExFreePool(Globals.RegistryPath.Buffer);
  620. Globals.RegistryPath.Buffer = NULL;
  621. Globals.RegistryPath.Length = 0;
  622. Globals.RegistryPath.MaximumLength = 0;
  623. }
  624. return;
  625. }
  626. #if PTDRV_VERBOSE
  627. VOID
  628. PtServiceParameters(
  629. IN PUNICODE_STRING RegistryPath
  630. )
  631. /*++
  632. Routine Description:
  633. This routine retrieves this driver's service parameters information
  634. from the registry.
  635. Arguments:
  636. RegistryPath - Pointer to the null-terminated Unicode name of the
  637. registry path for this driver.
  638. Return Value:
  639. None. As a side-effect, sets fields in DeviceExtension->Configuration.
  640. --*/
  641. {
  642. NTSTATUS status = STATUS_SUCCESS;
  643. PI8042_CONFIGURATION_INFORMATION configuration;
  644. PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
  645. PWSTR path = NULL;
  646. ULONG defaultDebugFlags = DEFAULT_DEBUG_FLAGS;
  647. ULONG i = 0;
  648. UNICODE_STRING parametersPath;
  649. USHORT queries = 2;
  650. if (Globals.ControllerData == NULL)
  651. return;
  652. configuration = &(Globals.ControllerData->Configuration);
  653. parametersPath.Buffer = NULL;
  654. Globals.DebugFlags = DEFAULT_DEBUG_FLAGS;
  655. //
  656. // Registry path is already null-terminated, so just use it.
  657. //
  658. path = RegistryPath->Buffer;
  659. if (NT_SUCCESS(status)) {
  660. //
  661. // Allocate the Rtl query table.
  662. //
  663. parameters = ExAllocatePool(
  664. PagedPool,
  665. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  666. );
  667. if (!parameters) {
  668. Print(DBG_SS_ERROR,
  669. ("%s: couldn't allocate table for Rtl query to %ws for %ws\n",
  670. pFncServiceParameters,
  671. pwParameters,
  672. path
  673. ));
  674. status = STATUS_UNSUCCESSFUL;
  675. } else {
  676. RtlZeroMemory(
  677. parameters,
  678. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  679. );
  680. //
  681. // Form a path to this driver's Parameters subkey.
  682. //
  683. RtlInitUnicodeString( &parametersPath, NULL );
  684. parametersPath.MaximumLength = RegistryPath->Length +
  685. (wcslen(pwParameters) * sizeof(WCHAR) ) + sizeof(UNICODE_NULL);
  686. parametersPath.Buffer = ExAllocatePool(
  687. PagedPool,
  688. parametersPath.MaximumLength
  689. );
  690. if (!parametersPath.Buffer) {
  691. Print(DBG_SS_ERROR,
  692. ("%s: Couldn't allocate string for path to %ws for %ws\n",
  693. pFncServiceParameters,
  694. pwParameters,
  695. path
  696. ));
  697. status = STATUS_UNSUCCESSFUL;
  698. }
  699. }
  700. }
  701. if (NT_SUCCESS(status)) {
  702. //
  703. // Form the parameters path.
  704. //
  705. RtlZeroMemory(
  706. parametersPath.Buffer,
  707. parametersPath.MaximumLength
  708. );
  709. RtlAppendUnicodeToString(
  710. &parametersPath,
  711. path
  712. );
  713. RtlAppendUnicodeToString(
  714. &parametersPath,
  715. pwParameters
  716. );
  717. Print(DBG_SS_INFO,
  718. ("%s: %ws path is %ws\n",
  719. pFncServiceParameters,
  720. pwParameters,
  721. parametersPath.Buffer
  722. ));
  723. parameters[i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  724. parameters[i].Name = pwDebugFlags;
  725. parameters[i].EntryContext = &Globals.DebugFlags;
  726. parameters[i].DefaultType = REG_DWORD;
  727. parameters[i].DefaultData = &defaultDebugFlags;
  728. parameters[i].DefaultLength = sizeof(ULONG);
  729. status = RtlQueryRegistryValues(
  730. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  731. parametersPath.Buffer,
  732. parameters,
  733. NULL,
  734. NULL
  735. );
  736. if (!NT_SUCCESS(status)) {
  737. Print(DBG_SS_INFO,
  738. ("%s: RtlQueryRegistryValues failed with 0x%x\n",
  739. pFncServiceParameters,
  740. status
  741. ));
  742. }
  743. }
  744. Print(DBG_SS_NOISE, ("PtServiceParameters results..\n"));
  745. Print(DBG_SS_NOISE,
  746. ("\tDebug flags are 0x%x\n",
  747. Globals.DebugFlags
  748. ));
  749. //
  750. // Free the allocated memory before returning.
  751. //
  752. if (parametersPath.Buffer)
  753. ExFreePool(parametersPath.Buffer);
  754. if (parameters)
  755. ExFreePool(parameters);
  756. }
  757. #endif // PTDRV_VERBOSE