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.

3203 lines
93 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsInit.cxx
  6. //
  7. // Contents: Contains initialization of server
  8. //
  9. // Classes: none.
  10. //
  11. // History: Dec. 8 2000, Author: udayh
  12. // Jan. 12 2001, Rohanp - Added retrieval of replica data
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include "DfsRegStrings.hxx"
  16. #include "DfsRegistryStore.hxx"
  17. #include "DfsADBlobStore.hxx"
  18. #include "DfsFolderReferralData.hxx"
  19. #include "DfsInit.hxx"
  20. #include "DfsServerSiteInfo.hxx"
  21. #include "DfsSiteSupport.hxx"
  22. #include "dfsfilterapi.hxx"
  23. #include "DfsClusterSupport.hxx"
  24. #include "DomainControllerSupport.hxx"
  25. #include "DfsDomainInformation.hxx"
  26. #include "dfsadsiapi.hxx"
  27. #include "DfsSynchronizeRoots.hxx"
  28. #include "DfsSiteCache.hxx"
  29. #include "DfsSiteNameSupport.hxx"
  30. #include "DfsISTGSupport.hxx"
  31. #include "DfsReparse.hxx"
  32. #include "dfsinit.tmh"
  33. #include <dsrole.h>
  34. #include "dfscompat.hxx"
  35. #include "dfssecurity.h"
  36. #include "ntlsa.h"
  37. //
  38. // DFS_REGISTER_STORE: A convenience define to be able to register a
  39. // number of differnet store types.
  40. //
  41. #define DFS_REGISTER_STORE(_name, _sts) \
  42. { \
  43. DFSSTATUS LocalStatus = ERROR_SUCCESS; \
  44. DfsServerGlobalData.pDfs ## _name ## Store = new Dfs ## _name ## Store(&LocalStatus); \
  45. \
  46. if (DfsServerGlobalData.pDfs ## _name ## Store == NULL) { \
  47. (_sts) = ERROR_NOT_ENOUGH_MEMORY; \
  48. } \
  49. else if (LocalStatus == ERROR_SUCCESS){ \
  50. DfsServerGlobalData.pDfs ## _name ## Store->pNextRegisteredStore = DfsServerGlobalData.pRegisteredStores; \
  51. DfsServerGlobalData.pRegisteredStores = DfsServerGlobalData.pDfs ## _name ## Store; \
  52. (_sts) = ERROR_SUCCESS; \
  53. } \
  54. else \
  55. { \
  56. (_sts) = LocalStatus; \
  57. } \
  58. }
  59. //
  60. // INITIALIZE_COMPUTER_INFO: A convenience define to initialize the
  61. // different information about the computer (netbios, dns, domain etc)
  62. //
  63. #define INITIALIZE_COMPUTER_INFO( _NamedInfo, _pBuffer, _Sz, _Sts ) \
  64. { \
  65. ULONG NumChars = _Sz; \
  66. if (_Sts == ERROR_SUCCESS) { \
  67. DWORD dwRet = GetComputerNameEx( _NamedInfo,_pBuffer,&NumChars ); \
  68. if (dwRet == 0) _Sts = GetLastError(); \
  69. } \
  70. if (_Sts == ERROR_SUCCESS) { \
  71. LPWSTR NewName = new WCHAR [ NumChars + 1 ]; \
  72. if (NewName == NULL) _Sts = ERROR_NOT_ENOUGH_MEMORY; \
  73. else wcscpy( NewName, _pBuffer ); \
  74. DfsServerGlobalData.DfsMachineInfo.Static ## _NamedInfo ## = NewName;\
  75. } \
  76. }
  77. //
  78. // The DfsServerGlobalData: the data structure that holds the registered
  79. // stores and the registered names, among others.
  80. //
  81. DFS_SERVER_GLOBAL_DATA DfsServerGlobalData;
  82. //
  83. // Varios strings that represent the names in registry where some of
  84. // DFS information is stored.
  85. //
  86. LPWSTR DfsSvcPath = DFS_REG_SVC_PATH;
  87. LPWSTR DfsDnsConfigValue = DFS_REG_DNS_CONFIG_VALUE;
  88. LPWSTR DfsParamPath = DFS_REG_PARAM_PATH;
  89. LPWSTR DfsRegistryHostLocation = DFS_REG_HOST_LOCATION;
  90. LPWSTR DfsOldRegistryLocation = DFS_REG_OLD_HOST_LOCATION;
  91. LPWSTR DfsVolumesLocation = DFS_REG_VOLUMES_LOCATION;
  92. LPWSTR DfsOldStandaloneChild = DFS_REG_OLD_STANDALONE_CHILD;
  93. LPWSTR DfsRegistryDfsLocation = DFS_REG_DFS_LOCATION;
  94. LPWSTR DfsNewRegistryLocation = DFS_REG_NEW_DFS_LOCATION;
  95. LPWSTR DfsRootLocation = DFS_REG_ROOT_LOCATION;
  96. LPWSTR DfsStandaloneChild = DFS_REG_STANDALONE_CHILD;
  97. LPWSTR DfsADBlobChild = DFS_REG_AD_BLOB_CHILD;
  98. LPWSTR DfsRootShareValueName = DFS_REG_ROOT_SHARE_VALUE;
  99. LPWSTR DfsMigratedValueName = DFS_REG_MIGRATED_VALUE;
  100. LPWSTR DfsLogicalShareValueName = DFS_REG_LOGICAL_SHARE_VALUE;
  101. LPWSTR DfsFtDfsValueName = DFS_REG_FT_DFS_VALUE;
  102. LPWSTR DfsFtDfsConfigDNValueName = DFS_REG_FT_DFS_CONFIG_DN_VALUE;
  103. LPWSTR DfsWorkerThreadIntervalName = DFS_SYNC_INTERVAL_NAME;
  104. LPWSTR DfsSiteSupportRefreshIntervalName = DFS_REG_SITE_SUPPORT_REFRESH_INTERVAL_NAME;
  105. LPWSTR DfsSiteIpCacheTrimValueName = DFS_REG_SITE_IP_CACHE_TRIM_VALUE;
  106. LPWSTR DfsAllowableErrorsValueName = DFS_REG_ALLOWABLE_ERRORS_VALUE;
  107. LPWSTR DfsLdapTimeoutValueName = DFS_REG_LDAP_TIMEOUT_VALUE;
  108. LPWSTR DfsSiteCostedReferralsValueName = DFS_REG_SITE_COSTED_REFERRALS_VALUE;
  109. LPWSTR DfsInsiteReferralsValueName = DFS_REG_INSITE_REFERRALS_VALUE;
  110. LPWSTR DfsMaxClientSiteValueName = DFS_REG_MAXSITE_VALUE;
  111. LPWSTR DfsQuerySiteCostTimeoutName = DFS_REG_QUERY_SITECOST_TIMEOUT_NAME;
  112. LPWSTR DfsDomainNameRefreshInterval = DFS_REG_DOMAIN_NAME_REFRESH_INTERVAL_NAME;
  113. static SECURITY_DESCRIPTOR AdminSecurityDesc;
  114. static GENERIC_MAPPING AdminGenericMapping = {
  115. STANDARD_RIGHTS_READ, // Generic read
  116. STANDARD_RIGHTS_WRITE, // Generic write
  117. STANDARD_RIGHTS_EXECUTE, // Generic execute
  118. STANDARD_RIGHTS_READ | // Generic all
  119. STANDARD_RIGHTS_WRITE |
  120. STANDARD_RIGHTS_EXECUTE
  121. };
  122. DFSSTATUS
  123. DfsRegisterStores( VOID );
  124. DFSSTATUS
  125. DfsRecognize( LPWSTR Name );
  126. DFSSTATUS
  127. DfsRegisterName(LPWSTR Name);
  128. DWORD
  129. DfsWorkerThread(LPVOID TData);
  130. DFSSTATUS
  131. DfsCreateRequiredDfsKeys(void);
  132. BOOLEAN
  133. DfsGetGlobalRegistrySettings(void);
  134. BOOLEAN
  135. DfsGetStaticGlobalRegistrySettings(void);
  136. BOOLEAN
  137. DfsInitializeSecurity();
  138. DWORD
  139. DfsSiteSupportThread(LPVOID TData);
  140. VOID
  141. StartPreloadingServerSiteData(void);
  142. DFSSTATUS
  143. DfsSetupPrivileges (void);
  144. extern
  145. DFSSTATUS
  146. DfsGetRootReferralDataEx(
  147. PUNICODE_STRING pName,
  148. PUNICODE_STRING pRemainingName,
  149. DfsFolderReferralData **ppReferralData,
  150. PBOOLEAN pCacheHit);
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Function: DfsGetRegistryStore
  154. //
  155. // Arguments: ppRegStore - the registered registry store.
  156. //
  157. // Returns: Status
  158. // ERROR_SUCCESS on success
  159. // ERROR status code otherwise
  160. //
  161. //
  162. // Description: This routine searches through the registered stores, and
  163. // picks the one that is the registry store. This is required for
  164. // specific API requests that target the Registry based DFS
  165. // For example: add standalone root, etc
  166. //
  167. //--------------------------------------------------------------------------
  168. DFSSTATUS
  169. DfsGetRegistryStore(
  170. DfsRegistryStore **ppRegStore )
  171. {
  172. DFSSTATUS Status = ERROR_SUCCESS;
  173. *ppRegStore = DfsServerGlobalData.pDfsRegistryStore;
  174. if (*ppRegStore != NULL)
  175. {
  176. (*ppRegStore)->AcquireReference();
  177. }
  178. else
  179. {
  180. Status = ERROR_NOT_SUPPORTED;
  181. }
  182. return Status;
  183. }
  184. //+-------------------------------------------------------------------------
  185. //
  186. // Function: DfsGetADBlobStore
  187. //
  188. // Arguments: ppRegStore - the registered ADBlob store.
  189. //
  190. // Returns: Status
  191. // ERROR_SUCCESS on success
  192. // ERROR status code otherwise
  193. //
  194. //
  195. // Description: This routine searches through the registered stores, and
  196. // picks the one that is the registry store. This is required for
  197. // specific API requests that target the ADBlob based DFS
  198. // For example: add root, etc
  199. //
  200. //--------------------------------------------------------------------------
  201. DFSSTATUS
  202. DfsGetADBlobStore(
  203. DfsADBlobStore **ppStore )
  204. {
  205. DFSSTATUS Status = ERROR_SUCCESS;
  206. *ppStore = DfsServerGlobalData.pDfsADBlobStore;
  207. if (*ppStore != NULL)
  208. {
  209. (*ppStore)->AcquireReference();
  210. }
  211. else
  212. {
  213. Status = ERROR_NOT_SUPPORTED;
  214. }
  215. return Status;
  216. }
  217. BOOL
  218. IsStandardServerSKU(
  219. PBOOL pIsServer
  220. )
  221. {
  222. BOOL fReturnValue = (BOOL) FALSE;
  223. OSVERSIONINFOEX VersionInfo;
  224. BOOL IsServer = FALSE;
  225. //
  226. // get the current SKU.
  227. //
  228. VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
  229. if (GetVersionEx((OSVERSIONINFO *)&VersionInfo))
  230. {
  231. fReturnValue = TRUE;
  232. //
  233. // is it some sort of server SKU?
  234. //
  235. if (VersionInfo.wProductType != VER_NT_WORKSTATION)
  236. {
  237. //
  238. // standard server or a server variant?
  239. //
  240. if ((VersionInfo.wSuiteMask & (VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER)) == 0)
  241. {
  242. //
  243. // it's standard server
  244. //
  245. IsServer = TRUE;
  246. }
  247. }
  248. *pIsServer = IsServer;
  249. }
  250. return(fReturnValue);
  251. }
  252. //+-------------------------------------------------------------------------
  253. //
  254. // Function: DfsServerInitialize
  255. //
  256. // Arguments: Flags - the server flags
  257. //
  258. // Returns: Status
  259. // ERROR_SUCCESS on success
  260. // ERROR status code otherwise
  261. //
  262. //
  263. // Description: This routine initializes the DFS server. It registers
  264. // all the different stores we care about, and also
  265. // starts up a thread that is responsible for keeping the
  266. // DFS info upto date.
  267. //
  268. //--------------------------------------------------------------------------
  269. DFSSTATUS
  270. DfsServerInitialize(
  271. ULONG Flags )
  272. {
  273. DFSSTATUS Status = ERROR_SUCCESS;
  274. BOOLEAN fSecurity = FALSE;
  275. BOOL fCritInit = FALSE;
  276. BOOL fIsStandardServer = TRUE;
  277. WSADATA wsadata;
  278. ZeroMemory(&DfsServerGlobalData, sizeof(DfsServerGlobalData));
  279. DfsServerGlobalData.pRegisteredStores = NULL;
  280. DfsServerGlobalData.Flags = Flags;
  281. DfsServerGlobalData.bDfsAdAlive = TRUE;
  282. DfsServerGlobalData.bIsShuttingDown = FALSE;
  283. DfsServerGlobalData.ServiceState = SERVICE_START_PENDING;
  284. IsStandardServerSKU(&fIsStandardServer);
  285. if(fIsStandardServer)
  286. {
  287. DfsServerGlobalData.bLimitRoots = TRUE;
  288. }
  289. DfsSetupPrivileges ();
  290. Status = WSAStartup( MAKEWORD( 1, 1 ), &wsadata );
  291. if(Status != 0)
  292. {
  293. DfsLogDfsEvent(DFS_ERROR_WINSOCKINIT_FAILED, 0, NULL, Status);
  294. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!] WSAStartup failed status %x\n", Status);
  295. goto Exit;
  296. }
  297. fSecurity = DfsInitializeSecurity();
  298. if(fSecurity == FALSE)
  299. {
  300. Status = GetLastError();
  301. DfsLogDfsEvent(DFS_ERROR_SECURITYINIT_FAILED, 0, NULL, Status);
  302. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsInitializeSecurity failed status %x\n", Status);
  303. goto Exit;
  304. }
  305. InitializeListHead(&DfsServerGlobalData.ReparseVolumeList);
  306. InitializeListHead(&DfsServerGlobalData.SiteCostTableMruList);
  307. DfsServerGlobalData.NumSiteCostTables = 0;
  308. // The following are statistics we keep around, primarily for diagnostic purposes.
  309. // There might be a better place for these. xxxdfsdev
  310. DfsServerGlobalData.NumDfsSites = 0;
  311. DfsServerGlobalData.NumClientDfsSiteEntries = 0;
  312. DfsServerGlobalData.NumServerDfsSiteEntries = 0;
  313. DfsServerGlobalData.NumDfsSitesInCache = 0; // not the same as NumDfsSites because of refcounts
  314. DfsServerGlobalData.NumSiteCostTablesOnMruList = 0;
  315. //
  316. // Create and initialize the cache that maps incoming IP addresses to their corresponding
  317. // DfsSites.
  318. //
  319. DfsServerGlobalData.pClientSiteSupport = DfsSiteNameCache::CreateSiteHashTable(&Status);
  320. if(DfsServerGlobalData.pClientSiteSupport == NULL)
  321. {
  322. DfsLogDfsEvent(DFS_ERROR_SITECACHEINIT_FAILED, 0, NULL, Status);
  323. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsSiteNameCache::CreateSiteHashTable failed status %x\n", Status);
  324. goto Exit;
  325. }
  326. //
  327. // Create and initialize the repository of known DfsSites indexed by their site names.
  328. //
  329. DfsServerGlobalData.pSiteNameSupport = DfsSiteNameSupport::CreateSiteNameSupport( &Status );
  330. if(DfsServerGlobalData.pSiteNameSupport == NULL)
  331. {
  332. DfsLogDfsEvent(DFS_ERROR_SITECACHEINIT_FAILED, 0, NULL, Status); // dfsdev: insert unique error code.
  333. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsSiteNameSupport::CreateSiteNameSupport failed status %x\n", Status);
  334. goto Exit;
  335. }
  336. //
  337. // Create a default DfsSite with a NULL sitename that we will always keep around..
  338. //
  339. DfsServerGlobalData.pDefaultSite = DfsSite::CreateDfsSite( &Status );
  340. if(DfsServerGlobalData.pDefaultSite == NULL)
  341. {
  342. Status = ERROR_NOT_ENOUGH_MEMORY;
  343. DfsLogDfsEvent(DFS_ERROR_SITECACHEINIT_FAILED, 0, NULL, Status); // dfsdev: insert unique error code.
  344. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Default DFS site creation failed with status %x\n",
  345. Status);
  346. goto Exit;
  347. }
  348. fCritInit = InitializeCriticalSectionAndSpinCount( &DfsServerGlobalData.DataLock, DFS_CRIT_SPIN_COUNT );
  349. if(!fCritInit)
  350. {
  351. Status = GetLastError();
  352. goto Exit;
  353. }
  354. DfsServerGlobalData.ShutdownHandle = CreateEvent( NULL,
  355. TRUE,
  356. FALSE,
  357. NULL );
  358. if(DfsServerGlobalData.ShutdownHandle == NULL)
  359. {
  360. Status = GetLastError();
  361. DfsLogDfsEvent(DFS_ERROR_CREATEEVENT_FAILED, 0, NULL, Status);
  362. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]CreateEvent failed status %x\n", Status);
  363. goto Exit;
  364. }
  365. DfsServerGlobalData.RegNotificationHandle = CreateEvent( NULL, FALSE, FALSE, NULL );
  366. if(DfsServerGlobalData.RegNotificationHandle == NULL)
  367. {
  368. Status = GetLastError();
  369. DfsLogDfsEvent(DFS_ERROR_CREATEEVENT_FAILED, 0, NULL, Status);
  370. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]CreateEvent2 failed status %x\n", Status);
  371. goto Exit;
  372. }
  373. //
  374. // Initialize the prefix table library.
  375. //
  376. DfsPrefixTableInit();
  377. Status = DfsCreateRequiredDfsKeys();
  378. //
  379. // Create a site support class that lets us look up the server-site
  380. // information of servers that configured in our metadata.
  381. //
  382. DfsServerGlobalData.pServerSiteSupport = DfsSiteSupport::DfsCreateSiteSupport(&Status);
  383. if(DfsServerGlobalData.pServerSiteSupport == NULL)
  384. {
  385. DfsLogDfsEvent(DFS_ERROR_SITESUPPOR_FAILED, 0, NULL, Status);
  386. goto Exit;
  387. }
  388. DfsServerGlobalData.CacheFlushInterval = CACHE_FLUSH_INTERVAL;
  389. DfsGetStaticGlobalRegistrySettings();
  390. DfsGetGlobalRegistrySettings();
  391. Status = DfsRootSynchronizeInit();
  392. if(Status != ERROR_SUCCESS)
  393. {
  394. DfsLogDfsEvent(DFS_ERROR_ROOTSYNCINIT_FAILED, 0, NULL, Status);
  395. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Initialize root synchronization status %x\n", Status);
  396. goto Exit;
  397. }
  398. //
  399. // Now initialize the computer info, so that this server knows
  400. // the netbios name, domain name and dns name of this machine.
  401. //
  402. Status = DfsInitializeComputerInfo();
  403. if(Status != ERROR_SUCCESS)
  404. {
  405. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Initialize computer info status %x\n", Status);
  406. DfsLogDfsEvent(DFS_ERROR_COMPUTERINFO_FAILED, 0, NULL, Status);
  407. goto Exit;
  408. }
  409. Status = DfsClusterInit( &DfsServerGlobalData.IsCluster );
  410. if (Status != ERROR_SUCCESS)
  411. {
  412. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Dfs Cluster Init Status %x IsCluster %d\n",
  413. Status, DfsServerGlobalData.IsCluster);
  414. DfsLogDfsEvent(DFS_ERROR_CLUSTERINFO_FAILED, 0, NULL, Status);
  415. goto Exit;
  416. }
  417. Status = DfsDcInit( &DfsServerGlobalData.IsDc);
  418. if (Status != ERROR_SUCCESS)
  419. {
  420. DfsLogDfsEvent(DFS_ERROR_DCINFO_FAILED, 0, NULL, Status);
  421. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Dfs DC Init Status %x, IsDC %d\n",
  422. Status, DfsServerGlobalData.IsDc);
  423. goto Exit;
  424. }
  425. //
  426. // We always create the ISTGHandleSupport instance, but the actual Bind call to the Ds won't
  427. // happen until we need it. This is because at this point we just don't know if any of the roots
  428. // has site-costing enabled or not.
  429. //
  430. Status = DfsISTGHandleSupport::DfsCreateISTGHandleSupport( &DfsServerGlobalData.pISTGHandleSupport );
  431. if (Status != ERROR_SUCCESS)
  432. {
  433. DfsLogDfsEvent(DFS_ERROR_DCINFO_FAILED, 0, NULL, Status); // xxx dfsdev: add new error
  434. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Dfs ISTGHandle creation Status %x\n",
  435. Status);
  436. goto Exit;
  437. }
  438. Status = DfsInitializePrefixTable( &DfsServerGlobalData.pDirectoryPrefixTable,
  439. FALSE,
  440. NULL );
  441. if ( Status != ERROR_SUCCESS )
  442. {
  443. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Initialize directory prefix table Status %x\n", Status);
  444. DfsLogDfsEvent(DFS_ERROR_PREFIXTABLE_FAILED, 0, NULL, Status);
  445. goto Exit;
  446. }
  447. DfsServerGlobalData.pRootReferralTable = NULL;
  448. if (DfsServerGlobalData.IsDc == TRUE)
  449. {
  450. Status = DfsInitializePrefixTable( &DfsServerGlobalData.pRootReferralTable,
  451. FALSE,
  452. NULL );
  453. if ( Status != ERROR_SUCCESS )
  454. {
  455. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Initialize Root Referral table Status %x\n", Status);
  456. DfsLogDfsEvent(DFS_ERROR_PREFIXTABLE_FAILED, 0, NULL, Status);
  457. return Status;
  458. }
  459. }
  460. //
  461. // If the flags indicate that we are handling all known local
  462. // namespace on this machine, add an empty string to the handled
  463. // namespace list.
  464. //
  465. if (Flags & DFS_LOCAL_NAMESPACE)
  466. {
  467. Status = DfsAddHandledNamespace(L"", TRUE);
  468. if (Status != ERROR_SUCCESS)
  469. {
  470. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsAddHandledNamespace Status %x\n", Status);
  471. DfsLogDfsEvent(DFS_ERROR_HANDLENAMESPACE_FAILED, 0, NULL, Status);
  472. goto Exit;
  473. }
  474. }
  475. //
  476. // Now register all the stores.
  477. //
  478. Status = DfsRegisterStores();
  479. if (Status != ERROR_SUCCESS)
  480. {
  481. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsRegisterStores Status %x\n", Status);
  482. DfsLogDfsEvent(DFS_ERROR_REGISTERSTORE_FAILED, 0, NULL, Status);
  483. goto Exit;
  484. }
  485. //
  486. // Create our sitesupport thread.
  487. //
  488. DWORD Tid;
  489. DfsServerGlobalData.SiteSupportThreadHandle = CreateThread (
  490. NULL,
  491. 0,
  492. DfsSiteSupportThread,
  493. 0,
  494. CREATE_SUSPENDED,
  495. &Tid);
  496. if (DfsServerGlobalData.SiteSupportThreadHandle != NULL)
  497. {
  498. DFS_TRACE_HIGH(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Created DfsSiteSupportThread (%d) Tid\n", Tid);
  499. }
  500. else
  501. {
  502. Status = GetLastError();
  503. DFS_TRACE_HIGH(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Failed DfsSiteSupportThread creation, Status %x\n", Status);
  504. DfsLogDfsEvent(DFS_ERROR_THREADINIT_FAILED, 0, NULL, Status);
  505. goto Exit;
  506. }
  507. //
  508. // Create our scavenge thread.
  509. //
  510. HANDLE THandle;
  511. THandle = CreateThread (
  512. NULL,
  513. 0,
  514. DfsWorkerThread,
  515. 0,
  516. 0,
  517. &Tid);
  518. if (THandle != NULL)
  519. {
  520. CloseHandle(THandle);
  521. DFS_TRACE_HIGH(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Created Scavenge Thread (%d) Tid\n", Tid);
  522. }
  523. else
  524. {
  525. Status = GetLastError();
  526. DFS_TRACE_HIGH(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Failed Scavenge Thread creation, Status %x\n", Status);
  527. CloseHandle(DfsServerGlobalData.SiteSupportThreadHandle);
  528. DfsServerGlobalData.SiteSupportThreadHandle = NULL;
  529. goto Exit;
  530. }
  531. Status = DfsInitializeReflectionEngine();
  532. if(Status != ERROR_SUCCESS)
  533. {
  534. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Initialize Reflection Engine, Status %x\n", Status);
  535. DfsLogDfsEvent(DFS_ERROR_REFLECTIONENGINE_FAILED, 0, NULL, Status);
  536. goto Exit;
  537. }
  538. Exit:
  539. if(Status != ERROR_SUCCESS)
  540. {
  541. DfsServerGlobalData.ServiceState = SERVICE_STOPPED;
  542. }
  543. return Status;
  544. }
  545. DFSSTATUS
  546. DfsServerStop(
  547. ULONG Flags )
  548. {
  549. UNREFERENCED_PARAMETER(Flags);
  550. DFSSTATUS Status = ERROR_SUCCESS;
  551. DfsServerGlobalData.bIsShuttingDown = TRUE;
  552. if(DfsServerGlobalData.ServiceState == SERVICE_RUNNING)
  553. {
  554. DfsServerGlobalData.ServiceState = SERVICE_STOP_PENDING;
  555. if(DfsServerGlobalData.ShutdownHandle)
  556. {
  557. SetEvent(DfsServerGlobalData.ShutdownHandle);
  558. }
  559. Status = DfsTerminateReflectionEngine();
  560. if(DfsServerGlobalData.ShutdownHandle)
  561. {
  562. CloseHandle(DfsServerGlobalData.ShutdownHandle);
  563. DfsServerGlobalData.ShutdownHandle = NULL;
  564. }
  565. DfsServerGlobalData.ServiceState = SERVICE_STOPPED;
  566. }
  567. return Status;
  568. }
  569. //+-------------------------------------------------------------------------
  570. //
  571. // Function: DfsServerLibraryInitialize
  572. //
  573. // Arguments: Flags - the server flags
  574. // DfsName - server name
  575. //
  576. // Returns: Status
  577. // ERROR_SUCCESS on success
  578. // ERROR status code otherwise
  579. //
  580. //
  581. // Description: This performs a trimmed down DfsServerInitialize
  582. // for clients who want to bypass the server and access
  583. // the domain dfs information directly.
  584. //
  585. //--------------------------------------------------------------------------
  586. DFSSTATUS
  587. DfsServerLibraryInitialize(
  588. ULONG Flags )
  589. {
  590. DFSSTATUS Status = ERROR_SUCCESS;
  591. BOOL fCritInit = FALSE;
  592. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL;
  593. ZeroMemory(&DfsServerGlobalData, sizeof(DfsServerGlobalData));
  594. DfsServerGlobalData.pRegisteredStores = NULL;
  595. DfsServerGlobalData.Flags = Flags;
  596. DfsServerGlobalData.bIsShuttingDown = FALSE;
  597. fCritInit = InitializeCriticalSectionAndSpinCount( &DfsServerGlobalData.DataLock, DFS_CRIT_SPIN_COUNT);
  598. if(!fCritInit)
  599. {
  600. Status = GetLastError();
  601. }
  602. //
  603. // Now register all the stores. This essentially constructs the respective
  604. // store class objects.
  605. //
  606. if (Status == ERROR_SUCCESS) {
  607. Status = DfsRegisterStores();
  608. DFS_TRACE_ERROR_HIGH(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsRegisterStores Status %x\n", Status);
  609. }
  610. DfsServerGlobalData.LdapTimeOut = DFS_LDAP_TIMEOUT;
  611. return Status;
  612. }
  613. //+-------------------------------------------------------------------------
  614. //
  615. // Function: DfsRegisterStores
  616. //
  617. // Arguments: NONE
  618. //
  619. // Returns: Status
  620. // ERROR_SUCCESS on success
  621. // ERROR status code otherwise
  622. //
  623. //
  624. // Description: This routine registers the different stores
  625. // that the referral library implements.
  626. //
  627. //--------------------------------------------------------------------------
  628. DFSSTATUS
  629. DfsRegisterStores(
  630. VOID )
  631. {
  632. DFSSTATUS Status = ERROR_SUCCESS;
  633. if(!DfsIsMachineWorkstation())
  634. {
  635. if (Status == ERROR_SUCCESS)
  636. DFS_REGISTER_STORE(ADBlob, Status);
  637. }
  638. if (Status == ERROR_SUCCESS)
  639. DFS_REGISTER_STORE(Registry, Status);
  640. return Status;
  641. }
  642. //+-------------------------------------------------------------------------
  643. //
  644. // Function: DfsAddHandleNamespace
  645. //
  646. // Arguments: Name - namespace to add
  647. //
  648. // Returns: Status
  649. // ERROR_SUCCESS on success
  650. // ERROR status code otherwise
  651. //
  652. //
  653. // Description: This routine registers the namespace, so that we handle
  654. // referrals to that namespace. We also migrate the DFS data
  655. // in the registry for the multiple root support. This
  656. // happens only if the client wants to migrate DFS.
  657. //
  658. //--------------------------------------------------------------------------
  659. DFSSTATUS
  660. DfsAddHandledNamespace(
  661. LPWSTR Name,
  662. BOOLEAN Migrate )
  663. {
  664. DFSSTATUS Status = ERROR_SUCCESS;
  665. LPWSTR NewName = NULL;
  666. //
  667. // allocate a new name, and copy the passed in string.
  668. //
  669. NewName = new WCHAR[wcslen(Name) + 1];
  670. if (NewName == NULL)
  671. {
  672. Status = ERROR_NOT_ENOUGH_MEMORY;
  673. }
  674. if (Status == ERROR_SUCCESS) {
  675. wcscpy( NewName, Name );
  676. //
  677. // always migrate the dfs to the new location.
  678. //
  679. if (Migrate == TRUE)
  680. {
  681. extern DFSSTATUS MigrateDfs(LPWSTR MachineName);
  682. Status = MigrateDfs(NewName);
  683. }
  684. //
  685. // Now register the passed in name.
  686. //
  687. if (Status == ERROR_SUCCESS)
  688. {
  689. Status = DfsRegisterName( NewName );
  690. //
  691. // 565500, delete allocation on errors.
  692. //
  693. if (Status != ERROR_SUCCESS)
  694. {
  695. delete [] NewName;
  696. }
  697. if (Status == ERROR_DUP_NAME)
  698. {
  699. Status = ERROR_SUCCESS;
  700. }
  701. }
  702. }
  703. else {
  704. Status = ERROR_NOT_ENOUGH_MEMORY;
  705. }
  706. return Status;
  707. }
  708. //+-------------------------------------------------------------------------
  709. //
  710. // Function: DfsRegisterName
  711. //
  712. // Arguments: Name - name to register
  713. //
  714. // Returns: Status
  715. // ERROR_SUCCESS on success
  716. // ERROR_DUP_NAME if name is already registered.
  717. // ERROR status code otherwise
  718. //
  719. //
  720. // Description: This routine registers the namespace, if it is not already
  721. // registered.
  722. //
  723. //--------------------------------------------------------------------------
  724. DFSSTATUS
  725. DfsRegisterName(
  726. LPWSTR Name )
  727. {
  728. DFSSTATUS Status = ERROR_SUCCESS;
  729. ULONG i = 0;
  730. if (DfsServerGlobalData.NumberOfNamespaces > MAX_DFS_NAMESPACES)
  731. {
  732. Status = ERROR_INVALID_PARAMETER;
  733. }
  734. else
  735. {
  736. for (i = 0; i < DfsServerGlobalData.NumberOfNamespaces; i++)
  737. {
  738. if (_wcsicmp( Name,
  739. DfsServerGlobalData.HandledNamespace[i] ) == 0)
  740. {
  741. Status = ERROR_DUP_NAME;
  742. break;
  743. }
  744. }
  745. if (Status == ERROR_SUCCESS)
  746. {
  747. DfsServerGlobalData.HandledNamespace[DfsServerGlobalData.NumberOfNamespaces++] = Name;
  748. }
  749. }
  750. return Status;
  751. }
  752. //+-------------------------------------------------------------------------
  753. //
  754. // Function: DfsHandleNamespaces()
  755. //
  756. // Arguments: None
  757. //
  758. // Returns: None
  759. //
  760. // Description: This routine runs through all the registered names, and
  761. // call the recognize method on each name.
  762. //
  763. //--------------------------------------------------------------------------
  764. DFSSTATUS
  765. DfsHandleNamespaces()
  766. {
  767. ULONG i = 0;
  768. DFSSTATUS Status = ERROR_SUCCESS;
  769. DFSSTATUS RetStatus = ERROR_SUCCESS;
  770. for (i = 0; i < DfsServerGlobalData.NumberOfNamespaces; i++) {
  771. DFSLOG("Calling recognize on %wS\n",
  772. DfsServerGlobalData.HandledNamespace[ i ] );
  773. Status = DfsRecognize( DfsServerGlobalData.HandledNamespace[ i ] );
  774. //
  775. // xxx This error isn't the original error; it's typically
  776. // something like ERROR_NOT_READY currently. We need to change that
  777. // in the future.
  778. //
  779. if (Status != ERROR_SUCCESS)
  780. {
  781. RetStatus = Status;
  782. }
  783. if (DfsIsShuttingDown())
  784. {
  785. break;
  786. }
  787. }
  788. // If we got an error at any point, return that.
  789. return RetStatus;
  790. }
  791. //+-------------------------------------------------------------------------
  792. //
  793. // Function: DfsRecognize
  794. //
  795. // Arguments: Namespace
  796. //
  797. // Returns: None
  798. //
  799. // Description: This routine passes the name to each registered store
  800. // by calling the StoreRecognize method. The store will
  801. // decide whether any roots exist on namespace, and add
  802. // the discovered roots to a list maintained by the store.
  803. //
  804. //--------------------------------------------------------------------------
  805. DFSSTATUS
  806. DfsRecognize(
  807. LPWSTR Name)
  808. {
  809. DfsStore *pStore = NULL;
  810. LPWSTR UseName = NULL;
  811. DFSSTATUS Status = ERROR_SUCCESS;
  812. DFSSTATUS RetStatus = ERROR_SUCCESS;
  813. //
  814. // If the string is empty, we are dealing with the local case.
  815. // Pass a null pointer, since the underlying routines expect a
  816. // a valid machine, or a null pointer to represent the local case.
  817. //
  818. if (IsEmptyString(Name) == FALSE)
  819. {
  820. UseName = Name;
  821. }
  822. //
  823. // Call the store recognizer of each registered store.
  824. //
  825. for (pStore = DfsServerGlobalData.pRegisteredStores;
  826. pStore != NULL;
  827. pStore = pStore->pNextRegisteredStore) {
  828. DFSLOG("Calling StoreRecognizer on %wS for store %p\n",
  829. Name, pStore );
  830. Status = pStore->StoreRecognizer( UseName );
  831. //
  832. // If any of the roots failed to load, typically because
  833. // the DC was unavailable, then we need to make a note of
  834. // that and retry later.
  835. //
  836. if (Status != ERROR_SUCCESS)
  837. {
  838. RetStatus = Status;
  839. }
  840. if (DfsIsShuttingDown())
  841. {
  842. break;
  843. }
  844. }
  845. return RetStatus;
  846. }
  847. //+-------------------------------------------------------------------------
  848. //
  849. // Function: DfsRecognize
  850. //
  851. // Arguments: Namespace
  852. // LogicalShare
  853. //
  854. // Returns: SUCCESS if we managed to create a root folder, ERROR otherwise.
  855. //
  856. // Description: This routine passes the name to each registered store
  857. // by calling the StoreRecognize method. The store will
  858. // decide whether the given root exist on that namespace, and adds
  859. // the discovered root to a list maintained by the store.
  860. //
  861. //--------------------------------------------------------------------------
  862. DFSSTATUS
  863. DfsRecognize(
  864. LPWSTR Name,
  865. PUNICODE_STRING pLogicalShare)
  866. {
  867. DfsStore *pStore = NULL;
  868. DFSSTATUS Status = ERROR_NOT_FOUND;
  869. if (IsEmptyString(Name) || IsEmptyString(pLogicalShare->Buffer))
  870. {
  871. return ERROR_INVALID_PARAMETER;
  872. }
  873. //
  874. // Call the store recognizer of each registered store.
  875. //
  876. for (pStore = DfsServerGlobalData.pRegisteredStores;
  877. pStore != NULL;
  878. pStore = pStore->pNextRegisteredStore) {
  879. DFSLOG("Calling StoreRecognizer (remote) on %wS for store %p\n",
  880. Name, pStore );
  881. Status = pStore->StoreRecognizer( Name, pLogicalShare );
  882. //
  883. // A store has successfully recognized a root for this <name,share>.
  884. // We are done.
  885. //
  886. if (Status == ERROR_SUCCESS)
  887. break;
  888. }
  889. DFS_TRACE_LOW(REFERRAL_SERVER, "StoreRecognizer (remote) Status %x\n", Status);
  890. return Status;
  891. }
  892. VOID
  893. DfsSynchronize()
  894. {
  895. DfsStore *pStore = NULL;
  896. //
  897. // Call the store recognizer of each registered store.
  898. //
  899. for (pStore = DfsServerGlobalData.pRegisteredStores;
  900. pStore != NULL;
  901. pStore = pStore->pNextRegisteredStore) {
  902. DFSLOG("Calling StoreSynchronizer for store %p\n", pStore );
  903. pStore->StoreSynchronizer();
  904. if (DfsIsShuttingDown())
  905. {
  906. break;
  907. }
  908. }
  909. return NOTHING;
  910. }
  911. //+-------------------------------------------------------------------------
  912. //
  913. // Function: DfsDumpStatistics
  914. //
  915. // Arguments: NONE
  916. //
  917. // Returns: None
  918. //
  919. //--------------------------------------------------------------------------
  920. VOID
  921. DfsDumpStatistics( )
  922. {
  923. DfsStore *pStore = NULL;
  924. //
  925. // Call the store recognizer of each registered store.
  926. //
  927. for (pStore = DfsServerGlobalData.pRegisteredStores;
  928. pStore != NULL;
  929. pStore = pStore->pNextRegisteredStore) {
  930. pStore->DumpStatistics();
  931. if (DfsIsShuttingDown())
  932. {
  933. break;
  934. }
  935. }
  936. return NOTHING;
  937. }
  938. void
  939. DfsinitializeWorkerThreadInfo(void)
  940. {
  941. //
  942. // Iterate through all the stores and 'recognize' their roots.
  943. //
  944. DfsHandleNamespaces();
  945. DfsLogDfsEvent(DFS_INFO_FINISH_BUILDING_NAMESPACE, 0, NULL, 0);
  946. StartPreloadingServerSiteData();
  947. DfsServerGlobalData.IsStartupProcessingDone = TRUE;
  948. DfsLogDfsEvent(DFS_INFO_FINISH_INIT, 0, NULL, 0);
  949. ResumeThread(DfsServerGlobalData.SiteSupportThreadHandle);
  950. CloseHandle(DfsServerGlobalData.SiteSupportThreadHandle);
  951. DfsServerGlobalData.SiteSupportThreadHandle = NULL;
  952. DfsServerGlobalData.ServiceState = SERVICE_RUNNING;
  953. }
  954. void
  955. DfsProcessAgedReferrelList(void)
  956. {
  957. DfsFolderReferralData *pRefData = NULL;
  958. DfsFolderReferralData *pRefList = NULL;
  959. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread handling all namespaces\n");
  960. DfsHandleNamespaces();
  961. DFS_TRACE_LOW(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread done syncing\n");
  962. DfsDumpStatistics();
  963. //
  964. // now run through the loaded list and pick up aged referrals.
  965. // and unload them.
  966. //
  967. DfsGetAgedReferralList( &pRefList );
  968. while (pRefList != NULL)
  969. {
  970. DfsFolder *pFolder;
  971. pRefData = pRefList;
  972. if (pRefData->pNextLoaded == pRefData)
  973. {
  974. pRefList = NULL;
  975. }
  976. else
  977. {
  978. pRefList = pRefData->pNextLoaded;
  979. pRefData->pNextLoaded->pPrevLoaded = pRefData->pPrevLoaded;
  980. pRefData->pPrevLoaded->pNextLoaded = pRefData->pNextLoaded;
  981. }
  982. pFolder = pRefData->GetOwningFolder();
  983. if (pFolder != NULL)
  984. {
  985. pFolder->RemoveReferralData( pRefData );
  986. }
  987. pRefData->ReleaseReference();
  988. } // while
  989. }
  990. //+-------------------------------------------------------------------------
  991. //
  992. // Function: DfsWorkedThread
  993. //
  994. // Arguments: TData
  995. //
  996. // Returns: DWORD
  997. //
  998. // Description: This is the scavenge thread. It sits in a loop forever,
  999. // waking up periodically to remove the aged referral data
  1000. // that had been cached during referral requests.
  1001. // Periodically, we call HAndleNamespaces so that the
  1002. // namespace we know of is kept in sync with the actual
  1003. // data in the respective metadata stores.
  1004. //
  1005. //--------------------------------------------------------------------------
  1006. DWORD ScavengeTime;
  1007. #define DFS_NAMESPACE_RETRY_STARTING_INTERVAL (15 * 1000);
  1008. #define DFS_NAMESPACE_MAX_RETRIES 5
  1009. DWORD
  1010. DfsWorkerThread(LPVOID TData)
  1011. {
  1012. DfsFolderReferralData *pRefData = NULL, *pRefList = NULL;
  1013. HRESULT hr = S_OK;
  1014. SYSTEMTIME StartupSystemTime;
  1015. FILETIME ReparseScavengeTime;
  1016. BOOLEAN DoReparseScavenge = TRUE;
  1017. DFSSTATUS RecognizeStatus = ERROR_SUCCESS;
  1018. DWORD RetryScavengeTimeLeft = 0;
  1019. ULONG InitialRetry = DFS_NAMESPACE_MAX_RETRIES;
  1020. static LoopCnt = 0;
  1021. ScavengeTime = DFS_NAMESPACE_RETRY_STARTING_INTERVAL; // 15 seconds
  1022. UNREFERENCED_PARAMETER(TData);
  1023. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  1024. //
  1025. // As long as reparse points are created after this time stamp, we are fine.
  1026. //
  1027. GetSystemTime( &StartupSystemTime );
  1028. if (!SystemTimeToFileTime( &StartupSystemTime, &ReparseScavengeTime ))
  1029. {
  1030. DoReparseScavenge = FALSE;
  1031. }
  1032. //
  1033. // Iterate through all the stores and 'recognize' their roots.
  1034. // If any of them failed to load we retry a set number of times below.
  1035. //
  1036. RecognizeStatus = DfsHandleNamespaces();
  1037. DfsLogDfsEvent(DFS_INFO_FINISH_BUILDING_NAMESPACE, 0, NULL, 0);
  1038. StartPreloadingServerSiteData();
  1039. DfsServerGlobalData.IsStartupProcessingDone = TRUE;
  1040. DfsLogDfsEvent(DFS_INFO_FINISH_INIT, 0, NULL, 0);
  1041. ResumeThread(DfsServerGlobalData.SiteSupportThreadHandle);
  1042. CloseHandle(DfsServerGlobalData.SiteSupportThreadHandle);
  1043. DfsServerGlobalData.SiteSupportThreadHandle = NULL;
  1044. DfsServerGlobalData.ServiceState = SERVICE_RUNNING;
  1045. // Retry failed namespaces.
  1046. while ( (RecognizeStatus != ERROR_SUCCESS) &&
  1047. (InitialRetry-- > 0) )
  1048. {
  1049. WaitForSingleObject(DfsServerGlobalData.ShutdownHandle, ScavengeTime);
  1050. if (DfsIsShuttingDown())
  1051. {
  1052. goto Exit;
  1053. }
  1054. DFS_TRACE_HIGH( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread retrying failed namespaces after %d secs\n",
  1055. ScavengeTime/1000);
  1056. RecognizeStatus = DfsHandleNamespaces();
  1057. DFS_TRACE_HIGH(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread done retrying, Status 0x%x\n", RecognizeStatus);
  1058. ScavengeTime *= 2;
  1059. }
  1060. // Revert to the 'normal' sleep time (~1hr)
  1061. ScavengeTime = SCAVENGE_TIME;
  1062. while (TRUE) {
  1063. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread sleeping for %d\n", ScavengeTime);
  1064. WaitForSingleObject(DfsServerGlobalData.ShutdownHandle, ScavengeTime);
  1065. if (DfsIsShuttingDown())
  1066. {
  1067. goto Exit;
  1068. }
  1069. LoopCnt++;
  1070. // DfsDev: need to define a better mechanism as to how often
  1071. // this gets to run.
  1072. //
  1073. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread handling all namespaces\n");
  1074. RecognizeStatus = DfsHandleNamespaces();
  1075. DFS_TRACE_LOW(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Worker thread done syncing, status 0x%x\n", RecognizeStatus);
  1076. DfsDumpStatistics();
  1077. //
  1078. // now run through the loaded list and pick up aged referrals.
  1079. // and unload them.
  1080. //
  1081. DfsGetAgedReferralList( &pRefList );
  1082. while (pRefList != NULL)
  1083. {
  1084. DfsFolder *pFolder;
  1085. pRefData = pRefList;
  1086. if (pRefData->pNextLoaded == pRefData)
  1087. {
  1088. pRefList = NULL;
  1089. }
  1090. else
  1091. {
  1092. pRefList = pRefData->pNextLoaded;
  1093. pRefData->pNextLoaded->pPrevLoaded = pRefData->pPrevLoaded;
  1094. pRefData->pPrevLoaded->pNextLoaded = pRefData->pNextLoaded;
  1095. }
  1096. pFolder = pRefData->GetOwningFolder();
  1097. if (pFolder != NULL)
  1098. {
  1099. pFolder->RemoveReferralData( pRefData );
  1100. }
  1101. pRefData->ReleaseReference();
  1102. } // while
  1103. //
  1104. // If we haven't cleaned up orphaned reparse points, do that now.
  1105. // Note that this doesn't run until SCAVEGE_TIME seconds after
  1106. // the service has started.
  1107. //
  1108. if (DoReparseScavenge)
  1109. {
  1110. // We have no choice but to ignore errors
  1111. (VOID)DfsRemoveOrphanedReparsePoints( ReparseScavengeTime );
  1112. // This gets to run only once, irrespective of any errors.
  1113. DoReparseScavenge = FALSE;
  1114. }
  1115. }
  1116. Exit:
  1117. CoUninitialize();
  1118. return 0;
  1119. }
  1120. DWORD
  1121. DfsSiteSupportThread(LPVOID TData)
  1122. {
  1123. DWORD dw = 0;
  1124. UNREFERENCED_PARAMETER(TData);
  1125. while (TRUE)
  1126. {
  1127. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]DfsSiteSupportThread sleeping for %d\n",
  1128. DfsServerGlobalData.SiteSupportThreadInterval);
  1129. dw = WaitForSingleObject(DfsServerGlobalData.ShutdownHandle,
  1130. DfsServerGlobalData.SiteSupportThreadInterval);
  1131. if(WAIT_TIMEOUT == dw)
  1132. {
  1133. DfsServerGlobalData.pSiteNameSupport->InvalidateAgedSites();
  1134. DfsServerGlobalData.pClientSiteSupport->RefreshSiteData();
  1135. StartPreloadingServerSiteData();
  1136. }
  1137. if (DfsIsShuttingDown())
  1138. {
  1139. break;
  1140. }
  1141. }
  1142. return 0;
  1143. }
  1144. //+-------------------------------------------------------------------------
  1145. //
  1146. // Function: DfsAddReferralDataToloadedList
  1147. //
  1148. // Arguments: pRefData
  1149. //
  1150. // Returns: Nothing
  1151. //
  1152. // Description: Given the referral data that was laoded, we add it
  1153. // to a loaded list, first acquiring a reference to
  1154. // it. This is effectively to keep track of the cached
  1155. // referral data in the folders.
  1156. //
  1157. // To scavenge the cache, we maintain this list, and we run
  1158. // through this list periodically freeing up aged data.
  1159. //
  1160. //--------------------------------------------------------------------------
  1161. VOID
  1162. DfsAddReferralDataToLoadedList(
  1163. DfsFolderReferralData *pRefData )
  1164. {
  1165. //
  1166. // we are going to save a pointer to the referral data.
  1167. // Acquire a reference on it
  1168. //
  1169. pRefData->AcquireReference();
  1170. //
  1171. // Now get a lock on the list, and add the ref data to the list
  1172. //
  1173. ACQUIRE_LOADED_LIST_LOCK();
  1174. if (DfsServerGlobalData.LoadedList == NULL) {
  1175. DfsServerGlobalData.LoadedList = pRefData;
  1176. pRefData->pPrevLoaded = pRefData->pNextLoaded = pRefData;
  1177. } else {
  1178. pRefData->pNextLoaded = DfsServerGlobalData.LoadedList;
  1179. pRefData->pPrevLoaded = DfsServerGlobalData.LoadedList->pPrevLoaded;
  1180. DfsServerGlobalData.LoadedList->pPrevLoaded->pNextLoaded = pRefData;
  1181. DfsServerGlobalData.LoadedList->pPrevLoaded = pRefData;
  1182. }
  1183. //
  1184. // we are done, release the list lock.
  1185. //
  1186. RELEASE_LOADED_LIST_LOCK();
  1187. }
  1188. //+-------------------------------------------------------------------------
  1189. //
  1190. // Function: DfsGetAgedReferralList
  1191. //
  1192. // Arguments: ppReferralData
  1193. //
  1194. // Returns: Nothing
  1195. //
  1196. // Description: This routine removes the list and hands it back to the
  1197. // caller. It sets the list as empty.
  1198. // The caller is responsible for freeing up the list
  1199. //
  1200. //--------------------------------------------------------------------------
  1201. VOID
  1202. DfsGetAgedReferralList(
  1203. DfsFolderReferralData **ppReferralData )
  1204. {
  1205. //
  1206. // this needs to be optimized to return a subset or LRU entries.
  1207. //
  1208. ACQUIRE_LOADED_LIST_LOCK();
  1209. *ppReferralData = DfsServerGlobalData.LoadedList;
  1210. DfsServerGlobalData.LoadedList = NULL;
  1211. RELEASE_LOADED_LIST_LOCK();
  1212. }
  1213. //+-------------------------------------------------------------------------
  1214. //
  1215. // Function: DfsGetServerInfo
  1216. //
  1217. // Arguments: pServer, ppInfo
  1218. //
  1219. // Returns: Status
  1220. //
  1221. // Description: This routine takes a server name and returns the
  1222. // structure that holds the site information for that server
  1223. //
  1224. // A referenced pointer is returned and the caller is
  1225. // required to release the reference when done.
  1226. //
  1227. //--------------------------------------------------------------------------
  1228. DFSSTATUS
  1229. DfsGetServerInfo (
  1230. PUNICODE_STRING pServer,
  1231. DfsServerSiteInfo **ppInfo,
  1232. BOOLEAN * CacheHit,
  1233. BOOLEAN SyncThread )
  1234. {
  1235. return DfsServerGlobalData.pServerSiteSupport->GetServerSiteInfo(pServer, ppInfo, CacheHit, SyncThread );
  1236. }
  1237. //+-------------------------------------------------------------------------
  1238. //
  1239. // Function: DfsReleaseServerInfo
  1240. //
  1241. // Arguments: pInfo
  1242. //
  1243. // Returns: Nothing
  1244. //
  1245. // Description: This routine releases a server info that was earlier
  1246. // got by calling GetServerInfo
  1247. //
  1248. //--------------------------------------------------------------------------
  1249. DFSSTATUS
  1250. DfsReleaseServerInfo (
  1251. DfsServerSiteInfo *pInfo)
  1252. {
  1253. return DfsServerGlobalData.pServerSiteSupport->ReleaseServerSiteInfo(pInfo);
  1254. }
  1255. //+-------------------------------------------------------------------------
  1256. //
  1257. // Function: DfsGetDefaultSite
  1258. //
  1259. // Arguments: Nothing
  1260. //
  1261. // Returns: DfsSite
  1262. //
  1263. // Description: This routine returns a referenced pointer to the default DfsSite.
  1264. // The site name of this site is empty. Once done, caller is supposed to call
  1265. // ReleaseReference() on the DfsSite returned here.
  1266. //--------------------------------------------------------------------------
  1267. DfsSite *
  1268. DfsGetDefaultSite( VOID )
  1269. {
  1270. DfsServerGlobalData.pDefaultSite->AcquireReference();
  1271. return DfsServerGlobalData.pDefaultSite;
  1272. }
  1273. //+-------------------------------------------------------------------------
  1274. //
  1275. // Function: DfsInitializeComputerInfo
  1276. //
  1277. // Arguments: NOTHING
  1278. //
  1279. // Returns: Status
  1280. //
  1281. // Description: This routine initializes the computer info, which contains the domain name
  1282. // of this computer, the netbios name and dns names of this computer.
  1283. //
  1284. //--------------------------------------------------------------------------
  1285. DFSSTATUS
  1286. DfsInitializeComputerInfo()
  1287. {
  1288. #define COMPUTER_NAME_BUFFER_SIZE 2048
  1289. LONG NameBufferCchLength;
  1290. LPWSTR NameBuffer;
  1291. DFSSTATUS Status = ERROR_SUCCESS ;
  1292. NameBufferCchLength = COMPUTER_NAME_BUFFER_SIZE;
  1293. NameBuffer = new WCHAR [ NameBufferCchLength ];
  1294. if (NameBuffer != NULL)
  1295. {
  1296. INITIALIZE_COMPUTER_INFO( ComputerNameNetBIOS, NameBuffer, NameBufferCchLength, Status );
  1297. INITIALIZE_COMPUTER_INFO( ComputerNameDnsFullyQualified, NameBuffer, NameBufferCchLength, Status );
  1298. INITIALIZE_COMPUTER_INFO( ComputerNameDnsDomain, NameBuffer, NameBufferCchLength, Status );
  1299. delete [] NameBuffer;
  1300. }
  1301. else {
  1302. Status = ERROR_NOT_ENOUGH_MEMORY;
  1303. }
  1304. return Status;
  1305. }
  1306. DFSSTATUS
  1307. DfsCreateRequiredOldDfsKeys(void)
  1308. {
  1309. DFSSTATUS Status = ERROR_SUCCESS;
  1310. HKEY RootKey, DfsLocationKey, DfsVolumesKey;
  1311. Status = RegConnectRegistry( NULL,
  1312. HKEY_LOCAL_MACHINE,
  1313. &RootKey );
  1314. if(Status == ERROR_SUCCESS)
  1315. {
  1316. Status = RegCreateKeyEx( RootKey, // the parent key
  1317. DfsRegistryHostLocation, // the key we are creating.
  1318. 0,
  1319. L"",
  1320. REG_OPTION_NON_VOLATILE,
  1321. KEY_READ | KEY_WRITE,
  1322. NULL,
  1323. &DfsLocationKey,
  1324. NULL );
  1325. RegCloseKey(RootKey);
  1326. if (Status == ERROR_SUCCESS)
  1327. {
  1328. Status = RegCreateKeyEx( DfsLocationKey, // the parent key
  1329. DfsVolumesLocation, // the key we are creating.
  1330. 0,
  1331. L"",
  1332. REG_OPTION_NON_VOLATILE,
  1333. KEY_READ | KEY_WRITE,
  1334. NULL,
  1335. &DfsVolumesKey,
  1336. NULL );
  1337. if (Status == ERROR_SUCCESS)
  1338. {
  1339. RegCloseKey(DfsVolumesKey);
  1340. }
  1341. RegCloseKey(DfsLocationKey);
  1342. }
  1343. }
  1344. return Status;
  1345. }
  1346. DFSSTATUS
  1347. DfsCreateRequiredDfsKeys(void)
  1348. {
  1349. DFSSTATUS Status = ERROR_SUCCESS;
  1350. HKEY RootKey, DfsLocationKey, DfsRootsKey, FlavorKey;
  1351. Status = DfsCreateRequiredOldDfsKeys();
  1352. if (Status != ERROR_SUCCESS)
  1353. {
  1354. return Status;
  1355. }
  1356. Status = RegConnectRegistry( NULL,
  1357. HKEY_LOCAL_MACHINE,
  1358. &RootKey );
  1359. if(Status == ERROR_SUCCESS)
  1360. {
  1361. Status = RegCreateKeyEx( RootKey, // the parent key
  1362. DfsRegistryDfsLocation, // the key we are creating.
  1363. 0,
  1364. L"",
  1365. REG_OPTION_NON_VOLATILE,
  1366. KEY_READ | KEY_WRITE,
  1367. NULL,
  1368. &DfsLocationKey,
  1369. NULL );
  1370. RegCloseKey(RootKey);
  1371. if (Status == ERROR_SUCCESS)
  1372. {
  1373. Status = RegCreateKeyEx( DfsLocationKey, // the parent key
  1374. DfsRootLocation, // the key we are creating.
  1375. 0,
  1376. L"",
  1377. REG_OPTION_NON_VOLATILE,
  1378. KEY_READ | KEY_WRITE,
  1379. NULL,
  1380. &DfsRootsKey,
  1381. NULL );
  1382. RegCloseKey(DfsLocationKey);
  1383. if (Status == ERROR_SUCCESS)
  1384. {
  1385. Status = RegCreateKeyEx( DfsRootsKey, // the parent key
  1386. DfsStandaloneChild,
  1387. 0,
  1388. L"",
  1389. REG_OPTION_NON_VOLATILE,
  1390. KEY_READ | KEY_WRITE,
  1391. NULL,
  1392. &FlavorKey,
  1393. NULL );
  1394. if (Status == ERROR_SUCCESS)
  1395. {
  1396. RegCloseKey(FlavorKey);
  1397. }
  1398. if (Status == ERROR_SUCCESS)
  1399. {
  1400. Status = RegCreateKeyEx( DfsRootsKey, // the parent key
  1401. DfsADBlobChild,
  1402. 0,
  1403. L"",
  1404. REG_OPTION_NON_VOLATILE,
  1405. KEY_READ | KEY_WRITE,
  1406. NULL,
  1407. &FlavorKey,
  1408. NULL );
  1409. }
  1410. if (Status == ERROR_SUCCESS)
  1411. {
  1412. RegCloseKey(FlavorKey);
  1413. }
  1414. RegCloseKey( DfsRootsKey );
  1415. }
  1416. }
  1417. }
  1418. return Status;
  1419. }
  1420. DFSSTATUS
  1421. DfsGetMachineName(
  1422. PUNICODE_STRING pName)
  1423. {
  1424. DFSSTATUS Status;
  1425. LPWSTR UseName;
  1426. if (DfsServerGlobalData.DfsDnsConfig == 0)
  1427. {
  1428. UseName = DfsServerGlobalData.DfsMachineInfo.StaticComputerNameNetBIOS;
  1429. }
  1430. else {
  1431. UseName = DfsServerGlobalData.DfsMachineInfo.StaticComputerNameDnsFullyQualified;
  1432. }
  1433. Status = DfsCreateUnicodeStringFromString( pName,
  1434. UseName );
  1435. return Status;
  1436. }
  1437. VOID
  1438. DfsReleaseMachineName(
  1439. PUNICODE_STRING pName )
  1440. {
  1441. DfsFreeUnicodeString( pName );
  1442. }
  1443. DFSSTATUS
  1444. DfsGetDomainName(
  1445. PUNICODE_STRING pName)
  1446. {
  1447. DFSSTATUS Status = ERROR_SUCCESS;
  1448. LPWSTR UseName = NULL;
  1449. if (DfsServerGlobalData.DfsDnsConfig == 0)
  1450. {
  1451. if (!IsEmptyString(DfsServerGlobalData.DomainNameFlat.Buffer))
  1452. {
  1453. UseName = DfsServerGlobalData.DomainNameFlat.Buffer;
  1454. }
  1455. else if (!IsEmptyString(DfsServerGlobalData.DomainNameDns.Buffer))
  1456. {
  1457. UseName = DfsServerGlobalData.DomainNameDns.Buffer;
  1458. }
  1459. else if (!IsEmptyString(DfsServerGlobalData.DfsMachineInfo.StaticComputerNameDnsDomain))
  1460. {
  1461. UseName = DfsServerGlobalData.DfsMachineInfo.StaticComputerNameDnsDomain;
  1462. }
  1463. else
  1464. {
  1465. Status = ERROR_INVALID_PARAMETER;
  1466. }
  1467. }
  1468. else
  1469. {
  1470. if (!IsEmptyString(DfsServerGlobalData.DomainNameDns.Buffer))
  1471. {
  1472. UseName = DfsServerGlobalData.DomainNameDns.Buffer;
  1473. }
  1474. else if (!IsEmptyString(DfsServerGlobalData.DfsMachineInfo.StaticComputerNameDnsDomain))
  1475. {
  1476. UseName = DfsServerGlobalData.DfsMachineInfo.StaticComputerNameDnsDomain;
  1477. }
  1478. else if (!IsEmptyString(DfsServerGlobalData.DomainNameFlat.Buffer))
  1479. {
  1480. UseName = DfsServerGlobalData.DomainNameFlat.Buffer;
  1481. }
  1482. else
  1483. {
  1484. Status = ERROR_INVALID_PARAMETER;
  1485. }
  1486. }
  1487. if (Status == ERROR_SUCCESS)
  1488. {
  1489. Status = DfsCreateUnicodeStringFromString( pName,
  1490. UseName );
  1491. }
  1492. return Status;
  1493. }
  1494. DFSSTATUS
  1495. DfsGetDnsDomainName(
  1496. PUNICODE_STRING pName)
  1497. {
  1498. DFSSTATUS Status = ERROR_SUCCESS;
  1499. LPWSTR UseName = NULL;
  1500. if (!IsEmptyString(DfsServerGlobalData.DomainNameDns.Buffer))
  1501. {
  1502. UseName = DfsServerGlobalData.DomainNameDns.Buffer;
  1503. }
  1504. else
  1505. {
  1506. Status = ERROR_NOT_FOUND;
  1507. }
  1508. if (Status == ERROR_SUCCESS)
  1509. {
  1510. Status = DfsCreateUnicodeStringFromString( pName,
  1511. UseName );
  1512. }
  1513. return Status;
  1514. }
  1515. VOID
  1516. DfsReleaseDomainName(
  1517. PUNICODE_STRING pName )
  1518. {
  1519. DfsFreeUnicodeString( pName );
  1520. }
  1521. DFSSTATUS
  1522. DfsAddKnownDirectoryPath(
  1523. PUNICODE_STRING pDirectoryName,
  1524. PUNICODE_STRING pLogicalShare )
  1525. {
  1526. DFSSTATUS Status = ERROR_SUCCESS;
  1527. NTSTATUS NtStatus = STATUS_SUCCESS;
  1528. PVOID pData = NULL;
  1529. BOOLEAN SubStringMatch = FALSE;
  1530. UNICODE_STRING RemainingName;
  1531. NtStatus = DfsPrefixTableAcquireWriteLock( DfsServerGlobalData.pDirectoryPrefixTable );
  1532. if ( NtStatus == STATUS_SUCCESS )
  1533. {
  1534. NtStatus = DfsFindUnicodePrefixLocked( DfsServerGlobalData.pDirectoryPrefixTable,
  1535. pDirectoryName,
  1536. &RemainingName,
  1537. &pData,
  1538. &SubStringMatch );
  1539. if ( (NtStatus == STATUS_SUCCESS) ||
  1540. ((NtStatus != STATUS_SUCCESS) && (SubStringMatch)) )
  1541. {
  1542. NtStatus = STATUS_OBJECT_NAME_COLLISION;
  1543. }
  1544. else
  1545. {
  1546. //
  1547. // Insert the directory and share information in our
  1548. // database.
  1549. //
  1550. NtStatus = DfsInsertInPrefixTableLocked(DfsServerGlobalData.pDirectoryPrefixTable,
  1551. pDirectoryName,
  1552. (PVOID)pLogicalShare);
  1553. }
  1554. DfsPrefixTableReleaseLock( DfsServerGlobalData.pDirectoryPrefixTable );
  1555. }
  1556. if(NtStatus != STATUS_SUCCESS)
  1557. {
  1558. Status = RtlNtStatusToDosError(NtStatus);
  1559. }
  1560. return Status;
  1561. }
  1562. DFSSTATUS
  1563. DfsRemoveKnownDirectoryPath(
  1564. PUNICODE_STRING pDirectoryName,
  1565. PUNICODE_STRING pLogicalShare)
  1566. {
  1567. DFSSTATUS Status = ERROR_SUCCESS;
  1568. NTSTATUS NtStatus = STATUS_SUCCESS;
  1569. PVOID pData = NULL;
  1570. BOOLEAN SubStringMatch = FALSE;
  1571. UNICODE_STRING RemainingName;
  1572. NtStatus = DfsPrefixTableAcquireWriteLock( DfsServerGlobalData.pDirectoryPrefixTable );
  1573. if ( NtStatus == STATUS_SUCCESS )
  1574. {
  1575. NtStatus = DfsFindUnicodePrefixLocked( DfsServerGlobalData.pDirectoryPrefixTable,
  1576. pDirectoryName,
  1577. &RemainingName,
  1578. &pData,
  1579. &SubStringMatch );
  1580. //
  1581. // if we found a perfect match, we can remove this
  1582. // from the table.
  1583. //
  1584. if ( (NtStatus == STATUS_SUCCESS) &&
  1585. (RemainingName.Length == 0) )
  1586. {
  1587. NtStatus = DfsRemoveFromPrefixTableLocked( DfsServerGlobalData.pDirectoryPrefixTable,
  1588. pDirectoryName,
  1589. (PVOID)pLogicalShare);
  1590. }
  1591. else
  1592. {
  1593. NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  1594. }
  1595. DfsPrefixTableReleaseLock( DfsServerGlobalData.pDirectoryPrefixTable );
  1596. }
  1597. if (NtStatus != STATUS_SUCCESS)
  1598. {
  1599. Status = RtlNtStatusToDosError(NtStatus);
  1600. }
  1601. return Status;
  1602. }
  1603. //
  1604. // Function AcquireLock: Acquires the lock on the folder
  1605. //
  1606. DFSSTATUS
  1607. DfsAcquireWriteLock(
  1608. PCRITICAL_SECTION pLock)
  1609. {
  1610. DFSSTATUS Status = ERROR_SUCCESS;
  1611. EnterCriticalSection(pLock);
  1612. return Status;
  1613. }
  1614. DFSSTATUS
  1615. DfsAcquireReadLock(
  1616. PCRITICAL_SECTION pLock)
  1617. {
  1618. DFSSTATUS Status = ERROR_SUCCESS;
  1619. EnterCriticalSection(pLock);
  1620. return Status;
  1621. }
  1622. VOID
  1623. DfsSetGlobalDomainInfo(
  1624. DfsDomainInformation *pDomainInfo)
  1625. {
  1626. DFSSTATUS Status;
  1627. DfsDomainInformation *pOldInfo = NULL;
  1628. Status = DfsAcquireGlobalDataLock();
  1629. if (Status == ERROR_SUCCESS)
  1630. {
  1631. pDomainInfo->AcquireReference();
  1632. pOldInfo = DfsServerGlobalData.pDomainInfo;
  1633. DfsServerGlobalData.pDomainInfo = pDomainInfo;
  1634. DfsReleaseGlobalDataLock();
  1635. }
  1636. if (pOldInfo != NULL)
  1637. {
  1638. pOldInfo->ReleaseReference();
  1639. }
  1640. return NOTHING;
  1641. }
  1642. DFSSTATUS
  1643. DfsAcquireDomainInfo (
  1644. DfsDomainInformation **ppDomainInfo )
  1645. {
  1646. DFSSTATUS Status = ERROR_SUCCESS;
  1647. Status = DfsAcquireGlobalDataLock();
  1648. if (Status == ERROR_SUCCESS)
  1649. {
  1650. *ppDomainInfo = DfsServerGlobalData.pDomainInfo;
  1651. if (*ppDomainInfo == NULL)
  1652. {
  1653. Status = ERROR_NOT_READY;
  1654. }
  1655. else
  1656. {
  1657. (*ppDomainInfo)->AcquireReference();
  1658. }
  1659. DfsReleaseGlobalDataLock();
  1660. }
  1661. return Status;
  1662. }
  1663. VOID
  1664. DfsReleaseDomainInfo (
  1665. DfsDomainInformation *pDomainInfo )
  1666. {
  1667. pDomainInfo->ReleaseReference();
  1668. return NOTHING;
  1669. }
  1670. DFSSTATUS
  1671. DfsSetDomainNameFlat(LPWSTR DomainNameFlatString)
  1672. {
  1673. DFSSTATUS Status = ERROR_SUCCESS;
  1674. UNICODE_STRING DomainNameFlat;
  1675. Status = DfsRtlInitUnicodeStringEx( &DomainNameFlat, DomainNameFlatString);
  1676. if(Status == ERROR_SUCCESS)
  1677. {
  1678. Status = DfsCreateUnicodeString( &DfsServerGlobalData.DomainNameFlat,
  1679. &DomainNameFlat );
  1680. }
  1681. return Status;
  1682. }
  1683. DFSSTATUS
  1684. DfsSetDomainNameDns( LPWSTR DomainNameDnsString )
  1685. {
  1686. DFSSTATUS Status = ERROR_SUCCESS;
  1687. UNICODE_STRING DomainNameDns;
  1688. Status = DfsRtlInitUnicodeStringEx( &DomainNameDns, DomainNameDnsString);
  1689. if(Status == ERROR_SUCCESS)
  1690. {
  1691. Status = DfsCreateUnicodeString( &DfsServerGlobalData.DomainNameDns,
  1692. &DomainNameDns);
  1693. }
  1694. return Status;
  1695. }
  1696. BOOLEAN
  1697. DfsIsNameContextDomainName( PUNICODE_STRING pName )
  1698. {
  1699. BOOLEAN ReturnValue = FALSE;
  1700. if (pName->Length == DfsServerGlobalData.DomainNameFlat.Length)
  1701. {
  1702. if (_wcsnicmp(DfsServerGlobalData.DomainNameFlat.Buffer,
  1703. pName->Buffer, pName->Length/sizeof(WCHAR)) == 0)
  1704. {
  1705. ReturnValue = TRUE;
  1706. }
  1707. }
  1708. else if (pName->Length == DfsServerGlobalData.DomainNameDns.Length)
  1709. {
  1710. if (_wcsnicmp(DfsServerGlobalData.DomainNameDns.Buffer,
  1711. pName->Buffer, pName->Length/sizeof(WCHAR)) == 0)
  1712. {
  1713. ReturnValue = TRUE;
  1714. }
  1715. }
  1716. return ReturnValue;
  1717. }
  1718. DWORD DfsReadRegistryDword( HKEY hkey,
  1719. LPWSTR pszValueName,
  1720. DWORD dwDefaultValue )
  1721. {
  1722. DWORD dwerr = 0;
  1723. DWORD dwBuffer = 0;
  1724. DWORD cbBuffer = sizeof(dwBuffer);
  1725. DWORD dwType = 0;
  1726. if( hkey != NULL )
  1727. {
  1728. dwerr = RegQueryValueEx( hkey,
  1729. pszValueName,
  1730. NULL,
  1731. &dwType,
  1732. (LPBYTE)&dwBuffer,
  1733. &cbBuffer );
  1734. if( ( dwerr == NO_ERROR ) && ( dwType == REG_DWORD ) )
  1735. {
  1736. dwDefaultValue = dwBuffer;
  1737. }
  1738. }
  1739. return dwDefaultValue;
  1740. }
  1741. //*************************************************************
  1742. //
  1743. // IsNullGUID()
  1744. //
  1745. // Purpose: Determines if the passed in GUID is all zeros
  1746. //
  1747. // Parameters: pguid GUID to compare
  1748. //
  1749. // Return: TRUE if the GUID is all zeros
  1750. // FALSE if not
  1751. //
  1752. //*************************************************************
  1753. BOOL IsNullGUID (GUID *pguid)
  1754. {
  1755. return ( (pguid->Data1 == 0) &&
  1756. (pguid->Data2 == 0) &&
  1757. (pguid->Data3 == 0) &&
  1758. (pguid->Data4[0] == 0) &&
  1759. (pguid->Data4[1] == 0) &&
  1760. (pguid->Data4[2] == 0) &&
  1761. (pguid->Data4[3] == 0) &&
  1762. (pguid->Data4[4] == 0) &&
  1763. (pguid->Data4[5] == 0) &&
  1764. (pguid->Data4[6] == 0) &&
  1765. (pguid->Data4[7] == 0) );
  1766. }
  1767. BOOLEAN
  1768. DfsGetGlobalRegistrySettings(void)
  1769. {
  1770. BOOLEAN fRet = TRUE;
  1771. HKEY hkeyDfs = NULL;
  1772. HKEY hkeyDfs2 = NULL;
  1773. DWORD dwErr = 0;
  1774. DWORD dwDisp = 0;
  1775. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, DfsSvcPath,
  1776. NULL,
  1777. NULL,
  1778. REG_OPTION_NON_VOLATILE,
  1779. KEY_READ|KEY_WRITE, // Write = Create if
  1780. NULL, &hkeyDfs, &dwDisp);
  1781. if (dwErr == ERROR_SUCCESS)
  1782. {
  1783. //
  1784. //support the old format of specifying the time interval to refresh.
  1785. //
  1786. DfsServerGlobalData.CacheFlushInterval = DfsReadRegistryDword(hkeyDfs,
  1787. DfsWorkerThreadIntervalName,
  1788. CACHE_FLUSH_INTERVAL/1000);
  1789. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, DfsParamPath, NULL, NULL,
  1790. REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &hkeyDfs2, &dwDisp);
  1791. if (dwErr == ERROR_SUCCESS)
  1792. {
  1793. DfsServerGlobalData.SiteSupportRefreshInterval = DfsReadRegistryDword(hkeyDfs2, DfsSiteSupportRefreshIntervalName, SITE_REFRESH_INTERVAL/1000);
  1794. //
  1795. // domain name refresh interval defaults to same as site refresh: 12 hours
  1796. //
  1797. DfsServerGlobalData.DomainNameRefreshInterval = DfsReadRegistryDword(hkeyDfs2, DfsDomainNameRefreshInterval, SITE_REFRESH_INTERVAL/1000);
  1798. DfsServerGlobalData.SiteIpCacheTrimValue = DfsReadRegistryDword(hkeyDfs2, DfsSiteIpCacheTrimValueName, SITE_IPCACHE_TRIM_VALUE);
  1799. DfsServerGlobalData.AllowedErrors = DfsReadRegistryDword(hkeyDfs2, DfsAllowableErrorsValueName, DFS_MAX_ROOT_ERRORS);
  1800. DfsServerGlobalData.LdapTimeOut = DfsReadRegistryDword(hkeyDfs2, DfsLdapTimeoutValueName, DFS_LDAP_TIMEOUT);
  1801. DfsServerGlobalData.NumClientSiteEntriesAllowed = DfsReadRegistryDword(hkeyDfs2, DfsMaxClientSiteValueName, DFS_INITIAL_CLIENTS_SITES);
  1802. DfsServerGlobalData.QuerySiteCostTimeoutInSeconds = DfsReadRegistryDword(hkeyDfs2, DfsQuerySiteCostTimeoutName, DFS_QUERY_SITE_COST_TIMEOUT);
  1803. DfsServerGlobalData.RootReferralRefreshInterval = DfsReadRegistryDword(hkeyDfs2, DFS_REG_ROOT_REFERRAL_TIMEOUT_NAME, ROOTREF_REFRESH_INTERVAL/1000);
  1804. if (DfsReadRegistryDword(hkeyDfs2, DfsSiteCostedReferralsValueName, 0) != 0)
  1805. {
  1806. DfsServerGlobalData.Flags |= DFS_SITE_COSTED_REFERRALS;
  1807. }
  1808. if (DfsReadRegistryDword(hkeyDfs2, DfsInsiteReferralsValueName, 0) != 0)
  1809. {
  1810. DfsServerGlobalData.Flags |= DFS_INSITE_REFERRALS;
  1811. }
  1812. //
  1813. // if we are possibly in a NT4 domain, check if we need to disable
  1814. // siteawareness.
  1815. //
  1816. {
  1817. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  1818. NTSTATUS status = 0;
  1819. LSA_HANDLE hPolicy;
  1820. BOOLEAN CheckRegistry = TRUE;
  1821. DfsServerGlobalData.DisableSiteAwareness = FALSE;
  1822. //attempt to open the policy.
  1823. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));//object attributes are reserved, so initalize to zeroes.
  1824. status = LsaOpenPolicy( NULL,
  1825. &ObjectAttributes,
  1826. POLICY_VIEW_LOCAL_INFORMATION,
  1827. &hPolicy); //recieves the policy handle
  1828. if (NT_SUCCESS(status))
  1829. {
  1830. //ask for audit event policy information
  1831. PPOLICY_DNS_DOMAIN_INFO info;
  1832. status = LsaQueryInformationPolicy(hPolicy,
  1833. PolicyDnsDomainInformation,
  1834. (PVOID *)&info);
  1835. if (NT_SUCCESS(status))
  1836. {
  1837. if (!IsNullGUID(&info->DomainGuid))
  1838. {
  1839. CheckRegistry = FALSE;
  1840. }
  1841. LsaFreeMemory((PVOID) info); //free policy info structure
  1842. }
  1843. LsaClose(hPolicy); //Freeing the policy object handle
  1844. }
  1845. if (CheckRegistry)
  1846. {
  1847. DWORD DisableSiteAwareness = 0;
  1848. DisableSiteAwareness =
  1849. DfsReadRegistryDword( hkeyDfs2,
  1850. DFS_DISABLE_SITE_AWARENESS,
  1851. DisableSiteAwareness );
  1852. DfsServerGlobalData.DisableSiteAwareness = (DisableSiteAwareness == 0) ? FALSE : TRUE;
  1853. }
  1854. }
  1855. RegCloseKey(hkeyDfs2);
  1856. }
  1857. RegCloseKey(hkeyDfs);
  1858. }
  1859. DfsServerGlobalData.CacheFlushInterval *= 1000;
  1860. if(DfsServerGlobalData.CacheFlushInterval < CACHE_FLUSH_MIN_INTERVAL)
  1861. {
  1862. DfsServerGlobalData.CacheFlushInterval = CACHE_FLUSH_MIN_INTERVAL;
  1863. DfsServerGlobalData.RetryFailedReferralLoadInterval = DfsServerGlobalData.CacheFlushInterval / 3;
  1864. }
  1865. else
  1866. {
  1867. DfsServerGlobalData.RetryFailedReferralLoadInterval = DfsServerGlobalData.CacheFlushInterval /4;
  1868. }
  1869. DfsServerGlobalData.SiteSupportRefreshInterval *= 1000;
  1870. if(DfsServerGlobalData.SiteSupportRefreshInterval == 0)
  1871. {
  1872. DfsServerGlobalData.SiteSupportRefreshInterval = SITE_REFRESH_INTERVAL;
  1873. }
  1874. if(DfsServerGlobalData.SiteSupportRefreshInterval < MIN_SITE_REFRESH_INTERVAL)
  1875. {
  1876. DfsServerGlobalData.SiteSupportRefreshInterval = MIN_SITE_REFRESH_INTERVAL;
  1877. }
  1878. if(DfsServerGlobalData.DomainNameRefreshInterval < MIN_DOMAIN_REFRESH_INTERVAL)
  1879. {
  1880. DfsServerGlobalData.DomainNameRefreshInterval = MIN_DOMAIN_REFRESH_INTERVAL;
  1881. }
  1882. if(DfsServerGlobalData.NumClientSiteEntriesAllowed < DFS_MINIMUM_CLIENTS_SITES)
  1883. {
  1884. DfsServerGlobalData.NumClientSiteEntriesAllowed = DFS_MINIMUM_CLIENTS_SITES;
  1885. }
  1886. if (DfsServerGlobalData.QuerySiteCostTimeoutInSeconds < DFS_MIN_QUERY_SITE_COST_TIMEOUT)
  1887. {
  1888. DfsServerGlobalData.QuerySiteCostTimeoutInSeconds = DFS_MIN_QUERY_SITE_COST_TIMEOUT;
  1889. }
  1890. else if (DfsServerGlobalData.QuerySiteCostTimeoutInSeconds > DFS_MAX_QUERY_SITE_COST_TIMEOUT)
  1891. {
  1892. DfsServerGlobalData.QuerySiteCostTimeoutInSeconds = DFS_MAX_QUERY_SITE_COST_TIMEOUT;
  1893. }
  1894. DfsServerGlobalData.RootReferralRefreshInterval *= 1000;
  1895. if(DfsServerGlobalData.RootReferralRefreshInterval < ROOTREF_REFRESH_INTERVAL)
  1896. {
  1897. DfsServerGlobalData.RootReferralRefreshInterval = ROOTREF_REFRESH_INTERVAL;
  1898. }
  1899. DfsServerGlobalData.SiteSupportThreadInterval = DfsServerGlobalData.SiteSupportRefreshInterval - SITE_THREAD_INTERVAL_DIFF;
  1900. DfsServerGlobalData.FirstContact = DFS_DS_ACTIVE;
  1901. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.SiteSupportRefreshInterval %d\n", DfsServerGlobalData.SiteSupportRefreshInterval);
  1902. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.CacheFlushInterval %d\n", DfsServerGlobalData.CacheFlushInterval);
  1903. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.SiteIpCacheTrimValue %d\n", DfsServerGlobalData.SiteIpCacheTrimValue);
  1904. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.AllowedErrors %d\n", DfsServerGlobalData.AllowedErrors);
  1905. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.LdapTimeOut %d\n", DfsServerGlobalData.LdapTimeOut);
  1906. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!]Read regkey DfsServerGlobalData.NumClientSiteEntriesAllowed %d\n", DfsServerGlobalData.NumClientSiteEntriesAllowed);
  1907. return fRet;
  1908. }
  1909. BOOLEAN
  1910. DfsGetStaticGlobalRegistrySettings(void)
  1911. {
  1912. BOOLEAN fRet = TRUE;
  1913. HKEY hkeyDfs = NULL;
  1914. HKEY hkeyDfs2 = NULL;
  1915. DWORD dwErr = 0;
  1916. DWORD dwDisp = 0;
  1917. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, DfsSvcPath,
  1918. NULL,
  1919. NULL,
  1920. REG_OPTION_NON_VOLATILE,
  1921. KEY_READ|KEY_WRITE, // Write = Create if
  1922. NULL, &hkeyDfs, &dwDisp);
  1923. if (dwErr == ERROR_SUCCESS)
  1924. {
  1925. DfsServerGlobalData.DfsDnsConfig = (DWORD) !!DfsReadRegistryDword(hkeyDfs,
  1926. DfsDnsConfigValue,
  1927. 0 );
  1928. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, DfsParamPath, NULL, NULL,
  1929. REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &hkeyDfs2, &dwDisp);
  1930. if (dwErr == ERROR_SUCCESS)
  1931. {
  1932. DfsServerGlobalData.NumWorkerThreads = DfsReadRegistryDword(hkeyDfs2, DFS_REG_WORKER_THREAD_VALUE, DFS_DEFAULT_WORKER_THREADS);
  1933. RegCloseKey(hkeyDfs2);
  1934. }
  1935. if(DfsServerGlobalData.NumWorkerThreads < DFS_MIN_WORKER_THREADS)
  1936. {
  1937. DfsServerGlobalData.NumWorkerThreads = DFS_MIN_WORKER_THREADS;
  1938. }
  1939. else if (DfsServerGlobalData.NumWorkerThreads > DFS_MAX_WORKER_THREADS)
  1940. {
  1941. DfsServerGlobalData.NumWorkerThreads = DFS_MAX_WORKER_THREADS;
  1942. }
  1943. RegCloseKey(hkeyDfs);
  1944. }
  1945. return fRet;
  1946. }
  1947. #define DFS_PDC_CACHE_TIME_INTERVAL 60 * 60 * 1000 // 60 minutes.
  1948. DFSSTATUS
  1949. DfsGetBlobPDCName(
  1950. DfsString **ppPDCName,
  1951. ULONG Flags,
  1952. LPWSTR DomainName )
  1953. {
  1954. PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
  1955. DFSSTATUS Status = ERROR_SUCCESS;
  1956. DFSSTATUS LockStatus = ERROR_SUCCESS;
  1957. ULONG CurrentTimeStamp = 0;
  1958. ULONG TimeDiff = 0;
  1959. BOOLEAN NewDcAttempted = FALSE;
  1960. DfsString NewDC;
  1961. *ppPDCName = NULL;
  1962. DfsGetTimeStamp(&CurrentTimeStamp);
  1963. TimeDiff = CurrentTimeStamp - DfsServerGlobalData.PDCTimeStamp;
  1964. if ((Flags & DFS_FORCE_DC_QUERY) ||
  1965. (TimeDiff > DFS_PDC_CACHE_TIME_INTERVAL) ||
  1966. (DfsServerGlobalData.PDCTimeStamp == 0))
  1967. {
  1968. NewDcAttempted = TRUE;
  1969. Status = DsGetDcName( NULL, //computer name
  1970. DomainName, // domain name
  1971. NULL, // domain guid
  1972. NULL, // site name
  1973. DS_DIRECTORY_SERVICE_REQUIRED |
  1974. DS_PDC_REQUIRED |
  1975. DS_FORCE_REDISCOVERY,
  1976. &pDomainControllerInfo );
  1977. DFS_TRACE_LOW( REFERRAL_SERVER, "Got New PDC, Status %x\n", Status);
  1978. if (Status == ERROR_SUCCESS)
  1979. {
  1980. Status = NewDC.CreateString(&pDomainControllerInfo->DomainControllerName[2] );
  1981. NetApiBufferFree(pDomainControllerInfo);
  1982. }
  1983. }
  1984. else
  1985. {
  1986. Status = DfsServerGlobalData.PDCStatus;
  1987. }
  1988. LockStatus = DfsAcquireGlobalDataLock();
  1989. if (LockStatus != ERROR_SUCCESS) {
  1990. return LockStatus;
  1991. }
  1992. if (NewDcAttempted == TRUE)
  1993. {
  1994. if (Status == ERROR_SUCCESS)
  1995. {
  1996. Status = DfsServerGlobalData.PDCName.CreateString(&NewDC);
  1997. }
  1998. if (Status == ERROR_SUCCESS)
  1999. {
  2000. DfsServerGlobalData.PDCTimeStamp = CurrentTimeStamp;
  2001. }
  2002. DfsServerGlobalData.PDCStatus = Status;
  2003. }
  2004. if ((Status == ERROR_SUCCESS) &&
  2005. (ppPDCName != NULL))
  2006. {
  2007. DfsString *pReturnDcName;
  2008. pReturnDcName = new DfsString;
  2009. if (pReturnDcName == NULL)
  2010. {
  2011. Status = ERROR_NOT_ENOUGH_MEMORY;
  2012. }
  2013. else
  2014. {
  2015. Status = pReturnDcName->CreateString(&DfsServerGlobalData.PDCName );
  2016. if (Status == ERROR_SUCCESS)
  2017. {
  2018. *ppPDCName = pReturnDcName;
  2019. }
  2020. else
  2021. {
  2022. delete pReturnDcName;
  2023. }
  2024. }
  2025. }
  2026. DfsReleaseGlobalDataLock();
  2027. if (*ppPDCName != NULL) {
  2028. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Returning PDC: %ws, Status %x\n",
  2029. (*ppPDCName)->GetString(), Status);
  2030. }
  2031. return Status;
  2032. }
  2033. DFSSTATUS
  2034. DfsSetBlobPDCName(
  2035. LPWSTR DCName,
  2036. DfsString **ppPDCName)
  2037. {
  2038. DFSSTATUS Status = ERROR_SUCCESS;
  2039. DFSSTATUS LockStatus = ERROR_SUCCESS;
  2040. DfsString NewDC;
  2041. ULONG CurrentTimeStamp = 0;
  2042. DfsGetTimeStamp(&CurrentTimeStamp);
  2043. *ppPDCName = NULL;
  2044. Status = NewDC.CreateString(DCName);
  2045. if (Status != ERROR_SUCCESS)
  2046. {
  2047. return Status;
  2048. }
  2049. LockStatus = DfsAcquireGlobalDataLock();
  2050. if (LockStatus != ERROR_SUCCESS) {
  2051. return LockStatus;
  2052. }
  2053. Status = DfsServerGlobalData.PDCName.CreateString(&NewDC);
  2054. if (Status == ERROR_SUCCESS)
  2055. {
  2056. DfsServerGlobalData.PDCTimeStamp = CurrentTimeStamp;
  2057. }
  2058. DfsServerGlobalData.PDCStatus = Status;
  2059. if ((Status == ERROR_SUCCESS) &&
  2060. (ppPDCName != NULL))
  2061. {
  2062. DfsString *pReturnDcName;
  2063. pReturnDcName = new DfsString;
  2064. if (pReturnDcName == NULL)
  2065. {
  2066. Status = ERROR_NOT_ENOUGH_MEMORY;
  2067. }
  2068. else
  2069. {
  2070. Status = pReturnDcName->CreateString(&DfsServerGlobalData.PDCName );
  2071. if (Status == ERROR_SUCCESS)
  2072. {
  2073. *ppPDCName = pReturnDcName;
  2074. }
  2075. else
  2076. {
  2077. delete pReturnDcName;
  2078. }
  2079. }
  2080. }
  2081. DfsReleaseGlobalDataLock();
  2082. if (*ppPDCName != NULL) {
  2083. DFS_TRACE_LOW( REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Returning PDC: %ws, Status %x\n",
  2084. (*ppPDCName)->GetString(), Status);
  2085. }
  2086. return Status;
  2087. }
  2088. VOID
  2089. DfsReleaseBlobPDCName(
  2090. DfsString *pDCName )
  2091. {
  2092. if (pDCName != NULL)
  2093. {
  2094. delete pDCName;
  2095. }
  2096. }
  2097. BOOLEAN
  2098. DfsIsTargetCurrentMachine (
  2099. PUNICODE_STRING pServer )
  2100. {
  2101. UNICODE_STRING MachineName;
  2102. DFSSTATUS Status = ERROR_SUCCESS;
  2103. BOOLEAN ReturnValue = FALSE;
  2104. Status = DfsGetMachineName(&MachineName);
  2105. if (Status == ERROR_SUCCESS)
  2106. {
  2107. if (RtlCompareUnicodeString( pServer, &MachineName, TRUE) == 0)
  2108. {
  2109. ReturnValue = TRUE;
  2110. }
  2111. DfsFreeUnicodeString( &MachineName );
  2112. }
  2113. return ReturnValue;
  2114. }
  2115. LPWSTR
  2116. DfsGetDfsAdNameContextString()
  2117. {
  2118. if (DfsServerGlobalData.DfsAdNameContext.Buffer == NULL)
  2119. {
  2120. //
  2121. // ignore return status: we should log it.
  2122. //
  2123. DFSSTATUS DummyStatus;
  2124. DummyStatus = DfsGenerateDfsAdNameContext(&DfsServerGlobalData.DfsAdNameContext);
  2125. }
  2126. return DfsServerGlobalData.DfsAdNameContext.Buffer;
  2127. }
  2128. LPWSTR
  2129. DfsGetDfsAdNameContextStringForDomain(LPWSTR UseDC)
  2130. {
  2131. extern DFSSTATUS DfsGenerateDfsAdNameContextForDomain(PUNICODE_STRING pString,LPWSTR DCName );
  2132. if (DfsServerGlobalData.DfsAdNameContext.Buffer != NULL)
  2133. {
  2134. DfsFreeUnicodeString(&DfsServerGlobalData.DfsAdNameContext);
  2135. RtlInitUnicodeString(&DfsServerGlobalData.DfsAdNameContext, NULL);
  2136. }
  2137. //
  2138. // ignore return status: we should log it.
  2139. //
  2140. DFSSTATUS DummyStatus;
  2141. DummyStatus = DfsGenerateDfsAdNameContextForDomain(&DfsServerGlobalData.DfsAdNameContext, UseDC);
  2142. return DfsServerGlobalData.DfsAdNameContext.Buffer;
  2143. }
  2144. extern SECURITY_DESCRIPTOR AdminSecurityDesc;
  2145. //+----------------------------------------------------------------------------
  2146. //
  2147. // Function: InitializeSecurity
  2148. //
  2149. // Synopsis: Initializes data needed to check the access rights of callers
  2150. // of the NetDfs APIs
  2151. //
  2152. // Arguments: None
  2153. //
  2154. // Returns: TRUE if successful, FALSE otherwise.
  2155. //
  2156. //-----------------------------------------------------------------------------
  2157. BOOLEAN
  2158. DfsInitializeSecurity()
  2159. {
  2160. static PSID AdminSid;
  2161. static PACL AdminAcl;
  2162. NTSTATUS status;
  2163. ULONG cbAcl;
  2164. BOOLEAN InitDone = FALSE;
  2165. SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
  2166. status = RtlAllocateAndInitializeSid(
  2167. &ntAuthority,
  2168. 2,
  2169. SECURITY_BUILTIN_DOMAIN_RID,
  2170. DOMAIN_ALIAS_RID_ADMINS,
  2171. 0,0,0,0,0,0,
  2172. &AdminSid);
  2173. if (!NT_SUCCESS(status))
  2174. return( FALSE );
  2175. cbAcl = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AdminSid);
  2176. do {
  2177. AdminAcl = (PACL) new BYTE[ cbAcl ];
  2178. if (AdminAcl == NULL)
  2179. break;
  2180. if (!InitializeAcl(AdminAcl, cbAcl, ACL_REVISION))
  2181. break;
  2182. if (!AddAccessAllowedAce(AdminAcl, ACL_REVISION, STANDARD_RIGHTS_WRITE, AdminSid))
  2183. break;
  2184. if (!InitializeSecurityDescriptor(&AdminSecurityDesc, SECURITY_DESCRIPTOR_REVISION))
  2185. break;
  2186. if (!SetSecurityDescriptorOwner(&AdminSecurityDesc, AdminSid, FALSE))
  2187. break;
  2188. if (!SetSecurityDescriptorGroup(&AdminSecurityDesc, AdminSid, FALSE))
  2189. break;
  2190. if (!SetSecurityDescriptorDacl(&AdminSecurityDesc, TRUE, AdminAcl, FALSE))
  2191. break;
  2192. InitDone = TRUE;
  2193. } while (FALSE);
  2194. if (InitDone == FALSE && AdminAcl != NULL)
  2195. {
  2196. delete [] AdminAcl;
  2197. AdminAcl = NULL;
  2198. }
  2199. return InitDone;
  2200. }
  2201. DFSSTATUS
  2202. AccessImpersonateCheckRpcClient(void)
  2203. {
  2204. DFSSTATUS dwErr = 0;
  2205. dwErr = AccessImpersonateCheckRpcClientEx(&AdminSecurityDesc,
  2206. &AdminGenericMapping,
  2207. STANDARD_RIGHTS_WRITE);
  2208. return dwErr;
  2209. }
  2210. VOID
  2211. StartPreloadingServerSiteData(void)
  2212. {
  2213. DfsStore *pStore = NULL;
  2214. for (pStore = DfsServerGlobalData.pRegisteredStores; pStore != NULL;
  2215. pStore = pStore->pNextRegisteredStore)
  2216. {
  2217. pStore->LoadServerSiteDataPerRoot();
  2218. if (DfsIsShuttingDown())
  2219. {
  2220. break;
  2221. }
  2222. }
  2223. }
  2224. DFSSTATUS
  2225. DfsGetCompatRootFolder(
  2226. PUNICODE_STRING pName,
  2227. DfsRootFolder **ppNewRoot )
  2228. {
  2229. DfsADBlobStore *pStore = NULL;
  2230. DFSSTATUS Status = ERROR_SUCCESS;
  2231. Status = DfsGetADBlobStore(&pStore );
  2232. if (Status == ERROR_SUCCESS)
  2233. {
  2234. Status = pStore->GetCompatRootFolder( pName,
  2235. ppNewRoot );
  2236. pStore->ReleaseReference();
  2237. }
  2238. return Status;
  2239. }
  2240. //+----------------------------------------------------------------------------
  2241. //
  2242. // Function: DfsCacheInsertADRootReferral
  2243. //
  2244. // Synopsis: Insert a ReferralData structure into our list.
  2245. //
  2246. // Returns: Status.
  2247. //
  2248. //-----------------------------------------------------------------------------
  2249. typedef struct _DFS_ROOTREF_INFORMATION
  2250. {
  2251. DfsFolderReferralData * pReferralData;
  2252. GUID RootGuid;
  2253. }DFS_ROOTREF_INFORMATION, *PDFS_ROOTREF_INFORMATION;
  2254. DFSSTATUS
  2255. DfsCacheInsertADRootReferral(
  2256. PUNICODE_STRING pRootName,
  2257. PDFS_ROOTREF_INFORMATION pRefInfo )
  2258. {
  2259. DFSSTATUS Status = ERROR_SUCCESS;
  2260. NTSTATUS NtStatus = STATUS_SUCCESS;
  2261. PVOID pData = NULL;
  2262. BOOLEAN SubStringMatch = FALSE;
  2263. UNICODE_STRING RemainingName;
  2264. pRefInfo->pReferralData->AcquireReference();
  2265. NtStatus = DfsPrefixTableAcquireWriteLock( DfsServerGlobalData.pRootReferralTable );
  2266. if ( NtStatus == STATUS_SUCCESS )
  2267. {
  2268. NtStatus = DfsFindUnicodePrefixLocked( DfsServerGlobalData.pRootReferralTable,
  2269. pRootName,
  2270. &RemainingName,
  2271. &pData,
  2272. &SubStringMatch );
  2273. if ( (NtStatus == STATUS_SUCCESS) ||
  2274. ((NtStatus != STATUS_SUCCESS) && (SubStringMatch)) )
  2275. {
  2276. NtStatus = STATUS_OBJECT_NAME_COLLISION;
  2277. }
  2278. else
  2279. {
  2280. //
  2281. // Insert the directory and share information in our
  2282. // database.
  2283. //
  2284. NtStatus = DfsInsertInPrefixTableLocked(DfsServerGlobalData.pRootReferralTable,
  2285. pRootName,
  2286. (PVOID)pRefInfo );
  2287. }
  2288. DfsPrefixTableReleaseLock( DfsServerGlobalData.pRootReferralTable );
  2289. }
  2290. if(NtStatus != STATUS_SUCCESS)
  2291. {
  2292. pRefInfo->pReferralData->ReleaseReference();
  2293. Status = RtlNtStatusToDosError(NtStatus);
  2294. }
  2295. return Status;
  2296. }
  2297. DFSSTATUS
  2298. DfsCacheRemoveADRootReferral(
  2299. PUNICODE_STRING pRootName,
  2300. PDFS_ROOTREF_INFORMATION pRefInfo )
  2301. {
  2302. DFSSTATUS Status = ERROR_SUCCESS;
  2303. NTSTATUS NtStatus = STATUS_SUCCESS;
  2304. PVOID pData = NULL;
  2305. BOOLEAN SubStringMatch = FALSE;
  2306. UNICODE_STRING RemainingName;
  2307. NtStatus = DfsPrefixTableAcquireWriteLock( DfsServerGlobalData.pRootReferralTable );
  2308. if ( NtStatus == STATUS_SUCCESS )
  2309. {
  2310. NtStatus = DfsFindUnicodePrefixLocked( DfsServerGlobalData.pRootReferralTable,
  2311. pRootName,
  2312. &RemainingName,
  2313. &pData,
  2314. &SubStringMatch );
  2315. //
  2316. // if we found a perfect match, we can remove this
  2317. // from the table.
  2318. //
  2319. if ( (NtStatus == STATUS_SUCCESS) &&
  2320. (RemainingName.Length == 0) )
  2321. {
  2322. if ((pRefInfo == NULL) || ((PVOID)pRefInfo == pData))
  2323. {
  2324. pRefInfo = (PDFS_ROOTREF_INFORMATION)pData;
  2325. NtStatus = DfsRemoveFromPrefixTableLocked( DfsServerGlobalData.pRootReferralTable,
  2326. pRootName,
  2327. (PVOID)pData );
  2328. }
  2329. else
  2330. {
  2331. NtStatus = STATUS_OBJECT_TYPE_MISMATCH;
  2332. }
  2333. }
  2334. else
  2335. {
  2336. NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  2337. }
  2338. DfsPrefixTableReleaseLock( DfsServerGlobalData.pRootReferralTable );
  2339. }
  2340. if (NtStatus == STATUS_SUCCESS)
  2341. {
  2342. pRefInfo->pReferralData->ReleaseReference();
  2343. delete [] pRefInfo;
  2344. }
  2345. else
  2346. {
  2347. Status = RtlNtStatusToDosError(NtStatus);
  2348. }
  2349. return Status;
  2350. }
  2351. DFSSTATUS
  2352. DfsGetADRootReferralInformation(
  2353. PUNICODE_STRING pRootName,
  2354. PDFS_ROOTREF_INFORMATION * pRefInformation,
  2355. GUID *pNewGuid)
  2356. {
  2357. DFSSTATUS Status = ERROR_SUCCESS;
  2358. DfsFolderReferralData *pReferralData = NULL;
  2359. BOOLEAN CacheHit = TRUE;
  2360. PDFS_ROOTREF_INFORMATION pRefInfo = NULL;
  2361. UNICODE_STRING RemainingName;
  2362. Status = DfsGetRootReferralDataEx(pRootName,
  2363. &RemainingName,
  2364. &pReferralData,
  2365. &CacheHit);
  2366. if(Status == ERROR_SUCCESS)
  2367. {
  2368. pRefInfo = (PDFS_ROOTREF_INFORMATION) new BYTE[sizeof(DFS_ROOTREF_INFORMATION)];
  2369. if(pRefInfo == NULL)
  2370. {
  2371. pReferralData->ReleaseReference();
  2372. Status = ERROR_NOT_ENOUGH_MEMORY;
  2373. }
  2374. else
  2375. {
  2376. pRefInfo->pReferralData = pReferralData;
  2377. RtlCopyMemory(&pRefInfo->RootGuid, pNewGuid, sizeof(GUID));
  2378. *pRefInformation = pRefInfo;
  2379. }
  2380. }
  2381. return Status;
  2382. }
  2383. DFSSTATUS
  2384. DfsCheckIfRootExist(
  2385. PUNICODE_STRING pName,
  2386. GUID *pNewGuid)
  2387. {
  2388. DFSSTATUS Status = ERROR_SUCCESS;
  2389. UNICODE_STRING ServerName, ShareName, Rest;
  2390. //
  2391. // Break up the path into name components.
  2392. //
  2393. Status = DfsGetPathComponents( pName,
  2394. &ServerName,
  2395. &ShareName,
  2396. &Rest );
  2397. if(Status == ERROR_SUCCESS)
  2398. {
  2399. Status = DfsCheckRootADObjectExistence(NULL,
  2400. &ShareName,
  2401. pNewGuid);
  2402. }
  2403. return Status;
  2404. }
  2405. DFSSTATUS
  2406. DfsGetADRootReferralData(
  2407. PUNICODE_STRING pRootName,
  2408. DfsReferralData **ppReferralData )
  2409. {
  2410. BOOLEAN SubStringMatch = FALSE;
  2411. DFSSTATUS Status = ERROR_SUCCESS;
  2412. NTSTATUS NtStatus = STATUS_SUCCESS;
  2413. NTSTATUS NtTempStatus = STATUS_SUCCESS;
  2414. DfsFolderReferralData *pReferralData = NULL;
  2415. PDFS_ROOTREF_INFORMATION pRefInfo = NULL;
  2416. BOOLEAN CacheHit = TRUE;
  2417. BOOLEAN RootExists = FALSE;
  2418. GUID NewGuid;
  2419. UNICODE_STRING RemainingName;
  2420. *ppReferralData = NULL;
  2421. DFS_TRACE_LOW(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Getting AD Root referral for %wZ\n", pRootName);
  2422. NtStatus = DfsPrefixTableAcquireWriteLock( DfsServerGlobalData.pRootReferralTable );
  2423. if ( NtStatus == STATUS_SUCCESS )
  2424. {
  2425. NtStatus = DfsFindUnicodePrefixLocked( DfsServerGlobalData.pRootReferralTable,
  2426. pRootName,
  2427. &RemainingName,
  2428. (PVOID *)&pRefInfo,
  2429. &SubStringMatch );
  2430. if (NtStatus == STATUS_SUCCESS)
  2431. {
  2432. DFS_TRACE_LOW(REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Found cached, for %wZ, %p\n", pRootName, pReferralData);
  2433. if (pRefInfo->pReferralData->TimeToRefresh() == TRUE)
  2434. {
  2435. //initialize the new guid
  2436. RtlZeroMemory(&NewGuid, sizeof(NewGuid));
  2437. //see if the root actually exists
  2438. Status = DfsCheckIfRootExist(pRootName,
  2439. &NewGuid);
  2440. if(Status == ERROR_SUCCESS)
  2441. {
  2442. RootExists = TRUE;
  2443. NtStatus = STATUS_UNSUCCESSFUL;
  2444. }
  2445. else
  2446. {
  2447. NtTempStatus = DfsCacheRemoveADRootReferral(pRootName, NULL);
  2448. }
  2449. }
  2450. else
  2451. {
  2452. pReferralData = pRefInfo->pReferralData;
  2453. pReferralData->AcquireReference();
  2454. *ppReferralData = pReferralData;
  2455. }
  2456. }
  2457. else
  2458. {
  2459. //No data in our table. see if the root actually exists.
  2460. //if it does not exist, then we bail out
  2461. Status = DfsCheckIfRootExist(pRootName,
  2462. &NewGuid);
  2463. if(Status == ERROR_SUCCESS)
  2464. {
  2465. RootExists = TRUE;
  2466. }
  2467. }
  2468. DfsPrefixTableReleaseLock( DfsServerGlobalData.pRootReferralTable );
  2469. }
  2470. if(RootExists && (NtStatus != STATUS_SUCCESS))
  2471. {
  2472. Status = DfsGetADRootReferralInformation(pRootName,
  2473. &pRefInfo,
  2474. &NewGuid);
  2475. if (Status == ERROR_SUCCESS)
  2476. {
  2477. *ppReferralData = pRefInfo->pReferralData;
  2478. NtTempStatus = DfsCacheRemoveADRootReferral(pRootName, NULL);
  2479. NtTempStatus = DfsCacheInsertADRootReferral(pRootName, pRefInfo);
  2480. if(NtTempStatus != STATUS_SUCCESS)
  2481. {
  2482. delete [] pRefInfo;
  2483. }
  2484. DFS_TRACE_ERROR_LOW( NtTempStatus, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]AD Root Referral, insert status %x\n",
  2485. NtTempStatus );
  2486. }
  2487. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]Generate AD ROOT referral, got %p, status %x\n",
  2488. pReferralData, Status);
  2489. }
  2490. DFS_TRACE_ERROR_HIGH( Status, REFERRAL_SERVER, "[%!FUNC!- Level %!LEVEL!]AD Root Referral for %wZ is %p, status %x\n",
  2491. pRootName, pReferralData, Status);
  2492. return Status;
  2493. }
  2494. BOOLEAN
  2495. DfsIsMachineDomainController()
  2496. {
  2497. return DfsServerGlobalData.IsDc;
  2498. }
  2499. DWORD
  2500. DfsGetNumReflectionThreads(void)
  2501. {
  2502. return DfsServerGlobalData.NumWorkerThreads;
  2503. }
  2504. DFSSTATUS
  2505. DfsSetupPrivileges (void)
  2506. {
  2507. DFSSTATUS Status = ERROR_SUCCESS;
  2508. //
  2509. // Get the SE_SECURITY_PRIVILEGE to read/write SACLs.
  2510. //
  2511. Status = DfsAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE);
  2512. if(Status != ERROR_SUCCESS)
  2513. {
  2514. return FALSE;
  2515. }
  2516. //
  2517. // Get backup/restore privilege to bypass ACL checks.
  2518. //
  2519. Status = DfsAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE);
  2520. if(Status != ERROR_SUCCESS)
  2521. {
  2522. return FALSE;
  2523. }
  2524. Status = DfsAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE);
  2525. if(Status != ERROR_SUCCESS)
  2526. {
  2527. return FALSE;
  2528. }
  2529. //disable stuff we don't need
  2530. Status = DfsAdjustPrivilege(SE_CREATE_TOKEN_PRIVILEGE, FALSE);
  2531. Status = DfsAdjustPrivilege(SE_LOCK_MEMORY_PRIVILEGE, FALSE);
  2532. Status = DfsAdjustPrivilege(SE_SYSTEMTIME_PRIVILEGE, FALSE);
  2533. Status = DfsAdjustPrivilege(SE_CREATE_PERMANENT_PRIVILEGE, FALSE);
  2534. Status = DfsAdjustPrivilege(SE_CREATE_PAGEFILE_PRIVILEGE, FALSE);
  2535. Status = DfsAdjustPrivilege(SE_DEBUG_PRIVILEGE, FALSE);
  2536. Status = DfsAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, FALSE);
  2537. Status = DfsAdjustPrivilege(SE_PROF_SINGLE_PROCESS_PRIVILEGE, FALSE);
  2538. //now, remove anything disabled
  2539. Status = DfsRemoveDisabledPrivileges();
  2540. return Status;
  2541. }
  2542. DFSSTATUS
  2543. DfsGetRootCount(
  2544. PULONG pRootCount )
  2545. {
  2546. DfsStore *pStore;
  2547. DFSSTATUS Status = ERROR_SUCCESS;
  2548. ULONG RootCount;
  2549. ULONG TotalCount = 0;
  2550. //
  2551. // For each store registered, get the number of roots.
  2552. //
  2553. for (pStore = DfsServerGlobalData.pRegisteredStores;
  2554. pStore != NULL;
  2555. pStore = pStore->pNextRegisteredStore) {
  2556. Status = pStore->GetRootCount(&RootCount);
  2557. if (Status == ERROR_SUCCESS)
  2558. {
  2559. TotalCount += RootCount;
  2560. }
  2561. else
  2562. {
  2563. break;
  2564. }
  2565. }
  2566. if (Status == ERROR_SUCCESS)
  2567. {
  2568. *pRootCount = TotalCount;
  2569. }
  2570. return Status;
  2571. }
  2572. DFSSTATUS
  2573. DfsCheckServerRootHandlingCapability()
  2574. {
  2575. DFSSTATUS Status = ERROR_SUCCESS;
  2576. if (DfsLimitRoots() == TRUE)
  2577. {
  2578. ULONG RootCount = 0;
  2579. Status = DfsGetRootCount(&RootCount);
  2580. if (Status == ERROR_SUCCESS)
  2581. {
  2582. if (RootCount >= 1)
  2583. {
  2584. Status = ERROR_NOT_SUPPORTED;
  2585. }
  2586. }
  2587. }
  2588. return Status;
  2589. }