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.

327 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. shadow.c
  5. Abstract:
  6. This module contains the code that implements the fast loopback routines
  7. Author:
  8. Ahmed Mohamed (ahmedm) 15-Dec-2001
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include <srvfsctl.h>
  16. #define SERVER_DEVICE_NAME_W L"\\Device\\LanmanServer"
  17. #define MrxLog(x) // DbgPrint x
  18. typedef struct {
  19. MRXSHADOW_SRV_OPEN;
  20. //
  21. // State obtained from srv
  22. //
  23. SRV_RESPONSE_HANDLE_DUP UnderlyingHandle;
  24. SRV_RESUME_KEY Key;
  25. }MRXSMBSHADOW_SRV_OPEN, *PMRXSMBSHADOW_SRV_OPEN;
  26. NTSTATUS
  27. MRxSmbCloseShadowSrvOpen(PRX_CONTEXT RxContext)
  28. {
  29. PMRXSMBSHADOW_SRV_OPEN MrxSmbShadowSrvOpen;
  30. NTSTATUS status;
  31. // if we can find an active queue then add this item to it, otherwise call
  32. // underlying device to satisfy IO
  33. MrxSmbShadowSrvOpen = (PMRXSMBSHADOW_SRV_OPEN) RxContext->pRelevantSrvOpen->ShadowContext;
  34. if (MrxSmbShadowSrvOpen != NULL) {
  35. ObDereferenceObject(MrxSmbShadowSrvOpen->UnderlyingFileObject);
  36. ZwClose(MrxSmbShadowSrvOpen->UnderlyingHandle.hFile);
  37. ExFreePool(MrxSmbShadowSrvOpen);
  38. RxContext->pRelevantSrvOpen->ShadowContext = NULL;
  39. }
  40. return STATUS_SUCCESS;
  41. }
  42. PSRV_REQUEST_RESUME_KEY
  43. MRxSmbQueryResumeKey(PRX_CONTEXT RxContext)
  44. {
  45. PRX_CONTEXT LocalRxContext = NULL;
  46. PSRV_REQUEST_RESUME_KEY key = NULL;
  47. NTSTATUS status = STATUS_NO_MEMORY;
  48. PIRP irp;
  49. IO_STATUS_BLOCK ios;
  50. irp = RxContext->CurrentIrp;
  51. if (irp != NULL) {
  52. key = ExAllocatePool( NonPagedPool,
  53. sizeof(*key) + SRV_LWIO_CONTEXT_SIZE);
  54. }
  55. if (key != NULL) {
  56. LocalRxContext = RxCreateRxContext(NULL,
  57. RxContext->RxDeviceObject,
  58. RX_CONTEXT_FLAG_WAIT);
  59. }
  60. if (LocalRxContext != NULL) {
  61. PLOWIO_CONTEXT LowIoContext = &LocalRxContext->LowIoContext;
  62. LocalRxContext->pFcb = RxContext->pFcb;
  63. LocalRxContext->pFobx = RxContext->pFobx;
  64. LocalRxContext->pRelevantSrvOpen = RxContext->pRelevantSrvOpen;
  65. LocalRxContext->CurrentIrp = irp;
  66. LocalRxContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  67. LowIoContext->Operation = LOWIO_OP_FSCTL;
  68. LowIoContext->ParamsFor.FsCtl.FsControlCode =
  69. FSCTL_SRV_REQUEST_RESUME_KEY;
  70. LowIoContext->ParamsFor.FsCtl.MinorFunction =
  71. IRP_MN_USER_FS_REQUEST;
  72. LowIoContext->ParamsFor.FsCtl.InputBufferLength = 0;
  73. LowIoContext->ParamsFor.FsCtl.pInputBuffer = NULL;
  74. LowIoContext->ParamsFor.FsCtl.OutputBufferLength =
  75. (sizeof(*key) + SRV_LWIO_CONTEXT_SIZE);
  76. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = (PVOID) key;
  77. SetFlag(LocalRxContext->Flags,
  78. RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED);
  79. LocalRxContext->InformationToReturn = 0;
  80. LowIoContext->CompletionRoutine = NULL;
  81. SetFlag(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_SYNCCALL);
  82. status = RxContext->RxDeviceObject->Dispatch->MRxLowIOSubmit[LowIoContext->Operation](LocalRxContext);
  83. if (status == STATUS_PENDING) {
  84. RxWaitSync(LocalRxContext);
  85. status = LocalRxContext->StoredStatus;
  86. }
  87. LocalRxContext->CurrentIrp = NULL;
  88. if (status == STATUS_SUCCESS) {
  89. MrxLog(("Key is %I64x %I64x pid %I64d\n",
  90. key->Key.ResumeKey, key->Key.Timestamp,
  91. key->Key.Pid));
  92. }
  93. }
  94. if (LocalRxContext) {
  95. RxDereferenceAndDeleteRxContext(LocalRxContext);
  96. }
  97. if (status != STATUS_SUCCESS && key != NULL) {
  98. ExFreePool(key);
  99. key = NULL;
  100. }
  101. return key;
  102. }
  103. NTSTATUS
  104. MrxSmbGetSrvHandle(PRX_CONTEXT RxContext)
  105. {
  106. OBJECT_ATTRIBUTES ObjectAttributes;
  107. IO_STATUS_BLOCK IoStatusBlock;
  108. UNICODE_STRING cwspath;
  109. NTSTATUS status;
  110. HANDLE FileHandle;
  111. PMRXSMBSHADOW_SRV_OPEN SrvOpen;
  112. SRV_REQUEST_HANDLE_DUP request;
  113. SrvOpen = (PMRXSMBSHADOW_SRV_OPEN) RxContext->MRxContext[0];
  114. RtlInitUnicodeString(&cwspath, SERVER_DEVICE_NAME_W);
  115. InitializeObjectAttributes(
  116. &ObjectAttributes,
  117. &cwspath,
  118. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  119. 0,
  120. NULL // !!! Security
  121. );
  122. status = ZwOpenFile(&FileHandle,
  123. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  124. &ObjectAttributes,
  125. &IoStatusBlock,
  126. FILE_SHARE_READ | FILE_SHARE_WRITE,
  127. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
  128. if (!NT_SUCCESS(status)) {
  129. MrxLog(("Unable to open srv %x\n", status));
  130. return status;
  131. }
  132. request.Key = SrvOpen->Key;
  133. request.Options = RxContext->CurrentIrpSp->Parameters.Create.Options;
  134. request.Options &= ~FILE_SYNCHRONOUS_IO_ALERT;
  135. request.Options &= ~FILE_SYNCHRONOUS_IO_NONALERT;
  136. request.Options &= ~FILE_COMPLETE_IF_OPLOCKED;
  137. status = ZwFsControlFile(FileHandle,
  138. NULL,
  139. NULL,
  140. NULL,
  141. &IoStatusBlock,
  142. FSCTL_SRV_REQUEST_HANDLE_DUP,
  143. (PVOID) &request,
  144. sizeof(request),
  145. (PVOID) &SrvOpen->UnderlyingHandle,
  146. sizeof(SrvOpen->UnderlyingHandle));
  147. if (status == STATUS_PENDING) {
  148. ZwWaitForSingleObject(FileHandle, FALSE, NULL);
  149. status = IoStatusBlock.Status;
  150. }
  151. ZwClose(FileHandle);
  152. if (status == STATUS_SUCCESS) {
  153. // set lock key
  154. SrvOpen->LockKey = SrvOpen->UnderlyingHandle.LockKey;
  155. // set file object
  156. status = ObReferenceObjectByHandle(SrvOpen->UnderlyingHandle.hFile,
  157. 0L,
  158. NULL,
  159. KernelMode,
  160. (PVOID *) &SrvOpen->UnderlyingFileObject,
  161. NULL );
  162. if (NT_SUCCESS(status)) {
  163. PFAST_IO_DISPATCH fastIoDispatch;
  164. SrvOpen->UnderlyingDeviceObject =
  165. IoGetRelatedDeviceObject(SrvOpen->UnderlyingFileObject );
  166. fastIoDispatch = SrvOpen->UnderlyingDeviceObject->DriverObject->FastIoDispatch;
  167. if ( fastIoDispatch != NULL ) {
  168. SrvOpen->FastIoRead = fastIoDispatch->FastIoRead;
  169. SrvOpen->FastIoWrite = fastIoDispatch->FastIoWrite;
  170. }
  171. }
  172. }
  173. RxContext->MRxContext[0] = (PVOID) ((ULONG_PTR)status);
  174. RxSignalSynchronousWaiter(RxContext);
  175. return STATUS_SUCCESS;
  176. }
  177. NTSTATUS
  178. MRxSmbCreateShadowSrvOpen(PRX_CONTEXT RxContext)
  179. {
  180. PFCB Fcb = (PFCB) RxContext->pFcb;
  181. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  182. ACCESS_MASK Access;
  183. NTSTATUS status = STATUS_NO_MEMORY;
  184. Access = RxContext->Create.NtCreateParameters.DesiredAccess;
  185. if ( !(Access & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
  186. (Access & DELETE) ) {
  187. // Only do READ's and WRITE's.
  188. // Don't activate on open-for-delete because of problems with RENAME
  189. return STATUS_NOT_SUPPORTED;
  190. }
  191. if (SrvOpen->ShadowContext != NULL ||
  192. !ExIsResourceAcquiredExclusiveLite(Fcb->Header.Resource)) {
  193. return STATUS_NOT_SUPPORTED;
  194. }
  195. MrxLog(("MrxLoop create access %x file '%wZ'\n", Access,
  196. &Fcb->PrivateAlreadyPrefixedName));
  197. if (TRUE) {
  198. PSRV_REQUEST_RESUME_KEY SrvKey = NULL;
  199. PMRXSMBSHADOW_SRV_OPEN MrxSmbShadowSrvOpen;
  200. MrxSmbShadowSrvOpen = ExAllocatePool( NonPagedPool, sizeof(*MrxSmbShadowSrvOpen));
  201. if (MrxSmbShadowSrvOpen == NULL) {
  202. return status;
  203. }
  204. RtlZeroMemory(MrxSmbShadowSrvOpen, sizeof(*MrxSmbShadowSrvOpen));
  205. SrvKey = MRxSmbQueryResumeKey(RxContext);
  206. if (SrvKey == NULL) {
  207. ExFreePool(MrxSmbShadowSrvOpen);
  208. return status;
  209. }
  210. MrxSmbShadowSrvOpen->Key = SrvKey->Key;
  211. SrvOpen->ShadowContext = (PMRXSHADOW_SRV_OPEN) MrxSmbShadowSrvOpen;
  212. KeInitializeEvent(&RxContext->SyncEvent,
  213. NotificationEvent,
  214. FALSE );
  215. // issue fsctl to get handle from srv
  216. RxContext->MRxContext[0] = (PVOID) MrxSmbShadowSrvOpen;
  217. // post to a worker thread
  218. status = RxPostToWorkerThread(RxContext->RxDeviceObject,
  219. CriticalWorkQueue,
  220. &RxContext->WorkQueueItem,
  221. MrxSmbGetSrvHandle,
  222. RxContext);
  223. if (status == STATUS_SUCCESS) {
  224. RxWaitSync(RxContext);
  225. status = (NTSTATUS) ((ULONG_PTR)RxContext->MRxContext[0]);
  226. }
  227. if (status == STATUS_SUCCESS) {
  228. if (!FlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED)) {
  229. SetFlag(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED);
  230. SetFlag(Fcb->FcbState, FCB_STATE_DISABLE_LOCAL_BUFFERING);
  231. RxChangeBufferingState(
  232. (PSRV_OPEN)SrvOpen,
  233. NULL,
  234. FALSE);
  235. }
  236. } else {
  237. SrvOpen->ShadowContext = NULL;
  238. ExFreePool(MrxSmbShadowSrvOpen);
  239. }
  240. ExFreePool(SrvKey);
  241. }
  242. return status;
  243. }