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.

333 lines
10 KiB

  1. /*
  2. * title: hidbattpnp.cpp
  3. *
  4. * purpose: support for plug and play routines
  5. *
  6. * Initial checkin for the hid to battery class driver. This should be
  7. * the same for both Win 98 and NT 5. Alpha level source. Requires
  8. * modified composite battery driver and modified battery class driver for
  9. * Windows 98 support
  10. *
  11. */
  12. #include "hidbatt.h"
  13. NTSTATUS HidBattInitializeDevice (PDEVICE_OBJECT pBatteryFdo, PIRP pIrp)
  14. {
  15. NTSTATUS ntStatus;
  16. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pBatteryFdo->DeviceExtension;
  17. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  18. ULONG ulBatteryStatus;
  19. bool bResult;
  20. BATTERY_MINIPORT_INFO BattInit;
  21. UNICODE_STRING Name;
  22. ULONG ulBufferLength = 0;
  23. PWCHAR pBuffer = NULL;
  24. CBattery * pBattery;
  25. PFILE_OBJECT fileObject;
  26. OBJECT_ATTRIBUTES objectAttributes;
  27. HANDLE fileHandle;
  28. IO_STATUS_BLOCK ioStatus;
  29. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  30. HidBattPrint (HIDBATT_PNP, ("HidBattInitializeDevice: Sending Irp (0x%x) to Pdo\n", pIrp));
  31. // now get file object using KenRay's method from mouclass
  32. ntStatus = IoGetDeviceProperty (
  33. pDevExt->m_pHidPdo,
  34. DevicePropertyPhysicalDeviceObjectName,
  35. ulBufferLength,
  36. pBuffer,
  37. &ulBufferLength);
  38. if(ntStatus != STATUS_BUFFER_TOO_SMALL)
  39. {
  40. // only thing we expect with a zero buffer is this error,
  41. // any other error must be fatal
  42. return STATUS_UNSUCCESSFUL;
  43. }
  44. pBuffer = (PWCHAR) ExAllocatePoolWithTag (NonPagedPool, ulBufferLength, HidBattTag);
  45. if (NULL == pBuffer) {
  46. return STATUS_INSUFFICIENT_RESOURCES;
  47. }
  48. ntStatus = IoGetDeviceProperty (
  49. pDevExt->m_pHidPdo,
  50. DevicePropertyPhysicalDeviceObjectName,
  51. ulBufferLength,
  52. pBuffer,
  53. &ulBufferLength);
  54. if(NT_ERROR(ntStatus))
  55. {
  56. ExFreePool(pBuffer);
  57. return ntStatus;
  58. }
  59. Name.MaximumLength = (USHORT) ulBufferLength;
  60. Name.Length = (USHORT) ulBufferLength - sizeof (UNICODE_NULL);
  61. Name.Buffer = pBuffer;
  62. pDevExt->m_OpeningThread = KeGetCurrentThread();
  63. //
  64. // Initialize the object attributes to open the device.
  65. //
  66. InitializeObjectAttributes( &objectAttributes,
  67. &Name,
  68. 0,
  69. (HANDLE) NULL,
  70. (PSECURITY_DESCRIPTOR) NULL );
  71. ntStatus = ZwOpenFile( &fileHandle,
  72. FILE_ALL_ACCESS,
  73. &objectAttributes,
  74. &ioStatus,
  75. FILE_SHARE_WRITE | FILE_SHARE_READ,
  76. FILE_NON_DIRECTORY_FILE );
  77. ExFreePool (pBuffer);
  78. if (NT_SUCCESS( ntStatus )) {
  79. //
  80. // The open operation was successful. Dereference the file handle
  81. // and obtain a pointer to the device object for the handle.
  82. //
  83. ntStatus = ObReferenceObjectByHandle( fileHandle,
  84. 0,
  85. *IoFileObjectType,
  86. KernelMode,
  87. (PVOID *) &pDevExt->m_pHidFileObject,
  88. NULL );
  89. ZwClose( fileHandle );
  90. }
  91. pDevExt->m_OpeningThread = NULL;
  92. if(NT_ERROR(ntStatus))
  93. {
  94. return ntStatus;
  95. }
  96. // now init new hid deviceclass object for this device
  97. CHidDevice * pHidDevice = new (NonPagedPool, HidBattTag) CHidDevice; // setup a new hid device
  98. if (!pHidDevice) {
  99. HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error allocating CHidDevice"));
  100. return STATUS_UNSUCCESSFUL;
  101. }
  102. pHidDevice->m_pFCB = pDevExt->m_pHidFileObject; // put usable file object into hid device
  103. pHidDevice->m_pLowerDeviceObject = pDevExt->m_pLowerDeviceObject;
  104. pHidDevice->m_pDeviceObject = pDevExt->m_pBatteryFdo;
  105. pHidDevice->m_pReadIrp = NULL;
  106. bResult = pHidDevice->OpenHidDevice(pDevExt->m_pHidPdo); // initialize the members of this device
  107. if(!bResult)
  108. {
  109. delete pHidDevice;
  110. return STATUS_UNSUCCESSFUL;
  111. }
  112. // check if this has a power page, ups application collection
  113. if(pHidDevice->m_UsagePage != UsagePowerPage || pHidDevice->m_UsageID != UsageUPS)
  114. {
  115. delete pHidDevice;
  116. return STATUS_UNSUCCESSFUL;
  117. }
  118. //
  119. // Initialize Fdo device extension data
  120. //
  121. // create the battery object
  122. pBattery = new (NonPagedPool, HidBattTag) CBattery(pHidDevice);
  123. if (!pBattery){
  124. HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error allocating CBattery"));
  125. return STATUS_UNSUCCESSFUL;
  126. }
  127. // and initialize battery values
  128. // now init in both new and replug states
  129. pBattery->m_pCHidDevice = pHidDevice; // save init'ed hid device object
  130. bResult = pBattery->InitValues();
  131. if(!bResult)
  132. {
  133. return STATUS_UNSUCCESSFUL;
  134. }
  135. // Attach to the Class Driver
  136. RtlZeroMemory (&BattInit, sizeof(BattInit));
  137. BattInit.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
  138. BattInit.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
  139. BattInit.Context = pDevExt;
  140. BattInit.QueryTag = HidBattQueryTag;
  141. BattInit.QueryInformation = HidBattQueryInformation;
  142. BattInit.SetInformation = HidBattSetInformation;
  143. BattInit.QueryStatus = HidBattQueryStatus;
  144. BattInit.SetStatusNotify = HidBattSetStatusNotify;
  145. BattInit.DisableStatusNotify = HidBattDisableStatusNotify;
  146. BattInit.Pdo = pDevExt->m_pHidPdo;
  147. BattInit.DeviceName = NULL;
  148. pHidDevice->m_pEventHandler = HidBattNotifyHandler;
  149. pHidDevice->m_pEventContext = (PVOID) pDevExt;
  150. //
  151. // save battery in device extension
  152. // This indicates that we are ready for IO.
  153. //
  154. pDevExt->m_pBattery = pBattery;
  155. //
  156. // Initialize stop lock
  157. //
  158. IoInitializeRemoveLock (&pDevExt->m_StopLock, HidBattTag, 10, 20);
  159. // and finally we can now start actively polling the device
  160. // start the read/notification process
  161. ntStatus = pBattery->m_pCHidDevice->ActivateInput();
  162. if(!NT_SUCCESS(ntStatus))
  163. {
  164. delete pHidDevice;
  165. HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error (0x%x) in ActivateInput.\n", ntStatus));
  166. return ntStatus;
  167. }
  168. ntStatus = BatteryClassInitializeDevice (&BattInit, &pBattery->m_pBatteryClass);
  169. if (!NT_SUCCESS(ntStatus))
  170. {
  171. //
  172. // if we can't attach to class driver we're toast
  173. //
  174. delete pHidDevice;
  175. HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error (0x%x) registering with class\n", ntStatus));
  176. return ntStatus;
  177. }
  178. HidBattPrint(HIDBATT_TRACE, ("HidBattInitializeDevice: returned ok\n"));
  179. return ntStatus;
  180. }
  181. NTSTATUS
  182. HidBattStopDevice(
  183. IN PDEVICE_OBJECT pBatteryFdo,
  184. IN PIRP pIrp
  185. )
  186. /*++
  187. Routine Description:
  188. This routine is called when we receive a IRP_MN_STOP_DEVICE. It just sends the
  189. request down the chain of drivers to the Pdo and waits for a response.
  190. Arguments:
  191. Fdo - a pointer to the fdo for this driver
  192. Irp - Pointer to the request packet.
  193. Return Value:
  194. Status is returned.
  195. --*/
  196. {
  197. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pBatteryFdo->DeviceExtension;
  198. KEVENT pdoStoppedEvent;
  199. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  200. NTSTATUS ntStatus;
  201. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  202. HidBattPrint ((HIDBATT_TRACE | HIDBATT_PNP), ("HidBattStopDevice\n"));
  203. if (!NT_SUCCESS (IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) {
  204. //
  205. // Don't release twice.
  206. //
  207. return STATUS_SUCCESS;
  208. }
  209. pDevExt->m_bJustStarted = FALSE;
  210. HidBattPrint (HIDBATT_PNP, ("HidBattStopDevice: Waiting to remove\n"));
  211. IoReleaseRemoveLockAndWait (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  212. if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pBatteryClass) {
  213. BatteryClassUnload(pDevExt->m_pBattery->m_pBatteryClass);
  214. }
  215. if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice &&
  216. pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp) {
  217. IoCancelIrp (pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp);
  218. }
  219. if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice &&
  220. pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject) {
  221. //
  222. // Clean up worker thread.
  223. //
  224. KeWaitForSingleObject (
  225. pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject,
  226. Executive,
  227. KernelMode,
  228. FALSE,
  229. NULL
  230. );
  231. HidBattPrint (HIDBATT_PNP, ("HidBattStopDevice: Done Waiting to remove\n"));
  232. ObDereferenceObject (pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject);
  233. } else {
  234. return STATUS_UNSUCCESSFUL;
  235. // If we can't be sure the Read Thread has terminated, it is unsafe to
  236. // stop or remove the device. This may cause a reboot to be needed.
  237. }
  238. if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice &&
  239. pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp) {
  240. IoFreeIrp(pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp); // clean up irp
  241. pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp = NULL;
  242. }
  243. //
  244. // Write default RemainingCapcitylimit back to UPS so the next time we enumerate
  245. // the device, we'll read back the right data.
  246. //
  247. pDevExt->m_pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,
  248. &pDevExt->m_ulDefaultAlert1,TRUE);
  249. // dereference our file object, if present
  250. if(pDevExt->m_pHidFileObject) {
  251. ObDereferenceObject(pDevExt->m_pHidFileObject);
  252. pDevExt->m_pBattery->m_pCHidDevice->m_pFCB = NULL;
  253. }
  254. if (pDevExt->m_pBattery) {
  255. delete pDevExt->m_pBattery;
  256. pDevExt->m_pBattery = NULL;
  257. }
  258. ntStatus = STATUS_SUCCESS;
  259. pDevExt->m_bIsStarted = FALSE;
  260. return STATUS_SUCCESS;
  261. }