Source code of Windows XP (NT5)
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.

1043 lines
24 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation
  4. //
  5. // File: dfssvc.c
  6. //
  7. // Contents: Code to interact with service manager.
  8. //
  9. // Classes:
  10. //
  11. // Functions:
  12. //
  13. // History: 12 Nov 92 Milans created.
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <dfsfsctl.h>
  20. #include <windows.h>
  21. #include <stdlib.h>
  22. #include <lm.h>
  23. #include <dsrole.h>
  24. #include <dfsstr.h>
  25. #include <libsup.h>
  26. #include <dfsmsrv.h>
  27. #include <winldap.h>
  28. #include "dfsipc.h"
  29. #include "dominfo.h"
  30. #include "wmlum.h"
  31. #include "wmlmacro.h"
  32. #include "svcwml.h"
  33. #include <debug.h>
  34. DECLARE_DEBUG(DfsSvc)
  35. DECLARE_INFOLEVEL(DfsSvc)
  36. #if DBG == 1
  37. #define svc_debug_error(x,y) DfsSvcInlineDebugOut(DEB_ERROR, x, y)
  38. #define svc_debug_trace(x,y) DfsSvcInlineDebugOut(DEB_TRACE, x, y)
  39. #else // DBG == 1
  40. #define svc_debug_error(x,y)
  41. #define svc_debug_trace(x,y)
  42. #endif // DBG == 1
  43. #define MAX_HINT_PERIODS 1000
  44. BOOLEAN fStartAsService;
  45. const PWSTR wszDfsServiceName = L"DfsService";
  46. SERVICE_STATUS DfsStatus;
  47. SERVICE_STATUS_HANDLE hDfsService;
  48. VOID DfsSvcMsgProc(
  49. DWORD dwControl);
  50. VOID StartDfsService(
  51. DWORD dwNumServiceArgs,
  52. LPWSTR *lpServiceArgs);
  53. DWORD
  54. DfsStartDfssrv(VOID);
  55. VOID
  56. DfsStopDfssrv( VOID);
  57. BOOL
  58. DfsIsThisADfsRoot();
  59. DWORD
  60. DfsInitializationLoop(
  61. LPVOID lpThreadParams);
  62. DWORD DfsManagerProc();
  63. DWORD DfsRegDeleteKeyAndChildren(HKEY hkey, LPWSTR s);
  64. DWORD DfsCleanLocalVols(void);
  65. DWORD DfsDeleteChildKeys(HKEY hkey, LPWSTR s);
  66. void UpdateStatus(
  67. SERVICE_STATUS_HANDLE hService,
  68. SERVICE_STATUS *pSStatus,
  69. DWORD Status);
  70. //
  71. // Event logging and debugging globals
  72. //
  73. extern ULONG DfsSvcVerbose;
  74. extern ULONG DfsEventLog;
  75. typedef void (FAR WINAPI *DLL_ENTRY_PROC)(PWSTR);
  76. //
  77. // Our domain name and machine name
  78. //
  79. WCHAR MachineName[MAX_PATH];
  80. WCHAR DomainName[MAX_PATH];
  81. WCHAR DomainNameDns[MAX_PATH];
  82. WCHAR LastMachineName[MAX_PATH];
  83. WCHAR LastDomainName[MAX_PATH];
  84. WCHAR SiteName[MAX_PATH];
  85. CRITICAL_SECTION DomListCritSection;
  86. //
  87. // Our role in life (see dsrole.h)
  88. //
  89. DSROLE_MACHINE_ROLE DfsMachineRole;
  90. //
  91. // Type of dfs (FtDfs==DFS_MANAGER_FTDFS/Machine-based==DFS_MANAGER_SERVER)
  92. //
  93. ULONG DfsServerType = 0;
  94. //
  95. // Long-lived ldap handle to the ds on this machine, if it is a DC
  96. //
  97. PLDAP pLdap = NULL;
  98. GUID DfsRtlTraceGuid = { // 79d1da1f-7268-441b-b835-7c7bed5ab39e
  99. 0x79d1da1f, 0x7268, 0x441b,
  100. {0xb8, 0x35, 0x7c, 0x7b, 0xed, 0x5a, 0xb3, 0x9e}};
  101. extern void DfsInitWml();
  102. //+----------------------------------------------------------------------------
  103. //
  104. // Function: WinMain
  105. //
  106. // Synopsis: This guy will set up link to service manager and install
  107. // ServiceMain as the service's entry point. Hopefully, the service
  108. // control dispatcher will call ServiceMain soon thereafter.
  109. //
  110. // Arguments:
  111. //
  112. // Returns:
  113. //
  114. //-----------------------------------------------------------------------------
  115. int PASCAL WinMain(HINSTANCE hInstance,
  116. HINSTANCE hPrevInstance,
  117. LPSTR lpszCmdLine,
  118. int nCmdShow)
  119. {
  120. SERVICE_TABLE_ENTRYW aServiceEntry[2];
  121. DWORD status;
  122. if (_stricmp( lpszCmdLine, "-noservice" ) == 0) {
  123. fStartAsService = FALSE;
  124. StartDfsService( 0, NULL );
  125. //
  126. // Since we were not started as a service, we wait for ever...
  127. //
  128. Sleep( INFINITE );
  129. } else {
  130. fStartAsService = TRUE;
  131. aServiceEntry[0].lpServiceName = wszDfsServiceName;
  132. aServiceEntry[0].lpServiceProc = StartDfsService;
  133. aServiceEntry[1].lpServiceName = NULL;
  134. aServiceEntry[1].lpServiceProc = NULL;
  135. svc_debug_trace("Starting Dfs Services...\n", 0);
  136. if (!StartServiceCtrlDispatcherW(aServiceEntry)) {
  137. svc_debug_error("Error %d starting as service!\n", GetLastError());
  138. return(GetLastError());
  139. }
  140. }
  141. //
  142. // If the StartServiceCtrlDispatcher call succeeded, we will never get to
  143. // this point until someone stops this service.
  144. //
  145. return(0);
  146. }
  147. //+----------------------------------------------------------------------------
  148. //
  149. // Function: StartDfsService
  150. //
  151. // Synopsis: Call back for DfsService service. This is called *once* by the
  152. // Service controller when the DfsService service is to be inited
  153. // This function is responsible for registering a message
  154. // handler function for the DfsService service.
  155. //
  156. // Arguments: Unused
  157. //
  158. // Returns: Nothing
  159. //
  160. //-----------------------------------------------------------------------------
  161. VOID
  162. StartDfsService(DWORD dwNumServiceArgs, LPWSTR *lpServiceArgs)
  163. {
  164. HANDLE hInit;
  165. DWORD dwErr;
  166. DWORD idThread;
  167. HKEY hkey;
  168. PSECURITY_ATTRIBUTES pSecAttribs = NULL;
  169. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo;
  170. ULONG CheckPoint = 0;
  171. #if (DBG == 1) || (_CT_TEST_HOOK == 1)
  172. SECURITY_DESCRIPTOR SD;
  173. SECURITY_ATTRIBUTES SA;
  174. BOOL fRC = InitializeSecurityDescriptor(
  175. &SD,
  176. SECURITY_DESCRIPTOR_REVISION);
  177. if( fRC == TRUE ) {
  178. fRC = SetSecurityDescriptorDacl(
  179. &SD,
  180. TRUE,
  181. NULL,
  182. FALSE);
  183. }
  184. SA.nLength = sizeof(SECURITY_ATTRIBUTES);
  185. SA.lpSecurityDescriptor = &SD;
  186. SA.bInheritHandle = FALSE;
  187. pSecAttribs = &SA;
  188. #endif
  189. svc_debug_trace("StartDfsService: fStartAsService = %d\n", fStartAsService);
  190. if (fStartAsService) {
  191. hDfsService = RegisterServiceCtrlHandlerW(
  192. wszDfsServiceName,
  193. DfsSvcMsgProc);
  194. if (!hDfsService) {
  195. svc_debug_error("Error %d installing Dfs msg handler\n", GetLastError());
  196. return;
  197. }
  198. DfsStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  199. DfsStatus.dwCurrentState = SERVICE_STOPPED;
  200. DfsStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  201. DfsStatus.dwWin32ExitCode = 0;
  202. DfsStatus.dwServiceSpecificExitCode = 0;
  203. DfsStatus.dwCheckPoint = CheckPoint++;
  204. DfsStatus.dwWaitHint = 1000 * 30;
  205. svc_debug_trace("Updating Status to Start Pending...\n", 0);
  206. UpdateStatus(hDfsService, &DfsStatus, SERVICE_START_PENDING);
  207. }
  208. //
  209. // Remove any old exit pt info from the registry
  210. //
  211. DfsCleanLocalVols();
  212. InitializeCriticalSection(&DomListCritSection);
  213. //
  214. // Get our machine name and type/role.
  215. //
  216. dwErr = DsRoleGetPrimaryDomainInformation(
  217. NULL,
  218. DsRolePrimaryDomainInfoBasic,
  219. (PBYTE *)&pPrimaryDomainInfo);
  220. if (dwErr == ERROR_SUCCESS) {
  221. DfsMachineRole = pPrimaryDomainInfo->MachineRole;
  222. DomainName[0] = LastDomainName[0] = L'\0';
  223. DomainNameDns[0] = L'\0';
  224. if (pPrimaryDomainInfo->DomainNameFlat != NULL) {
  225. if (wcslen(pPrimaryDomainInfo->DomainNameFlat) < MAX_PATH) {
  226. wcscpy(DomainName,pPrimaryDomainInfo->DomainNameFlat);
  227. wcscpy(LastDomainName, DomainName);
  228. } else {
  229. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  230. }
  231. }
  232. if (pPrimaryDomainInfo->DomainNameDns != NULL) {
  233. if (wcslen(pPrimaryDomainInfo->DomainNameDns) < MAX_PATH) {
  234. wcscpy(DomainNameDns,pPrimaryDomainInfo->DomainNameDns);
  235. } else {
  236. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  237. }
  238. }
  239. DsRoleFreeMemory(pPrimaryDomainInfo);
  240. }
  241. if (dwErr != ERROR_SUCCESS) {
  242. svc_debug_error("StartDfsService:DsRoleGetPrimaryDomainInformation %08lx!\n", dwErr);
  243. DfsStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  244. DfsStatus.dwServiceSpecificExitCode = dwErr;
  245. DfsStatus.dwCheckPoint = 0;
  246. UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
  247. return;
  248. }
  249. //
  250. // Create a thread to finish initialization
  251. //
  252. hInit = CreateThread(
  253. NULL, // Security attributes
  254. 0, // Use default stack size
  255. DfsInitializationLoop, // Thread entry procedure
  256. 0, // Thread context parameter
  257. 0, // Start immediately
  258. &idThread); // Thread ID
  259. if (hInit == NULL) {
  260. svc_debug_error(
  261. "Unable to create Driver Init thread %08lx\n", GetLastError());
  262. DfsStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  263. DfsStatus.dwServiceSpecificExitCode = GetLastError();
  264. DfsStatus.dwCheckPoint = 0;
  265. UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
  266. return;
  267. }
  268. else {
  269. // 428812: no need to keep the handle around. prevent thread leak.
  270. CloseHandle( hInit );
  271. }
  272. DfsStatus.dwCheckPoint = CheckPoint++;
  273. UpdateStatus(hDfsService, &DfsStatus, SERVICE_RUNNING);
  274. return;
  275. }
  276. DWORD
  277. DfsInitializationLoop(
  278. LPVOID lpThreadParams)
  279. {
  280. HANDLE hLPC;
  281. DWORD idLpcThread;
  282. HANDLE hDfs;
  283. ULONG Retry;
  284. DWORD dwErr;
  285. NTSTATUS Status;
  286. Retry = 0;
  287. DfsInitWml();
  288. do {
  289. dwErr = DfsManagerProc();
  290. } while (dwErr != ERROR_SUCCESS && ++Retry < 10);
  291. if (dwErr != ERROR_SUCCESS) {
  292. svc_debug_error("Dfs Manager failed %08lx!\n", dwErr);
  293. }
  294. switch (DfsMachineRole) {
  295. case DsRole_RoleBackupDomainController:
  296. case DsRole_RolePrimaryDomainController:
  297. //
  298. // Init the special name table
  299. //
  300. Retry = 0;
  301. DfsInitDomainList();
  302. do {
  303. Status = DfsInitOurDomainDCs();
  304. if (Status != ERROR_SUCCESS) {
  305. Sleep(10*1000);
  306. }
  307. } while (Status != ERROR_SUCCESS && ++Retry < 10);
  308. DfsInitRemainingDomainDCs();
  309. pLdap = ldap_init(L"LocalHost", LDAP_PORT);
  310. if (pLdap != NULL) {
  311. dwErr = ldap_set_option(pLdap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  312. if (dwErr != LDAP_SUCCESS) {
  313. pLdap = NULL;
  314. } else {
  315. dwErr = ldap_bind_s(pLdap, NULL, NULL, LDAP_AUTH_SSPI);
  316. if (dwErr != ERROR_SUCCESS) {
  317. svc_debug_error("Could not bind to LocalHost\n", 0);
  318. pLdap = NULL;
  319. }
  320. }
  321. } else {
  322. svc_debug_error("Could not open LocalHost\n", 0);
  323. }
  324. /* Fall THRU */
  325. case DsRole_RoleMemberServer:
  326. //
  327. // Start the dfs lpc server
  328. //
  329. hLPC = CreateThread(
  330. NULL, // Security attributes
  331. 0, // Use default stack size
  332. (LPTHREAD_START_ROUTINE)DfsStartDfssrv, // Thread entry procedure
  333. 0, // Thread context parameter
  334. 0, // Start immediately
  335. &idLpcThread); // Thread ID
  336. if (hLPC == NULL) {
  337. svc_debug_error(
  338. "Unable to create Driver LPC thread %08lx\n", GetLastError());
  339. }
  340. else {
  341. CloseHandle(hLPC);
  342. }
  343. }
  344. Status = DfsOpen( &hDfs, NULL );
  345. if (NT_SUCCESS(Status)) {
  346. switch (DfsMachineRole) {
  347. case DsRole_RoleBackupDomainController:
  348. case DsRole_RolePrimaryDomainController:
  349. Status = DfsFsctl(
  350. hDfs,
  351. FSCTL_DFS_ISDC,
  352. NULL,
  353. 0L,
  354. NULL,
  355. 0L);
  356. }
  357. NtClose( hDfs );
  358. } else {
  359. svc_debug_error("Unable to open dfs driver %08lx\n", Status);
  360. svc_debug_error("UNC names will not work!\n", 0);
  361. }
  362. switch (DfsMachineRole) {
  363. case DsRole_RoleBackupDomainController:
  364. case DsRole_RolePrimaryDomainController:
  365. do {
  366. Status = DfsInitRemainingDomainDCs();
  367. if (Status != ERROR_SUCCESS) {
  368. Sleep(1000 * 60 * 10); // 10 min
  369. }
  370. } while (Status != ERROR_SUCCESS && ++Retry < 100);
  371. do {
  372. Sleep(1000 * 60 * 15); // 15 min
  373. DfsInitDomainList();
  374. DfsInitOurDomainDCs();
  375. DfsInitRemainingDomainDCs();
  376. } while (TRUE);
  377. }
  378. return 0;
  379. }
  380. //+----------------------------------------------------------------------------
  381. //
  382. // Function: DfsSvcMsgProc
  383. //
  384. // Synopsis: Service-Message handler for DFSInit.
  385. //
  386. // Arguments: [dwControl] - the message
  387. //
  388. // Returns: nothing
  389. //
  390. //-----------------------------------------------------------------------------
  391. VOID
  392. DfsSvcMsgProc(DWORD dwControl)
  393. {
  394. NTSTATUS Status;
  395. HANDLE hDfs;
  396. switch(dwControl) {
  397. case SERVICE_CONTROL_STOP:
  398. #if DBG
  399. if (DfsSvcVerbose)
  400. DbgPrint("DfsSvcMsgProc(SERVICE_CONTROL_STOP)\n");
  401. #endif
  402. //
  403. // Stop the driver
  404. //
  405. Status = DfsOpen( &hDfs, NULL );
  406. if (NT_SUCCESS(Status)) {
  407. Status = DfsFsctl(
  408. hDfs,
  409. FSCTL_DFS_STOP_DFS,
  410. NULL,
  411. 0L,
  412. NULL,
  413. 0L);
  414. svc_debug_trace("Fsctl STOP_DFS returned %08lx\n", Status);
  415. Status = DfsFsctl(
  416. hDfs,
  417. FSCTL_DFS_RESET_PKT,
  418. NULL,
  419. 0L,
  420. NULL,
  421. 0L);
  422. svc_debug_trace("Fsctl FSCTL_DFS_RESET_PKT returned %08lx\n", Status);
  423. NtClose( hDfs );
  424. }
  425. #if DBG
  426. if (DfsSvcVerbose)
  427. DbgPrint("DfsSvcMsgProc: calling DfsStopDfssvc\n");
  428. #endif
  429. DfsStopDfssrv();
  430. #if DBG
  431. if (DfsSvcVerbose)
  432. DbgPrint("DfsSvcMsgProc: DfsStopDfssvc returned\n");
  433. #endif
  434. UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
  435. break;
  436. case SERVICE_INTERROGATE:
  437. #if DBG
  438. if (DfsSvcVerbose)
  439. DbgPrint("DfsSvcMsgProc(SERVICE_INTERROGATE)\n");
  440. #endif
  441. //
  442. // We don't seem to be called with SERVICE_INTERROGATE ever!
  443. //
  444. if (DfsStatus.dwCurrentState == SERVICE_START_PENDING &&
  445. DfsStatus.dwCheckPoint < MAX_HINT_PERIODS) {
  446. DfsStatus.dwCheckPoint++;
  447. svc_debug_trace("DFSInit Checkpoint == %d\n", DfsStatus.dwCheckPoint);
  448. UpdateStatus(hDfsService, &DfsStatus, SERVICE_START_PENDING);
  449. } else {
  450. DfsStatus.dwCheckPoint = 0;
  451. UpdateStatus(hDfsService, &DfsStatus, DfsStatus.dwCurrentState);
  452. }
  453. break;
  454. default:
  455. break;
  456. }
  457. }
  458. //+----------------------------------------------------------------------------
  459. //
  460. // Function: UpdateStatus
  461. //
  462. // Synopsis: Pushes a ServiceStatus to the service manager.
  463. //
  464. // Arguments: [hService] - handle returned from RegisterServiceCtrlHandler
  465. // [pSStatus] - pointer to service-status block
  466. // [Status] - The status to set.
  467. //
  468. // Returns: Nothing.
  469. //
  470. //-----------------------------------------------------------------------------
  471. static void
  472. UpdateStatus(SERVICE_STATUS_HANDLE hService, SERVICE_STATUS *pSStatus, DWORD Status)
  473. {
  474. if (fStartAsService) {
  475. pSStatus->dwCurrentState = Status;
  476. if (Status == SERVICE_START_PENDING) {
  477. pSStatus->dwCheckPoint++;
  478. pSStatus->dwWaitHint = 1000;
  479. } else {
  480. pSStatus->dwCheckPoint = 0;
  481. pSStatus->dwWaitHint = 0;
  482. }
  483. SetServiceStatus(hService, pSStatus);
  484. }
  485. }
  486. //+----------------------------------------------------------------------------
  487. //
  488. // Function: DfsManagerIsDomainDfsEnabled
  489. //
  490. // Synopsis:
  491. //
  492. // Arguments:
  493. //
  494. // Returns:
  495. //
  496. //-----------------------------------------------------------------------------
  497. BOOL
  498. DfsManagerIsDomainDfsEnabled()
  499. {
  500. DWORD dwErr;
  501. HKEY hkey;
  502. dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, REG_KEY_ENABLE_DOMAIN_DFS, &hkey);
  503. if (dwErr == ERROR_SUCCESS) {
  504. RegCloseKey( hkey );
  505. return( TRUE );
  506. } else {
  507. return( FALSE );
  508. }
  509. }
  510. //+----------------------------------------------------------------------------
  511. //
  512. // Function: DfsIsThisADfsRoot
  513. //
  514. // Synopsis:
  515. //
  516. // Arguments:
  517. //
  518. // Returns:
  519. //
  520. //-----------------------------------------------------------------------------
  521. BOOL
  522. DfsIsThisADfsRoot()
  523. {
  524. DWORD dwErr;
  525. HKEY hkey;
  526. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  527. if (dwErr == ERROR_SUCCESS) {
  528. RegCloseKey( hkey );
  529. return( TRUE );
  530. }
  531. return( FALSE );
  532. }
  533. //+----------------------------------------------------------------------------
  534. //
  535. // Function: DfsManagerProc
  536. //
  537. // Synopsis: The Dfs Manager side implementation of Dfs Service.
  538. //
  539. // Arguments: None
  540. //
  541. // Returns: TRUE if everything went ok, FALSE otherwise
  542. //
  543. //-----------------------------------------------------------------------------
  544. DWORD
  545. DfsManagerProc()
  546. {
  547. DWORD dwErr;
  548. PWKSTA_INFO_100 wkstaInfo = NULL;
  549. HKEY hkey;
  550. WCHAR wszFTDfsName[ MAX_PATH ];
  551. DWORD cbName, dwType;
  552. BOOLEAN fIsFTDfs = FALSE;
  553. //
  554. // Get our Machine name
  555. //
  556. dwErr = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo );
  557. if (dwErr == ERROR_SUCCESS) {
  558. if (wcslen(wkstaInfo->wki100_computername) < MAX_PATH) {
  559. wcscpy(MachineName,wkstaInfo->wki100_computername);
  560. wcscpy(LastMachineName, MachineName);
  561. } else {
  562. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  563. }
  564. NetApiBufferFree( wkstaInfo );
  565. }
  566. if (dwErr != ERROR_SUCCESS) {
  567. svc_debug_error("DfsManagerProc:NetWkstaGetInfo %08lx!\n", dwErr);
  568. }
  569. //
  570. // Check VOLUMES_DIR, if it exists, get machine and domain name, and determine
  571. // if this is an FtDfs participant
  572. //
  573. if (dwErr == ERROR_SUCCESS) {
  574. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  575. if (dwErr == ERROR_SUCCESS) {
  576. cbName = sizeof(LastMachineName);
  577. dwErr = RegQueryValueEx(
  578. hkey,
  579. MACHINE_VALUE_NAME,
  580. NULL,
  581. &dwType,
  582. (PBYTE) LastMachineName,
  583. &cbName);
  584. if (dwErr != ERROR_SUCCESS) {
  585. dwErr = RegSetValueEx(
  586. hkey,
  587. MACHINE_VALUE_NAME,
  588. 0,
  589. REG_SZ,
  590. (PCHAR)MachineName,
  591. wcslen(MachineName) * sizeof(WCHAR));
  592. } else if (dwType != REG_SZ) {
  593. LastMachineName[0] = L'\0';
  594. }
  595. cbName = sizeof(LastDomainName);
  596. dwErr = RegQueryValueEx(
  597. hkey,
  598. DOMAIN_VALUE_NAME,
  599. NULL,
  600. &dwType,
  601. (PBYTE) LastDomainName,
  602. &cbName);
  603. if (dwErr != ERROR_SUCCESS) {
  604. dwErr = RegSetValueEx(
  605. hkey,
  606. DOMAIN_VALUE_NAME,
  607. 0,
  608. REG_SZ,
  609. (PCHAR)DomainName,
  610. wcslen(DomainName) * sizeof(WCHAR));
  611. } else if (dwType != REG_SZ) {
  612. LastDomainName[0] = L'\0';
  613. }
  614. //
  615. // See if this is a Fault-Tolerant Dfs vs Server-Based Dfs
  616. //
  617. cbName = sizeof(wszFTDfsName);
  618. dwErr = RegQueryValueEx(
  619. hkey,
  620. FTDFS_VALUE_NAME,
  621. NULL,
  622. &dwType,
  623. (PBYTE) wszFTDfsName,
  624. &cbName);
  625. if ((dwErr == ERROR_SUCCESS) && (dwType == REG_SZ)) {
  626. fIsFTDfs = TRUE;
  627. }
  628. RegCloseKey( hkey );
  629. }
  630. dwErr = ERROR_SUCCESS;
  631. }
  632. //
  633. // Now we check if the machine role is appropriate
  634. //
  635. if (dwErr == ERROR_SUCCESS) {
  636. switch(DfsMachineRole) {
  637. //
  638. // Somehow we were started on a workstation
  639. //
  640. case DsRole_RoleStandaloneWorkstation:
  641. case DsRole_RoleMemberWorkstation:
  642. dwErr = ERROR_NOT_SUPPORTED;
  643. break;
  644. //
  645. // We can run, but not in FtDFS mode,
  646. //
  647. // If the domain name has changed, clean up the registry.
  648. //
  649. case DsRole_RoleStandaloneServer:
  650. if (fIsFTDfs == TRUE || _wcsicmp(DomainName, LastDomainName) != 0) {
  651. fIsFTDfs = FALSE;
  652. }
  653. break;
  654. //
  655. // Fully supported modes
  656. //
  657. case DsRole_RoleMemberServer:
  658. case DsRole_RoleBackupDomainController:
  659. case DsRole_RolePrimaryDomainController:
  660. break;
  661. }
  662. }
  663. if (dwErr == ERROR_SUCCESS) {
  664. if (fIsFTDfs) {
  665. dwErr = DfsManager(
  666. wszFTDfsName,
  667. DFS_MANAGER_FTDFS );
  668. } else {
  669. dwErr = DfsManager(
  670. MachineName,
  671. DFS_MANAGER_SERVER );
  672. }
  673. }
  674. return( dwErr );
  675. }
  676. //+----------------------------------------------------------------------------
  677. //
  678. // Function: DfsCleanLocalVols
  679. //
  680. // Synopsis: Cleans out the LocalVolumes part of the registry, if there are
  681. // dfs-link keys left over from older versions.
  682. //
  683. // Arguments:
  684. //
  685. // Returns:
  686. //
  687. //-----------------------------------------------------------------------------
  688. DWORD
  689. DfsCleanLocalVols(void)
  690. {
  691. HKEY hLvolKey = NULL;
  692. HKEY hRootKey = NULL;
  693. DWORD dwErr = ERROR_SUCCESS;
  694. PWCHAR wCp;
  695. wCp = malloc(4096);
  696. if (wCp == NULL) {
  697. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  698. goto Cleanup;
  699. }
  700. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES, &hLvolKey);
  701. if (dwErr != ERROR_SUCCESS)
  702. goto Cleanup;
  703. //
  704. // Find the key representing the root
  705. //
  706. dwErr = RegEnumKey(hLvolKey, 0, wCp, 100);
  707. if (dwErr != ERROR_SUCCESS)
  708. goto Cleanup;
  709. dwErr = RegOpenKey(hLvolKey, wCp, &hRootKey);
  710. if (dwErr != ERROR_SUCCESS)
  711. goto Cleanup;
  712. while (dwErr == ERROR_SUCCESS && RegEnumKey(hRootKey, 0, wCp, 100) == ERROR_SUCCESS)
  713. dwErr = DfsDeleteChildKeys(hRootKey, wCp);
  714. Cleanup:
  715. if (hLvolKey != NULL)
  716. RegCloseKey(hLvolKey);
  717. if (hRootKey != NULL)
  718. RegCloseKey(hRootKey);
  719. if (wCp != NULL)
  720. free(wCp);
  721. return dwErr;
  722. }
  723. //+----------------------------------------------------------------------------
  724. //
  725. // Function: DfsRegDeleteChildKeys
  726. //
  727. // Synopsis: Helper for DfsRegDeleteKeyAndChildren
  728. //
  729. // Arguments:
  730. //
  731. // Returns: ERROR_SUCCESS or failure code
  732. //
  733. //-----------------------------------------------------------------------------
  734. DWORD
  735. DfsDeleteChildKeys(HKEY hKey, LPWSTR s)
  736. {
  737. WCHAR *wCp;
  738. HKEY nKey = NULL;
  739. DWORD dwErr;
  740. DWORD i = 0;
  741. dwErr = RegOpenKey(hKey, s, &nKey);
  742. if (dwErr != ERROR_SUCCESS)
  743. return dwErr;
  744. for (wCp = s; *wCp; wCp++)
  745. ;
  746. while (dwErr == ERROR_SUCCESS && RegEnumKey(nKey, 0, wCp, 100) == ERROR_SUCCESS)
  747. dwErr = DfsDeleteChildKeys(nKey, wCp);
  748. *wCp = L'\0';
  749. if (nKey != NULL)
  750. RegCloseKey(nKey);
  751. dwErr = RegDeleteKey(hKey, s);
  752. return dwErr;
  753. }