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.

2439 lines
63 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // File: setup.cxx
  4. //
  5. // Contents: This module contains the functions which remote setup
  6. //
  7. // History: 11-Feb-1998 JHarper Created
  8. //
  9. //--------------------------------------------------------------------------
  10. //#include <ntos.h>
  11. //#include <ntrtl.h>
  12. //#include <nturtl.h>
  13. //#include <dfsfsctl.h>
  14. //#include <windows.h>
  15. #include "headers.hxx"
  16. #pragma hdrstop
  17. extern "C" {
  18. #include <srvfsctl.h>
  19. #include <winldap.h>
  20. #include <dsgetdc.h>
  21. #include "dfsmsrv.h"
  22. }
  23. #include "registry.hxx"
  24. #include "setup.hxx"
  25. #include "dfsmwml.h"
  26. #include <winioctl.h>
  27. //
  28. // Until we get the schema right in the DS, we have to set our own SD on
  29. // certain objects
  30. //
  31. #include <aclapi.h>
  32. #include <permit.h>
  33. DECLARE_DEBUG(Setup)
  34. DECLARE_INFOLEVEL(Setup)
  35. #if DBG == 1
  36. #define dprintf(x) SetupInlineDebugOut x
  37. # else
  38. #define dprintf(x)
  39. #endif
  40. DWORD
  41. InitStdVolumeObjectStorage(VOID);
  42. DWORD
  43. GetShareAndPath(
  44. IN LPWSTR wszShare,
  45. OUT LPWSTR wszPath);
  46. DWORD
  47. CreateFtRootVolRegInfo(
  48. LPWSTR wszObjectName,
  49. LPWSTR wszFTDfsConfigDN,
  50. LPWSTR wszDomainName,
  51. LPWSTR wszDfsName,
  52. LPWSTR wszServerName,
  53. LPWSTR wszShareName,
  54. LPWSTR wszSharePath,
  55. BOOLEAN fNewFTDfs);
  56. DWORD
  57. CreateStdVolumeObject(
  58. LPWSTR wszObjectName,
  59. LPWSTR pwszEntryPath,
  60. LPWSTR pwszServer,
  61. LPWSTR pwszShare,
  62. LPWSTR pwszComment,
  63. GUID *guidVolume);
  64. DWORD
  65. CreateFtVolumeObject(
  66. LPWSTR wszObjectName,
  67. LPWSTR wszFTDfsConfigDN,
  68. LPWSTR wszDomainName,
  69. LPWSTR wszDfsName,
  70. LPWSTR wszServerName,
  71. LPWSTR wszShareName,
  72. LPWSTR wszSharePath,
  73. LPWSTR wszComment,
  74. BOOLEAN fNewFTDfs);
  75. DWORD
  76. StoreLocalVolInfo(
  77. IN GUID *pVolumeID,
  78. IN PWSTR pwszStorageID,
  79. IN PWSTR pwszShareName,
  80. IN PWSTR pwszEntryPath,
  81. IN ULONG ulVolumeType);
  82. DWORD
  83. LdapFlushTable(
  84. void);
  85. DWORD
  86. DfspCreateRootServerList(
  87. IN LDAP *pldap,
  88. IN LPWSTR wszServerShare,
  89. IN LPWSTR wszDfsConfigDN,
  90. IN PDFSM_ROOT_LIST *ppRootList);
  91. VOID GuidToString(
  92. IN GUID *pGuid,
  93. OUT PWSTR pwszGuid);
  94. extern PLDAP pLdapConnection;
  95. //+-------------------------------------------------------------------------
  96. //
  97. // Function: DfsmInitLocalPartitions
  98. //
  99. // Synopsis: Tell dfs.sys to read the local volume part of the registry
  100. // Sends FSCTL_DFS_INIT_LOCAL_PARTITIONS to dfs.sys
  101. //
  102. //--------------------------------------------------------------------------
  103. NTSTATUS
  104. DfsmInitLocalPartitions(
  105. VOID)
  106. {
  107. NTSTATUS NtStatus;
  108. HANDLE DriverHandle = NULL;
  109. IO_STATUS_BLOCK IoStatusBlock;
  110. OBJECT_ATTRIBUTES objectAttributes;
  111. UNICODE_STRING DfsServerName;
  112. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  113. InitializeObjectAttributes(
  114. &objectAttributes,
  115. &DfsServerName,
  116. OBJ_CASE_INSENSITIVE,
  117. NULL,
  118. NULL
  119. );
  120. NtStatus = NtCreateFile(
  121. &DriverHandle,
  122. SYNCHRONIZE | FILE_WRITE_DATA,
  123. &objectAttributes,
  124. &IoStatusBlock,
  125. NULL,
  126. FILE_ATTRIBUTE_NORMAL,
  127. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  128. FILE_OPEN_IF,
  129. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  130. NULL,
  131. 0);
  132. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmInitLocalPartitions_Error_NtCreateFile,
  133. LOGSTATUS(NtStatus));
  134. if (NT_SUCCESS(NtStatus)) {
  135. NtStatus = NtFsControlFile(
  136. DriverHandle,
  137. NULL, // Event,
  138. NULL, // ApcRoutine,
  139. NULL, // ApcContext,
  140. &IoStatusBlock,
  141. FSCTL_DFS_INIT_LOCAL_PARTITIONS,
  142. NULL,
  143. 0,
  144. NULL,
  145. 0);
  146. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmInitLocalPartitions_Error_NtFsCOntrolFile,
  147. LOGSTATUS(NtStatus));
  148. NtClose(DriverHandle);
  149. }
  150. return NtStatus;
  151. }
  152. //+-------------------------------------------------------------------------
  153. //
  154. // Function: DfsmStartDfs
  155. //
  156. // Synopsis: Tell dfs.sys to turn itself on
  157. // Sends FSCTL_DFS_START_DFS to dfs.sys
  158. //
  159. //--------------------------------------------------------------------------
  160. NTSTATUS
  161. DfsmStartDfs(
  162. VOID)
  163. {
  164. NTSTATUS NtStatus;
  165. HANDLE DriverHandle = NULL;
  166. IO_STATUS_BLOCK IoStatusBlock;
  167. OBJECT_ATTRIBUTES objectAttributes;
  168. UNICODE_STRING DfsServerName;
  169. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  170. InitializeObjectAttributes(
  171. &objectAttributes,
  172. &DfsServerName,
  173. OBJ_CASE_INSENSITIVE,
  174. NULL,
  175. NULL
  176. );
  177. NtStatus = NtCreateFile(
  178. &DriverHandle,
  179. SYNCHRONIZE | FILE_WRITE_DATA,
  180. &objectAttributes,
  181. &IoStatusBlock,
  182. NULL,
  183. FILE_ATTRIBUTE_NORMAL,
  184. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  185. FILE_OPEN_IF,
  186. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  187. NULL,
  188. 0);
  189. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStartDfs_Error_NtCreateFile,
  190. LOGSTATUS(NtStatus));
  191. if (NT_SUCCESS(NtStatus)) {
  192. NtStatus = NtFsControlFile(
  193. DriverHandle,
  194. NULL, // Event,
  195. NULL, // ApcRoutine,
  196. NULL, // ApcContext,
  197. &IoStatusBlock,
  198. FSCTL_DFS_START_DFS,
  199. NULL,
  200. 0,
  201. NULL,
  202. 0);
  203. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStartDfs_Error_NtFsControlFile,
  204. LOGSTATUS(NtStatus));
  205. NtClose(DriverHandle);
  206. }
  207. return NtStatus;
  208. }
  209. //+-------------------------------------------------------------------------
  210. //
  211. // Function: DfsmStopDfs
  212. //
  213. // Synopsis: Tell dfs.sys to turn itself off
  214. // Sends FSCTL_DFS_STOP_DFS to dfs.sys
  215. //
  216. //--------------------------------------------------------------------------
  217. NTSTATUS
  218. DfsmStopDfs(
  219. VOID)
  220. {
  221. NTSTATUS NtStatus;
  222. HANDLE DriverHandle = NULL;
  223. IO_STATUS_BLOCK IoStatusBlock;
  224. OBJECT_ATTRIBUTES objectAttributes;
  225. UNICODE_STRING DfsServerName;
  226. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  227. InitializeObjectAttributes(
  228. &objectAttributes,
  229. &DfsServerName,
  230. OBJ_CASE_INSENSITIVE,
  231. NULL,
  232. NULL
  233. );
  234. NtStatus = NtCreateFile(
  235. &DriverHandle,
  236. SYNCHRONIZE | FILE_WRITE_DATA,
  237. &objectAttributes,
  238. &IoStatusBlock,
  239. NULL,
  240. FILE_ATTRIBUTE_NORMAL,
  241. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  242. FILE_OPEN_IF,
  243. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  244. NULL,
  245. 0);
  246. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStopDfs_Error_NtCreateFile,
  247. LOGSTATUS(NtStatus));
  248. if (NT_SUCCESS(NtStatus)) {
  249. NtStatus = NtFsControlFile(
  250. DriverHandle,
  251. NULL, // Event,
  252. NULL, // ApcRoutine,
  253. NULL, // ApcContext,
  254. &IoStatusBlock,
  255. FSCTL_DFS_STOP_DFS,
  256. NULL,
  257. 0,
  258. NULL,
  259. 0);
  260. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStopDfs_Error_NtFsControlFile,
  261. LOGSTATUS(NtStatus));
  262. NtClose(DriverHandle);
  263. }
  264. return NtStatus;
  265. }
  266. //+-------------------------------------------------------------------------
  267. //
  268. // Function: DfsmResetPkt
  269. //
  270. // Synopsis: Tell dfs.sys to throw away all state and turn off
  271. // Sends FSCTL_DFS_RESET_PKT to dfs.sys
  272. //
  273. //--------------------------------------------------------------------------
  274. NTSTATUS
  275. DfsmResetPkt(
  276. VOID)
  277. {
  278. NTSTATUS NtStatus;
  279. HANDLE DriverHandle = NULL;
  280. IO_STATUS_BLOCK IoStatusBlock;
  281. OBJECT_ATTRIBUTES objectAttributes;
  282. UNICODE_STRING DfsServerName;
  283. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  284. InitializeObjectAttributes(
  285. &objectAttributes,
  286. &DfsServerName,
  287. OBJ_CASE_INSENSITIVE,
  288. NULL,
  289. NULL
  290. );
  291. NtStatus = NtCreateFile(
  292. &DriverHandle,
  293. SYNCHRONIZE | FILE_WRITE_DATA,
  294. &objectAttributes,
  295. &IoStatusBlock,
  296. NULL,
  297. FILE_ATTRIBUTE_NORMAL,
  298. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  299. FILE_OPEN_IF,
  300. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  301. NULL,
  302. 0);
  303. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmResetPkt_Error_NtCreateFile,
  304. LOGSTATUS(NtStatus));
  305. //
  306. // Toss the Pkt
  307. //
  308. if (NT_SUCCESS(NtStatus)) {
  309. NtStatus = NtFsControlFile(
  310. DriverHandle,
  311. NULL, // Event,
  312. NULL, // ApcRoutine,
  313. NULL, // ApcContext,
  314. &IoStatusBlock,
  315. FSCTL_DFS_RESET_PKT,
  316. NULL,
  317. 0,
  318. NULL,
  319. 0);
  320. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmResetPkt_Error_NtFsControlFile,
  321. LOGSTATUS(NtStatus));
  322. NtClose(DriverHandle);
  323. }
  324. return NtStatus;
  325. }
  326. //+-------------------------------------------------------------------------
  327. //
  328. // Function: DfsmPktFlushCache
  329. //
  330. // Synopsis: Tell dfs.sys to turn itself off
  331. // Sends FSCTL_DFS_PKT_FLUSH_CACHE to mup.sys
  332. //
  333. //--------------------------------------------------------------------------
  334. NTSTATUS
  335. DfsmPktFlushCache(
  336. VOID)
  337. {
  338. NTSTATUS NtStatus;
  339. HANDLE DriverHandle = NULL;
  340. IO_STATUS_BLOCK IoStatusBlock;
  341. OBJECT_ATTRIBUTES objectAttributes;
  342. UNICODE_STRING DfsDriverName;
  343. WCHAR EntryPath[5];
  344. //
  345. // Flush the local/client side pkt, too
  346. //
  347. RtlInitUnicodeString(&DfsDriverName, DFS_DRIVER_NAME);
  348. InitializeObjectAttributes(
  349. &objectAttributes,
  350. &DfsDriverName,
  351. OBJ_CASE_INSENSITIVE,
  352. NULL,
  353. NULL
  354. );
  355. NtStatus = NtCreateFile(
  356. &DriverHandle,
  357. SYNCHRONIZE | FILE_WRITE_DATA,
  358. &objectAttributes,
  359. &IoStatusBlock,
  360. NULL,
  361. FILE_ATTRIBUTE_NORMAL,
  362. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  363. FILE_OPEN_IF,
  364. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  365. NULL,
  366. 0);
  367. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmPktFlushCache_Error_NtCreateFile,
  368. LOGSTATUS(NtStatus));
  369. if (NT_SUCCESS(NtStatus)) {
  370. wcscpy(EntryPath, L"*");
  371. NtStatus = NtFsControlFile(
  372. DriverHandle,
  373. NULL, // Event,
  374. NULL, // ApcRoutine,
  375. NULL, // ApcContext,
  376. &IoStatusBlock,
  377. FSCTL_DFS_PKT_FLUSH_CACHE,
  378. EntryPath,
  379. wcslen(EntryPath) * sizeof(WCHAR),
  380. NULL,
  381. 0);
  382. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmPktFlushCache_Error_NtFsControlFile,
  383. LOGSTATUS(NtStatus));
  384. NtClose(DriverHandle);
  385. }
  386. return NtStatus;
  387. }
  388. //+-------------------------------------------------------------------------
  389. //
  390. // Function: DfsmMarkStalePktEntries
  391. //
  392. // Synopsis: Tell dfs.sys to throw away all state and turn off
  393. // Sends FSCTL_DFS_MARK_STALE_PKT_ENTRIES to dfs.sys
  394. //
  395. //--------------------------------------------------------------------------
  396. NTSTATUS
  397. DfsmMarkStalePktEntries(
  398. VOID)
  399. {
  400. NTSTATUS NtStatus;
  401. HANDLE DriverHandle = NULL;
  402. IO_STATUS_BLOCK IoStatusBlock;
  403. OBJECT_ATTRIBUTES objectAttributes;
  404. UNICODE_STRING DfsServerName;
  405. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  406. InitializeObjectAttributes(
  407. &objectAttributes,
  408. &DfsServerName,
  409. OBJ_CASE_INSENSITIVE,
  410. NULL,
  411. NULL
  412. );
  413. NtStatus = NtCreateFile(
  414. &DriverHandle,
  415. SYNCHRONIZE | FILE_WRITE_DATA,
  416. &objectAttributes,
  417. &IoStatusBlock,
  418. NULL,
  419. FILE_ATTRIBUTE_NORMAL,
  420. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  421. FILE_OPEN_IF,
  422. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  423. NULL,
  424. 0);
  425. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmMarkStalePktEntries_Error_NtCreateFile,
  426. LOGSTATUS(NtStatus));
  427. //
  428. // Toss the Pkt
  429. //
  430. if (NT_SUCCESS(NtStatus)) {
  431. NtStatus = NtFsControlFile(
  432. DriverHandle,
  433. NULL, // Event,
  434. NULL, // ApcRoutine,
  435. NULL, // ApcContext,
  436. &IoStatusBlock,
  437. FSCTL_DFS_MARK_STALE_PKT_ENTRIES,
  438. NULL,
  439. 0,
  440. NULL,
  441. 0);
  442. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmMarkStalePktEntries_Error_NtFsControlFile,
  443. LOGSTATUS(NtStatus));
  444. NtClose(DriverHandle);
  445. }
  446. return NtStatus;
  447. }
  448. //+-------------------------------------------------------------------------
  449. //
  450. // Function: DfsmFlushStalePktEntries
  451. //
  452. // Synopsis: Tell dfs.sys to throw away all state and turn off
  453. // Sends FSCTL_DFS_FLUSH_STALE_PKT_ENTRIES to dfs.sys
  454. //
  455. //--------------------------------------------------------------------------
  456. NTSTATUS
  457. DfsmFlushStalePktEntries(
  458. VOID)
  459. {
  460. NTSTATUS NtStatus;
  461. HANDLE DriverHandle = NULL;
  462. IO_STATUS_BLOCK IoStatusBlock;
  463. OBJECT_ATTRIBUTES objectAttributes;
  464. UNICODE_STRING DfsServerName;
  465. RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
  466. InitializeObjectAttributes(
  467. &objectAttributes,
  468. &DfsServerName,
  469. OBJ_CASE_INSENSITIVE,
  470. NULL,
  471. NULL
  472. );
  473. NtStatus = NtCreateFile(
  474. &DriverHandle,
  475. SYNCHRONIZE | FILE_WRITE_DATA,
  476. &objectAttributes,
  477. &IoStatusBlock,
  478. NULL,
  479. FILE_ATTRIBUTE_NORMAL,
  480. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  481. FILE_OPEN_IF,
  482. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  483. NULL,
  484. 0);
  485. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmFlushStalePktEntries_Error_NtCreateFile,
  486. LOGSTATUS(NtStatus));
  487. //
  488. // Toss the Pkt
  489. //
  490. if (NT_SUCCESS(NtStatus)) {
  491. NtStatus = NtFsControlFile(
  492. DriverHandle,
  493. NULL, // Event,
  494. NULL, // ApcRoutine,
  495. NULL, // ApcContext,
  496. &IoStatusBlock,
  497. FSCTL_DFS_FLUSH_STALE_PKT_ENTRIES,
  498. NULL,
  499. 0,
  500. NULL,
  501. 0);
  502. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmFlushStalePktEntries_Error_NtFsControl,
  503. LOGSTATUS(NtStatus));
  504. NtClose(DriverHandle);
  505. }
  506. return NtStatus;
  507. }
  508. //+----------------------------------------------------------------------------
  509. //
  510. // Function: SetupStdDfs
  511. //
  512. // Synopsis: Does necessary setup to make this Dfs a root of the Dfs.
  513. //
  514. // Arguments: [wszComputerName] -- The name of the computer
  515. // [wszDfsRootShare] -- The share to use as the Dfs root.
  516. // [wszComment] -- Comment for root share
  517. // [dwFlags] -- Flags for operation
  518. //
  519. // Returns: Win32 error from configuring the root storages etc.
  520. //
  521. //-----------------------------------------------------------------------------
  522. DWORD
  523. SetupStdDfs(
  524. LPWSTR wszComputerName,
  525. LPWSTR wszDfsRootShare,
  526. LPWSTR wszComment,
  527. DWORD dwFlags,
  528. LPWSTR wszDfsRoot)
  529. {
  530. DWORD dwErr = ERROR_SUCCESS;
  531. GUID guid;
  532. WCHAR wszDfsRootPath[MAX_PATH+1];
  533. PWCHAR wszDfsRootPrefix = NULL;
  534. TCHAR szPath[] = TEXT("A:\\");
  535. //
  536. // Figure out the share path for the Root Dfs share
  537. //
  538. if (dwErr == ERROR_SUCCESS) {
  539. if (wszDfsRoot == NULL) {
  540. dwErr = GetShareAndPath( wszDfsRootShare, wszDfsRootPath );
  541. } else {
  542. wcscpy(wszDfsRootPath, wszDfsRoot);
  543. }
  544. }
  545. // Check if we are trying to create a root on removable media.
  546. // Return an error if we are.
  547. // We can't allow this because, for example, if the root is a floppy
  548. // that is not present at boot time, the system hangs and doesn't
  549. // even boot up. It isn't possible to detect this at boot time and ignore
  550. // the drive, so we must prevent such roots from existing at all.
  551. if(dwErr == ERROR_SUCCESS) {
  552. szPath[0] = (TCHAR)wszDfsRootPath[0];
  553. if (GetDriveType(szPath) != DRIVE_FIXED) {
  554. dwErr = ERROR_INVALID_MEDIA;
  555. }
  556. }
  557. //
  558. // We have all the info we need now. Lets get to work....
  559. //
  560. // 1. Initialize the volume object section in the registry.
  561. //
  562. // 2. Initialize (ie, create if necessary) the storage used for the
  563. // Dfs root.
  564. //
  565. // 3. Create the root volume object.
  566. //
  567. // 4. Configure the root volume as a local volume by updating the
  568. // LocalVolumes section in the registry.
  569. //
  570. //
  571. // Initialize the Dfs Manager Volume Object Store
  572. //
  573. if (dwErr == ERROR_SUCCESS) {
  574. dwErr = InitStdVolumeObjectStorage();
  575. }
  576. if (dwErr == ERROR_SUCCESS) {
  577. dprintf((DEB_TRACE,
  578. "Setting [%ws] as Dfs storage root...\n", wszDfsRootPath));
  579. dwErr = DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER );
  580. if (pwszDfsRootName != NULL)
  581. wcscpy(wszComputerName, pwszDfsRootName);
  582. if (dwErr == ERROR_SUCCESS) {
  583. wszDfsRootPrefix = new WCHAR[1 +
  584. wcslen(wszComputerName) +
  585. 1 +
  586. wcslen(wszDfsRootShare) +
  587. 1];
  588. if (wszDfsRootPrefix == NULL) {
  589. dwErr = ERROR_OUTOFMEMORY;
  590. }
  591. }
  592. if (dwErr == ERROR_SUCCESS) {
  593. wszDfsRootPrefix[0] = UNICODE_PATH_SEP;
  594. wcscpy( &wszDfsRootPrefix[1], wszComputerName );
  595. wcscat( wszDfsRootPrefix, UNICODE_PATH_SEP_STR );
  596. wcscat( wszDfsRootPrefix, wszDfsRootShare );
  597. dwErr = CreateStdVolumeObject(
  598. DOMAIN_ROOT_VOL, // Name of volume object
  599. wszDfsRootPrefix, // EntryPath of volume
  600. wszComputerName, // Server name
  601. wszDfsRootShare, // Share name
  602. wszComment, // Comment
  603. &guid); // Id of created volume
  604. }
  605. if (dwErr == ERROR_SUCCESS) {
  606. dwErr = StoreLocalVolInfo(
  607. &guid,
  608. wszDfsRootPath,
  609. wszDfsRootShare,
  610. wszDfsRootPrefix,
  611. DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
  612. }
  613. if (wszDfsRootPrefix != NULL)
  614. delete [] wszDfsRootPrefix;
  615. if (dwErr != ERROR_SUCCESS)
  616. dwErr = ERROR_INVALID_FUNCTION;
  617. if (dwErr == ERROR_SUCCESS) {
  618. DWORD dwErr;
  619. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
  620. if (dwErr == ERROR_SUCCESS) {
  621. CRegSZ cregRootShare(
  622. cregVolumesDir,
  623. ROOT_SHARE_VALUE_NAME,
  624. wszDfsRootShare );
  625. dwErr = cregRootShare.QueryErrorStatus();
  626. }
  627. }
  628. }
  629. return( dwErr );
  630. }
  631. //+----------------------------------------------------------------------------
  632. //
  633. // Function: SetupFtDfs
  634. //
  635. // Synopsis: Completes necessary setup to make this Dfs an FtDfs root
  636. //
  637. // Arguments: [wszServerName] -- The name of the machine
  638. // [wszDomainName] -- Domain the machine is in
  639. // [wszDfsRootShare] -- The share to use as the FtDfs root.
  640. // [wszFtDfsName] -- The name for the FtDfs
  641. // [wszComment] -- Comment for root share
  642. // [wszConfigDN] -- The obj name to create
  643. // [NewFtDfs] -- TRUE to create new, FALSE to join existing
  644. // [dwFlags] -- Flags
  645. //
  646. // Returns: Win32 error from configuring the root storages etc.
  647. //
  648. //-----------------------------------------------------------------------------
  649. DWORD
  650. SetupFtDfs(
  651. LPWSTR wszServerName,
  652. LPWSTR wszDomainName,
  653. LPWSTR wszRootShare,
  654. LPWSTR wszFtDfsName,
  655. LPWSTR wszComment,
  656. LPWSTR wszConfigDN,
  657. BOOLEAN NewFtDfs,
  658. DWORD dwFlags)
  659. {
  660. DWORD dwErr = ERROR_SUCCESS;
  661. WCHAR wszRootSharePath[MAX_PATH+1];
  662. WCHAR wszServerShare[MAX_PATH+1];
  663. TCHAR szPath[] = TEXT("A:\\");
  664. dwErr = GetShareAndPath( wszRootShare, wszRootSharePath );
  665. if (dwErr != ERROR_SUCCESS) {
  666. dprintf((
  667. DEB_ERROR,
  668. "Win32 Error %d getting share path for %ws\n",
  669. dwErr, wszRootShare));
  670. goto Cleanup;
  671. }
  672. // Check if we are trying to create a root on removable media.
  673. // Return an error if we are.
  674. // We can't allow this because, for example, if the root is a floppy
  675. // that is not present at boot time, the system hangs and doesn't
  676. // even boot up. It isn't possible to detect this at boot time and ignore
  677. // the drive, so we must prevent such roots from existing at all.
  678. if(dwErr == ERROR_SUCCESS) {
  679. szPath[0] = (TCHAR)wszRootSharePath[0];
  680. if (GetDriveType(szPath) != DRIVE_FIXED) {
  681. dwErr = ERROR_INVALID_MEDIA;
  682. goto Cleanup;
  683. }
  684. }
  685. wsprintf(
  686. wszServerShare,
  687. L"\\\\%ws\\%ws",
  688. wszServerName,
  689. wszRootShare);
  690. //
  691. // Create the DfsHost root entry in the registry
  692. //
  693. dwErr = CreateFtRootVolRegInfo(
  694. DOMAIN_ROOT_VOL,
  695. wszConfigDN,
  696. wszDomainName,
  697. wszFtDfsName,
  698. wszServerName,
  699. wszRootShare,
  700. wszRootSharePath,
  701. NewFtDfs);
  702. //
  703. // Reinitialize global stuff
  704. //
  705. if (dwErr == ERROR_SUCCESS) {
  706. dwErr = DfsReInitGlobals(
  707. wszFtDfsName,
  708. DFS_MANAGER_FTDFS);
  709. }
  710. //
  711. // Finally, create the root volume object
  712. //
  713. if (dwErr == ERROR_SUCCESS) {
  714. dwErr = CreateFtVolumeObject(
  715. DOMAIN_ROOT_VOL,
  716. wszConfigDN,
  717. wszDomainName,
  718. wszFtDfsName,
  719. wszServerName,
  720. wszRootShare,
  721. wszRootSharePath,
  722. wszComment,
  723. NewFtDfs);
  724. }
  725. if (dwErr == ERROR_SUCCESS) {
  726. dprintf((
  727. DEB_TRACE, "Successfully created FT-Dfs Configuration!\n"));
  728. goto Cleanup;
  729. }
  730. dprintf((
  731. DEB_ERROR, "CreateFtVolumeObject failed with error %d\n", dwErr));
  732. Cleanup:
  733. return( dwErr );
  734. }
  735. //+----------------------------------------------------------------------------
  736. //
  737. // Function: GetShareAndPath
  738. //
  739. // Synopsis: Returns the share path for a share on the local machine
  740. //
  741. // Arguments: [wszShare] -- Name of share
  742. //
  743. // [wszPath] -- On return, share path of wszShare
  744. //
  745. // Returns: [ERROR_SUCCESS] -- Successfully returning share path
  746. //
  747. // Win32 error from NetShareGetInfo
  748. //
  749. //-----------------------------------------------------------------------------
  750. DWORD
  751. GetShareAndPath(
  752. IN LPWSTR wszShare,
  753. OUT LPWSTR wszPath)
  754. {
  755. DWORD dwErr;
  756. PSHARE_INFO_2 pshi2;
  757. dwErr = NetShareGetInfo(
  758. NULL, // Server (local machine)
  759. wszShare, // Share Name
  760. 2, // Level,
  761. (LPBYTE *) &pshi2); // Buffer
  762. if (dwErr == ERROR_SUCCESS) {
  763. wcscpy( wszPath, pshi2->shi2_path );
  764. NetApiBufferFree( pshi2 );
  765. }
  766. return( dwErr );
  767. }
  768. //+----------------------------------------------------------------------------
  769. //
  770. // Function: CreateFtRootVolRegInfo
  771. //
  772. // Synopsis: Creates root vol info in the registry
  773. //
  774. // Arguments: [wszObjectName] -- Name of volume object
  775. // [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS
  776. // [wszDomainName] -- Name of FTDfs domain
  777. // [wszDfsName] -- Name of Dfs
  778. // [wszServerName] -- Name of root server
  779. // [wszShareName] -- Name of root share
  780. // [fNewFTDfs] -- If true, this is a new FTDfs
  781. //
  782. // Returns:
  783. //
  784. //-----------------------------------------------------------------------------
  785. DWORD
  786. CreateFtRootVolRegInfo(
  787. LPWSTR wszObjectName,
  788. LPWSTR wszFTDfsConfigDN,
  789. LPWSTR wszDomainName,
  790. LPWSTR wszDfsName,
  791. LPWSTR wszServerName,
  792. LPWSTR wszShareName,
  793. LPWSTR wszSharePath,
  794. BOOLEAN fNewFTDfs)
  795. {
  796. DWORD dwErr;
  797. WCHAR wszFullObjectName[ MAX_PATH ];
  798. WCHAR wszDfsPrefix[ MAX_PATH ];
  799. GUID idVolume;
  800. wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  801. wcscat( wszDfsPrefix, wszDomainName );
  802. wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  803. wcscat( wszDfsPrefix, wszDfsName );
  804. wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
  805. wcscat( wszFullObjectName, wszObjectName );
  806. //
  807. // Create the volumes dir key that indicates that this machine is to
  808. // be a root of an FTDfs
  809. //
  810. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, VOLUMES_DIR );
  811. dwErr = cregVolumesDir.QueryErrorStatus();
  812. if (dwErr == ERROR_SUCCESS) {
  813. CRegSZ cregRootShare(
  814. cregVolumesDir,
  815. ROOT_SHARE_VALUE_NAME,
  816. wszShareName );
  817. dwErr = cregRootShare.QueryErrorStatus();
  818. if (dwErr == ERROR_SUCCESS) {
  819. CRegSZ cregFTDfs(
  820. cregVolumesDir,
  821. FTDFS_VALUE_NAME,
  822. wszDfsName);
  823. CRegSZ cregFTDfsConfigDN(
  824. cregVolumesDir,
  825. FTDFS_DN_VALUE_NAME,
  826. wszFTDfsConfigDN);
  827. dwErr = cregFTDfs.QueryErrorStatus();
  828. if (dwErr == ERROR_SUCCESS) {
  829. dwErr = cregFTDfsConfigDN.QueryErrorStatus();
  830. if (dwErr != ERROR_SUCCESS)
  831. cregFTDfs.Delete();
  832. }
  833. }
  834. }
  835. return( dwErr );
  836. }
  837. //+----------------------------------------------------------------------------
  838. //
  839. // Function: CreateFtVolumeObject
  840. //
  841. // Synopsis: Creates root vol object
  842. //
  843. // Arguments: [wszObjectName] -- Name of volume object
  844. // [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS
  845. // [wszDomainName] -- Name of FTDfs domain
  846. // [wszDfsName] -- Name of Dfs
  847. // [wszServerName] -- Name of root server
  848. // [wszShareName] -- Name of root share
  849. // [wszComment] -- Comment for root
  850. // [fNewFTDfs] -- If true, this is a new FTDfs
  851. //
  852. // Returns:
  853. //
  854. //-----------------------------------------------------------------------------
  855. DWORD
  856. CreateFtVolumeObject(
  857. LPWSTR wszObjectName,
  858. LPWSTR wszFTDfsConfigDN,
  859. LPWSTR wszDomainName,
  860. LPWSTR wszDfsName,
  861. LPWSTR wszServerName,
  862. LPWSTR wszShareName,
  863. LPWSTR wszSharePath,
  864. LPWSTR wszComment,
  865. BOOLEAN fNewFTDfs)
  866. {
  867. DWORD dwErr = ERROR_SUCCESS;
  868. WCHAR wszFullObjectName[ MAX_PATH ];
  869. WCHAR wszDfsPrefix[ MAX_PATH ];
  870. GUID idVolume;
  871. wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  872. wcscat( wszDfsPrefix, wszDomainName );
  873. wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR );
  874. wcscat( wszDfsPrefix, wszDfsName );
  875. wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
  876. wcscat( wszFullObjectName, wszObjectName );
  877. if (fNewFTDfs) {
  878. //
  879. // Generate a Guid for the new Volume
  880. //
  881. UuidCreate( &idVolume );
  882. dwErr = DfsManagerCreateVolumeObject(
  883. wszFullObjectName,
  884. wszDfsPrefix,
  885. wszServerName,
  886. wszShareName,
  887. wszComment,
  888. &idVolume);
  889. } else {
  890. dwErr = DfsManagerAddService(
  891. wszFullObjectName,
  892. wszServerName,
  893. wszShareName,
  894. &idVolume);
  895. }
  896. //
  897. // Write the root local vol info into the registry
  898. //
  899. if (dwErr == ERROR_SUCCESS) {
  900. dwErr = StoreLocalVolInfo(
  901. &idVolume,
  902. wszSharePath,
  903. wszShareName,
  904. wszDfsPrefix,
  905. DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
  906. if (dwErr == ERROR_SUCCESS) {
  907. dwErr = LdapFlushTable();
  908. }
  909. }
  910. return( dwErr );
  911. }
  912. //+----------------------------------------------------------------------------
  913. //
  914. // Function: CreateStdVolumeObject
  915. //
  916. // Synopsis: Creates a volume object to bootstrap the Dfs namespace.
  917. //
  918. // Arguments: [pwszObjectName] -- The name of the volume object, relative
  919. // to VOLUMES_DIR
  920. // [pwszEntryPath] -- EntryPath of the volume.
  921. // [pwszServer] -- Name of server used to access this Dfs volume
  922. // [pwszShare] -- Name of share used to access this Dfs volume
  923. // [pwszComment] -- Comment to stamp on the volume object.
  924. // [guidVolume] -- ID of newly create dfs volume
  925. //
  926. // Returns:
  927. //
  928. //-----------------------------------------------------------------------------
  929. DWORD
  930. CreateStdVolumeObject(
  931. LPWSTR wszObjectName,
  932. LPWSTR pwszEntryPath,
  933. LPWSTR pwszServer,
  934. LPWSTR pwszShare,
  935. LPWSTR pwszComment,
  936. GUID *guidVolume)
  937. {
  938. DWORD dwErr;
  939. WCHAR wszFullObject[ MAX_PATH ];
  940. //
  941. // First, compute the full object name, storage ids, and machine name.
  942. //
  943. wcscpy( wszFullObject, VOLUMES_DIR );
  944. wcscat( wszFullObject, wszObjectName );
  945. //
  946. // Next, get a guid for this volume
  947. //
  948. UuidCreate( guidVolume );
  949. //
  950. // Lastly, create this volume object
  951. //
  952. dwErr = DfsManagerCreateVolumeObject(
  953. wszFullObject,
  954. pwszEntryPath,
  955. pwszServer,
  956. pwszShare,
  957. pwszComment,
  958. guidVolume);
  959. if (dwErr == ERROR_SUCCESS) {
  960. dprintf((DEB_TRACE,"Successfully inited Dfs Manager Volume [%ws]...\n", pwszEntryPath));
  961. }
  962. return(dwErr);
  963. }
  964. //+----------------------------------------------------------------------------
  965. //
  966. // Function: InitStdVolumeObjectStorage
  967. //
  968. // Synopsis: Initializes the Dfs Manager Volume Object store.
  969. //
  970. // Arguments: None
  971. //
  972. // Returns: DWORD from registry operations.
  973. //
  974. //-----------------------------------------------------------------------------
  975. DWORD
  976. InitStdVolumeObjectStorage()
  977. {
  978. DWORD dwErr;
  979. CRegKey *pcregVolumeObjectStore;
  980. pcregVolumeObjectStore = new CRegKey(HKEY_LOCAL_MACHINE, VOLUMES_DIR );
  981. if (pcregVolumeObjectStore != NULL) {
  982. dwErr = pcregVolumeObjectStore->QueryErrorStatus();
  983. delete pcregVolumeObjectStore;
  984. } else {
  985. dwErr = ERROR_OUTOFMEMORY;
  986. }
  987. if (dwErr == ERROR_SUCCESS) {
  988. dprintf((DEB_TRACE,"Successfully inited Dfs Manager Volume Storage...\n"));
  989. }
  990. return(dwErr);
  991. }
  992. //+----------------------------------------------------------------------------
  993. //
  994. // Function: StoreLocalVolInfo
  995. //
  996. // Synopsis: Stores information about a local volume in the registry.
  997. //
  998. // Arguments: [pVolumeID] -- Id of dfs volume
  999. // [pwszStorageId] -- Storage used by dfs volume
  1000. // [pwszShareName] -- LM Share used to access dfs volume
  1001. // [pwszEntryPath] -- EntryPath of dfs volume
  1002. // [ulVolumeType] -- Type of dfs volume. See DFS_VOL_TYPE_xxx
  1003. //
  1004. // Returns: DWORD from registry operations.
  1005. //
  1006. //-----------------------------------------------------------------------------
  1007. extern VOID
  1008. GuidToString(
  1009. IN GUID *pID,
  1010. OUT PWSTR pwszID);
  1011. DWORD
  1012. StoreLocalVolInfo(
  1013. IN GUID *pVolumeID,
  1014. IN PWSTR pwszStorageID,
  1015. IN PWSTR pwszShareName,
  1016. IN PWSTR pwszEntryPath,
  1017. IN ULONG ulVolumeType)
  1018. {
  1019. DWORD dwErr;
  1020. WCHAR wszLvolKey[_MAX_PATH];
  1021. UNICODE_STRING ustrNtStorageId;
  1022. PWCHAR pwcGuid;
  1023. wcscpy(wszLvolKey, REG_KEY_LOCAL_VOLUMES);
  1024. wcscat(wszLvolKey, UNICODE_PATH_SEP_STR);
  1025. pwcGuid = wszLvolKey + wcslen(wszLvolKey);
  1026. ASSERT( *pwcGuid == UNICODE_NULL );
  1027. GuidToString( pVolumeID, pwcGuid );
  1028. if (!RtlDosPathNameToNtPathName_U(
  1029. pwszStorageID,
  1030. &ustrNtStorageId,
  1031. NULL,
  1032. NULL)) {
  1033. return(ERROR_OUTOFMEMORY);
  1034. } else {
  1035. ustrNtStorageId.Buffer[ustrNtStorageId.Length/sizeof(WCHAR)] = UNICODE_NULL;
  1036. }
  1037. CRegKey rkeyLvol(HKEY_LOCAL_MACHINE, wszLvolKey, KEY_WRITE, NULL, REG_OPTION_NON_VOLATILE);
  1038. dwErr = rkeyLvol.QueryErrorStatus();
  1039. if (dwErr != ERROR_SUCCESS) {
  1040. RtlFreeUnicodeString(&ustrNtStorageId);
  1041. return(dwErr);
  1042. }
  1043. CRegSZ rvEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_PATH, pwszEntryPath);
  1044. CRegSZ rvShortEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_SHORT_PATH, pwszEntryPath);
  1045. CRegDWORD rvEntryType((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_TYPE, ulVolumeType);
  1046. CRegSZ rvStorageId((const CRegKey &) rkeyLvol, REG_VALUE_STORAGE_ID, ustrNtStorageId.Buffer);
  1047. CRegSZ rvShareName((const CRegKey &) rkeyLvol, REG_VALUE_SHARE_NAME, pwszShareName);
  1048. RtlFreeUnicodeString(&ustrNtStorageId);
  1049. if (ERROR_SUCCESS != (dwErr = rvEntryPath.QueryErrorStatus()) ||
  1050. ERROR_SUCCESS != (dwErr = rvShortEntryPath.QueryErrorStatus()) ||
  1051. ERROR_SUCCESS != (dwErr = rvEntryType.QueryErrorStatus()) ||
  1052. ERROR_SUCCESS != (dwErr = rvStorageId.QueryErrorStatus()) ||
  1053. ERROR_SUCCESS != (dwErr = rvShareName.QueryErrorStatus())) {
  1054. rkeyLvol.Delete();
  1055. } else {
  1056. dprintf((DEB_TRACE,"Successfully stored local volume info for [%ws]\n", pwszEntryPath));
  1057. }
  1058. return(dwErr);
  1059. }
  1060. //+----------------------------------------------------------------------------
  1061. //
  1062. // Function: DfsRemoveRoot
  1063. //
  1064. // Synopsis: Removes the registry info that makes a machine a root
  1065. //
  1066. // Arguments: None
  1067. //
  1068. // Returns: Win32 error from registry actions
  1069. //
  1070. //-----------------------------------------------------------------------------
  1071. DWORD
  1072. DfsRemoveRoot()
  1073. {
  1074. DWORD dwErr;
  1075. CRegKey *pcregLV;
  1076. //
  1077. // Now the volumes section
  1078. pcregLV = new CRegKey( // Open local volumes section
  1079. HKEY_LOCAL_MACHINE,
  1080. REG_KEY_LOCAL_VOLUMES);
  1081. if (pcregLV != NULL) {
  1082. dwErr = pcregLV->QueryErrorStatus();
  1083. } else {
  1084. dwErr = ERROR_OUTOFMEMORY;
  1085. }
  1086. if (dwErr == ERROR_SUCCESS) {
  1087. dwErr = pcregLV->DeleteChildren(); // Delete local volumes
  1088. delete pcregLV;
  1089. pcregLV = NULL;
  1090. if(dwErr == ERROR_SUCCESS) {
  1091. // now delete the key
  1092. dwErr = RegDeleteKey( HKEY_LOCAL_MACHINE,
  1093. REG_KEY_LOCAL_VOLUMES);
  1094. }
  1095. if (dwErr == ERROR_SUCCESS) {
  1096. //
  1097. // Recreate an empty local volumes key
  1098. //
  1099. pcregLV = new CRegKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES);
  1100. if (pcregLV != NULL) {
  1101. delete pcregLV;
  1102. pcregLV = NULL;
  1103. }
  1104. }
  1105. }
  1106. if(dwErr == ERROR_SUCCESS) {
  1107. //
  1108. // The DfsHost stuff
  1109. //
  1110. CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
  1111. if (dwErr != ERROR_SUCCESS) { // Unable to open volumes dir
  1112. return(dwErr);
  1113. }
  1114. dwErr = cregVolumesDir.DeleteChildren(); // Delete volumes dir
  1115. }
  1116. if(dwErr == ERROR_SUCCESS) {
  1117. dwErr = RegDeleteKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR );
  1118. }
  1119. if(pcregLV) {
  1120. delete pcregLV;
  1121. }
  1122. return( dwErr );
  1123. }
  1124. //+----------------------------------------------------------------------------
  1125. //
  1126. // Function: DfspCreateFtDfsDsObj
  1127. //
  1128. // Synopsis: Updates (by adding to) the Ds objects representing the FtDfs
  1129. //
  1130. // Arguments: wszServerName - Name of server we'll be adding
  1131. // wszDcName - Dc to use
  1132. // wszRootShare - Share to become the root share
  1133. // wszFtDfsName - Name of FtDfs we are creating
  1134. // ppRootList - List of FtDfs roots that need to be informed of
  1135. // the changed Ds object
  1136. //
  1137. // Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
  1138. //
  1139. //-----------------------------------------------------------------------------
  1140. DWORD
  1141. DfspCreateFtDfsDsObj(
  1142. LPWSTR wszServerName,
  1143. LPWSTR wszDcName,
  1144. LPWSTR wszRootShare,
  1145. LPWSTR wszFtDfsName,
  1146. PDFSM_ROOT_LIST *ppRootList)
  1147. {
  1148. DWORD dwErr = ERROR_SUCCESS;
  1149. DWORD i, j;
  1150. WCHAR wszDfsConfigDN[MAX_PATH+1];
  1151. WCHAR wszServerShare[MAX_PATH+1];
  1152. LPWSTR wszConfigurationDN = NULL;
  1153. LDAP *pldap = NULL;
  1154. PLDAPMessage pMsg = NULL;
  1155. LDAPModW ldapModServer;
  1156. LPWSTR rgAttrs[5];
  1157. PLDAPModW rgldapMods[6];
  1158. LDAPMessage *pmsgServers;
  1159. PWCHAR *rgServers;
  1160. PWCHAR *rgNewServers;
  1161. DWORD cServers;
  1162. dwErr = DfspLdapOpen(wszDcName, &pldap, &wszConfigurationDN);
  1163. if (dwErr != ERROR_SUCCESS) {
  1164. pldap = NULL;
  1165. goto Cleanup;
  1166. }
  1167. wcscpy(wszDfsConfigDN,L"CN=");
  1168. wcscat(wszDfsConfigDN,wszFtDfsName);
  1169. wcscat(wszDfsConfigDN,L",");
  1170. wcscat(wszDfsConfigDN,wszConfigurationDN);
  1171. wcscpy(wszServerShare,L"\\\\");
  1172. wcscat(wszServerShare,wszServerName);
  1173. wcscat(wszServerShare,L"\\");
  1174. wcscat(wszServerShare,wszRootShare);
  1175. rgAttrs[0] = L"remoteServerName";
  1176. rgAttrs[1] = NULL;
  1177. if (DfsSvcLdap)
  1178. DbgPrint("DfspCreateFtDfsDsObj:ldap_search_s(%ws)\n", rgAttrs[0]);
  1179. dwErr = ldap_search_sW(
  1180. pldap,
  1181. wszDfsConfigDN,
  1182. LDAP_SCOPE_BASE,
  1183. L"(objectClass=*)",
  1184. rgAttrs,
  1185. 0,
  1186. &pMsg);
  1187. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1188. DfspCreateFtDfsDsObj_Error_ldap_search_sW,
  1189. LOGULONG(dwErr));
  1190. if (dwErr == LDAP_SUCCESS) {
  1191. //
  1192. // We are joining an existing FT Dfs. Append our server\share to it
  1193. //
  1194. pmsgServers = ldap_first_entry(pldap, pMsg);
  1195. if (pmsgServers != NULL) {
  1196. rgServers = ldap_get_valuesW(
  1197. pldap,
  1198. pmsgServers,
  1199. L"remoteServerName");
  1200. if (rgServers != NULL) {
  1201. cServers = ldap_count_valuesW( rgServers );
  1202. //
  1203. // Check that we're not adding the same server in again somehow
  1204. //
  1205. for (i = 0; i < cServers; i++) {
  1206. if (_wcsicmp(wszServerShare,rgServers[i]) == 0) {
  1207. dwErr = ERROR_DUP_NAME;
  1208. ldap_value_freeW( rgServers );
  1209. ldap_msgfree( pMsg );
  1210. pMsg = NULL;
  1211. goto Cleanup;
  1212. }
  1213. }
  1214. rgNewServers = (PWCHAR *) malloc(sizeof(LPWSTR) * (cServers+2));
  1215. if (rgNewServers != NULL) {
  1216. CopyMemory( rgNewServers, rgServers, cServers * sizeof(rgServers[0]) );
  1217. rgNewServers[cServers] = wszServerShare;
  1218. rgNewServers[cServers+1] = NULL;
  1219. ldapModServer.mod_op = LDAP_MOD_REPLACE;
  1220. ldapModServer.mod_type = L"remoteServerName";
  1221. ldapModServer.mod_vals.modv_strvals = rgNewServers;
  1222. rgldapMods[0] = &ldapModServer;
  1223. rgldapMods[1] = NULL;
  1224. if (DfsSvcLdap)
  1225. DbgPrint("DfspCreateFtDfsDsObj:ldap_modify(%ws)\n", L"remoteServerName");
  1226. dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
  1227. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1228. DfspCreateFtDfsDsObj_Error_ldap_modify_sW_2,
  1229. LOGULONG(dwErr));
  1230. if (dwErr == LDAP_ATTRIBUTE_OR_VALUE_EXISTS)
  1231. dwErr = LDAP_SUCCESS;
  1232. if (dwErr != LDAP_SUCCESS) {
  1233. dwErr = LdapMapErrorToWin32(dwErr);
  1234. } else {
  1235. dwErr = ERROR_SUCCESS;
  1236. }
  1237. free(rgNewServers);
  1238. } else {
  1239. dwErr = ERROR_OUTOFMEMORY;
  1240. }
  1241. ldap_value_freeW( rgServers );
  1242. } else {
  1243. dwErr = ERROR_OUTOFMEMORY;
  1244. }
  1245. } else {
  1246. dwErr = ERROR_OUTOFMEMORY;
  1247. }
  1248. ldap_msgfree( pMsg );
  1249. pMsg = NULL;
  1250. } else {
  1251. dwErr = LdapMapErrorToWin32(dwErr);
  1252. }
  1253. if (dwErr != ERROR_SUCCESS) {
  1254. goto Cleanup;
  1255. }
  1256. //
  1257. // Create list of other roots
  1258. //
  1259. DfspCreateRootServerList(
  1260. pldap,
  1261. wszServerName,
  1262. wszDfsConfigDN,
  1263. ppRootList);
  1264. Cleanup:
  1265. if (pMsg != NULL)
  1266. ldap_msgfree(pMsg);
  1267. if (pldap != NULL && pldap != pLdapConnection) {
  1268. if (DfsSvcLdap)
  1269. DbgPrint("DfspCreateFtDfsDsObj:ldap_unbind()\n");
  1270. ldap_unbind( pldap );
  1271. }
  1272. if (wszConfigurationDN == NULL)
  1273. free(wszConfigurationDN);
  1274. return( dwErr );
  1275. }
  1276. //+----------------------------------------------------------------------------
  1277. //
  1278. // Function: DfspRemoveFtDfsDsObj
  1279. //
  1280. // Synopsis: Updates (by removing from) the Ds objects representing the FtDfs
  1281. //
  1282. // Arguments: wszServerName - Name of server we'll be adding
  1283. // wszDcName - Dc to use
  1284. // wszRootShare - Share to become the root share
  1285. // wszFtDfsName - Name of FtDfs we are creating
  1286. // ppRootList - List of FtDfs roots that need to be informed of
  1287. // the changed Ds object
  1288. //
  1289. // Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
  1290. //
  1291. //-----------------------------------------------------------------------------
  1292. DWORD
  1293. DfspRemoveFtDfsDsObj(
  1294. LPWSTR wszServerName,
  1295. LPWSTR wszDcName,
  1296. LPWSTR wszRootShare,
  1297. LPWSTR wszFtDfsName,
  1298. PDFSM_ROOT_LIST *ppRootList)
  1299. {
  1300. DWORD dwErr = ERROR_SUCCESS;
  1301. BOOLEAN fFoundIt = FALSE;
  1302. DWORD i, j;
  1303. WCHAR wszDfsConfigDN[MAX_PATH+1];
  1304. WCHAR wszServerShare[MAX_PATH+1];
  1305. LPWSTR wszConfigurationDN = NULL;
  1306. LDAP *pldap = NULL;
  1307. PLDAPMessage pMsg = NULL;
  1308. LDAPModW ldapModServer;
  1309. LPWSTR rgAttrs[5];
  1310. PLDAPModW rgldapMods[6];
  1311. LDAPMessage *pmsgServers;
  1312. PWCHAR *rgServers;
  1313. PWCHAR *rgNewServers;
  1314. DWORD cServers;
  1315. #if DBG
  1316. if (DfsSvcVerbose)
  1317. DbgPrint("DfspRemoveFtDfsDsObj(%ws,%ws,%ws,%ws)\n",
  1318. wszServerName,
  1319. wszDcName,
  1320. wszRootShare,
  1321. wszFtDfsName);
  1322. #endif
  1323. dwErr = DfspLdapOpen(wszDcName, &pldap, &wszConfigurationDN);
  1324. if (dwErr != ERROR_SUCCESS) {
  1325. goto Cleanup;
  1326. }
  1327. //
  1328. // Search for the FtDfs object
  1329. //
  1330. wcscpy(wszDfsConfigDN,L"CN=");
  1331. wcscat(wszDfsConfigDN,wszFtDfsName);
  1332. wcscat(wszDfsConfigDN,L",");
  1333. wcscat(wszDfsConfigDN,wszConfigurationDN);
  1334. wcscpy(wszServerShare,L"\\\\");
  1335. wcscat(wszServerShare,wszServerName);
  1336. wcscat(wszServerShare,L"\\");
  1337. wcscat(wszServerShare,wszRootShare);
  1338. rgAttrs[0] = L"remoteServerName";
  1339. rgAttrs[1] = NULL;
  1340. if (DfsSvcLdap)
  1341. DbgPrint("DfspRemoveFtDfsDsObj:ldap_search_s(%ws)\n", rgAttrs[0]);
  1342. dwErr = ldap_search_sW(
  1343. pldap,
  1344. wszDfsConfigDN,
  1345. LDAP_SCOPE_BASE,
  1346. L"(objectClass=*)",
  1347. rgAttrs,
  1348. 0,
  1349. &pMsg);
  1350. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1351. DfspRemoveFtDfsDsObj_Error_ldap_search_sW,
  1352. LOGULONG(dwErr));
  1353. if (dwErr != LDAP_SUCCESS) {
  1354. dwErr = LdapMapErrorToWin32(dwErr);
  1355. goto Cleanup;
  1356. }
  1357. dwErr = ERROR_SUCCESS;
  1358. //
  1359. // We found a Dfs object to update
  1360. //
  1361. pmsgServers = ldap_first_entry(pldap, pMsg);
  1362. if (pmsgServers != NULL) {
  1363. rgServers = ldap_get_valuesW(
  1364. pldap,
  1365. pmsgServers,
  1366. L"remoteServerName");
  1367. if (rgServers != NULL) {
  1368. cServers = ldap_count_valuesW( rgServers );
  1369. rgNewServers = (PWCHAR *)malloc(sizeof(LPWSTR) * (cServers+1));
  1370. if (rgNewServers != NULL) {
  1371. for (i = j = 0; i < cServers; i += 1) {
  1372. if (_wcsicmp(wszServerShare, rgServers[i]) == 0) {
  1373. fFoundIt = TRUE;
  1374. continue;
  1375. }
  1376. rgNewServers[j++] = rgServers[i];
  1377. }
  1378. rgNewServers[j] = NULL;
  1379. if (j > 0 && fFoundIt == TRUE) {
  1380. ldapModServer.mod_op = LDAP_MOD_REPLACE;
  1381. ldapModServer.mod_type = L"remoteServerName";
  1382. ldapModServer.mod_vals.modv_strvals = rgNewServers;
  1383. rgldapMods[0] = &ldapModServer;
  1384. rgldapMods[1] = NULL;
  1385. if (DfsSvcLdap)
  1386. DbgPrint("DfspRemoveFtDfsDsObj:ldap_modify(%ws)\n", L"remoteServerName");
  1387. dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
  1388. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1389. DfspRemoveFtDfsDsObj_Error_ldap_modify_sW,
  1390. LOGULONG(dwErr));
  1391. if (dwErr != LDAP_SUCCESS) {
  1392. dwErr = LdapMapErrorToWin32(dwErr);
  1393. } else {
  1394. dwErr = ERROR_SUCCESS;
  1395. }
  1396. }
  1397. free(rgNewServers);
  1398. } else {
  1399. dwErr = ERROR_OUTOFMEMORY;
  1400. }
  1401. ldap_value_freeW( rgServers );
  1402. } else {
  1403. dwErr = ERROR_OUTOFMEMORY;
  1404. }
  1405. } else {
  1406. dwErr = ERROR_OUTOFMEMORY;
  1407. }
  1408. if (pMsg != NULL) {
  1409. ldap_msgfree( pMsg );
  1410. pMsg = NULL;
  1411. }
  1412. if (fFoundIt == FALSE) {
  1413. dwErr = ERROR_OBJECT_NOT_FOUND;
  1414. goto Cleanup;
  1415. }
  1416. if (dwErr != ERROR_SUCCESS) {
  1417. goto Cleanup;
  1418. }
  1419. //
  1420. // Create list of other roots
  1421. //
  1422. DfspCreateRootServerList(
  1423. pldap,
  1424. wszServerName,
  1425. wszDfsConfigDN,
  1426. ppRootList);
  1427. Cleanup:
  1428. if (pMsg != NULL)
  1429. ldap_msgfree( pMsg );
  1430. if (pldap != NULL && pldap != pLdapConnection) {
  1431. if (DfsSvcLdap)
  1432. DbgPrint("DfspRemoveFtDfsDsObj:ldap_unbind()\n");
  1433. ldap_unbind( pldap );
  1434. }
  1435. if (wszConfigurationDN != NULL)
  1436. free(wszConfigurationDN);
  1437. #if DBG
  1438. if (DfsSvcVerbose)
  1439. DbgPrint("DfspRemoveFtDfsDsObj returning %d\n", dwErr);
  1440. #endif
  1441. return( dwErr );
  1442. }
  1443. //+----------------------------------------------------------------------------
  1444. //
  1445. // Function: DfspCreateRootServerList
  1446. //
  1447. // Synopsis: Creates a list of root which have to be informed of the change
  1448. // to the Ds object
  1449. // tells them which DC to go to for the latest blob.
  1450. //
  1451. // Arguments: pldap -- Ldap handle to use
  1452. // wszServerName - Name of server to skip
  1453. // wszDfsConfigDN - The DN to use
  1454. // ppRootList - List of FtDfs roots that need to be informed of
  1455. // the changed Ds object
  1456. //
  1457. // Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
  1458. //
  1459. //-----------------------------------------------------------------------------
  1460. DWORD
  1461. DfspCreateRootServerList(
  1462. IN LDAP *pldap,
  1463. IN LPWSTR wszServerName,
  1464. IN LPWSTR wszDfsConfigDN,
  1465. IN PDFSM_ROOT_LIST *ppRootList)
  1466. {
  1467. DWORD dwErr = ERROR_SUCCESS;
  1468. DWORD cServers;
  1469. DWORD cRoots;
  1470. DWORD i;
  1471. PDFSM_ROOT_LIST pRootList = NULL;
  1472. ULONG Size = 0;
  1473. WCHAR *pWc;
  1474. PLDAPMessage pMsg = NULL;
  1475. LDAPMessage *pmsgServers;
  1476. LPWSTR rgAttrs[5];
  1477. PWCHAR *rgServers = NULL;
  1478. #if DBG
  1479. if (DfsSvcVerbose)
  1480. DbgPrint("DfspCreateRootServerList(%ws,%ws)\n",
  1481. wszServerName,
  1482. wszDfsConfigDN);
  1483. #endif
  1484. //
  1485. // Search for the FtDfs object
  1486. //
  1487. rgAttrs[0] = L"remoteServerName";
  1488. rgAttrs[1] = NULL;
  1489. if (DfsSvcLdap)
  1490. DbgPrint("DfspCreateRootServerList:ldap_search_s(%ws)\n", rgAttrs[0]);
  1491. dwErr = ldap_search_sW(
  1492. pldap,
  1493. wszDfsConfigDN,
  1494. LDAP_SCOPE_BASE,
  1495. L"(objectClass=*)",
  1496. rgAttrs,
  1497. 0,
  1498. &pMsg);
  1499. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1500. DfspCreateRootServerList_Error_ldap_search_sW,
  1501. LOGULONG(dwErr));
  1502. if (dwErr != ERROR_SUCCESS) {
  1503. dwErr = LdapMapErrorToWin32(dwErr);
  1504. goto Cleanup;
  1505. }
  1506. dwErr = ERROR_SUCCESS;
  1507. pmsgServers = ldap_first_entry(pldap, pMsg);
  1508. if (pmsgServers != NULL) {
  1509. rgServers = ldap_get_valuesW(
  1510. pldap,
  1511. pmsgServers,
  1512. L"remoteServerName");
  1513. if (rgServers != NULL) {
  1514. cServers = ldap_count_valuesW( rgServers );
  1515. for (cRoots = i = 0; i < cServers; i++) {
  1516. if (wcslen(rgServers[i]) < 3 ||
  1517. rgServers[i][0] != UNICODE_PATH_SEP ||
  1518. _wcsnicmp(wszServerName, &rgServers[i][2], wcslen(wszServerName)) == 0
  1519. ) {
  1520. continue;
  1521. }
  1522. Size += (wcslen(rgServers[i]) + 1) * sizeof(WCHAR);
  1523. cRoots++;
  1524. }
  1525. Size += FIELD_OFFSET(DFSM_ROOT_LIST,Entry[cRoots+1]);
  1526. pRootList = (PDFSM_ROOT_LIST)MIDL_user_allocate(Size);
  1527. if (pRootList != NULL) {
  1528. RtlZeroMemory(pRootList, Size);
  1529. pRootList->cEntries = cRoots;
  1530. pWc = (WCHAR *)&pRootList->Entry[cRoots+1];
  1531. for (cRoots = i = 0; i < cServers; i++) {
  1532. if (wcslen(rgServers[i]) < 3 ||
  1533. rgServers[i][0] != UNICODE_PATH_SEP ||
  1534. _wcsnicmp(wszServerName, &rgServers[i][2], wcslen(wszServerName)) == 0
  1535. ) {
  1536. continue;
  1537. }
  1538. pWc = (WCHAR *)MIDL_user_allocate((wcslen(rgServers[i]) + 1) * sizeof(WCHAR));
  1539. pRootList->Entry[cRoots].ServerShare = pWc;
  1540. wcscpy(pRootList->Entry[cRoots++].ServerShare, rgServers[i]);
  1541. }
  1542. *ppRootList = pRootList;
  1543. } else {
  1544. dwErr = ERROR_OUTOFMEMORY;
  1545. }
  1546. } else {
  1547. dwErr = ERROR_OUTOFMEMORY;
  1548. }
  1549. } else {
  1550. dwErr = ERROR_OUTOFMEMORY;
  1551. }
  1552. Cleanup:
  1553. if (rgServers != NULL)
  1554. ldap_value_freeW(rgServers);
  1555. if (pMsg != NULL)
  1556. ldap_msgfree( pMsg );
  1557. #if DBG
  1558. if (DfsSvcVerbose) {
  1559. DbgPrint("DfspCreateRootServerList dwErr=%d\n", dwErr);
  1560. if (dwErr == NO_ERROR) {
  1561. for (i = 0; i < pRootList->cEntries; i++)
  1562. DbgPrint("[%d][%ws]\n", i, pRootList->Entry[i].ServerShare);
  1563. }
  1564. }
  1565. #endif
  1566. return( dwErr );
  1567. }
  1568. //+----------------------------------------------------------------------------
  1569. //
  1570. // Function: DfspCreateRootList
  1571. //
  1572. // Synopsis: Helper for adding/removing jp's, really a wrapper for
  1573. // DfspCreateRootServerList
  1574. //
  1575. // Arguments: DfsEntryPath - Path (of form \\domainname\ftdfsname)
  1576. // DcName - Dc name to be used
  1577. // ppRootList - Pointer to arg for results
  1578. //
  1579. // Returns: [ERROR_SUCCESS] -- Successfully returning list
  1580. //
  1581. // [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate list
  1582. //
  1583. // [??] - From ldap open/bind, etc.
  1584. //
  1585. //-----------------------------------------------------------------------------
  1586. DWORD
  1587. DfspCreateRootList(
  1588. IN LPWSTR DfsEntryPath,
  1589. IN LPWSTR DcName,
  1590. IN PDFSM_ROOT_LIST *ppRootList)
  1591. {
  1592. ULONG start, end;
  1593. DWORD dwErr = ERROR_SUCCESS;
  1594. WCHAR wszDfsConfigDN[MAX_PATH+1];
  1595. WCHAR wszFtDfsName[MAX_PATH+1];
  1596. WCHAR wszComputerName[MAX_PATH+1];
  1597. LPWSTR wszConfigurationDN = NULL;
  1598. LDAP *pldap = NULL;
  1599. LPWSTR rgAttrs[5];
  1600. DFS_NAME_CONVENTION NameType;
  1601. #if DBG
  1602. if (DfsSvcVerbose)
  1603. DbgPrint("DfspCreateRootList(%ws,%ws)\n",
  1604. DfsEntryPath,
  1605. DcName);
  1606. #endif
  1607. if (DfsEntryPath == NULL || DcName == NULL) {
  1608. dwErr = ERROR_INVALID_PARAMETER;
  1609. goto Cleanup;
  1610. }
  1611. NameType = (ulDfsManagerType == DFS_MANAGER_FTDFS) ? DFS_NAMETYPE_DNS : DFS_NAMETYPE_EITHER;
  1612. dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
  1613. if (dwErr != ERROR_SUCCESS) {
  1614. dprintf((
  1615. DEB_ERROR,
  1616. "Win32 Error %d getting Domain/Computer name\n", dwErr));
  1617. goto Cleanup;
  1618. }
  1619. //
  1620. // Extract the ftdfs name from the DfsEntryPath
  1621. //
  1622. for (start = 1;
  1623. DfsEntryPath[start] != UNICODE_PATH_SEP && DfsEntryPath[start] != UNICODE_NULL;
  1624. start++) {
  1625. NOTHING;
  1626. }
  1627. if (DfsEntryPath[start] == UNICODE_PATH_SEP)
  1628. start++;
  1629. for (end = start;
  1630. DfsEntryPath[end] != UNICODE_PATH_SEP && DfsEntryPath[end] != UNICODE_NULL;
  1631. end++) {
  1632. NOTHING;
  1633. }
  1634. if (DfsEntryPath[start] == UNICODE_PATH_SEP)
  1635. end--;
  1636. if (start >= end) {
  1637. ERROR_INVALID_PARAMETER;
  1638. }
  1639. RtlZeroMemory(wszFtDfsName, sizeof(wszFtDfsName));
  1640. RtlCopyMemory(wszFtDfsName, &DfsEntryPath[start], (end - start) * sizeof(WCHAR));
  1641. #if DBG
  1642. if (DfsSvcVerbose)
  1643. DbgPrint("wszFtDfsName=[%ws]\n", wszFtDfsName);
  1644. #endif
  1645. //
  1646. // Open & bind to the ds
  1647. //
  1648. dwErr = DfspLdapOpen(DcName, &pldap, &wszConfigurationDN);
  1649. if (dwErr != ERROR_SUCCESS) {
  1650. goto Cleanup;
  1651. }
  1652. //
  1653. // Search for the FtDfs object
  1654. //
  1655. wcscpy(wszDfsConfigDN,L"CN=");
  1656. wcscat(wszDfsConfigDN,wszFtDfsName);
  1657. wcscat(wszDfsConfigDN,L",");
  1658. wcscat(wszDfsConfigDN,wszConfigurationDN);
  1659. //
  1660. // Create the list of roots
  1661. //
  1662. dwErr = DfspCreateRootServerList(
  1663. pldap,
  1664. wszComputerName,
  1665. wszDfsConfigDN,
  1666. ppRootList);
  1667. Cleanup:
  1668. if (pldap != NULL && pldap != pLdapConnection) {
  1669. if (DfsSvcLdap)
  1670. DbgPrint("DfspCreateRootList:ldap_unbind()\n");
  1671. ldap_unbind( pldap );
  1672. }
  1673. if (wszConfigurationDN != NULL)
  1674. free(wszConfigurationDN);
  1675. #if DBG
  1676. if (DfsSvcVerbose)
  1677. DbgPrint("DfspCreateRootList returning %d\n", dwErr);
  1678. #endif
  1679. return dwErr;
  1680. }
  1681. //+----------------------------------------------------------------------------
  1682. //
  1683. // Function: DfspLdapOpen
  1684. //
  1685. // Synopsis: Open ldap storage and returns the object name of the
  1686. // Dfs-Configuration object.
  1687. //
  1688. // Arguments: DfsEntryPath - wszDcName - Dc name to be used
  1689. // ppldap -- pointer to pointer to ldap obj, filled in on success
  1690. // pwszObjectName -- pointer to LPWSTR for name of dfs-config object
  1691. //
  1692. // Returns: [ERROR_SUCCESS] -- Successfully returning list
  1693. //
  1694. // [??] - From ldap open/bind, etc.
  1695. //
  1696. //-----------------------------------------------------------------------------
  1697. DWORD
  1698. DfspLdapOpen(
  1699. LPWSTR wszDcName,
  1700. LDAP **ppldap,
  1701. LPWSTR *pwszObjectName)
  1702. {
  1703. DWORD dwErr = ERROR_SUCCESS;
  1704. DWORD i;
  1705. ULONG Size;
  1706. PLDAPMessage pMsg = NULL;
  1707. LDAP *pldap = NULL;
  1708. LPWSTR rgAttrs[5];
  1709. if ( ppldap == NULL || pwszObjectName == NULL) {
  1710. dwErr = ERROR_INVALID_PARAMETER;
  1711. goto Cleanup;
  1712. }
  1713. #if DBG
  1714. if (DfsSvcVerbose)
  1715. DbgPrint("DfspLdapOpen(%ws,0x%x)\n", wszDcName,*ppldap);
  1716. #endif
  1717. //
  1718. // We must be given either a DC name or an ldap connection. If neither, then
  1719. // return an error.
  1720. //
  1721. if (*ppldap == NULL && wszDcName == NULL) {
  1722. dwErr = ERROR_INVALID_PARAMETER;
  1723. goto Cleanup;
  1724. }
  1725. //
  1726. // If we were given an ldap connection, but no DC name, then we just want
  1727. // the name of the dfs config object.
  1728. //
  1729. if (wszDcName == NULL) {
  1730. pldap = *ppldap;
  1731. goto GetConfigObject;
  1732. }
  1733. //
  1734. // We were given a DC name and possibly an ldap connection.
  1735. //
  1736. if (*ppldap == NULL || pLdapConnection == NULL || pwszDSMachineName == NULL) {
  1737. if (pLdapConnection != NULL &&
  1738. pwszDSMachineName != NULL &&
  1739. wszDcName != NULL &&
  1740. wcscmp(pwszDSMachineName, wszDcName) == 0) {
  1741. pldap = pLdapConnection;
  1742. dwErr = ERROR_SUCCESS;
  1743. } else {
  1744. if (DfsSvcLdap)
  1745. DbgPrint("DfspLdapOpen:ldap_init(%ws)\n", wszDcName);
  1746. pldap = ldap_initW(wszDcName, LDAP_PORT);
  1747. if (pldap == NULL) {
  1748. #if DBG
  1749. if (DfsSvcVerbose)
  1750. DbgPrint("DfspLdapOpen:ldap_init failed\n");
  1751. #endif
  1752. LdapGetLastError();
  1753. dwErr = ERROR_INVALID_NAME;
  1754. goto Cleanup; // added to prevent error masking!!
  1755. }
  1756. dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  1757. if (dwErr != LDAP_SUCCESS) {
  1758. dprintf((
  1759. DEB_ERROR,
  1760. "ldap_set_option failed with ldap error %d\n", dwErr));
  1761. pldap = NULL;
  1762. goto Cleanup;
  1763. }
  1764. if (DfsSvcLdap)
  1765. DbgPrint("DfspLdapOpen:ldap_bind()\n");
  1766. dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI);
  1767. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1768. DfspLdapOpen_Error_ldap_bind_s,
  1769. LOGULONG(dwErr));
  1770. if (dwErr != LDAP_SUCCESS) {
  1771. #if DBG
  1772. if (DfsSvcVerbose)
  1773. DbgPrint("ldap_bind_s failed with ldap error %d\n", dwErr);
  1774. #endif
  1775. pldap = NULL;
  1776. dwErr = LdapMapErrorToWin32(dwErr);
  1777. goto Cleanup;
  1778. }
  1779. if (DfsSvcLdap)
  1780. DbgPrint("DfspLdapOpen:pLdapConnection set to %ws\n", wszDcName);
  1781. if (pLdapConnection != NULL)
  1782. ldap_unbind(pLdapConnection);
  1783. pLdapConnection = pldap;
  1784. pwszDSMachineName = wszDSMachineName;
  1785. wcscpy(pwszDSMachineName, wszDcName);
  1786. if (DfsSvcLdap)
  1787. DbgPrint("DfspLdapOpen:pLdapConnection:0x%x\n", pLdapConnection);
  1788. }
  1789. } else {
  1790. pldap = *ppldap;
  1791. }
  1792. //
  1793. // Get attribute "defaultNameContext" containing name of entry we'll be
  1794. // using for our DN
  1795. //
  1796. GetConfigObject:
  1797. if (gConfigurationDN == NULL) {
  1798. rgAttrs[0] = L"defaultnamingContext";
  1799. rgAttrs[1] = NULL;
  1800. if (DfsSvcLdap)
  1801. DbgPrint("DfspLdapOpen:ldap_search_s(%ws)\n", rgAttrs[0]);
  1802. dwErr = ldap_search_sW(
  1803. pldap,
  1804. L"",
  1805. LDAP_SCOPE_BASE,
  1806. L"(objectClass=*)",
  1807. rgAttrs,
  1808. 0,
  1809. &pMsg);
  1810. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
  1811. DfspLdapOpen_Error_ldap_search_sW,
  1812. LOGULONG(dwErr));
  1813. if (dwErr == LDAP_SUCCESS) {
  1814. PLDAPMessage pEntry = NULL;
  1815. PWCHAR *rgszNamingContexts = NULL;
  1816. DWORD i, cNamingContexts;
  1817. dwErr = ERROR_SUCCESS;
  1818. if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL &&
  1819. (rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL &&
  1820. (cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) {
  1821. gConfigurationDN = (LPWSTR)malloc((wcslen(*rgszNamingContexts)+1) * sizeof(WCHAR));
  1822. if (gConfigurationDN == NULL)
  1823. dwErr = ERROR_OUTOFMEMORY;
  1824. else
  1825. wcscpy( gConfigurationDN, *rgszNamingContexts );
  1826. } else {
  1827. dwErr = ERROR_UNEXP_NET_ERR;
  1828. }
  1829. if (rgszNamingContexts != NULL)
  1830. ldap_value_freeW( rgszNamingContexts );
  1831. } else {
  1832. dwErr = LdapMapErrorToWin32(dwErr);
  1833. }
  1834. if (dwErr != ERROR_SUCCESS) {
  1835. #if DBG
  1836. if (DfsSvcVerbose)
  1837. DbgPrint("Unable to find Configuration naming context\n");
  1838. #endif
  1839. goto Cleanup;
  1840. }
  1841. }
  1842. //
  1843. // Create string with full object name
  1844. //
  1845. Size = wcslen(DfsConfigContainer) * sizeof(WCHAR) +
  1846. sizeof(WCHAR) +
  1847. wcslen(gConfigurationDN) * sizeof(WCHAR) +
  1848. sizeof(WCHAR);
  1849. *pwszObjectName = (LPWSTR)malloc(Size);
  1850. if (*pwszObjectName == NULL) {
  1851. dwErr = ERROR_OUTOFMEMORY;
  1852. goto Cleanup;
  1853. }
  1854. wcscpy(*pwszObjectName,DfsConfigContainer);
  1855. wcscat(*pwszObjectName,L",");
  1856. wcscat(*pwszObjectName,gConfigurationDN);
  1857. #if DBG
  1858. if (DfsSvcVerbose)
  1859. DbgPrint("DfspLdapOpen:object name=[%ws]\n", *pwszObjectName);
  1860. #endif
  1861. Cleanup:
  1862. //
  1863. // If we had an error and we check if the ldap connection was passed in.
  1864. // If not, and it is not pLdapConnection, close it.
  1865. //
  1866. if (dwErr != ERROR_SUCCESS &&
  1867. pldap != NULL &&
  1868. pldap != pLdapConnection &&
  1869. *ppldap == NULL) {
  1870. if (DfsSvcLdap)
  1871. DbgPrint("DfspLdapOpen:ldap_unbind()\n");
  1872. ldap_unbind( pldap );
  1873. pldap = NULL;
  1874. }
  1875. if (pMsg != NULL)
  1876. ldap_msgfree(pMsg);
  1877. if (*ppldap == NULL) {
  1878. *ppldap = pldap;
  1879. }
  1880. #if DBG
  1881. if (DfsSvcVerbose)
  1882. DbgPrint("DfspLdapOpen:returning %d\n", dwErr);
  1883. #endif
  1884. return( dwErr );
  1885. }