Windows NT 4.0 source code leak
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.

385 lines
11 KiB

4 years ago
  1. //+------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation
  4. //
  5. // File: Know.C
  6. //
  7. // Contents: This file has all the code that involves with knowledge
  8. // synchronisation on the DC.
  9. //
  10. // Synoposis: This code handles the fixing of knowledge inconsistencies.
  11. // All this code runs only on the DC in response to FSCTRLs from
  12. // a client etc.
  13. //
  14. // Functions: DfsModifyRemotePrefix -
  15. // DfsCreateRemoteExitPoint -
  16. // DfsDeleteRemoteExitPoint -
  17. // DfsTriggerKnowledgeVerification -
  18. // DfsFsctrlVerifyRemoteVolumeKnowledge -
  19. // DfsFsctrlVerifyLocalVolumeKnowledge -
  20. // DfsFsctrlGetKnowledgeSyncParameters -
  21. // DfsDispatchUserModeThread -
  22. // DfsFsctrlFixLocalVolumeKnowledge -
  23. //
  24. // History: 22-March-1993 SudK Created
  25. // 18-June-1992 SudK Added FixLocalVolumeKnowledge
  26. //
  27. //-------------------------------------------------------------------
  28. #include "dfsprocs.h"
  29. #include "fsctrl.h"
  30. #include "dnr.h"
  31. #include "know.h"
  32. #include "log.h"
  33. #include "smbtypes.h"
  34. #include "smbtrans.h"
  35. #define Dbg (DEBUG_TRACE_LOCALVOL)
  36. //
  37. // local function prototypes
  38. //
  39. #ifdef ALLOC_PRAGMA
  40. #pragma alloc_text( PAGE, DfsTriggerKnowledgeVerification )
  41. #pragma alloc_text( PAGE, DfsDispatchUserModeThread )
  42. #endif // ALLOC_PRAGMA
  43. //+------------------------------------------------------------------
  44. //
  45. // Function: DfsTriggerKnowledgeVerification
  46. //
  47. // Synopsis: This function calls the DC and informs it that a specific
  48. // service for a volume seems to have inconsistenct knowledge
  49. // with the DC.
  50. //
  51. // If the service in question is a local service, then it means
  52. // that there is an extra exit point on the disk. In that event
  53. // this routine merely deletes the extra exit point.
  54. //
  55. // Arguments: [DnrContext] -- The DnrContext has all that this func needs.
  56. //
  57. // Returns: The status from this not checked by anyone actually.
  58. //
  59. // History: 4-April-1993 SudK Created
  60. //
  61. // Notes: This method should be called from DNR only. It is
  62. // assumed that the caller has released any locks on the
  63. // PKT. There is a possibility of deadlock if the PKT lock
  64. // is held over this function, since the DC may call back
  65. // to us to correct knowledge errors.
  66. //
  67. //-------------------------------------------------------------------
  68. NTSTATUS
  69. DfsTriggerKnowledgeVerification(
  70. IN PDNR_CONTEXT DnrContext)
  71. {
  72. NTSTATUS status = STATUS_SUCCESS;
  73. NTSTATUS ReplStatus;
  74. IO_STATUS_BLOCK ioStatusBlock;
  75. ULONG size;
  76. PBYTE buffer = NULL;
  77. PDFS_REFERRAL_V1 ref;
  78. UNICODE_STRING prefix, address;
  79. PDFS_PKT_ENTRY pPktEntryDC;
  80. PDFS_SERVICE DCService;
  81. PPROVIDER_DEF DCProvider;
  82. REPL_SELECT_CONTEXT DCSelectContext;
  83. HANDLE remoteHandle;
  84. UNICODE_STRING puStr[2];
  85. DfsDbgTrace(+1, Dbg, "DfsTriggerKnowledgeVerification: %wZ\n",
  86. &DnrContext->pPktEntry->Id.Prefix);
  87. DfsDbgTrace(0, Dbg, " ServiceName: [%wZ]\n",
  88. (DnrContext->pService->Type & DFS_SERVICE_TYPE_LOCAL) ?
  89. &DnrContext->pService->Address :
  90. &DnrContext->pService->Name);
  91. //
  92. // First, create a REQ_REPORT_DFS_INCONSISTENCY buffer for the rdr to
  93. // send to the DC.
  94. //
  95. if (DnrContext->pPktEntry->USN != DnrContext->USN) {
  96. DfsDbgTrace(0, Dbg,"Pkt Entry changed!\n", 0);
  97. DfsDbgTrace(0, Dbg, "Old USN: %d\n", DnrContext->USN);
  98. DfsDbgTrace(0, Dbg, "New USN: %d\n", DnrContext->pPktEntry->USN);
  99. status = STATUS_INVALID_HANDLE;
  100. }
  101. if (NT_SUCCESS(status)) {
  102. prefix = DnrContext->pPktEntry->Id.Prefix;
  103. address = DnrContext->pService->Address;
  104. size = prefix.Length +
  105. sizeof(WCHAR) +
  106. sizeof(DFS_REFERRAL_V1) +
  107. address.Length +
  108. sizeof(WCHAR);
  109. buffer = ExAllocatePool( PagedPool, size );
  110. if (buffer != NULL) {
  111. RtlMoveMemory( buffer, prefix.Buffer, prefix.Length);
  112. ((PWCHAR)buffer)[prefix.Length/sizeof(WCHAR)] = UNICODE_NULL;
  113. ref = (PDFS_REFERRAL_V1) (buffer + prefix.Length + sizeof(WCHAR));
  114. ref->VersionNumber = 1;
  115. ref->Size = sizeof(DFS_REFERRAL_V1) + address.Length + sizeof(WCHAR);
  116. ref->ServerType = 0;
  117. RtlMoveMemory( ref->ShareName, address.Buffer, address.Length );
  118. ref->ShareName[ address.Length/sizeof(WCHAR) ] = UNICODE_NULL;
  119. } else {
  120. status = STATUS_INSUFFICIENT_RESOURCES;
  121. }
  122. }
  123. //
  124. // Next, connect to the DC.
  125. //
  126. if (NT_SUCCESS(status)) {
  127. BOOLEAN pktLocked;
  128. //
  129. // We need to get a handle to the DC now. So that we can make an
  130. // FSCTRL to the DC.
  131. //
  132. PktAcquireShared( TRUE, &pktLocked );
  133. ExAcquireResourceExclusive( &DfsData.Resource, TRUE );
  134. pPktEntryDC = PktLookupReferralEntry(
  135. &DfsData.Pkt,
  136. DnrContext->pPktEntry);
  137. if (pPktEntryDC != NULL) {
  138. ReplStatus = ReplFindFirstProvider(
  139. pPktEntryDC,
  140. NULL,
  141. NULL,
  142. &DCService,
  143. &DCSelectContext);
  144. }
  145. if (pPktEntryDC == NULL || !NT_SUCCESS(ReplStatus)) {
  146. DfsDbgTrace(0, Dbg,
  147. "DfsTriggerKnowVerification. Failed to find DC\n", 0);
  148. status = STATUS_CANT_ACCESS_DOMAIN_INFO;
  149. } else {
  150. DCProvider = DCService->pProvider;
  151. }
  152. ExReleaseResource( &DfsData.Resource );
  153. if (NT_SUCCESS(status)) {
  154. status = DfsCreateConnection(
  155. DCService,
  156. DCProvider,
  157. &remoteHandle);
  158. }
  159. PktRelease();
  160. }
  161. //
  162. // Lastly, tell the DC to try and fix up the volume on the server. This
  163. // call may result in a call back to ourselves in the event that we
  164. // are missing knowledge about a local volume.
  165. //
  166. if (NT_SUCCESS(status)) {
  167. status = ZwFsControlFile(
  168. remoteHandle,
  169. NULL,
  170. NULL,
  171. NULL,
  172. &ioStatusBlock,
  173. FSCTL_DFS_VERIFY_REMOTE_VOLUME_KNOWLEDGE,
  174. buffer,
  175. size + sizeof(ULONG),
  176. NULL,
  177. 0
  178. );
  179. if (NT_SUCCESS(status))
  180. status = ioStatusBlock.Status;
  181. ZwClose( remoteHandle );
  182. }
  183. if (buffer != NULL)
  184. ExFreePool(buffer);
  185. DfsDbgTrace(-1, Dbg,
  186. "DfsTriggerKnowledgeVerification - exit %08lx\n", status);
  187. return(status);
  188. }
  189. //+------------------------------------------------------------------
  190. //
  191. // Function: DfsDispatchUserModeThread
  192. //
  193. // Synopsis: This function is called on the DC when the driver discovers
  194. // a knowledge inconsistency and attempts to fix it. This
  195. // function wakes up a user level thread and tells it the
  196. // GUID and ServiceName of the volume to be fixed. This is done
  197. // by simply writing into a named pipe, which the user level
  198. // thread should be listening on.
  199. //
  200. // Arguments: [arg] -- The DFS_VOL_VERIFY struct has ID and SvcName which
  201. // need to be sent to the user mode server.
  202. //
  203. // Returns:
  204. //
  205. // History: 05-April-1993 SudK Created
  206. //
  207. // Notes:
  208. //
  209. //-------------------------------------------------------------------
  210. NTSTATUS
  211. DfsDispatchUserModeThread(
  212. IN PVOID InputBuffer,
  213. IN ULONG InputBufferLength)
  214. {
  215. NTSTATUS status = STATUS_SUCCESS;
  216. BOOLEAN ProcessAttached = FALSE;
  217. HANDLE hPipe;
  218. OBJECT_ATTRIBUTES ObjectAttributes;
  219. UNICODE_STRING UnicodeString;
  220. IO_STATUS_BLOCK Iosb;
  221. DfsDbgTrace(+1, Dbg, "DfsDispatchUserModeThread: Entered\n", 0);
  222. RtlInitUnicodeString(&UnicodeString, DFS_KERNEL_MESSAGE_PIPE);
  223. InitializeObjectAttributes(
  224. &ObjectAttributes,
  225. &UnicodeString,
  226. OBJ_CASE_INSENSITIVE,
  227. NULL,
  228. NULL);
  229. status = ZwOpenFile(&hPipe,
  230. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  231. &ObjectAttributes,
  232. &Iosb,
  233. FILE_SHARE_READ,
  234. FILE_SYNCHRONOUS_IO_NONALERT
  235. );
  236. if ( !NT_SUCCESS(status) || !NT_SUCCESS(Iosb.Status) ) {
  237. DfsDbgTrace(0, Dbg, "Open of named pipe failed - %08lx\n", status);
  238. return(status);
  239. }
  240. status = ZwWriteFile(
  241. hPipe,
  242. NULL,
  243. NULL,
  244. NULL,
  245. &Iosb,
  246. &InputBufferLength,
  247. sizeof(InputBufferLength),
  248. NULL,
  249. NULL);
  250. if (NT_SUCCESS(status)) {
  251. status = Iosb.Status;
  252. } else {
  253. DfsDbgTrace(0, Dbg, "Write to named pipe failed -> %08lx\n", status);
  254. }
  255. if (NT_SUCCESS(status)) {
  256. status = ZwWriteFile(
  257. hPipe,
  258. NULL,
  259. NULL,
  260. NULL,
  261. &Iosb,
  262. InputBuffer,
  263. InputBufferLength,
  264. NULL,
  265. NULL);
  266. if (NT_SUCCESS(status)) {
  267. status = Iosb.Status;
  268. } else {
  269. DfsDbgTrace(0, Dbg, "Write to named pipe failed -> %08lx\n", status);
  270. }
  271. }
  272. if (NT_SUCCESS(status)) {
  273. //
  274. // Attempt to read back the status of the user-level operation
  275. //
  276. NTSTATUS OperationStatus ;
  277. status = ZwReadFile(
  278. hPipe,
  279. NULL,
  280. NULL,
  281. NULL,
  282. &Iosb,
  283. &OperationStatus,
  284. sizeof(OperationStatus),
  285. NULL,
  286. NULL);
  287. if (NT_SUCCESS(status)) {
  288. status = OperationStatus;
  289. }
  290. }
  291. ZwClose(hPipe);
  292. DfsDbgTrace(-1, Dbg, "DfsDispatchUserModeThread: Exited -> %08lx\n", status);
  293. return(status);
  294. }