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.

304 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. volume.c
  5. Abstract:
  6. This module implements power management function releated to volume devices
  7. Author:
  8. Ken Reneris (kenr) 04-April-1997
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. typedef struct {
  13. LIST_ENTRY List;
  14. LONG Count;
  15. KEVENT Wait;
  16. } POP_FLUSH_VOLUME, *PPOP_FLUSH_VOLUME;
  17. VOID
  18. PoVolumeDevice (
  19. IN PDEVICE_OBJECT DeviceObject
  20. );
  21. VOID
  22. PopFlushVolumeWorker (
  23. IN PPOP_FLUSH_VOLUME Flush
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text(PAGE,PoVolumeDevice)
  27. #pragma alloc_text(PAGE,PopFlushVolumes)
  28. #pragma alloc_text(PAGE,PopFlushVolumeWorker)
  29. #endif
  30. VOID
  31. PoVolumeDevice (
  32. IN PDEVICE_OBJECT DeviceObject
  33. )
  34. /*++
  35. Routine Description:
  36. Called for any device object which gets allocated a VPB.
  37. The power policy manager keeps a list of all such device objects
  38. in order to flush all volumes before putting the system to sleep
  39. Arguments:
  40. DeviceObject - The volume device object
  41. Return Value:
  42. None
  43. --*/
  44. {
  45. PDEVICE_OBJECT_POWER_EXTENSION Dope;
  46. Dope = PopGetDope(DeviceObject);
  47. if (Dope) {
  48. PopAcquireVolumeLock ();
  49. if (!Dope->Volume.Flink) {
  50. InsertTailList (&PopVolumeDevices, &Dope->Volume);
  51. }
  52. PopReleaseVolumeLock ();
  53. }
  54. }
  55. VOID
  56. PopFlushVolumes (
  57. VOID
  58. )
  59. /*++
  60. Routine Description:
  61. Called to flush all volumes.
  62. Arguments:
  63. None
  64. Return Value:
  65. None
  66. --*/
  67. {
  68. PDEVICE_OBJECT_POWER_EXTENSION Dope;
  69. PLIST_ENTRY Link;
  70. POP_FLUSH_VOLUME Flush;
  71. OBJECT_ATTRIBUTES ObjectAttributes;
  72. NTSTATUS Status;
  73. HANDLE Thread;
  74. ULONG i;
  75. UNICODE_STRING RegistryName;
  76. HANDLE Key;
  77. Flush.Count = 1;
  78. InitializeListHead (&Flush.List);
  79. KeInitializeEvent (&Flush.Wait, NotificationEvent, FALSE);
  80. InitializeObjectAttributes(&ObjectAttributes,
  81. NULL,
  82. 0,
  83. NULL,
  84. NULL);
  85. //
  86. // Move volumes onto flush work queue
  87. //
  88. PopAcquireVolumeLock ();
  89. Link = PopVolumeDevices.Flink;
  90. while (Link != &PopVolumeDevices) {
  91. Dope = CONTAINING_RECORD (Link, DEVICE_OBJECT_POWER_EXTENSION, Volume);
  92. Link = Link->Flink;
  93. if (!(Dope->DeviceObject->Vpb->Flags & VPB_MOUNTED) ||
  94. (Dope->DeviceObject->Characteristics & FILE_FLOPPY_DISKETTE) ||
  95. (Dope->DeviceObject->Characteristics & FILE_READ_ONLY_DEVICE) ||
  96. (Dope->DeviceObject->Vpb->RealDevice &&
  97. Dope->DeviceObject->Vpb->RealDevice->Characteristics & FILE_FLOPPY_DISKETTE)) {
  98. //
  99. // Skip this device, there is no point in flushing it.
  100. //
  101. } else {
  102. RemoveEntryList (&Dope->Volume);
  103. InsertTailList (&Flush.List, &Dope->Volume);
  104. }
  105. }
  106. //
  107. // Allocate worker threads to flush volumes
  108. //
  109. i = Flush.Count;
  110. if (i > 8) {
  111. i = 8;
  112. }
  113. while (i) {
  114. i -= 1;
  115. Status = PsCreateSystemThread(&Thread,
  116. THREAD_ALL_ACCESS,
  117. &ObjectAttributes,
  118. 0L,
  119. NULL,
  120. PopFlushVolumeWorker,
  121. &Flush);
  122. if (NT_SUCCESS(Status)) {
  123. Flush.Count += 1;
  124. NtClose (Thread);
  125. }
  126. }
  127. PopReleaseVolumeLock ();
  128. //
  129. // Flush the registry as well.
  130. //
  131. RtlInitUnicodeString(&RegistryName, L"\\Registry");
  132. InitializeObjectAttributes(&ObjectAttributes,
  133. &RegistryName,
  134. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  135. NULL,
  136. NULL);
  137. Status = ZwOpenKey(&Key,
  138. KEY_READ,
  139. &ObjectAttributes);
  140. if (NT_SUCCESS(Status)) {
  141. ZwFlushKey(Key);
  142. ZwClose(Key);
  143. }
  144. //
  145. // Verify work in complete
  146. //
  147. PopFlushVolumeWorker (&Flush);
  148. KeWaitForSingleObject (&Flush.Wait, Suspended, KernelMode, TRUE, NULL);
  149. }
  150. VOID
  151. PopFlushVolumeWorker (
  152. IN PPOP_FLUSH_VOLUME Flush
  153. )
  154. /*++
  155. Routine Description:
  156. Worker routine for PopFlushVolumes to flush a single volume
  157. Arguments:
  158. None
  159. Return Value:
  160. None
  161. --*/
  162. {
  163. PDEVICE_OBJECT_POWER_EXTENSION Dope;
  164. PLIST_ENTRY Link;
  165. NTSTATUS Status;
  166. UCHAR Buffer[512];
  167. POBJECT_NAME_INFORMATION ObName;
  168. ULONG len;
  169. IO_STATUS_BLOCK IoStatus;
  170. OBJECT_ATTRIBUTES objA;
  171. HANDLE handle;
  172. PopAcquireVolumeLock ();
  173. while (!IsListEmpty (&Flush->List)) {
  174. Link = Flush->List.Flink;
  175. RemoveEntryList (Link);
  176. InsertTailList (&PopVolumeDevices, Link);
  177. PopReleaseVolumeLock ();
  178. Dope = CONTAINING_RECORD (Link, DEVICE_OBJECT_POWER_EXTENSION, Volume);
  179. //
  180. // Get the name of this object
  181. //
  182. ObName = (POBJECT_NAME_INFORMATION) Buffer;
  183. Status = ObQueryNameString (
  184. Dope->DeviceObject,
  185. ObName,
  186. sizeof (Buffer),
  187. &len
  188. );
  189. if (NT_SUCCESS(Status) && ObName->Name.Buffer) {
  190. //
  191. // Open the volume
  192. //
  193. InitializeObjectAttributes (
  194. &objA,
  195. &ObName->Name,
  196. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  197. 0,
  198. 0
  199. );
  200. Status = ZwCreateFile (
  201. &handle,
  202. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  203. &objA,
  204. &IoStatus,
  205. NULL,
  206. GENERIC_READ | GENERIC_WRITE,
  207. FILE_SHARE_READ | FILE_SHARE_WRITE,
  208. FILE_OPEN,
  209. 0,
  210. NULL,
  211. 0
  212. );
  213. if (NT_SUCCESS(Status)) {
  214. //
  215. // Flush the volume
  216. //
  217. ZwFlushBuffersFile (handle, &IoStatus);
  218. //
  219. // Close the reference to the volume
  220. //
  221. ZwClose (handle);
  222. }
  223. }
  224. PopAcquireVolumeLock ();
  225. }
  226. Flush->Count -= 1;
  227. if (Flush->Count == 0) {
  228. KeSetEvent (&Flush->Wait, IO_NO_INCREMENT, FALSE);
  229. }
  230. PopReleaseVolumeLock ();
  231. }