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.

338 lines
8.8 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: openclos.c
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // This file contains functions associated with Create/Open, Cleanup, and Close
  12. //
  13. #include "pch.h"
  14. #include "ecp.h"
  15. NTSTATUS
  16. ParCreateOpen(
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PIRP Irp
  19. )
  20. /*++
  21. Routine Description:
  22. This routine is the dispatch for a create requests.
  23. Arguments:
  24. DeviceObject - Supplies the device object.
  25. Irp - Supplies the I/O request packet.
  26. Return Value:
  27. STATUS_SUCCESS - Success.
  28. !STATUS_SUCCESS - Failure.
  29. --*/
  30. {
  31. NTSTATUS Status;
  32. PDEVICE_EXTENSION Extension;
  33. USHORT i;
  34. ParDump2(PAROPENCLOSE, ("openclose::ParCreateOpen - IRP_MJ_CREATE - Enter\n") );
  35. Extension = DeviceObject->DeviceExtension;
  36. Irp->IoStatus.Information = 0;
  37. ExAcquireFastMutex(&Extension->OpenCloseMutex);
  38. //
  39. // bail out if a delete is pending for this device object
  40. //
  41. if(Extension->DeviceStateFlags & PAR_DEVICE_DELETE_PENDING) {
  42. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  43. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  44. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  45. return STATUS_DELETE_PENDING;
  46. }
  47. //
  48. // bail out if a remove is pending for our ParPort device object
  49. //
  50. if(Extension->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
  51. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  52. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  53. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  54. return STATUS_DELETE_PENDING;
  55. }
  56. //
  57. // bail out if device has been removed
  58. //
  59. if(Extension->DeviceStateFlags & (PAR_DEVICE_REMOVED|PAR_DEVICE_SURPRISE_REMOVAL) ) {
  60. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  61. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  62. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  63. return STATUS_DEVICE_REMOVED;
  64. }
  65. //
  66. // fail IRP if no hardware under this device
  67. //
  68. if (!Extension->PortDeviceObject) {
  69. ParDump2(PAROPENCLOSE, ("NULL PortDeviceObject pointer - FAIL IRP - This is the FDO!!!\n") );
  70. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  71. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  72. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  73. return STATUS_INVALID_DEVICE_REQUEST;
  74. }
  75. // this is an exclusive access device - fail IRP if we are already open
  76. if (InterlockedIncrement(&Extension->OpenCloseRefCount) != 1) {
  77. ParDump2(PAROPENCLOSE, ("ParCreateOpen - Device Already Open - Fail request\n") );
  78. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  79. InterlockedDecrement(&Extension->OpenCloseRefCount);
  80. Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  81. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  82. return STATUS_ACCESS_DENIED;
  83. }
  84. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  85. //
  86. // Lock in code.
  87. //
  88. ParClaimDriver();
  89. //
  90. // Lock in the port driver.
  91. //
  92. // RMT - what if this fails?
  93. ParGetPortInfoFromPortDevice(Extension);
  94. //
  95. // Set the default ieee1284 modes
  96. //
  97. ParInitializeExtension1284Info( Extension );
  98. ExInitializeFastMutex (&Extension->LockPortMutex);
  99. KeInitializeEvent(&Extension->PauseEvent, NotificationEvent, TRUE);
  100. Extension->TimeToTerminateThread = FALSE;
  101. // assert that we do not already have a thread
  102. ASSERT(!Extension->ThreadObjectPointer);
  103. // - replaced following by above assertion: Extension->ThreadObjectPointer = NULL;
  104. KeInitializeSemaphore(&Extension->RequestSemaphore, 0, MAXLONG);
  105. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
  106. Status = Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
  107. } else {
  108. Status = Irp->IoStatus.Status = ParCreateSystemThread(Extension);
  109. }
  110. ParDump2(PAROPENCLOSE, ("About to complete IRP in create/open - Irp: %x status: %x Information: %x\n",
  111. Irp, Irp->IoStatus.Status, Irp->IoStatus.Information) );
  112. if (!NT_SUCCESS(Status)) {
  113. // open failed
  114. ULONG openCloseCount = InterlockedDecrement(&Extension->OpenCloseRefCount);
  115. ASSERT(0 == openCloseCount);
  116. }
  117. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  118. return Status;
  119. }
  120. NTSTATUS
  121. ParCleanup(
  122. IN PDEVICE_OBJECT DeviceObject,
  123. IN PIRP Irp
  124. )
  125. /*++
  126. Routine Description:
  127. This routine is the dispatch for a cleanup requests.
  128. Arguments:
  129. DeviceObject - Supplies the device object.
  130. Irp - Supplies the I/O request packet.
  131. Return Value:
  132. STATUS_SUCCESS - Success.
  133. --*/
  134. {
  135. PDEVICE_EXTENSION Extension;
  136. KIRQL CancelIrql;
  137. PDRIVER_CANCEL CancelRoutine;
  138. PIRP CurrentLastIrp;
  139. ParDump2(PAROPENCLOSE, ("In ParCleanup\n") );
  140. Extension = DeviceObject->DeviceExtension;
  141. //
  142. // While the list is not empty, go through and cancel each irp.
  143. //
  144. IoAcquireCancelSpinLock(&CancelIrql);
  145. //
  146. // Clean the list from back to front.
  147. //
  148. while (!IsListEmpty(&Extension->WorkQueue)) {
  149. CurrentLastIrp = CONTAINING_RECORD(Extension->WorkQueue.Blink,
  150. IRP, Tail.Overlay.ListEntry);
  151. RemoveEntryList(Extension->WorkQueue.Blink);
  152. CancelRoutine = CurrentLastIrp->CancelRoutine;
  153. CurrentLastIrp->CancelIrql = CancelIrql;
  154. CurrentLastIrp->CancelRoutine = NULL;
  155. CurrentLastIrp->Cancel = TRUE;
  156. CancelRoutine(DeviceObject, CurrentLastIrp);
  157. IoAcquireCancelSpinLock(&CancelIrql);
  158. }
  159. //
  160. // If there is a current irp then mark it as cancelled.
  161. //
  162. if (Extension->CurrentOpIrp) {
  163. Extension->CurrentOpIrp->Cancel = TRUE;
  164. }
  165. IoReleaseCancelSpinLock(CancelIrql);
  166. Irp->IoStatus.Information = 0;
  167. Irp->IoStatus.Status = STATUS_SUCCESS;
  168. // ParDump(PARIRPPATH | PARDUMP_VERBOSE_MAX,
  169. // ("PARALLEL: "
  170. // "About to complete IRP in cleanup - "
  171. // "Irp: %x status: %x Information: %x\n",
  172. // Irp, Irp->IoStatus.Status, Irp->IoStatus.Information) );
  173. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  174. return STATUS_SUCCESS;
  175. }
  176. NTSTATUS
  177. ParClose(
  178. IN PDEVICE_OBJECT DeviceObject,
  179. IN PIRP Irp
  180. )
  181. /*++
  182. Routine Description:
  183. This routine is the dispatch for a close requests.
  184. Arguments:
  185. DeviceObject - Supplies the device object.
  186. Irp - Supplies the I/O request packet.
  187. Return Value:
  188. STATUS_SUCCESS - Success.
  189. --*/
  190. {
  191. PDEVICE_EXTENSION Extension;
  192. // NTSTATUS StatusOfWait;
  193. ParDump2(PAROPENCLOSE, ( "ParClose(...)\n") );
  194. Extension = DeviceObject->DeviceExtension;
  195. // immediately stop signalling event
  196. Extension->P12843DL.bEventActive = FALSE;
  197. Irp->IoStatus.Status = STATUS_SUCCESS;
  198. Irp->IoStatus.Information = 0;
  199. if (Extension->bShadowBuffer)
  200. {
  201. Queue_Delete(&(Extension->ShadowBuffer));
  202. Extension->bShadowBuffer = FALSE;
  203. }
  204. // if we still have a worker thread, kill it
  205. if(Extension->ThreadObjectPointer) {
  206. // set the flag for the worker thread to kill itself
  207. Extension->TimeToTerminateThread = TRUE;
  208. // wake up the thread so it can kill itself
  209. KeReleaseSemaphore(&Extension->RequestSemaphore, 0, 1, FALSE);
  210. // allow thread to get past PauseEvent so it can kill self
  211. KeSetEvent(&Extension->PauseEvent, 0, TRUE);
  212. // wait for the thread to die
  213. KeWaitForSingleObject(Extension->ThreadObjectPointer, UserRequest, KernelMode, FALSE, NULL);
  214. // allow the system to release the thread object
  215. ObDereferenceObject(Extension->ThreadObjectPointer);
  216. // note that we no longer have a worker thread
  217. Extension->ThreadObjectPointer = NULL;
  218. }
  219. // release our hold on ParPort, possibly allowing ParPort to be paged
  220. ParReleasePortInfoToPortDevice(Extension);
  221. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  222. // RMT - is underflow possible?
  223. {
  224. ULONG openCloseRefCount;
  225. ExAcquireFastMutex(&Extension->OpenCloseMutex);
  226. openCloseRefCount = InterlockedDecrement(&Extension->OpenCloseRefCount);
  227. ASSERT(0 == openCloseRefCount);
  228. if(openCloseRefCount != 0) {
  229. // if we underflowed, increment and check again
  230. openCloseRefCount = InterlockedIncrement(&Extension->OpenCloseRefCount);
  231. ASSERT(0 == openCloseRefCount);
  232. }
  233. ExReleaseFastMutex(&Extension->OpenCloseMutex);
  234. }
  235. // Unlock the code that was locked during the open.
  236. ParReleaseDriver();
  237. return STATUS_SUCCESS;
  238. }