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.

456 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. battmisc.c
  5. Abstract:
  6. Miscellaneous functions needed by the composite battery to talk to
  7. the batteries in the system.
  8. Author:
  9. Scott Brenden
  10. Environment:
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "compbatt.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, BatteryIoctl)
  17. #pragma alloc_text(PAGE, CompBattGetDeviceObjectPointer)
  18. #endif
  19. NTSTATUS
  20. BattIoctlComplete (
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN PIRP Irp,
  23. IN PVOID Context
  24. )
  25. {
  26. PKEVENT Event;
  27. Event = (PKEVENT) Context;
  28. KeSetEvent (Event, 0, FALSE);
  29. return STATUS_MORE_PROCESSING_REQUIRED;
  30. }
  31. NTSTATUS
  32. BatteryIoctl(
  33. IN ULONG Ioctl,
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN PVOID InputBuffer,
  36. IN ULONG InputBufferLength,
  37. IN PVOID OutputBuffer,
  38. IN ULONG OutputBufferLength,
  39. IN BOOLEAN PrivateIoctl
  40. )
  41. /*++
  42. Routine Description:
  43. The routine Creates an IRP and does Ioctl to the device object passed in.
  44. Arguments:
  45. Ioctl - code for the Ioctl
  46. DeviceObject - Device object to send the ioctl to
  47. InputBuffer - Input buffer for the ioctl
  48. InputBufferLength - length of the input buffer
  49. OutputBuffer - Buffer for containing the results of the ioctl
  50. OutputBufferLength - Length of the output buffer
  51. PrivateIoctl - TRUE if this is to be an IRP_MJ_DEVICE_CONTROL, FALSE
  52. if this is to be an IRP_MJ_INTERNAL_DEVICE_CONTROL.
  53. Return Value:
  54. Status returned by the Ioctl
  55. --*/
  56. {
  57. NTSTATUS status;
  58. IO_STATUS_BLOCK IOSB;
  59. PIRP irp;
  60. KEVENT event;
  61. // PUCHAR buffer;
  62. // ULONG bufferSize;
  63. // PIO_STACK_LOCATION irpSp;
  64. PAGED_CODE();
  65. BattPrint (BATT_TRACE, ("CompBatt: ENTERING BatteryIoctl\n"));
  66. //
  67. // Set the event object to the unsignaled state.
  68. // It will be used to signal request completion.
  69. //
  70. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  71. //
  72. // Build synchronous request with no transfer.
  73. //
  74. irp = IoBuildDeviceIoControlRequest(
  75. Ioctl,
  76. DeviceObject,
  77. InputBuffer,
  78. InputBufferLength,
  79. OutputBuffer,
  80. OutputBufferLength,
  81. PrivateIoctl,
  82. &event,
  83. &IOSB
  84. );
  85. if (irp == NULL) {
  86. BattPrint (BATT_ERROR, ("BatteryIoctl: couldn't create Irp\n"));
  87. return STATUS_INSUFFICIENT_RESOURCES;
  88. }
  89. //
  90. // Pass request to port driver and wait for request to complete.
  91. //
  92. status = IoCallDriver(DeviceObject, irp);
  93. if (status == STATUS_PENDING) {
  94. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  95. status = IOSB.Status;
  96. }
  97. if (!NT_SUCCESS(status)) {
  98. BattPrint (BATT_ERROR, ("BatteryIoctl: Irp failed - %x\n", status));
  99. }
  100. BattPrint (BATT_TRACE, ("CompBatt: EXITING BatteryIoctl\n"));
  101. return status;
  102. }
  103. BOOLEAN
  104. IsBatteryAlreadyOnList(
  105. IN PUNICODE_STRING SymbolicLinkName,
  106. IN PCOMPOSITE_BATTERY CompBatt
  107. )
  108. /*++
  109. Routine Description:
  110. The routine runs through the list of batteries the composite keeps and checks
  111. to see if the symbolic link name passed in matches one of them.
  112. Arguments:
  113. SymbolicLinkName - Name for battery to check if already on list
  114. Return Value:
  115. TRUE if the SymbolicLinkName belongs to a battery already on the list, FALSE
  116. otherwise.
  117. --*/
  118. {
  119. PCOMPOSITE_ENTRY batt;
  120. PLIST_ENTRY entry;
  121. BattPrint (BATT_TRACE, ("CompBatt: ENTERING IsBatteryAlreadyOnList\n"));
  122. //
  123. // Run through the list of batteries looking for new batteries
  124. //
  125. ExAcquireFastMutex (&CompBatt->ListMutex);
  126. for (entry = CompBatt->Batteries.Flink; entry != &CompBatt->Batteries; entry = entry->Flink) {
  127. batt = CONTAINING_RECORD (entry, COMPOSITE_ENTRY, Batteries);
  128. if (!RtlCompareUnicodeString(SymbolicLinkName, &batt->BattName, TRUE)) {
  129. //
  130. // The battery is already on the list
  131. //
  132. ExReleaseFastMutex (&CompBatt->ListMutex);
  133. return TRUE;
  134. }
  135. }
  136. BattPrint (BATT_TRACE, ("CompBatt: EXITING IsBatteryAlreadyOnList\n"));
  137. ExReleaseFastMutex (&CompBatt->ListMutex);
  138. return FALSE;
  139. }
  140. PCOMPOSITE_ENTRY
  141. RemoveBatteryFromList(
  142. IN PUNICODE_STRING SymbolicLinkName,
  143. IN PCOMPOSITE_BATTERY CompBatt
  144. )
  145. /*++
  146. Routine Description:
  147. The routine runs through the list of batteries the composite keeps and checks
  148. to see if the symbolic link name passed in matches one of them. If a match is found,
  149. the entry is removed from the list of batteries
  150. Arguments:
  151. SymbolicLinkName - Name for battery to check if already on list
  152. Return Value:
  153. TRUE if the SymbolicLinkName was found and deleted. FALSE otherwise.
  154. --*/
  155. {
  156. PCOMPOSITE_ENTRY batt;
  157. PLIST_ENTRY entry;
  158. BattPrint (BATT_TRACE, ("CompBatt: ENTERING RemoveBatteryFromList\n"));
  159. //
  160. // Run through the list of batteries looking for new batteries
  161. //
  162. ExAcquireFastMutex (&CompBatt->ListMutex);
  163. for (entry = CompBatt->Batteries.Flink; entry != &CompBatt->Batteries; entry = entry->Flink) {
  164. batt = CONTAINING_RECORD (entry, COMPOSITE_ENTRY, Batteries);
  165. if (!RtlCompareUnicodeString(SymbolicLinkName, &batt->BattName, TRUE)) {
  166. //
  167. // The battery is on the list, remove
  168. //
  169. //
  170. // Wait until no one else is looking at this battery before removing it.
  171. //
  172. CompbattAcquireDeleteLock (&batt->DeleteLock);
  173. ExReleaseFastMutex (&CompBatt->ListMutex);
  174. CompbattReleaseDeleteLockAndWait (&batt->DeleteLock);
  175. ExAcquireFastMutex (&CompBatt->ListMutex);
  176. RemoveEntryList(entry);
  177. ExReleaseFastMutex (&CompBatt->ListMutex);
  178. return batt;
  179. }
  180. }
  181. ExReleaseFastMutex (&CompBatt->ListMutex);
  182. BattPrint (BATT_TRACE, ("CompBatt: EXITING RemoveBatteryFromList\n"));
  183. return NULL;
  184. }
  185. NTSTATUS
  186. CompBattGetDeviceObjectPointer(
  187. IN PUNICODE_STRING ObjectName,
  188. IN ACCESS_MASK DesiredAccess,
  189. OUT PFILE_OBJECT *FileObject,
  190. OUT PDEVICE_OBJECT *DeviceObject
  191. )
  192. /*++
  193. Routine Description:
  194. This routine is essentially a copy from ntos\io\iosubs.c
  195. The reason for this is that we need to open the device with shared access
  196. rather than exclusive access. In addition ZwCreateFile was used instead of
  197. ZwOpenFile becuase that didn't seem to complie right when only wdm.h instead
  198. of ntddk.h was included.
  199. This routine returns a pointer to the device object specified by the
  200. object name. It also returns a pointer to the referenced file object
  201. that has been opened to the device that ensures that the device cannot
  202. go away.
  203. To close access to the device, the caller should dereference the file
  204. object pointer.
  205. Arguments:
  206. ObjectName - Name of the device object for which a pointer is to be
  207. returned.
  208. DesiredAccess - Access desired to the target device object.
  209. FileObject - Supplies the address of a variable to receive a pointer
  210. to the file object for the device.
  211. DeviceObject - Supplies the address of a variable to receive a pointer
  212. to the device object for the specified device.
  213. Return Value:
  214. The function value is a referenced pointer to the specified device
  215. object, if the device exists. Otherwise, NULL is returned.
  216. --*/
  217. {
  218. PFILE_OBJECT fileObject;
  219. OBJECT_ATTRIBUTES objectAttributes;
  220. HANDLE fileHandle;
  221. IO_STATUS_BLOCK ioStatus;
  222. NTSTATUS status;
  223. PAGED_CODE();
  224. //
  225. // Initialize the object attributes to open the device.
  226. //
  227. InitializeObjectAttributes( &objectAttributes,
  228. ObjectName,
  229. 0,
  230. (HANDLE) NULL,
  231. (PSECURITY_DESCRIPTOR) NULL );
  232. status = ZwCreateFile (
  233. &fileHandle,
  234. DesiredAccess, // desired access
  235. &objectAttributes,
  236. &ioStatus,
  237. (PLARGE_INTEGER) NULL,
  238. 0L,
  239. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  240. FILE_OPEN,
  241. 0,
  242. NULL,
  243. 0);
  244. if (NT_SUCCESS( status )) {
  245. //
  246. // The open operation was successful. Dereference the file handle
  247. // and obtain a pointer to the device object for the handle.
  248. //
  249. status = ObReferenceObjectByHandle( fileHandle,
  250. 0,
  251. *IoFileObjectType,
  252. KernelMode,
  253. (PVOID *) &fileObject,
  254. NULL );
  255. if (NT_SUCCESS( status )) {
  256. *FileObject = fileObject;
  257. //
  258. // Get a pointer to the device object for this file.
  259. //
  260. *DeviceObject = IoGetRelatedDeviceObject( fileObject );
  261. }
  262. (VOID) ZwClose( fileHandle );
  263. }
  264. return status;
  265. }
  266. //
  267. // Delete Lock routines from io\remlock.c
  268. //
  269. VOID
  270. CompbattInitializeDeleteLock (
  271. IN PCOMPBATT_DELETE_LOCK Lock
  272. )
  273. {
  274. Lock->Deleted = FALSE;
  275. Lock->RefCount = 1;
  276. KeInitializeEvent(&Lock->DeleteEvent,
  277. SynchronizationEvent,
  278. FALSE);
  279. }
  280. NTSTATUS
  281. CompbattAcquireDeleteLock (
  282. IN PCOMPBATT_DELETE_LOCK Lock
  283. )
  284. {
  285. LONG lockValue;
  286. lockValue = InterlockedIncrement(&Lock->RefCount);
  287. if (Lock->Deleted) {
  288. if (0 == InterlockedDecrement (&Lock->RefCount)) {
  289. KeSetEvent (&Lock->DeleteEvent, 0, FALSE);
  290. }
  291. return STATUS_DELETE_PENDING;
  292. }
  293. return STATUS_SUCCESS;
  294. }
  295. VOID
  296. CompbattReleaseDeleteLock (
  297. IN PCOMPBATT_DELETE_LOCK Lock
  298. )
  299. {
  300. if (0 == InterlockedDecrement(&Lock->RefCount)) {
  301. KeSetEvent(&Lock->DeleteEvent,
  302. IO_NO_INCREMENT,
  303. FALSE);
  304. }
  305. }
  306. VOID
  307. CompbattReleaseDeleteLockAndWait (
  308. IN PCOMPBATT_DELETE_LOCK Lock
  309. )
  310. {
  311. Lock->Deleted = TRUE;
  312. InterlockedDecrement (&Lock->RefCount);
  313. if (0 < InterlockedDecrement (&Lock->RefCount)) {
  314. KeWaitForSingleObject (&Lock->DeleteEvent,
  315. Executive,
  316. KernelMode,
  317. FALSE,
  318. NULL);
  319. }
  320. }