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.

281 lines
7.6 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->pObjectHeader = NULL;
  51. this->pParentInstance = pParentInstance;
  52. AddList(&pParentInstance->lstChildInstance);
  53. }
  54. CInstance::~CInstance(
  55. )
  56. {
  57. Assert(this);
  58. RemoveList();
  59. // IMPORTANT : Caller must acquire gmutex.
  60. //
  61. // "RemoveRef" from file object
  62. if(pNextFileObject != NULL) {
  63. ObDereferenceObject(pNextFileObject);
  64. pNextFileObject = NULL;
  65. }
  66. if(pObjectHeader != NULL) {
  67. KsFreeObjectHeader(pObjectHeader);
  68. }
  69. // "RemoveRef" from parent file object
  70. if(pParentFileObject != NULL) {
  71. ObDereferenceObject(pParentFileObject);
  72. }
  73. // Clean up pin mutex
  74. if(pMutex != NULL) {
  75. ExFreePool(pMutex);
  76. }
  77. }
  78. NTSTATUS
  79. CInstance::DispatchCreate(
  80. IN PIRP pIrp,
  81. IN UTIL_PFN pfnDispatchCreate,
  82. IN OUT PVOID pReference,
  83. IN ULONG cCreateItems,
  84. IN PKSOBJECT_CREATE_ITEM pCreateItems OPTIONAL,
  85. IN const KSDISPATCH_TABLE *pDispatchTable OPTIONAL
  86. )
  87. {
  88. PIO_STACK_LOCATION pIrpStack;
  89. NTSTATUS Status;
  90. Assert(this);
  91. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  92. pParentFileObject = pIrpStack->FileObject->RelatedFileObject;
  93. ObReferenceObject(pParentFileObject);
  94. pMutex = (KMUTEX *)ExAllocatePoolWithTag(
  95. NonPagedPool,
  96. sizeof(KMUTEX),
  97. POOLTAG_SYSA);
  98. if(pMutex == NULL) {
  99. Status = STATUS_INSUFFICIENT_RESOURCES;
  100. goto exit;
  101. }
  102. KeInitializeMutex(pMutex, 0);
  103. Status = KsAllocateObjectHeader(
  104. &pObjectHeader,
  105. cCreateItems,
  106. pCreateItems,
  107. pIrp,
  108. pDispatchTable);
  109. if(!NT_SUCCESS(Status)) {
  110. Trap();
  111. goto exit;
  112. }
  113. Status = pfnDispatchCreate(this, pReference);
  114. if(!NT_SUCCESS(Status)) {
  115. goto exit;
  116. }
  117. pNextDeviceObject = IoGetRelatedDeviceObject(pNextFileObject);
  118. //
  119. // ISSUE: 05/10/02 ALPERS
  120. // Windows does not support dynamically adjusting StackSizes on the fly.
  121. // The only place we are supposed to change this is in AddDevice.
  122. // This must be fixed later.
  123. //
  124. //
  125. // Never make the StackSize smaller. It can cause unexpected problems
  126. // if there are devices with deeper stacks.
  127. //
  128. if (pIrpStack->DeviceObject->StackSize < pNextDeviceObject->StackSize) {
  129. pIrpStack->DeviceObject->StackSize = pNextDeviceObject->StackSize;
  130. }
  131. pIrpStack->FileObject->FsContext = this;
  132. exit:
  133. return(Status);
  134. }
  135. VOID
  136. CInstance::Invalidate(
  137. )
  138. {
  139. Assert(this);
  140. GrabInstanceMutex();
  141. DPF1(50, "CInstance::Invalidate %08x", this);
  142. // "RemoveRef" from file object
  143. if(pNextFileObject != NULL) {
  144. ObDereferenceObject(pNextFileObject);
  145. }
  146. pNextFileObject = NULL;
  147. ReleaseInstanceMutex();
  148. }
  149. VOID
  150. CParentInstance::Invalidate(
  151. )
  152. {
  153. PINSTANCE pInstance;
  154. Assert(this);
  155. FOR_EACH_LIST_ITEM_DELETE(&lstChildInstance, pInstance) {
  156. pInstance->Invalidate();
  157. } END_EACH_LIST_ITEM
  158. }
  159. NTSTATUS
  160. CInstance::DispatchClose(
  161. IN PDEVICE_OBJECT pDeviceObject,
  162. IN PIRP pIrp
  163. )
  164. {
  165. PIO_STACK_LOCATION pIrpStack;
  166. PINSTANCE pInstance;
  167. //
  168. // ISSUE: 02/26/02 ALPERS
  169. // Why do we need the global mutex here. Can't we do it with
  170. // instance mutex?
  171. //
  172. ::GrabMutex();
  173. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  174. pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
  175. Assert(pInstance);
  176. pIrpStack->FileObject->FsContext = NULL;
  177. delete pInstance;
  178. ::ReleaseMutex();
  179. pIrp->IoStatus.Information = 0;
  180. pIrp->IoStatus.Status = STATUS_SUCCESS;
  181. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  182. return(STATUS_SUCCESS);
  183. }
  184. #pragma LOCKED_CODE
  185. #pragma LOCKED_DATA
  186. NTSTATUS
  187. CInstance::DispatchForwardIrp(
  188. IN PDEVICE_OBJECT pDeviceObject,
  189. IN PIRP pIrp
  190. )
  191. {
  192. PIO_STACK_LOCATION pIrpStack;
  193. PFILE_OBJECT pNextFileObject;
  194. PINSTANCE pInstance;
  195. NTSTATUS Status = STATUS_SUCCESS;
  196. #ifdef DEBUG
  197. DumpIoctl(pIrp, "ForwardIrp", DBG_IOCTL_LOG);
  198. #endif
  199. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  200. pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
  201. // Use gMutex instead of instance mutex. The instance mutex
  202. // is not used in any of the dispatch handlers, therefore will
  203. // not synchronize DispatchForwardIrp with other DispatchHandlers in
  204. // CPinInstance.
  205. // Grab mutex for a very short time to check the validity of CInstance.
  206. // If it is valid, IoCallDriver is called. This does not need
  207. // synchronization
  208. //
  209. ::GrabMutex();
  210. Assert(pInstance);
  211. pNextFileObject = pInstance->pNextFileObject;
  212. if(pNextFileObject == NULL) {
  213. DPF(60, "DispatchIoControl: pNextFileObject == NULL");
  214. Status = pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  215. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  216. }
  217. ::ReleaseMutex();
  218. //
  219. // ISSUE: 02/21/02 ALPERS
  220. // This is totally wrong. How would sysaudio know that the pNextDeviceObject
  221. // and sysaudio has the same DeviceStack.
  222. // Sysaudio should allocate a new IRP and send the new IRP down to
  223. // pNextDeviceObject.
  224. //
  225. // This code path is executed for IOCTL_KS_READ_STREAM,
  226. // IOCTL_KS_WRITE_STREAM and IOCTL_KS_RESET_STATE requests.
  227. //
  228. // In order to solve the problem mentioned above sysaudio has to
  229. // create new irps, pend/queue original irp and complete irps
  230. // asynchronously.
  231. // There is no infrastructure to do it in sysaudio. And this is
  232. // not directly related to security.
  233. //
  234. if (NT_SUCCESS(Status)) {
  235. pIrpStack->FileObject = pNextFileObject;
  236. IoSkipCurrentIrpStackLocation(pIrp);
  237. AssertFileObject(pIrpStack->FileObject);
  238. Status = IoCallDriver(pInstance->pNextDeviceObject, pIrp);
  239. }
  240. return(Status);
  241. }