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.

2517 lines
61 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation
  4. //
  5. // File: dfssetup.cxx
  6. //
  7. // Contents: Code to setup Dfs on a machine.
  8. //
  9. // Note that this code can be built as an exe or as a DLL. To
  10. // switch between the two, simply edit the following fields in
  11. // the sources file:
  12. // TARGETTYPE=[PROGRAM | DYNLINK]
  13. // UMTYPE=[console | windows]
  14. // Delete the following two lines from sources to build an exe.
  15. // DLLDEF=obj\*\dfssetup.def
  16. // DLLENTRY=_DllMainCRTStartup
  17. // DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,dfssetup
  18. //
  19. // Classes: None
  20. //
  21. // Functions:
  22. //
  23. // History: 12-28-95 Milans Created
  24. //
  25. //-----------------------------------------------------------------------------
  26. extern "C" {
  27. #include <nt.h>
  28. #include <ntrtl.h>
  29. #include <nturtl.h>
  30. #include <stdlib.h>
  31. }
  32. #include <windows.h>
  33. #include <rpc.h> // For UuidCreate
  34. #include <winldap.h>
  35. #include <dsgetdc.h>
  36. #include <lm.h>
  37. #include <dfsstr.h>
  38. #include <dfsmsrv.h>
  39. #include <debug.h> // Needed for debug printing
  40. #include <dfsm.hxx> // Needed for volume types
  41. #include <lmerrext.h>
  42. #include "registry.hxx" // Helper functions...
  43. #include "setupsvc.hxx"
  44. #include "config.hxx" // Config UI functions
  45. //
  46. // Until we get the schema right in the DS, we have to set our own SD on
  47. // certain objects
  48. //
  49. #include <aclapi.h>
  50. #include <permit.h>
  51. DECLARE_DEBUG(DfsSetup)
  52. DECLARE_INFOLEVEL(DfsSetup)
  53. #if DBG == 1
  54. #define dprintf(x) DfsSetupInlineDebugOut x
  55. # else
  56. #define dprintf(x)
  57. #endif
  58. #define MAX_NETBIOS_NAME_LEN 16+1
  59. extern DWORD
  60. RemoveDfs(void);
  61. BOOLEAN
  62. DfsCheckForOldDfsService();
  63. BOOLEAN
  64. DfsIsDfsServiceRunning();
  65. VOID
  66. Usage();
  67. DWORD
  68. SetupDfsRoot(
  69. LPWSTR wszDfsRootShare);
  70. DWORD
  71. SetupFTDfs(
  72. IN LPWSTR wszRootShare,
  73. IN LPWSTR wszFTDfsName);
  74. DWORD
  75. InitializeVolumeObjectStorage();
  76. DWORD
  77. CreateVolumeObject(
  78. IN LPWSTR wszObjectName,
  79. IN LPWSTR pwszEntryPath,
  80. IN LPWSTR pwszServer,
  81. IN LPWSTR pwszShare,
  82. IN LPWSTR pwszComment,
  83. OUT GUID *guidVolume);
  84. DWORD
  85. CreateFTRootVolumeInfo(
  86. LPWSTR wszObjectName,
  87. LPWSTR wszFTDfsConfigDN,
  88. LPWSTR wszDomainName,
  89. LPWSTR wszDfsName,
  90. LPWSTR wszServerName,
  91. LPWSTR wszShareName,
  92. LPWSTR wszSharePath,
  93. LPWSTR wszDCName,
  94. BOOLEAN fNewFTDfs);
  95. DWORD
  96. StoreLvolInfo(
  97. IN GUID *pVolumeID,
  98. IN PWSTR pwszStorageID,
  99. IN PWSTR pwszShareName,
  100. IN PWSTR pwszEntryPath,
  101. IN ULONG ulVolumeType);
  102. DWORD
  103. GetDomainAndComputerName(
  104. OUT LPWSTR wszDomain OPTIONAL,
  105. OUT LPWSTR wszComputer OPTIONAL);
  106. DWORD
  107. GetSharePath(
  108. IN LPWSTR wszShareName,
  109. OUT LPWSTR wszSharePath);
  110. DWORD
  111. TeardownFtDfs(
  112. IN LPWSTR wszRootShare,
  113. IN LPWSTR wszFTDfsName);
  114. //+----------------------------------------------------------------------------
  115. //
  116. // Function: main
  117. //
  118. // Synopsis: Entry point in case you want to build this as an exe.
  119. // Configures all Dfs components on a machine.
  120. //
  121. // Arguments: [argc] --
  122. // [argv] --
  123. //
  124. // Returns: Nothing
  125. //
  126. //-----------------------------------------------------------------------------
  127. void _cdecl
  128. main(int argc, char *argv[])
  129. {
  130. DWORD dwErr = ERROR_SUCCESS;
  131. DWORD cbRootLen;
  132. BOOL fRootSetup = FALSE;
  133. BOOLEAN OldDfsService = FALSE;
  134. WCHAR wszDfsRootShare[ MAX_PATH ];
  135. //
  136. // Figure out the type of machine we are installing on - client or root
  137. //
  138. if (argc != 1 && argc != 3) {
  139. Usage();
  140. return;
  141. }
  142. if (argc == 3) {
  143. fRootSetup = TRUE;
  144. }
  145. if ((dwErr == ERROR_SUCCESS) && fRootSetup) {
  146. if (_stricmp( argv[1], "-root" ) != 0) {
  147. Usage();
  148. return;
  149. }
  150. cbRootLen = strlen(argv[2]);
  151. mbstowcs( wszDfsRootShare, argv[2], cbRootLen + 1 );
  152. dprintf((DEB_ERROR,"Setting up Dfs Root...\n"));
  153. } else {
  154. dprintf((DEB_ERROR,"Setting up Dfs Server...\n"));
  155. }
  156. //
  157. // Configure the Dfs Driver
  158. //
  159. if (dwErr == ERROR_SUCCESS) {
  160. dwErr = ConfigDfs();
  161. if (dwErr == ERROR_SUCCESS) {
  162. dwErr = ConfigDfsService();
  163. if (dwErr != ERROR_SUCCESS) {
  164. dprintf((
  165. DEB_ERROR, "Win32 error configuring Dfs Service %d\n",
  166. dwErr));
  167. (void)RemoveDfs();
  168. } else {
  169. dprintf((DEB_ERROR,"Successfully configured Dfs...\n") );
  170. }
  171. } else {
  172. dprintf((DEB_ERROR,"Error %d configuring Dfs driver!\n", dwErr));
  173. }
  174. }
  175. //
  176. // If this is a root setup, configure the necessary information
  177. //
  178. if (dwErr == ERROR_SUCCESS && fRootSetup) {
  179. dwErr = SetupDfsRoot( wszDfsRootShare );
  180. }
  181. }
  182. //+----------------------------------------------------------------------------
  183. //
  184. // Function: SetupDfsRoot
  185. //
  186. // Synopsis: Does necessary setup to make this Dfs a root of the Dfs.
  187. //
  188. // Arguments: [wszDfsRootShare] -- The share to use as the Dfs root.
  189. //
  190. // Returns: Win32 error from configuring the root storages etc.
  191. //
  192. //-----------------------------------------------------------------------------
  193. DWORD
  194. SetupDfsRoot(
  195. LPWSTR wszDfsRootShare)
  196. {
  197. DWORD dwErr = ERROR_SUCCESS;
  198. GUID guid;
  199. WCHAR wszDfsRootPath[ MAX_PATH ];
  200. WCHAR wszComputerName[ MAX_NETBIOS_NAME_LEN ];
  201. PWCHAR wszDfsRootPrefix = NULL;
  202. dwErr = GetDomainAndComputerName( NULL, wszComputerName );
  203. //
  204. // Figure out the share path for the Root Dfs share
  205. //
  206. if (dwErr == ERROR_SUCCESS) {
  207. dwErr = GetSharePath( wszDfsRootShare, wszDfsRootPath );
  208. }
  209. //
  210. // We have all the info we need now. Lets get to work....
  211. //
  212. // 1. Initialize the volume object section in the registry.
  213. //
  214. // 2. Initialize (ie, create if necessary) the storage used for the
  215. // Dfs root.
  216. //
  217. // 3. Create the root volume object.
  218. //
  219. // 4. Configure the root volume as a local volume by updating the
  220. // LocalVolumes section in the registry.
  221. //
  222. //
  223. // Initialize the Dfs Manager Volume Object Store
  224. //
  225. if (dwErr == ERROR_SUCCESS) {
  226. dwErr = InitializeVolumeObjectStorage();
  227. }
  228. if (dwErr == ERROR_SUCCESS) {
  229. dprintf((DEB_ERROR,
  230. "Setting [%ws] as Dfs storage root...\n", wszDfsRootPath));
  231. dwErr = DfsInitGlobals( wszComputerName, DFS_MANAGER_SERVER );
  232. if (dwErr == ERROR_SUCCESS) {
  233. wszDfsRootPrefix = new WCHAR[1 +
  234. wcslen(wszComputerName) +
  235. 1 +
  236. wcslen(wszDfsRootShare) +
  237. 1];
  238. if (wszDfsRootPrefix == NULL) {
  239. dwErr = ERROR_OUTOFMEMORY;
  240. }
  241. }
  242. if (dwErr == ERROR_SUCCESS) {
  243. wszDfsRootPrefix[0] = UNICODE_PATH_SEP;
  244. wcscpy( &wszDfsRootPrefix[1], wszComputerName );
  245. wcscat( wszDfsRootPrefix, UNICODE_PATH_SEP_STR );
  246. wcscat( wszDfsRootPrefix, wszDfsRootShare );
  247. dwErr = CreateVolumeObject(
  248. DOMAIN_ROOT_VOL, // Name of volume object
  249. wszDfsRootPrefix, // EntryPath of volume
  250. wszComputerName, // Server name
  251. wszDfsRootShare, // Share name
  252. L"Dfs Root Volume", // Comment
  253. &guid); // Id of created volume
  254. }
  255. if (dwErr == ERROR_SUCCESS) {
  256. dwErr = StoreLvolInfo(
  257. &guid,
  258. wszDfsRootPath,
  259. wszDfsRootShare,
  260. wszDfsRootPrefix,
  261. DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
  262. }
  263. if (wszDfsRootPrefix != NULL)
  264. delete [] wszDfsRootPrefix;
  265. if (dwErr != ERROR_SUCCESS)
  266. dwErr = ERROR_INVALID_FUNCTION;
  267. if (dwErr == ERROR_SUCCESS) {
  268. DWORD dwErr;
  269. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
  270. if (dwErr == ERROR_SUCCESS) {
  271. CRegSZ cregRootShare(
  272. cregVolumesDir,
  273. ROOT_SHARE_VALUE_NAME,
  274. wszDfsRootShare );
  275. dwErr = cregRootShare.QueryErrorStatus();
  276. }
  277. }
  278. }
  279. return( dwErr );
  280. }
  281. //+----------------------------------------------------------------------------
  282. //
  283. // Function: SetupFTDfs
  284. //
  285. // Synopsis: Main exported function
  286. //
  287. // Arguments: [argc] --
  288. // [argv] --
  289. //
  290. // Returns: Nothing
  291. //
  292. //-----------------------------------------------------------------------------
  293. DWORD
  294. SetupFTDfs(
  295. IN LPWSTR wszRootShare,
  296. IN LPWSTR wszFTDfsName)
  297. {
  298. DWORD dwErr = ERROR_SUCCESS;
  299. WCHAR wszDomainName[MAX_PATH+1];
  300. WCHAR wszComputerName[MAX_PATH+1];
  301. WCHAR wszRootSharePath[MAX_PATH+1];
  302. WCHAR wszDfsConfigDN[MAX_PATH+1];
  303. WCHAR wszSDDfsConfigDN[MAX_PATH+1];
  304. WCHAR wszConfigurationDN[ MAX_PATH+1 ];
  305. WCHAR wszServerShare[MAX_PATH+1];
  306. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  307. LDAP *pldap = NULL;
  308. PLDAPMessage pMsg = NULL;
  309. LDAPModW ldapModClass, ldapModCN, ldapModPkt, ldapModPktGuid, ldapModServer;
  310. LDAP_BERVAL ldapPkt, ldapPktGuid;
  311. PLDAP_BERVAL rgModPktVals[2];
  312. PLDAP_BERVAL rgModPktGuidVals[2];
  313. LPWSTR rgModClassVals[2];
  314. LPWSTR rgModCNVals[2];
  315. LPWSTR rgModServerVals[5];
  316. LPWSTR rgAttrs[5];
  317. PLDAPModW rgldapMods[6];
  318. BOOLEAN fNewFTDfs;
  319. //
  320. // We need some information before we start:
  321. //
  322. // 1. Our Domain name
  323. //
  324. // 2. Our Computer name
  325. //
  326. // 3. The share path of wszRootShare
  327. //
  328. // 4. The DN of the Configuration OU of our domain
  329. //
  330. dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName );
  331. if (dwErr != ERROR_SUCCESS) {
  332. dprintf((
  333. DEB_ERROR,
  334. "Win32 Error %d getting Domain/Computer name\n", dwErr));
  335. goto Cleanup;
  336. }
  337. dwErr = GetSharePath( wszRootShare, wszRootSharePath );
  338. if (dwErr != ERROR_SUCCESS) {
  339. dprintf((
  340. DEB_ERROR,
  341. "Win32 Error %d getting share path for %ws\n",
  342. dwErr, wszRootShare));
  343. goto Cleanup;
  344. }
  345. dwErr = DsGetDcName(
  346. NULL, // Computer to remote to
  347. NULL, // Domain - use our own
  348. NULL, // Domain Guid
  349. NULL, // Site Guid
  350. DS_DIRECTORY_SERVICE_REQUIRED | // Flags
  351. DS_PDC_REQUIRED,
  352. &pDCInfo); // Return info
  353. if (dwErr != ERROR_SUCCESS) {
  354. dprintf((
  355. DEB_ERROR,
  356. "DsGetDcName failed with Win32 Error %d\n", dwErr));
  357. goto Cleanup;
  358. }
  359. pldap = ldap_initW(&pDCInfo->DomainControllerAddress[2], LDAP_PORT);
  360. if (pldap == NULL) {
  361. dprintf((DEB_ERROR, "ldap_init failed\n"));
  362. goto Cleanup;
  363. }
  364. dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  365. if (dwErr != LDAP_SUCCESS) {
  366. dprintf((
  367. DEB_ERROR,
  368. "ldap_set_option failed with ldap error %d\n", dwErr));
  369. pldap = NULL;
  370. goto Cleanup;
  371. }
  372. dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI);
  373. if (dwErr != LDAP_SUCCESS) {
  374. dprintf((
  375. DEB_ERROR,
  376. "ldap_bind_s failed with ldap error %d\n", dwErr));
  377. pldap = NULL;
  378. goto Cleanup;
  379. }
  380. rgAttrs[0] = L"defaultnamingContext";
  381. rgAttrs[1] = NULL;
  382. dwErr = ldap_search_sW(
  383. pldap,
  384. L"",
  385. LDAP_SCOPE_BASE,
  386. L"(objectClass=*)",
  387. rgAttrs,
  388. 0,
  389. &pMsg);
  390. if (dwErr == LDAP_SUCCESS) {
  391. PLDAPMessage pEntry = NULL;
  392. PWCHAR *rgszNamingContexts = NULL;
  393. DWORD i, cNamingContexts;
  394. BOOLEAN fFoundCfg;
  395. if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL &&
  396. (rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL &&
  397. (cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) {
  398. wcscpy( wszConfigurationDN, *rgszNamingContexts );
  399. fFoundCfg = TRUE;
  400. if (!fFoundCfg) {
  401. dwErr = ERROR_UNEXP_NET_ERR;
  402. }
  403. } else {
  404. dwErr = ERROR_UNEXP_NET_ERR;
  405. }
  406. if (pEntry != NULL)
  407. ldap_msgfree( pEntry );
  408. if (rgszNamingContexts != NULL)
  409. ldap_value_freeW( rgszNamingContexts );
  410. }
  411. if (dwErr != ERROR_SUCCESS) {
  412. dprintf((DEB_ERROR, "Unable to find Configuration naming context\n"));
  413. goto Cleanup;
  414. }
  415. //
  416. // Great, we have all the parameters now, so configure the DS
  417. //
  418. //
  419. // See if the DfsConfiguration object exists; if not, create it.
  420. //
  421. wsprintf(
  422. wszDfsConfigDN,
  423. L"CN=Dfs-Configuration,CN=System,%ws",
  424. wszConfigurationDN);
  425. rgAttrs[0] = L"cn";
  426. rgAttrs[1] = NULL;
  427. dwErr = ldap_search_sW(
  428. pldap,
  429. wszDfsConfigDN,
  430. LDAP_SCOPE_BASE,
  431. L"(objectClass=*)",
  432. rgAttrs,
  433. 0,
  434. &pMsg);
  435. if (dwErr == LDAP_SUCCESS)
  436. ldap_msgfree( pMsg );
  437. if (dwErr == LDAP_NO_SUCH_OBJECT) {
  438. rgModClassVals[0] = L"dfsConfiguration";
  439. rgModClassVals[1] = NULL;
  440. ldapModClass.mod_op = LDAP_MOD_ADD;
  441. ldapModClass.mod_type = L"objectClass";
  442. ldapModClass.mod_vals.modv_strvals = rgModClassVals;
  443. rgModCNVals[0] = L"Dfs-Configuration";
  444. rgModCNVals[1] = NULL;
  445. ldapModCN.mod_op = LDAP_MOD_ADD;
  446. ldapModCN.mod_type = L"cn";
  447. ldapModCN.mod_vals.modv_strvals = rgModCNVals;
  448. rgldapMods[0] = &ldapModClass;
  449. rgldapMods[1] = &ldapModCN;
  450. rgldapMods[2] = NULL;
  451. dwErr = ldap_add_sW(
  452. pldap,
  453. wszDfsConfigDN,
  454. rgldapMods);
  455. }
  456. if (dwErr != LDAP_SUCCESS) {
  457. dprintf((
  458. DEB_ERROR,
  459. "1:ldap_add_s for %ws failed with LDAP error %d\n",
  460. wszDfsConfigDN, dwErr ));
  461. goto Cleanup;
  462. }
  463. //
  464. // Check to see if we are joining an FTDfs or creating a new one.
  465. //
  466. wsprintf(
  467. wszDfsConfigDN,
  468. L"CN=%ws,CN=Dfs-Configuration,CN=System,%ws",
  469. wszFTDfsName,
  470. wszConfigurationDN);
  471. wsprintf(
  472. wszServerShare,
  473. L"\\\\%ws\\%ws",
  474. wszComputerName,
  475. wszRootShare);
  476. rgAttrs[0] = L"remoteServerName";
  477. rgAttrs[1] = NULL;
  478. dwErr = ldap_search_sW(
  479. pldap,
  480. wszDfsConfigDN,
  481. LDAP_SCOPE_BASE,
  482. L"(objectClass=*)",
  483. rgAttrs,
  484. 0,
  485. &pMsg);
  486. if (dwErr == ERROR_SUCCESS) {
  487. //
  488. // We are joining an existing FT Dfs. Append our server\share to it
  489. //
  490. LDAPMessage *pmsgServers;
  491. PWCHAR *rgServers, *rgNewServers;
  492. DWORD cServers;
  493. fNewFTDfs = FALSE;
  494. pmsgServers = ldap_first_entry(pldap, pMsg);
  495. if (pmsgServers != NULL) {
  496. rgServers = ldap_get_valuesW(
  497. pldap,
  498. pmsgServers,
  499. L"remoteServerName");
  500. if (rgServers != NULL) {
  501. cServers = ldap_count_valuesW( rgServers );
  502. rgNewServers = new LPWSTR [ cServers + 2 ];
  503. if (rgNewServers != NULL) {
  504. CopyMemory( rgNewServers, rgServers, cServers * sizeof(rgServers[0]) );
  505. rgNewServers[cServers] = wszServerShare;
  506. rgNewServers[cServers+1] = NULL;
  507. ldapModServer.mod_op = LDAP_MOD_REPLACE;
  508. ldapModServer.mod_type = L"remoteServerName";
  509. ldapModServer.mod_vals.modv_strvals = rgNewServers;
  510. rgldapMods[0] = &ldapModServer;
  511. rgldapMods[1] = NULL;
  512. dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
  513. if (LDAP_ATTRIBUTE_OR_VALUE_EXISTS == dwErr)
  514. dwErr = ERROR_SUCCESS;
  515. delete [] rgNewServers;
  516. } else {
  517. dwErr = ERROR_OUTOFMEMORY;
  518. }
  519. ldap_value_freeW( rgServers );
  520. } else {
  521. dwErr = ERROR_OUTOFMEMORY;
  522. }
  523. ldap_msgfree( pmsgServers );
  524. } else {
  525. dwErr = ERROR_OUTOFMEMORY;
  526. }
  527. } else if (dwErr == LDAP_NO_SUCH_OBJECT) {
  528. GUID idPkt;
  529. DWORD dwPktVersion = 1;
  530. //
  531. // We are creating a new FTDfs, create a container to hold the Dfs
  532. // configuration for it.
  533. //
  534. fNewFTDfs = TRUE;
  535. //
  536. // Generate the class and CN attributes
  537. //
  538. rgModClassVals[0] = L"ftDfs";
  539. rgModClassVals[1] = NULL;
  540. ldapModClass.mod_op = LDAP_MOD_ADD;
  541. ldapModClass.mod_type = L"objectClass";
  542. ldapModClass.mod_vals.modv_strvals = rgModClassVals;
  543. rgModCNVals[0] = wszFTDfsName;
  544. rgModCNVals[1] = NULL;
  545. ldapModCN.mod_op = LDAP_MOD_ADD;
  546. ldapModCN.mod_type = L"cn";
  547. ldapModCN.mod_vals.modv_strvals = rgModCNVals;
  548. //
  549. // Generate the null PKT attribute
  550. //
  551. ldapPkt.bv_len = sizeof(DWORD);
  552. ldapPkt.bv_val = (PCHAR) &dwPktVersion;
  553. rgModPktVals[0] = &ldapPkt;
  554. rgModPktVals[1] = NULL;
  555. ldapModPkt.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
  556. ldapModPkt.mod_type = L"pKT";
  557. ldapModPkt.mod_vals.modv_bvals = rgModPktVals;
  558. //
  559. // Generate a PKT Guid attribute
  560. //
  561. UuidCreate( &idPkt );
  562. ldapPktGuid.bv_len = sizeof(GUID);
  563. ldapPktGuid.bv_val = (PCHAR) &idPkt;
  564. rgModPktGuidVals[0] = &ldapPktGuid;
  565. rgModPktGuidVals[1] = NULL;
  566. ldapModPktGuid.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
  567. ldapModPktGuid.mod_type = L"pKTGuid";
  568. ldapModPktGuid.mod_vals.modv_bvals = rgModPktGuidVals;
  569. //
  570. // Generate a Remote-Server-Name attribute
  571. //
  572. rgModServerVals[0] = wszServerShare;
  573. rgModServerVals[1] = NULL;
  574. ldapModServer.mod_op = LDAP_MOD_ADD;
  575. ldapModServer.mod_type = L"remoteServerName";
  576. ldapModServer.mod_vals.modv_strvals = rgModServerVals;
  577. //
  578. // Assemble all the LDAPMod structures
  579. //
  580. rgldapMods[0] = &ldapModClass;
  581. rgldapMods[1] = &ldapModCN;
  582. rgldapMods[2] = &ldapModPkt;
  583. rgldapMods[3] = &ldapModPktGuid;
  584. rgldapMods[4] = &ldapModServer;
  585. rgldapMods[5] = NULL;
  586. //
  587. // Create the Dfs metadata object.
  588. //
  589. dwErr = ldap_add_sW( pldap, wszDfsConfigDN, rgldapMods );
  590. if (dwErr == ERROR_SUCCESS) {
  591. dprintf((
  592. DEB_ERROR,
  593. "2:ldap_add_s worked for %ws with ldap error %d\n",
  594. wszDfsConfigDN, dwErr));
  595. }
  596. }
  597. if (dwErr != LDAP_SUCCESS) {
  598. dprintf((
  599. DEB_ERROR,
  600. "2:ldap_add_s failed for %ws with ldap error %d\n",
  601. wszDfsConfigDN, dwErr));
  602. goto Cleanup;
  603. }
  604. //
  605. // Finally, create the root volume object
  606. //
  607. dwErr = CreateFTRootVolumeInfo(
  608. DOMAIN_ROOT_VOL,
  609. wszDfsConfigDN,
  610. wszDomainName,
  611. wszFTDfsName,
  612. wszComputerName,
  613. wszRootShare,
  614. wszRootSharePath,
  615. &pDCInfo->DomainControllerAddress[2],
  616. fNewFTDfs);
  617. if (dwErr != LDAP_SUCCESS) {
  618. dprintf((
  619. DEB_ERROR, "CreateVolumeObject failed with error %d\n", dwErr));
  620. } else {
  621. dprintf((
  622. DEB_ERROR, "Successfully created FT-Dfs Configuration!\n"));
  623. }
  624. Cleanup:
  625. if (pDCInfo != NULL)
  626. NetApiBufferFree( pDCInfo );
  627. if (pldap != NULL)
  628. ldap_unbind( pldap );
  629. return( dwErr );
  630. }
  631. //+----------------------------------------------------------------------------
  632. //
  633. // Function: RemoveDfsRoot
  634. //
  635. // Synopsis: Removes the Dfs Root config info.
  636. //
  637. // Arguments: None
  638. //
  639. // Returns: Win32 error from registry actions
  640. //
  641. //-----------------------------------------------------------------------------
  642. DWORD
  643. RemoveDfsRoot()
  644. {
  645. DWORD dwErr;
  646. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
  647. CRegKey *pcregLV = NULL;
  648. if (dwErr != ERROR_SUCCESS) { // Unable to open volumes dir
  649. return(dwErr);
  650. }
  651. pcregLV = new CRegKey( // Open local volumes section
  652. HKEY_LOCAL_MACHINE,
  653. REG_KEY_LOCAL_VOLUMES);
  654. if (pcregLV != NULL) {
  655. dwErr = pcregLV->QueryErrorStatus();
  656. } else {
  657. dwErr = ERROR_OUTOFMEMORY;
  658. }
  659. if (dwErr == ERROR_SUCCESS) {
  660. dwErr = pcregLV->Delete(); // Delete local volumes
  661. delete pcregLV;
  662. pcregLV = NULL;
  663. if (dwErr == ERROR_SUCCESS) {
  664. //
  665. // Recreate an empty local volumes key
  666. //
  667. pcregLV = new CRegKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES);
  668. cregVolumesDir.Delete(); // Delete volumes dir
  669. }
  670. }
  671. if (pcregLV != NULL) {
  672. delete pcregLV;
  673. }
  674. return( dwErr );
  675. }
  676. //+----------------------------------------------------------------------------
  677. //
  678. // Function: DfsSetupDfs
  679. //
  680. // Synopsis: Entry point in case you want to build this as a DLL. This
  681. // function is suitable for being called from a setup .inf
  682. // file.
  683. //
  684. // Arguments: [cArgs] -- Count of args
  685. // [lpszArgs] -- Array of args
  686. // [lpszTextOut] -- On return, points to a global buffer
  687. // containing the null string. This is required by the
  688. // .inf file
  689. //
  690. // Returns: TRUE.
  691. //
  692. //-----------------------------------------------------------------------------
  693. LPSTR szReturn = "";
  694. extern "C" BOOL
  695. DfsSetupDfs(
  696. DWORD cArgs,
  697. LPSTR lpszArgs[],
  698. LPSTR *lpszTextOut)
  699. {
  700. int argc;
  701. LPSTR *argv;
  702. argv = (LPSTR *) malloc( (cArgs+1) * sizeof(LPSTR) );
  703. if (argv == NULL) {
  704. return( FALSE );
  705. }
  706. argv[0] = "DfsSetup";
  707. for (argc = 1; argc <= (int) cArgs; argc++) {
  708. argv[ argc ] = lpszArgs[ argc-1 ];
  709. }
  710. main( argc, argv );
  711. free( argv );
  712. *lpszTextOut = szReturn;
  713. return( TRUE );
  714. }
  715. //+----------------------------------------------------------------------------
  716. //
  717. // Function: DfsSetupDfsRoot
  718. //
  719. // Synopsis: Entry point for setting up just the root part of Dfs in
  720. // case you want to build this as a DLL. This function is
  721. // suitable for being called from a setup .inf file.
  722. //
  723. // Arguments: [cArgs] -- Count of args
  724. // [lpszArgs] -- Array of args
  725. // [lpszTextOut] -- On return, points to a global buffer
  726. // containing the null string. This is required by the
  727. // .inf file
  728. //
  729. // Returns: TRUE.
  730. //
  731. //-----------------------------------------------------------------------------
  732. BOOLEAN
  733. DfsSetupDfsRoot(
  734. DWORD cArgs,
  735. LPSTR szArgs[],
  736. LPSTR *szTextOut)
  737. {
  738. if (cArgs == 1) {
  739. DWORD dwErr;
  740. WCHAR wszDfsRootShare[MAX_PATH];
  741. mbstowcs( wszDfsRootShare, szArgs[0], strlen(szArgs[0]) + 1);
  742. dwErr = SetupDfsRoot( wszDfsRootShare );
  743. }
  744. *szTextOut = szReturn;
  745. return( TRUE );
  746. }
  747. //+----------------------------------------------------------------------------
  748. //
  749. // Function: DfsSetupGetConfig
  750. //
  751. // Synopsis: Reads the current configuration from the registry.
  752. //
  753. // Arguments: [pcfg] -- The DFS_CONFIGURATION info to fill
  754. //
  755. // Returns: TRUE if successfully read the config info, FALSE otherwise
  756. //
  757. //-----------------------------------------------------------------------------
  758. BOOLEAN
  759. DfsSetupGetConfig(
  760. HWND hwnd,
  761. DFS_CONFIGURATION *pcfg)
  762. {
  763. DWORD dwErr;
  764. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
  765. ULONG cbBuffer;
  766. WCHAR wszErr[128];
  767. ZeroMemory( pcfg, sizeof(DFS_CONFIGURATION) );
  768. if (dwErr == ERROR_ACCESS_DENIED) {
  769. MessageBox(
  770. hwnd,
  771. L"Insufficient priviledge",
  772. DFS_COMPONENT_NAME,
  773. MB_OK | MB_ICONSTOP);
  774. return( FALSE );
  775. } else if (dwErr != ERROR_SUCCESS && dwErr != ERROR_FILE_NOT_FOUND) {
  776. swprintf(wszErr, L"Unexpected error %08lx accessing registry", dwErr);
  777. MessageBox( hwnd, wszErr, DFS_COMPONENT_NAME, MB_OK | MB_ICONSTOP);
  778. return( FALSE );
  779. }
  780. if (dwErr == ERROR_SUCCESS) {
  781. pcfg->fHostsDfs = TRUE;
  782. CRegSZ cregRootShare( cregVolumesDir, ROOT_SHARE_VALUE_NAME );
  783. dwErr = cregRootShare.QueryErrorStatus();
  784. if (dwErr == ERROR_SUCCESS) {
  785. cbBuffer = sizeof(pcfg->szRootShare);
  786. dwErr = cregRootShare.GetString( pcfg->szRootShare, &cbBuffer );
  787. }
  788. if (dwErr == ERROR_SUCCESS) {
  789. DWORD dwErrFTDfs;
  790. CRegSZ cregFTDfs( cregVolumesDir, FTDFS_VALUE_NAME );
  791. dwErrFTDfs = cregFTDfs.QueryErrorStatus();
  792. if (dwErrFTDfs == ERROR_SUCCESS) {
  793. pcfg->fFTDfs = TRUE;
  794. cbBuffer = sizeof(pcfg->szFTDfs);
  795. dwErr = cregFTDfs.GetString(pcfg->szFTDfs, &cbBuffer);
  796. }
  797. }
  798. if (dwErr != ERROR_SUCCESS) {
  799. swprintf(wszErr, L"Error %08lx accessing registry", dwErr);
  800. MessageBox( hwnd, wszErr, DFS_COMPONENT_NAME, MB_OK | MB_ICONSTOP);
  801. return( FALSE );
  802. }
  803. }
  804. return( TRUE );
  805. }
  806. //+----------------------------------------------------------------------------
  807. //
  808. // Function: DfsSetupConfigure
  809. //
  810. // Synopsis: Presents the dialog box for configuring the Dfs root.
  811. //
  812. // Arguments: [cArgs] -- Count of args
  813. // [lpszArgs] -- Array of args
  814. // [lpszTextOut] -- On return, points to a global buffer
  815. // containing the name of the share selected by the
  816. // user to serve as the root of the Dfs. If the user
  817. // hits Cancel, or decides not to setup a Dfs root,
  818. // this string is set to point to the NULL string.
  819. //
  820. // Returns: TRUE iff machine should be rebooted
  821. //
  822. //-----------------------------------------------------------------------------
  823. LPSTR szCancel = "Cancel";
  824. LPSTR szReboot = "Reboot";
  825. BOOLEAN
  826. DfsSetupConfigure(
  827. DWORD cArgs,
  828. LPSTR szArgs[],
  829. LPSTR *szTextOut)
  830. {
  831. DWORD dwErr = 0;
  832. HWND hwnd;
  833. DFS_CONFIGURATION dfscfg, dfsNewCfg;
  834. CHAR *pchUnused;
  835. BOOLEAN fRtn=FALSE;
  836. *szTextOut = szCancel; // Default return result
  837. ASSERT( cArgs == 1 );
  838. hwnd = (HWND) LongToHandle( strtoul( szArgs[0], &pchUnused, 16 ) );
  839. //
  840. // Read the current configuration
  841. //
  842. HCURSOR hCursor=LoadCursor(NULL,IDC_WAIT);
  843. if (!DfsSetupGetConfig( hwnd, &dfscfg )) {
  844. return fRtn;
  845. }
  846. //
  847. // Next, pop up a dialog to allow the user to change the configuration
  848. //
  849. dfsNewCfg = dfscfg;
  850. // Prompt the user for what flavour of Dfs to create
  851. if (ConfigureDfs( hwnd, &dfsNewCfg ) == TRUE)
  852. {
  853. // Prompt the user for a local machine share
  854. if (ConfigDfsShare(hwnd, &dfsNewCfg) == TRUE)
  855. {
  856. // Set the Hourglass
  857. if (hCursor)
  858. SetCursor(hCursor);
  859. //
  860. // User hit OK. Figure out what changed, if anything.
  861. //
  862. if (dfscfg.fHostsDfs == FALSE && dfsNewCfg.fHostsDfs == FALSE) {
  863. //
  864. // No change...
  865. //
  866. NOTHING;
  867. } else if (dfscfg.fHostsDfs == FALSE && dfsNewCfg.fHostsDfs == TRUE) {
  868. //
  869. // We want to host a new Dfs, so call SetupDfsRoot or
  870. // SetupFTDfsRoot depending on what kind of Dfs Host the user
  871. // wants to setup
  872. //
  873. if (dfsNewCfg.fFTDfs) {
  874. dwErr = SetupFTDfs( dfsNewCfg.szRootShare, dfsNewCfg.szFTDfs );
  875. } else {
  876. dwErr = SetupDfsRoot( dfsNewCfg.szRootShare );
  877. }
  878. *szTextOut = szReboot;
  879. if (dwErr == 0) {
  880. CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS,
  881. NULL, REG_OPTION_VOLATILE);
  882. dwErr = RebootKey.QueryErrorStatus();
  883. if (dwErr) {
  884. dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n"));
  885. }
  886. else {
  887. CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1);
  888. dwErr = rvReboot.QueryErrorStatus();
  889. }
  890. }
  891. } else if (dfscfg.fHostsDfs == TRUE && dfsNewCfg.fHostsDfs == FALSE) {
  892. //
  893. // We want to delete our Dfs root
  894. //
  895. if (MessageBox(
  896. hwnd,
  897. L"Are you sure you want to delete the Dfs\n"
  898. L"rooted at this machine?",
  899. DFS_COMPONENT_NAME,
  900. MB_ICONQUESTION | MB_YESNO) == IDYES) {
  901. dwErr = RemoveDfsRoot();
  902. *szTextOut = dwErr == ERROR_SUCCESS ? szReboot : szCancel;
  903. if (dwErr == 0) {
  904. CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS,
  905. NULL, REG_OPTION_VOLATILE);
  906. dwErr = RebootKey.QueryErrorStatus();
  907. if (dwErr) {
  908. dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n"));
  909. }
  910. else {
  911. CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1);
  912. dwErr = rvReboot.QueryErrorStatus();
  913. }
  914. }
  915. }
  916. } else if (dfscfg.fHostsDfs == TRUE && dfsNewCfg.fHostsDfs == TRUE) {
  917. //
  918. // User might have changed the root share, or simply changed
  919. // status with respect to FTDfs
  920. //
  921. if ((_wcsicmp( dfscfg.szRootShare, dfsNewCfg.szRootShare )) != 0 ||
  922. dfscfg.fFTDfs != dfsNewCfg.fFTDfs) {
  923. dwErr = RemoveDfsRoot();
  924. if (dwErr == ERROR_SUCCESS) {
  925. if (dfsNewCfg.fFTDfs) {
  926. dwErr = SetupFTDfs(
  927. dfsNewCfg.szRootShare,
  928. dfsNewCfg.szFTDfs);
  929. } else {
  930. dwErr = SetupDfsRoot( dfsNewCfg.szRootShare );
  931. }
  932. }
  933. *szTextOut = szReboot;
  934. if (dwErr == 0) {
  935. CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS,
  936. NULL, REG_OPTION_VOLATILE);
  937. dwErr = RebootKey.QueryErrorStatus();
  938. if (dwErr) {
  939. dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n"));
  940. }
  941. else {
  942. CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1);
  943. dwErr = rvReboot.QueryErrorStatus();
  944. }
  945. }
  946. }
  947. //
  948. // Raid: 455295 Put in code to handle FTDfs name change
  949. //
  950. }
  951. //
  952. // Only request a reboot if everything has gone fine so far.
  953. // MariusB and JonN 8/20/97
  954. //
  955. if (!dwErr)
  956. fRtn=TRUE;
  957. }
  958. }
  959. return fRtn;
  960. }
  961. //+----------------------------------------------------------------------------
  962. //
  963. // Function: Usage
  964. //
  965. // Synopsis: Prints out the usage message in case you want to build this
  966. // as an .exe
  967. //
  968. // Arguments:
  969. //
  970. // Returns:
  971. //
  972. //-----------------------------------------------------------------------------
  973. VOID
  974. Usage()
  975. {
  976. dprintf((DEB_ERROR,"Usage: dfssetup -root <path name> -share <root share>\n"));
  977. dprintf((DEB_ERROR," <path name> is the name of an empty directory to use\n"));
  978. dprintf((DEB_ERROR," as the root storage for Dfs\n"));
  979. dprintf((DEB_ERROR," <root share> is the share name to access <path name>\n"));
  980. }
  981. //+----------------------------------------------------------------------------
  982. //
  983. // Function: InitializeVolumeObjectStorage
  984. //
  985. // Synopsis: Initializes the Dfs Manager Volume Object store.
  986. //
  987. // Arguments: None
  988. //
  989. // Returns: DWORD from registry operations.
  990. //
  991. //-----------------------------------------------------------------------------
  992. DWORD
  993. InitializeVolumeObjectStorage()
  994. {
  995. DWORD dwErr;
  996. CRegKey *pcregVolumeObjectStore = NULL;
  997. pcregVolumeObjectStore = new CRegKey(HKEY_LOCAL_MACHINE, VOLUMES_DIR );
  998. if (pcregVolumeObjectStore != NULL) {
  999. dwErr = pcregVolumeObjectStore->QueryErrorStatus();
  1000. if ( dwErr == ERROR_SUCCESS ) {
  1001. dwErr = pcregVolumeObjectStore->Delete();
  1002. if (dwErr == ERROR_SUCCESS) {
  1003. delete pcregVolumeObjectStore;
  1004. pcregVolumeObjectStore = new CRegKey(
  1005. HKEY_LOCAL_MACHINE,
  1006. VOLUMES_DIR );
  1007. if (pcregVolumeObjectStore != NULL) {
  1008. dwErr = pcregVolumeObjectStore->QueryErrorStatus();
  1009. } else {
  1010. dwErr = ERROR_OUTOFMEMORY;
  1011. }
  1012. }
  1013. }
  1014. } else {
  1015. dwErr = ERROR_OUTOFMEMORY;
  1016. }
  1017. if (dwErr == ERROR_SUCCESS) {
  1018. dprintf((DEB_ERROR,"Successfully inited Dfs Manager Volume Storage...\n"));
  1019. }
  1020. if (pcregVolumeObjectStore != NULL) {
  1021. delete pcregVolumeObjectStore;
  1022. }
  1023. return(dwErr);
  1024. }
  1025. //+----------------------------------------------------------------------------
  1026. //
  1027. // Function: CreateVolumeObject
  1028. //
  1029. // Synopsis: Creates a volume object to bootstrap the Dfs namespace.
  1030. //
  1031. // Arguments: [pwszObjectName] -- The name of the volume object, relative
  1032. // to VOLUMES_DIR
  1033. // [pwszEntryPath] -- EntryPath of the volume.
  1034. // [pwszServer] -- Name of server used to access this Dfs volume
  1035. // [pwszShare] -- Name of share used to access this Dfs volume
  1036. // [pwszComment] -- Comment to stamp on the volume object.
  1037. // [guidVolume] -- ID of newly create dfs volume
  1038. //
  1039. // Returns:
  1040. //
  1041. //-----------------------------------------------------------------------------
  1042. DWORD
  1043. CreateVolumeObject(
  1044. LPWSTR wszObjectName,
  1045. LPWSTR pwszEntryPath,
  1046. LPWSTR pwszServer,
  1047. LPWSTR pwszShare,
  1048. LPWSTR pwszComment,
  1049. GUID *guidVolume)
  1050. {
  1051. DWORD dwErr;
  1052. WCHAR wszFullObject[ MAX_PATH ];
  1053. //
  1054. // First, compute the full object name, storage ids, and machine name.
  1055. //
  1056. wcscpy( wszFullObject, VOLUMES_DIR );
  1057. wcscat( wszFullObject, wszObjectName );
  1058. //
  1059. // Next, get a guid for this volume
  1060. //
  1061. UuidCreate( guidVolume );
  1062. //
  1063. // Lastly, create this volume object
  1064. //
  1065. dwErr = DfsManagerCreateVolumeObject(
  1066. wszFullObject,
  1067. pwszEntryPath,
  1068. pwszServer,
  1069. pwszShare,
  1070. pwszComment,
  1071. guidVolume);
  1072. if (dwErr == ERROR_SUCCESS) {
  1073. dprintf((DEB_ERROR,"Successfully inited Dfs Manager Volume [%ws]...\n", pwszEntryPath));
  1074. }
  1075. return(dwErr);
  1076. }
  1077. //+----------------------------------------------------------------------------
  1078. //
  1079. // Function: CreateFTRootVolumeInfo
  1080. //
  1081. // Synopsis: Creates a Dfs volume object - used to bootstrap a Dfs by
  1082. // creating a root volume object
  1083. //
  1084. // Arguments: [wszObjectName] -- Name of volume object
  1085. // [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS
  1086. // [wszDomainName] -- Name of FTDfs domain
  1087. // [wszDfsName] -- Name of Dfs
  1088. // [wszServerName] -- Name of root server
  1089. // [wszShareName] -- Name of root share
  1090. // [wszDCName] -- DC to use
  1091. // [fNewFTDfs] -- If true, this is a new FTDfs
  1092. //
  1093. // Returns:
  1094. //
  1095. //-----------------------------------------------------------------------------
  1096. DWORD
  1097. CreateFTRootVolumeInfo(
  1098. LPWSTR wszObjectName,
  1099. LPWSTR wszFTDfsConfigDN,
  1100. LPWSTR wszDomainName,
  1101. LPWSTR wszDfsName,
  1102. LPWSTR wszServerName,
  1103. LPWSTR wszShareName,
  1104. LPWSTR wszSharePath,
  1105. LPWSTR wszDCName,
  1106. BOOLEAN fNewFTDfs)
  1107. {
  1108. DWORD dwErr = ERROR_SUCCESS;
  1109. WCHAR wszFullObjectName[ MAX_PATH ];
  1110. WCHAR wszDfsPrefix[ MAX_PATH ];
  1111. GUID idVolume;
  1112. static BOOLEAN fInited = FALSE;
  1113. wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  1114. wcscat( wszDfsPrefix, wszDomainName );
  1115. wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  1116. wcscat( wszDfsPrefix, wszDfsName );
  1117. wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
  1118. wcscat( wszFullObjectName, wszObjectName );
  1119. if (!fInited) {
  1120. //
  1121. // Create the volumes dir key that indicates that this machine is to
  1122. // be a root of an FTDfs
  1123. //
  1124. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, VOLUMES_DIR );
  1125. dwErr = cregVolumesDir.QueryErrorStatus();
  1126. if (dwErr == ERROR_SUCCESS) {
  1127. CRegSZ cregRootShare(
  1128. cregVolumesDir,
  1129. ROOT_SHARE_VALUE_NAME,
  1130. wszShareName );
  1131. dwErr = cregRootShare.QueryErrorStatus();
  1132. if (dwErr == ERROR_SUCCESS) {
  1133. CRegSZ cregFTDfs(
  1134. cregVolumesDir,
  1135. FTDFS_VALUE_NAME,
  1136. wszDfsName);
  1137. CRegSZ cregFTDfsConfigDN(
  1138. cregVolumesDir,
  1139. FTDFS_DN_VALUE_NAME,
  1140. wszFTDfsConfigDN);
  1141. dwErr = cregFTDfs.QueryErrorStatus();
  1142. if (dwErr == ERROR_SUCCESS) {
  1143. dwErr = cregFTDfsConfigDN.QueryErrorStatus();
  1144. if (dwErr != ERROR_SUCCESS)
  1145. cregFTDfs.Delete();
  1146. }
  1147. }
  1148. }
  1149. if (dwErr == ERROR_SUCCESS) {
  1150. dwErr = DfsInitGlobals(
  1151. wszDfsName,
  1152. DFS_MANAGER_FTDFS);
  1153. }
  1154. if (dwErr == ERROR_SUCCESS)
  1155. fInited = TRUE;
  1156. }
  1157. DfsManagerSetDcName(wszDCName);
  1158. if (dwErr == ERROR_SUCCESS) {
  1159. if (fNewFTDfs) {
  1160. //
  1161. // Generate a Guid for the new Volume
  1162. //
  1163. UuidCreate( &idVolume );
  1164. dwErr = DfsManagerCreateVolumeObject(
  1165. wszFullObjectName,
  1166. wszDfsPrefix,
  1167. wszServerName,
  1168. wszShareName,
  1169. L"Root Volume",
  1170. &idVolume);
  1171. } else {
  1172. dwErr = DfsManagerAddService(
  1173. wszFullObjectName,
  1174. wszServerName,
  1175. wszShareName,
  1176. &idVolume);
  1177. }
  1178. }
  1179. if (dwErr == ERROR_SUCCESS) {
  1180. dwErr = StoreLvolInfo(
  1181. &idVolume,
  1182. wszSharePath,
  1183. wszShareName,
  1184. wszDfsPrefix,
  1185. DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
  1186. }
  1187. return( dwErr );
  1188. }
  1189. //+----------------------------------------------------------------------------
  1190. //
  1191. // Function: StoreLvolInfo
  1192. //
  1193. // Synopsis: Stores information about a local volume in the registry.
  1194. //
  1195. // Arguments: [pVolumeID] -- Id of dfs volume
  1196. // [pwszStorageId] -- Storage used by dfs volume
  1197. // [pwszShareName] -- LM Share used to access dfs volume
  1198. // [pwszEntryPath] -- EntryPath of dfs volume
  1199. // [ulVolumeType] -- Type of dfs volume. See DFS_VOL_TYPE_xxx
  1200. //
  1201. // Returns: DWORD from registry operations.
  1202. //
  1203. //-----------------------------------------------------------------------------
  1204. extern VOID
  1205. GuidToString(
  1206. IN GUID *pID,
  1207. OUT PWSTR pwszID);
  1208. DWORD
  1209. StoreLvolInfo(
  1210. IN GUID *pVolumeID,
  1211. IN PWSTR pwszStorageID,
  1212. IN PWSTR pwszShareName,
  1213. IN PWSTR pwszEntryPath,
  1214. IN ULONG ulVolumeType)
  1215. {
  1216. DWORD dwErr;
  1217. WCHAR wszLvolKey[_MAX_PATH];
  1218. UNICODE_STRING ustrNtStorageId;
  1219. PWCHAR pwcGuid;
  1220. wcscpy(wszLvolKey, REG_KEY_LOCAL_VOLUMES);
  1221. wcscat(wszLvolKey, UNICODE_PATH_SEP_STR);
  1222. pwcGuid = wszLvolKey + wcslen(wszLvolKey);
  1223. ASSERT( *pwcGuid == UNICODE_NULL );
  1224. GuidToString( pVolumeID, pwcGuid );
  1225. if (!RtlDosPathNameToNtPathName_U(
  1226. pwszStorageID,
  1227. &ustrNtStorageId,
  1228. NULL,
  1229. NULL)) {
  1230. return(ERROR_OUTOFMEMORY);
  1231. } else {
  1232. ustrNtStorageId.Buffer[ustrNtStorageId.Length/sizeof(WCHAR)] = UNICODE_NULL;
  1233. }
  1234. CRegKey rkeyLvol(HKEY_LOCAL_MACHINE, wszLvolKey, KEY_WRITE, NULL, REG_OPTION_NON_VOLATILE);
  1235. dwErr = rkeyLvol.QueryErrorStatus();
  1236. if (dwErr != ERROR_SUCCESS) {
  1237. RtlFreeUnicodeString(&ustrNtStorageId);
  1238. return(dwErr);
  1239. }
  1240. CRegSZ rvEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_PATH, pwszEntryPath);
  1241. CRegSZ rvShortEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_SHORT_PATH, pwszEntryPath);
  1242. CRegDWORD rvEntryType((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_TYPE, ulVolumeType);
  1243. CRegSZ rvStorageId((const CRegKey &) rkeyLvol, REG_VALUE_STORAGE_ID, ustrNtStorageId.Buffer);
  1244. CRegSZ rvShareName((const CRegKey &) rkeyLvol, REG_VALUE_SHARE_NAME, pwszShareName);
  1245. RtlFreeUnicodeString(&ustrNtStorageId);
  1246. if (ERROR_SUCCESS != (dwErr = rvEntryPath.QueryErrorStatus()) ||
  1247. ERROR_SUCCESS != (dwErr = rvShortEntryPath.QueryErrorStatus()) ||
  1248. ERROR_SUCCESS != (dwErr = rvEntryType.QueryErrorStatus()) ||
  1249. ERROR_SUCCESS != (dwErr = rvStorageId.QueryErrorStatus()) ||
  1250. ERROR_SUCCESS != (dwErr = rvShareName.QueryErrorStatus())) {
  1251. rkeyLvol.Delete();
  1252. } else {
  1253. dprintf((DEB_ERROR,"Successfully stored local volume info for [%ws]\n", pwszEntryPath));
  1254. }
  1255. return(dwErr);
  1256. }
  1257. //+------------------------------------------------------------------
  1258. //
  1259. // Function: CheckForOldDfsService
  1260. //
  1261. // Synopsis:
  1262. //
  1263. // Effects: -none-
  1264. //
  1265. // Arguments: -none-
  1266. //
  1267. // Returns: TRUE if the old (pre -ds build) dfs service is installed
  1268. //
  1269. //
  1270. // History: 10-09-96 JimMcN Created
  1271. //
  1272. // Notes:
  1273. //
  1274. //
  1275. //-------------------------------------------------------------------
  1276. BOOLEAN DfsCheckForOldDfsService( )
  1277. {
  1278. DWORD dwErr = 0;
  1279. DWORD DfsVersion;
  1280. // Open Service Controller
  1281. CService cSvc;
  1282. if (!(dwErr = cSvc.Init()))
  1283. {
  1284. dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS);
  1285. cSvc._CloseService();
  1286. if (dwErr != 0) {
  1287. return(FALSE);
  1288. }
  1289. CRegKey cregDfsService( HKEY_LOCAL_MACHINE,
  1290. &dwErr,
  1291. L"System\\CurrentControlSet\\Services\\Dfs"
  1292. );
  1293. if (dwErr == ERROR_SUCCESS) {
  1294. CRegDWORD DfsNewService((const CRegKey &)cregDfsService,
  1295. L"DfsVersion", &DfsVersion);
  1296. dwErr = DfsNewService.QueryErrorStatus();
  1297. if (dwErr != 0) {
  1298. dprintf((DEB_ERROR,"CheckForOldDfsService Failed Newserv\n"));
  1299. return(TRUE);
  1300. }
  1301. if (DfsVersion < DFS_VERSION_NUMBER) {
  1302. return(TRUE);
  1303. }
  1304. return(FALSE);
  1305. }
  1306. return(FALSE);
  1307. }
  1308. return FALSE ;
  1309. }
  1310. //+----------------------------------------------------------------------------
  1311. //
  1312. // Function: GetDomainAndComputerName
  1313. //
  1314. // Synopsis: Retrieves the domain and computer name of the local machine
  1315. //
  1316. // Arguments: [wszDomain] -- On successful return, contains name of domain.
  1317. // If this parameter is NULL on entry, the domain name is
  1318. // not returned.
  1319. //
  1320. // [wszComputer] -- On successful return, contains name of
  1321. // computer. If this parameter is NULL on entry, the
  1322. // computer name is not returned.
  1323. //
  1324. // Returns: [ERROR_SUCCESS] -- Successfully returning names.
  1325. //
  1326. // Win32 Error from calling NetWkstaGetInfo
  1327. //
  1328. //-----------------------------------------------------------------------------
  1329. DWORD
  1330. GetDomainAndComputerName(
  1331. OUT LPWSTR wszDomain OPTIONAL,
  1332. OUT LPWSTR wszComputer OPTIONAL)
  1333. {
  1334. DWORD dwErr;
  1335. PWKSTA_INFO_100 wkstaInfo = NULL;
  1336. dwErr = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo );
  1337. if (dwErr == NERR_Success) {
  1338. if (wszDomain)
  1339. wcscpy(wszDomain, wkstaInfo->wki100_langroup);
  1340. if (wszComputer)
  1341. wcscpy(wszComputer, wkstaInfo->wki100_computername);
  1342. NetApiBufferFree( wkstaInfo );
  1343. }
  1344. return( dwErr );
  1345. }
  1346. //+----------------------------------------------------------------------------
  1347. //
  1348. // Function: GetSharePath
  1349. //
  1350. // Synopsis: Returns the share path for a share on the local machine
  1351. //
  1352. // Arguments: [wszShare] -- Name of share
  1353. //
  1354. // [wszPath] -- On return, share path of wszShare
  1355. //
  1356. // Returns: [ERROR_SUCCESS] -- Successfully returning share path
  1357. //
  1358. // Win32 error from NetShareGetInfo
  1359. //
  1360. //-----------------------------------------------------------------------------
  1361. DWORD
  1362. GetSharePath(
  1363. IN LPWSTR wszShare,
  1364. OUT LPWSTR wszPath)
  1365. {
  1366. DWORD dwErr;
  1367. PSHARE_INFO_2 pshi2;
  1368. dwErr = NetShareGetInfo(
  1369. NULL, // Server (local machine)
  1370. wszShare, // Share Name
  1371. 2, // Level,
  1372. (LPBYTE *) &pshi2); // Buffer
  1373. if (dwErr == ERROR_SUCCESS) {
  1374. wcscpy( wszPath, pshi2->shi2_path );
  1375. NetApiBufferFree( pshi2 );
  1376. }
  1377. return( dwErr );
  1378. }
  1379. //+----------------------------------------------------------------------------
  1380. //
  1381. // Function: DfsIsServiceRunning
  1382. //
  1383. // Synopsis: Check for active dfs servvice..
  1384. //
  1385. // Arguments:
  1386. //
  1387. // Returns: [TRUE] -- if dfs service is active.
  1388. // FALSE otherwise.
  1389. //
  1390. //-----------------------------------------------------------------------------
  1391. BOOLEAN
  1392. DfsIsDfsServiceRunning()
  1393. {
  1394. DWORD dwErr;
  1395. CService cSvc;
  1396. if (!(dwErr = cSvc.Init()))
  1397. {
  1398. dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS);
  1399. cSvc._CloseService();
  1400. return(dwErr == 0);
  1401. }
  1402. return(FALSE);
  1403. }
  1404. //+----------------------------------------------------------------------------
  1405. //
  1406. // Function: DfsGetDfsName
  1407. //
  1408. // Synopsis: Returns the share for a local dfs
  1409. //
  1410. // Arguments: [DfsRootShare] -- Name of share
  1411. //
  1412. // Returns: [TRUE] -- Successfully returning share path
  1413. //
  1414. // FALSE otherwise.
  1415. //
  1416. //-----------------------------------------------------------------------------
  1417. BOOLEAN
  1418. DfsGetDfsName(
  1419. OUT LPWSTR DfsRootShare,
  1420. IN OUT ULONG *Length,
  1421. OUT BOOLEAN *IsFtDfs)
  1422. {
  1423. DWORD dwErr;
  1424. ULONG SaveLength = *Length;
  1425. // CService cSvc;
  1426. ULONG ul = MAX_PATH;
  1427. WCHAR wc[MAX_PATH];
  1428. *IsFtDfs = FALSE;
  1429. #if 0
  1430. if (!(dwErr = cSvc.Init()))
  1431. {
  1432. dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS);
  1433. cSvc._CloseService();
  1434. if (dwErr != 0) {
  1435. return(FALSE);
  1436. }
  1437. }
  1438. #endif
  1439. CRegKey VolKey(HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR, KEY_READ);
  1440. if (dwErr) {
  1441. dprintf((DEB_ERROR,"DfsGetDfsName Failed to open VOLUMES_DIR\n"));
  1442. return(FALSE);
  1443. }
  1444. CRegSZ RootShare((const CRegKey &)VolKey, ROOT_SHARE_VALUE_NAME);
  1445. dwErr = RootShare.QueryErrorStatus();
  1446. if (dwErr) {
  1447. dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share name\n"));
  1448. return(FALSE);
  1449. }
  1450. dwErr = RootShare.GetString(DfsRootShare, Length);
  1451. if (dwErr) {
  1452. dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share val\n"));
  1453. return(FALSE);
  1454. }
  1455. CRegSZ FtDfs((const CRegKey &)VolKey, FTDFS_VALUE_NAME);
  1456. dwErr = FtDfs.QueryErrorStatus();
  1457. dwErr = FtDfs.GetString(wc, &ul);
  1458. *IsFtDfs = (dwErr == 0);
  1459. if (*IsFtDfs) {
  1460. memset(DfsRootShare, 0, SaveLength);
  1461. memcpy(DfsRootShare, wc, ul);
  1462. *Length=ul; }
  1463. dprintf((DEB_ERROR,"DfsGetDfsName is %s FTDFS\n", *IsFtDfs?"":"NOT"));
  1464. return(TRUE);
  1465. }
  1466. //+----------------------------------------------------------------------------
  1467. //
  1468. // Function: DfsNeedReboot
  1469. //
  1470. // Synopsis: Returns true if reboot is required for completing configuration.
  1471. //
  1472. // Arguments:
  1473. //
  1474. // Returns: [TRUE] -- Reboot Needed.
  1475. //
  1476. // FALSE otherwise.
  1477. //
  1478. //-----------------------------------------------------------------------------
  1479. BOOLEAN
  1480. DfsNeedReboot()
  1481. {
  1482. DWORD dwErr;
  1483. DWORD RebootDW = 20;
  1484. WCHAR buffer[20];
  1485. CRegKey RebootKey(HKEY_LOCAL_MACHINE, &dwErr, REBOOT_KEY, KEY_READ);
  1486. if (dwErr = RebootKey.QueryErrorStatus()) {
  1487. return(FALSE);
  1488. }
  1489. CRegSZ RebootVal((const CRegKey &)RebootKey, REG_VALUE_REBOOT);
  1490. dwErr = RebootVal.QueryErrorStatus();
  1491. DWORD GetString( LPWSTR pwszData, ULONG *pcbData);
  1492. dwErr = RebootVal.GetString(buffer, &RebootDW);
  1493. dprintf((DEB_ERROR,"DfsNeedReboot is %s Needed\n", dwErr == 0?"":"NOT"));
  1494. return(dwErr == 0);
  1495. }
  1496. //+----------------------------------------------------------------------------
  1497. //
  1498. // Function: DfsStopHostingDfs
  1499. //
  1500. // Synopsis: Remove this machine from a machine/ft dfs.
  1501. //
  1502. // Arguments:
  1503. //
  1504. // Returns: ERROR_SUCCESS if no error
  1505. //
  1506. // setup error otherwise.
  1507. //
  1508. //-----------------------------------------------------------------------------
  1509. DWORD
  1510. DfsStopHostingDfs()
  1511. {
  1512. DWORD dwErr = 0;
  1513. BOOLEAN ftDfs = FALSE;
  1514. ULONG ul = MAX_PATH;
  1515. WCHAR FtDfsName[MAX_PATH];
  1516. WCHAR DfsRootShare[MAX_PATH];
  1517. WCHAR wszFullObjectName[MAX_PATH];
  1518. WCHAR wszDomainName[MAX_PATH];
  1519. WCHAR wszComputerName[MAX_PATH];
  1520. if (DfsGetDfsName(FtDfsName, &ul, &ftDfs)) {
  1521. if (ftDfs) {
  1522. wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
  1523. wcscat( wszFullObjectName, DOMAIN_ROOT_VOL );
  1524. dwErr = DfsInitGlobals(
  1525. FtDfsName,
  1526. DFS_MANAGER_FTDFS);
  1527. if (dwErr) {
  1528. dprintf((DEB_ERROR,"DfsStopHostingDfs init globals fail.\n"));
  1529. return(dwErr);
  1530. }
  1531. CRegKey VolKey(HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR, KEY_READ);
  1532. if (dwErr) {
  1533. dprintf((DEB_ERROR,"DfsGetDfsName Failed to open VOLUMES_DIR\n"));
  1534. return(dwErr);
  1535. }
  1536. CRegSZ RootShare((const CRegKey &)VolKey, ROOT_SHARE_VALUE_NAME);
  1537. dwErr = RootShare.QueryErrorStatus();
  1538. if (dwErr) {
  1539. dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share name\n"));
  1540. return(dwErr);
  1541. }
  1542. ul = MAX_PATH;
  1543. dwErr = RootShare.GetString(DfsRootShare, &ul);
  1544. if (dwErr) {
  1545. dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share val\n"));
  1546. return(dwErr);
  1547. }
  1548. dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName );
  1549. if (dwErr) {
  1550. dprintf((DEB_ERROR,"DfsGetDfsName Failed computer name\n"));
  1551. return(dwErr);
  1552. }
  1553. dwErr = DfsManagerRemoveService(wszFullObjectName, wszComputerName);
  1554. if (dwErr && dwErr != NERR_DfsCantRemoveLastServerShare) {
  1555. return(dwErr);
  1556. }
  1557. dwErr = TeardownFtDfs(DfsRootShare, FtDfsName);
  1558. }
  1559. if (dwErr)
  1560. return(dwErr);
  1561. dwErr = RemoveDfsRoot();
  1562. }
  1563. if (dwErr == 0) {
  1564. CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS, NULL, REG_OPTION_VOLATILE);
  1565. dwErr = RebootKey.QueryErrorStatus();
  1566. if (dwErr) {
  1567. dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n"));
  1568. }
  1569. else {
  1570. CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1);
  1571. dwErr = rvReboot.QueryErrorStatus();
  1572. }
  1573. }
  1574. else {
  1575. dprintf((DEB_ERROR,"DfsStopHosting Dfs Failed to remove dfs root\n"));
  1576. }
  1577. return(dwErr);
  1578. }
  1579. //+----------------------------------------------------------------------------
  1580. //
  1581. // Function: TeardownFtDfs
  1582. //
  1583. // Synopsis: Removes FtDfs information from the ds.
  1584. //
  1585. // Arguments: wszRootShare the share hosting the dfs.
  1586. // wszFTDfsName the name of the FtDfs to remove from the ds.
  1587. //
  1588. //
  1589. // Returns: Nothing
  1590. //
  1591. //-----------------------------------------------------------------------------
  1592. DWORD
  1593. TeardownFtDfs(
  1594. IN LPWSTR wszRootShare,
  1595. IN LPWSTR wszFTDfsName)
  1596. {
  1597. DWORD dwErr = ERROR_SUCCESS;
  1598. DWORD i, j;
  1599. WCHAR wszDomainName[MAX_PATH];
  1600. WCHAR wszComputerName[MAX_PATH];
  1601. WCHAR wszRootSharePath[MAX_PATH];
  1602. WCHAR wszConfigurationDN[ MAX_PATH ];
  1603. WCHAR wszDfsConfigDN[ MAX_PATH ];
  1604. WCHAR wszServerShare[MAX_PATH];
  1605. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  1606. LDAP *pldap = NULL;
  1607. PLDAPMessage pMsg = NULL;
  1608. LDAPModW ldapModClass, ldapModCN, ldapModPkt, ldapModPktGuid, ldapModServer;
  1609. LDAP_BERVAL ldapPkt, ldapPktGuid;
  1610. PLDAP_BERVAL rgModPktVals[2];
  1611. PLDAP_BERVAL rgModPktGuidVals[2];
  1612. LPWSTR rgModClassVals[2];
  1613. LPWSTR rgModCNVals[2];
  1614. LPWSTR rgModServerVals[5];
  1615. LPWSTR rgAttrs[5];
  1616. PLDAPModW rgldapMods[6];
  1617. BOOLEAN fNewFTDfs;
  1618. //
  1619. // We need some information before we start:
  1620. //
  1621. // 1. Our Domain name
  1622. //
  1623. // 2. Our Computer name
  1624. //
  1625. // 3. The share path of wszRootShare
  1626. //
  1627. // 4. The DN of the Configuration OU of our domain
  1628. //
  1629. dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName );
  1630. if (dwErr != ERROR_SUCCESS) {
  1631. dprintf((
  1632. DEB_ERROR,
  1633. "Win32 Error %d getting Domain/Computer name\n", dwErr));
  1634. goto Cleanup;
  1635. }
  1636. dwErr = GetSharePath( wszRootShare, wszRootSharePath );
  1637. if (dwErr != ERROR_SUCCESS) {
  1638. dprintf((
  1639. DEB_ERROR,
  1640. "Win32 Error %d getting share path for %ws\n",
  1641. dwErr, wszRootShare));
  1642. goto Cleanup;
  1643. }
  1644. dwErr = DsGetDcName(
  1645. NULL, // Computer to remote to
  1646. NULL, // Domain - use our own
  1647. NULL, // Domain Guid
  1648. NULL, // Site Guid
  1649. DS_DIRECTORY_SERVICE_REQUIRED | // Flags
  1650. DS_PDC_REQUIRED,
  1651. &pDCInfo); // Return info
  1652. if (dwErr != ERROR_SUCCESS) {
  1653. dprintf((
  1654. DEB_ERROR,
  1655. "DsGetDcName failed with Win32 Error %d\n", dwErr));
  1656. goto Cleanup;
  1657. }
  1658. pldap = ldap_initW(&pDCInfo->DomainControllerAddress[2], LDAP_PORT);
  1659. if (pldap == NULL) {
  1660. dprintf((DEB_ERROR, "ldap_init failed\n"));
  1661. goto Cleanup;
  1662. }
  1663. dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  1664. if (dwErr != LDAP_SUCCESS) {
  1665. dprintf((
  1666. DEB_ERROR,
  1667. "ldap_set_option failed with ldap error %d\n", dwErr));
  1668. pldap = NULL;
  1669. goto Cleanup;
  1670. }
  1671. dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI);
  1672. if (dwErr != LDAP_SUCCESS) {
  1673. dprintf((
  1674. DEB_ERROR,
  1675. "ldap_bind_s failed with ldap error %d\n", dwErr));
  1676. pldap = NULL;
  1677. goto Cleanup;
  1678. }
  1679. rgAttrs[0] = L"defaultnamingContext";
  1680. rgAttrs[1] = NULL;
  1681. dwErr = ldap_search_sW(
  1682. pldap,
  1683. L"",
  1684. LDAP_SCOPE_BASE,
  1685. L"(objectClass=*)",
  1686. rgAttrs,
  1687. 0,
  1688. &pMsg);
  1689. if (dwErr == LDAP_SUCCESS) {
  1690. PLDAPMessage pEntry = NULL;
  1691. PWCHAR *rgszNamingContexts = NULL;
  1692. DWORD i, cNamingContexts;
  1693. BOOLEAN fFoundCfg;
  1694. if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL &&
  1695. (rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL &&
  1696. (cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) {
  1697. wcscpy( wszConfigurationDN, *rgszNamingContexts );
  1698. fFoundCfg = TRUE;
  1699. if (!fFoundCfg) {
  1700. dwErr = ERROR_UNEXP_NET_ERR;
  1701. }
  1702. } else {
  1703. dwErr = ERROR_UNEXP_NET_ERR;
  1704. }
  1705. if (rgszNamingContexts != NULL)
  1706. ldap_value_freeW( rgszNamingContexts );
  1707. ldap_msgfree( pMsg );
  1708. }
  1709. if (dwErr != ERROR_SUCCESS) {
  1710. dprintf((DEB_ERROR, "TD:Unable to find Configuration naming context\n"));
  1711. goto Cleanup;
  1712. }
  1713. //
  1714. // Great, we have all the parameters now, so configure the DS
  1715. //
  1716. //
  1717. // See if the DfsConfiguration object exists; if not, create it.
  1718. //
  1719. wsprintf(
  1720. wszDfsConfigDN,
  1721. L"CN=Dfs-Configuration,CN=System,%ws",
  1722. wszConfigurationDN);
  1723. rgAttrs[0] = L"cn";
  1724. rgAttrs[1] = NULL;
  1725. dwErr = ldap_search_sW(
  1726. pldap,
  1727. wszDfsConfigDN,
  1728. LDAP_SCOPE_BASE,
  1729. L"(objectClass=*)",
  1730. rgAttrs,
  1731. 0,
  1732. &pMsg);
  1733. if (dwErr == LDAP_SUCCESS)
  1734. ldap_msgfree( pMsg );
  1735. if (dwErr != LDAP_SUCCESS) {
  1736. dprintf((
  1737. DEB_ERROR,
  1738. "3: ldap_search_sW for %ws failed with LDAP error %d\n",
  1739. wszDfsConfigDN, dwErr ));
  1740. goto Cleanup;
  1741. }
  1742. //
  1743. // Check to see if we are joining an FTDfs or creating a new one.
  1744. //
  1745. wsprintf(
  1746. wszDfsConfigDN,
  1747. L"CN=%ws,CN=Dfs-Configuration,CN=System,%ws",
  1748. wszFTDfsName,
  1749. wszConfigurationDN);
  1750. wsprintf(
  1751. wszServerShare,
  1752. L"\\\\%ws\\%ws",
  1753. wszComputerName,
  1754. wszRootShare);
  1755. rgAttrs[0] = L"remoteServerName";
  1756. rgAttrs[1] = NULL;
  1757. dwErr = ldap_search_sW(
  1758. pldap,
  1759. wszDfsConfigDN,
  1760. LDAP_SCOPE_BASE,
  1761. L"(objectClass=*)",
  1762. rgAttrs,
  1763. 0,
  1764. &pMsg);
  1765. if (dwErr == ERROR_SUCCESS) {
  1766. //
  1767. // We found a Dfs object to modify/delete
  1768. //
  1769. LDAPMessage *pmsgServers;
  1770. PWCHAR *rgServers, *rgNewServers;
  1771. DWORD cServers;
  1772. fNewFTDfs = FALSE;
  1773. pmsgServers = ldap_first_entry(pldap, pMsg);
  1774. if (pmsgServers != NULL) {
  1775. rgServers = ldap_get_valuesW(
  1776. pldap,
  1777. pmsgServers,
  1778. L"remoteServerName");
  1779. if (rgServers != NULL) {
  1780. cServers = ldap_count_valuesW( rgServers );
  1781. rgNewServers = new LPWSTR [ cServers + 1 ];
  1782. if (rgNewServers != NULL) {
  1783. for (i = j = 0; i < cServers; i += 1) {
  1784. if (wcscmp(wszServerShare, rgServers[i]) == 0) {
  1785. continue;
  1786. }
  1787. rgNewServers[j++] = rgServers[i];
  1788. }
  1789. rgNewServers[j] = NULL;
  1790. if (j) {
  1791. ldapModServer.mod_op = LDAP_MOD_REPLACE;
  1792. ldapModServer.mod_type = L"remoteServerName";
  1793. ldapModServer.mod_vals.modv_strvals = rgNewServers;
  1794. rgldapMods[0] = &ldapModServer;
  1795. rgldapMods[1] = NULL;
  1796. dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
  1797. } else {
  1798. //
  1799. // Delete the Dfs metadata object.
  1800. //
  1801. dwErr = ldap_delete_sW( pldap, wszDfsConfigDN);
  1802. }
  1803. delete [] rgNewServers;
  1804. } else {
  1805. dwErr = ERROR_OUTOFMEMORY;
  1806. }
  1807. ldap_value_freeW( rgServers );
  1808. } else {
  1809. dwErr = ERROR_OUTOFMEMORY;
  1810. }
  1811. } else {
  1812. dwErr = ERROR_OUTOFMEMORY;
  1813. }
  1814. ldap_msgfree( pMsg );
  1815. }
  1816. if (dwErr != LDAP_SUCCESS) {
  1817. dprintf((
  1818. DEB_ERROR,
  1819. "4: ldap_modify_s/ldap_delete_s failed for %ws with ldap error %d\n",
  1820. wszDfsConfigDN, dwErr));
  1821. goto Cleanup;
  1822. }
  1823. Cleanup:
  1824. if (pDCInfo != NULL)
  1825. NetApiBufferFree( pDCInfo );
  1826. if (pldap != NULL)
  1827. ldap_unbind( pldap );
  1828. return( dwErr );
  1829. }