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.

258 lines
6.4 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: ins.cpp
  4. //
  5. // Description:
  6. //
  7. // KS Instance base class definitions
  8. //
  9. //@@BEGIN_MSINTERNAL
  10. // Development Team:
  11. // Mike McLaughlin
  12. //
  13. // History: Date Author Comment
  14. //
  15. // To Do: Date Author Comment
  16. //
  17. //@@END_MSINTERNAL
  18. //
  19. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  20. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  22. // PURPOSE.
  23. //
  24. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  25. //
  26. //---------------------------------------------------------------------------
  27. #include "common.h"
  28. //---------------------------------------------------------------------------
  29. //---------------------------------------------------------------------------
  30. DEFINE_KSDISPATCH_TABLE(
  31. DispatchTable,
  32. CInstance::DispatchForwardIrp, // Ioctl
  33. DispatchInvalidDeviceRequest, // Read
  34. DispatchInvalidDeviceRequest, // Write
  35. DispatchInvalidDeviceRequest, // Flush
  36. CInstance::DispatchClose, // Close
  37. DispatchInvalidDeviceRequest, // QuerySecurity
  38. DispatchInvalidDeviceRequest, // SetSeturity
  39. DispatchFastIoDeviceControlFailure, // FastDeviceIoControl
  40. DispatchFastReadFailure, // FastRead
  41. DispatchFastWriteFailure // FastWrite
  42. );
  43. //---------------------------------------------------------------------------
  44. //---------------------------------------------------------------------------
  45. CInstance::CInstance(
  46. IN PPARENT_INSTANCE pParentInstance
  47. )
  48. {
  49. Assert(pParentInstance);
  50. this->pParentInstance = pParentInstance;
  51. AddList(&pParentInstance->lstChildInstance);
  52. }
  53. CInstance::~CInstance(
  54. )
  55. {
  56. Assert(this);
  57. RemoveList();
  58. // IMPORTANT : Caller must acquire gmutex.
  59. //
  60. // "RemoveRef" from file object
  61. if(pNextFileObject != NULL) {
  62. ObDereferenceObject(pNextFileObject);
  63. pNextFileObject = NULL;
  64. }
  65. if(pObjectHeader != NULL) {
  66. KsFreeObjectHeader(pObjectHeader);
  67. }
  68. // "RemoveRef" from parent file object
  69. if(pParentFileObject != NULL) {
  70. ObDereferenceObject(pParentFileObject);
  71. }
  72. // Clean up pin mutex
  73. if(pMutex != NULL) {
  74. ExFreePool(pMutex);
  75. }
  76. }
  77. NTSTATUS
  78. CInstance::DispatchCreate(
  79. IN PIRP pIrp,
  80. IN UTIL_PFN pfnDispatchCreate,
  81. IN OUT PVOID pReference,
  82. IN ULONG cCreateItems,
  83. IN PKSOBJECT_CREATE_ITEM pCreateItems OPTIONAL,
  84. IN const KSDISPATCH_TABLE *pDispatchTable OPTIONAL
  85. )
  86. {
  87. PIO_STACK_LOCATION pIrpStack;
  88. NTSTATUS Status;
  89. Assert(this);
  90. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  91. pParentFileObject = pIrpStack->FileObject->RelatedFileObject;
  92. ObReferenceObject(pParentFileObject);
  93. pMutex = (KMUTEX *)ExAllocatePoolWithTag(
  94. NonPagedPool,
  95. sizeof(KMUTEX),
  96. 0x41535953);
  97. if(pMutex == NULL) {
  98. Status = STATUS_INSUFFICIENT_RESOURCES;
  99. goto exit;
  100. }
  101. KeInitializeMutex(pMutex, 0);
  102. Status = KsAllocateObjectHeader(
  103. &pObjectHeader,
  104. cCreateItems,
  105. pCreateItems,
  106. pIrp,
  107. pDispatchTable);
  108. if(!NT_SUCCESS(Status)) {
  109. Trap();
  110. goto exit;
  111. }
  112. Status = pfnDispatchCreate(this, pReference);
  113. if(!NT_SUCCESS(Status)) {
  114. goto exit;
  115. }
  116. pNextDeviceObject = IoGetRelatedDeviceObject(pNextFileObject);
  117. //
  118. // ISSUE: 05/10/02 ALPERS
  119. // Windows does not support dynamically adjusting StackSizes on the fly.
  120. // The only place we are supposed to change this is in AddDevice.
  121. // This must be fixed later.
  122. //
  123. //
  124. // Never make the StackSize smaller. It can cause unexpected problems
  125. // if there are devices with deeper stacks.
  126. //
  127. if (pIrpStack->DeviceObject->StackSize < pNextDeviceObject->StackSize) {
  128. pIrpStack->DeviceObject->StackSize = pNextDeviceObject->StackSize;
  129. }
  130. pIrpStack->FileObject->FsContext = this;
  131. exit:
  132. return(Status);
  133. }
  134. VOID
  135. CInstance::Invalidate(
  136. )
  137. {
  138. Assert(this);
  139. GrabMutex();
  140. DPF1(50, "CInstance::Invalidate %08x", this);
  141. // "RemoveRef" from file object
  142. if(pNextFileObject != NULL) {
  143. ObDereferenceObject(pNextFileObject);
  144. }
  145. pNextFileObject = NULL;
  146. ReleaseMutex();
  147. }
  148. VOID
  149. CParentInstance::Invalidate(
  150. )
  151. {
  152. PINSTANCE pInstance;
  153. Assert(this);
  154. FOR_EACH_LIST_ITEM_DELETE(&lstChildInstance, pInstance) {
  155. pInstance->Invalidate();
  156. } END_EACH_LIST_ITEM
  157. }
  158. NTSTATUS
  159. CInstance::DispatchClose(
  160. IN PDEVICE_OBJECT pDeviceObject,
  161. IN PIRP pIrp
  162. )
  163. {
  164. PIO_STACK_LOCATION pIrpStack;
  165. PINSTANCE pInstance;
  166. ::GrabMutex();
  167. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  168. pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
  169. Assert(pInstance);
  170. pIrpStack->FileObject->FsContext = NULL;
  171. delete pInstance;
  172. ::ReleaseMutex();
  173. pIrp->IoStatus.Information = 0;
  174. pIrp->IoStatus.Status = STATUS_SUCCESS;
  175. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  176. return(STATUS_SUCCESS);
  177. }
  178. #pragma LOCKED_CODE
  179. #pragma LOCKED_DATA
  180. NTSTATUS
  181. CInstance::DispatchForwardIrp(
  182. IN PDEVICE_OBJECT pDeviceObject,
  183. IN PIRP pIrp
  184. )
  185. {
  186. PIO_STACK_LOCATION pIrpStack;
  187. PFILE_OBJECT pNextFileObject;
  188. PINSTANCE pInstance;
  189. NTSTATUS Status = STATUS_SUCCESS;
  190. #ifdef DEBUG
  191. DumpIoctl(pIrp, "ForwardIrp");
  192. #endif
  193. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  194. pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
  195. // Use gMutex instead of instance mutex. The instance mutex
  196. // is not used in any of the dispatch handlers, therefore will
  197. // not synchronize DispatchForwardIrp with other DispatchHandlers in
  198. // CPinInstance.
  199. // Grab mutex for a very short time to check the validity of CInstance.
  200. // If it is valid, IoCallDriver is called. This does not need
  201. // synchronization
  202. //
  203. ::GrabMutex();
  204. Assert(pInstance);
  205. pNextFileObject = pInstance->pNextFileObject;
  206. if(pNextFileObject == NULL) {
  207. DPF(60, "DispatchIoControl: pNextFileObject == NULL");
  208. Status = pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  209. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  210. }
  211. ::ReleaseMutex();
  212. if (NT_SUCCESS(Status)) {
  213. pIrpStack->FileObject = pNextFileObject;
  214. IoSkipCurrentIrpStackLocation(pIrp);
  215. AssertFileObject(pIrpStack->FileObject);
  216. Status = IoCallDriver(pInstance->pNextDeviceObject, pIrp);
  217. }
  218. return(Status);
  219. }