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.

254 lines
7.5 KiB

  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: DfsTriggerKnowledgeVerification -
  15. //
  16. // History: 22-March-1993 SudK Created
  17. // 18-June-1992 SudK Added FixLocalVolumeKnowledge
  18. //
  19. //-------------------------------------------------------------------
  20. #include "dfsprocs.h"
  21. #include "fsctrl.h"
  22. #include "dnr.h"
  23. #include "know.h"
  24. #include "log.h"
  25. #include "smbtypes.h"
  26. #include "smbtrans.h"
  27. #define Dbg (DEBUG_TRACE_LOCALVOL)
  28. //
  29. // local function prototypes
  30. //
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text( PAGE, DfsTriggerKnowledgeVerification )
  33. #endif // ALLOC_PRAGMA
  34. //+------------------------------------------------------------------
  35. //
  36. // Function: DfsTriggerKnowledgeVerification
  37. //
  38. // Synopsis: This function calls the DC and informs it that a specific
  39. // service for a volume seems to have inconsistenct knowledge
  40. // with the DC.
  41. //
  42. // If the service in question is a local service, then it means
  43. // that there is an extra exit point on the disk. In that event
  44. // this routine merely deletes the extra exit point.
  45. //
  46. // Arguments: [DnrContext] -- The DnrContext has all that this func needs.
  47. //
  48. // Returns: The status from this not checked by anyone actually.
  49. //
  50. // History: 4-April-1993 SudK Created
  51. //
  52. // Notes: This method should be called from DNR only. It is
  53. // assumed that the caller has released any locks on the
  54. // PKT. There is a possibility of deadlock if the PKT lock
  55. // is held over this function, since the DC may call back
  56. // to us to correct knowledge errors.
  57. //
  58. //-------------------------------------------------------------------
  59. NTSTATUS
  60. DfsTriggerKnowledgeVerification(
  61. IN PDNR_CONTEXT DnrContext)
  62. {
  63. NTSTATUS status = STATUS_SUCCESS;
  64. NTSTATUS ReplStatus;
  65. IO_STATUS_BLOCK ioStatusBlock;
  66. ULONG size;
  67. PBYTE buffer = NULL;
  68. PDFS_REFERRAL_V1 ref;
  69. UNICODE_STRING prefix, address;
  70. PDFS_PKT_ENTRY pPktEntryDC;
  71. PDFS_SERVICE DCService;
  72. PPROVIDER_DEF DCProvider;
  73. REPL_SELECT_CONTEXT DCSelectContext;
  74. HANDLE remoteHandle;
  75. UNICODE_STRING puStr[2];
  76. DfsDbgTrace(+1, Dbg, "DfsTriggerKnowledgeVerification: %wZ\n",
  77. &DnrContext->pPktEntry->Id.Prefix);
  78. DfsDbgTrace( 0, Dbg, " ServiceName: [%wZ]\n",
  79. ((DnrContext->pService->Type & DFS_SERVICE_TYPE_LOCAL) ?
  80. &DnrContext->pService->Address :
  81. &DnrContext->pService->Name) );
  82. RtlZeroMemory(&DCSelectContext, sizeof(REPL_SELECT_CONTEXT));
  83. //
  84. // First, create a REQ_REPORT_DFS_INCONSISTENCY buffer for the rdr to
  85. // send to the DC.
  86. //
  87. if (DnrContext->pPktEntry->USN != DnrContext->USN) {
  88. DfsDbgTrace(0, Dbg,"Pkt Entry changed!\n", 0 );
  89. DfsDbgTrace(0, Dbg, "Old USN: %d\n", ULongToPtr(DnrContext->USN) );
  90. DfsDbgTrace(0, Dbg, "New USN: %d\n", ULongToPtr(DnrContext->pPktEntry->USN) );
  91. status = STATUS_INVALID_HANDLE;
  92. }
  93. if (NT_SUCCESS(status)) {
  94. prefix = DnrContext->pPktEntry->Id.Prefix;
  95. address = DnrContext->pService->Address;
  96. size = prefix.Length +
  97. sizeof(WCHAR) +
  98. sizeof(DFS_REFERRAL_V1) +
  99. address.Length +
  100. sizeof(WCHAR);
  101. // For some strange, undocumented reason, the buffer size passed in
  102. // to ZwFsControlFile is size + sizeof(ULONG). So allocate that size here.
  103. buffer = ExAllocatePoolWithTag( PagedPool, size + sizeof(ULONG), ' puM' );
  104. if (buffer != NULL) {
  105. RtlMoveMemory( buffer, prefix.Buffer, prefix.Length);
  106. ((PWCHAR)buffer)[prefix.Length/sizeof(WCHAR)] = UNICODE_NULL;
  107. ref = (PDFS_REFERRAL_V1) (buffer + prefix.Length + sizeof(WCHAR));
  108. ref->VersionNumber = 1;
  109. ref->Size = sizeof(DFS_REFERRAL_V1) + address.Length + sizeof(WCHAR);
  110. ref->ServerType = 0;
  111. RtlMoveMemory( ref->ShareName, address.Buffer, address.Length );
  112. ref->ShareName[ address.Length/sizeof(WCHAR) ] = UNICODE_NULL;
  113. } else {
  114. status = STATUS_INSUFFICIENT_RESOURCES;
  115. }
  116. }
  117. //
  118. // Next, connect to the DC.
  119. //
  120. if (NT_SUCCESS(status)) {
  121. BOOLEAN pktLocked;
  122. BOOLEAN LastEntry = FALSE;
  123. //
  124. // We need to get a handle to the DC now. So that we can make an
  125. // FSCTRL to the DC.
  126. //
  127. PktAcquireShared( TRUE, &pktLocked );
  128. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  129. pPktEntryDC = PktLookupReferralEntry(
  130. &DfsData.Pkt,
  131. DnrContext->pPktEntry);
  132. if (pPktEntryDC != NULL) {
  133. ReplStatus = ReplFindFirstProvider(
  134. pPktEntryDC,
  135. NULL,
  136. NULL,
  137. &DCService,
  138. &DCSelectContext,
  139. &LastEntry);
  140. }
  141. if (pPktEntryDC == NULL || !NT_SUCCESS(ReplStatus)) {
  142. DfsDbgTrace(0, Dbg,
  143. "DfsTriggerKnowVerification. Failed to find DC\n", 0);
  144. status = STATUS_CANT_ACCESS_DOMAIN_INFO;
  145. } else {
  146. DCProvider = DCService->pProvider;
  147. }
  148. ExReleaseResourceLite( &DfsData.Resource );
  149. if (NT_SUCCESS(status)) {
  150. status = DfsCreateConnection(
  151. DCService,
  152. DCProvider,
  153. (BOOLEAN)((DnrContext->Vcb->VcbState & VCB_STATE_CSCAGENT_VOLUME) != 0),
  154. &remoteHandle);
  155. }
  156. PktRelease();
  157. }
  158. //
  159. // Lastly, tell the DC to try and fix up the volume on the server. This
  160. // call may result in a call back to ourselves in the event that we
  161. // are missing knowledge about a local volume.
  162. //
  163. if (NT_SUCCESS(status)) {
  164. status = ZwFsControlFile(
  165. remoteHandle,
  166. NULL,
  167. NULL,
  168. NULL,
  169. &ioStatusBlock,
  170. FSCTL_DFS_VERIFY_REMOTE_VOLUME_KNOWLEDGE,
  171. buffer,
  172. size + sizeof(ULONG),
  173. NULL,
  174. 0
  175. );
  176. if (NT_SUCCESS(status))
  177. status = ioStatusBlock.Status;
  178. ZwClose( remoteHandle );
  179. }
  180. if (buffer != NULL)
  181. ExFreePool(buffer);
  182. DfsDbgTrace(-1, Dbg,
  183. "DfsTriggerKnowledgeVerification - exit %08lx\n", ULongToPtr(status) );
  184. return(status);
  185. }