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.

5393 lines
134 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation
  4. //
  5. // File: dfsmsrv.cxx
  6. //
  7. // Contents: The server side stubs for the Dfs Manager Admin RPC interface
  8. //
  9. // Classes:
  10. //
  11. // Functions: GetDfsVolumeFromPath --
  12. // AddReplica --
  13. // RemoveReplica --
  14. // Delete --
  15. // SetComment --
  16. // GetInfo --
  17. // Move --
  18. // Rename --
  19. // CreateChild --
  20. // GetReplicaSetID --
  21. // SetReplicaSetID --
  22. // ChangeStorageID --
  23. // SetReplicaState --
  24. // SetVolumeState --
  25. //
  26. // History: 12-27-95 Milans Created.
  27. //
  28. //-----------------------------------------------------------------------------
  29. //#include <ntos.h>
  30. //#include <ntrtl.h>
  31. //#include <nturtl.h>
  32. //#include <dfsfsctl.h>
  33. //#include <windows.h>
  34. #include <headers.hxx>
  35. #pragma hdrstop
  36. extern "C" {
  37. #include "dfspriv.h" // For I_NetDfsXXX calls
  38. #include <dfsmsrv.h>
  39. #include <srvfsctl.h>
  40. #include <icanon.h>
  41. #include <validc.h>
  42. #include <winldap.h>
  43. #include <dsrole.h>
  44. }
  45. extern "C" {
  46. DWORD
  47. DfsGetFtServersFromDs(
  48. IN PVOID pLDAP OPTIONAL,
  49. IN LPWSTR wszDomainName OPTIONAL,
  50. IN LPWSTR wszDfsName,
  51. OUT LPWSTR **List
  52. );
  53. }
  54. NET_API_STATUS
  55. NetrDfsEnum200(
  56. IN DWORD Level,
  57. IN DWORD PrefMaxLen,
  58. IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
  59. IN OUT LPDWORD ResumeHandle
  60. );
  61. #include "cdfsvol.hxx"
  62. #include "jnpt.hxx"
  63. #include "security.hxx"
  64. #include "registry.hxx"
  65. #include "setup.hxx"
  66. #include "ftsup.hxx"
  67. #include "dfsmwml.h"
  68. NET_API_STATUS
  69. DfspGetOneEnumInfo(
  70. DWORD i,
  71. DWORD Level,
  72. LPBYTE InfoArray,
  73. LPDWORD InfoSize,
  74. LPDWORD ResumeHandle);
  75. DWORD
  76. DfspGetOneEnumInfoEx(
  77. PDFS_VOLUME_LIST pDfsVolList,
  78. DWORD i,
  79. DWORD Level,
  80. LPBYTE InfoArray,
  81. LPDWORD InfoSize);
  82. VOID
  83. DfspFreeOneEnumInfo(
  84. DWORD i,
  85. DWORD Level,
  86. LPBYTE InfoArray);
  87. DWORD
  88. DfspAllocateRelationInfo(
  89. PDFS_PKT_RELATION_INFO pDfsRelationInfo,
  90. LPDFSM_RELATION_INFO *ppRelationInfo);
  91. DWORD
  92. DfsManagerRemoveServiceForced(
  93. LPWSTR wszServerName,
  94. LPWSTR wszDCName,
  95. LPWSTR wszFtDfsName);
  96. DWORD
  97. InitializeDfsManager(void);
  98. VOID
  99. GetDebugSwitches();
  100. VOID
  101. GetConfigSwitches();
  102. extern HANDLE hSyncEvent;
  103. extern ULONG DcLockIntervalInMs;
  104. extern PLDAP pLdapConnection;
  105. //+----------------------------------------------------------------------------
  106. //
  107. // Function: NormalizeEntryPath
  108. //
  109. // Synopsis: Normalizes an EntryPath argument to a prefix.
  110. //
  111. // Arguments: [pwszEntryPath] -- The entry path to normalize.
  112. //
  113. // Returns: If pwszEntryPath is a UNC path, this routine returns
  114. // &pwszEntryPath[1]; if pwszEntryPath starts with a backslash,
  115. // this routine returns pwszEntryPath. In all other cases, this
  116. // routine returns NULL.
  117. //
  118. //-----------------------------------------------------------------------------
  119. LPWSTR
  120. NormalizeEntryPath(
  121. IN LPWSTR pwszEntryPath)
  122. {
  123. LPWSTR pwszEntryPathCanon;
  124. DWORD Type = 0;
  125. DWORD dwErr;
  126. ULONG Size = wcslen(pwszEntryPath) + 1;
  127. WCHAR *wCp;
  128. #if DBG
  129. if (DfsSvcVerbose)
  130. DbgPrint("NormalizeEntryPath(%ws)\n", pwszEntryPath);
  131. #endif
  132. if (pwszEntryPath == NULL)
  133. return( NULL );
  134. if (wcslen(pwszEntryPath) < 2)
  135. return( NULL );
  136. if (pwszEntryPath[0] != UNICODE_PATH_SEP)
  137. return( NULL );
  138. pwszEntryPathCanon = new WCHAR [ Size ];
  139. if (pwszEntryPathCanon == NULL)
  140. return( NULL );
  141. dwErr = I_NetPathCanonicalize(
  142. NULL,
  143. pwszEntryPath,
  144. pwszEntryPathCanon,
  145. Size * sizeof(WCHAR),
  146. NULL,
  147. &Type,
  148. 0);
  149. #if DBG
  150. if (DfsSvcVerbose)
  151. DbgPrint("NormalizeEntryPath:pwszEntryPathCanon:%ws)\n", pwszEntryPathCanon);
  152. #endif
  153. if (dwErr != 0 || (Type != ITYPE_UNC && Type != (ITYPE_PATH | ITYPE_ABSOLUTE))) {
  154. delete [] pwszEntryPathCanon;
  155. return( NULL );
  156. }
  157. if (ulDfsManagerType == DFS_MANAGER_SERVER) {
  158. if (pwszDfsRootName == NULL)
  159. return NULL;
  160. wcscpy(pwszEntryPath, UNICODE_PATH_SEP_STR);
  161. wcscat(pwszEntryPath, pwszDfsRootName);
  162. if (pwszEntryPathCanon[1] == UNICODE_PATH_SEP) {
  163. wCp = wcschr(&pwszEntryPathCanon[2], UNICODE_PATH_SEP);
  164. } else {
  165. wCp = wcschr(&pwszEntryPathCanon[1], UNICODE_PATH_SEP);
  166. }
  167. if(wCp == NULL) {
  168. return NULL;
  169. }
  170. wcscat(pwszEntryPath, wCp);
  171. } else {
  172. if (pwszEntryPathCanon[1] == UNICODE_PATH_SEP) {
  173. wcscpy(pwszEntryPath, &pwszEntryPathCanon[1]);
  174. } else {
  175. wcscpy(pwszEntryPath, pwszEntryPathCanon);
  176. }
  177. }
  178. delete [] pwszEntryPathCanon;
  179. #if DBG
  180. if (DfsSvcVerbose)
  181. DbgPrint("NormalizeEntryPath returning %ws\n", pwszEntryPath);
  182. #endif
  183. return( pwszEntryPath );
  184. }
  185. //+----------------------------------------------------------------------------
  186. //
  187. // Function: FormFTDfsEntryPath
  188. //
  189. // Synopsis: When the NetDfsXXX APIs are used to administer an FTDfs, the
  190. // entry path passed in is of the form \servername\sharename\p
  191. // These first two components must be massaged to the form
  192. // \domainname\ftdfsname\p
  193. //
  194. // Arguments: [pwszEntryPath] -- The entry path to massage
  195. //
  196. // Returns: If successfully massaged the entry path, returns a pointer to
  197. // the newly allocated FTDfs entry path, else NULL
  198. //
  199. //-----------------------------------------------------------------------------
  200. LPWSTR
  201. FormFTDfsEntryPath(
  202. IN LPWSTR pwszEntryPath)
  203. {
  204. LPWSTR pwszFTDfsPath;
  205. LPWSTR pwszRestOfPath;
  206. if (pwszDomainName == NULL || pwszDfsRootName == NULL)
  207. return NULL;
  208. if (pwszEntryPath[0] == UNICODE_PATH_SEP &&
  209. pwszEntryPath[1] == UNICODE_PATH_SEP) {
  210. pwszEntryPath++;
  211. }
  212. pwszFTDfsPath = new WCHAR [
  213. wcslen(pwszEntryPath) +
  214. wcslen(UNICODE_PATH_SEP_STR) +
  215. wcslen(pwszDomainName) +
  216. wcslen(UNICODE_PATH_SEP_STR) +
  217. wcslen(pwszDfsRootName) ];
  218. if (pwszFTDfsPath != NULL) {
  219. wcscpy(pwszFTDfsPath, UNICODE_PATH_SEP_STR);
  220. wcscat(pwszFTDfsPath, pwszDomainName);
  221. wcscat(pwszFTDfsPath, UNICODE_PATH_SEP_STR);
  222. wcscat(pwszFTDfsPath, pwszDfsRootName);
  223. //
  224. // Skip past the first three backslashes of the input parameter
  225. //
  226. if (pwszEntryPath[0] != UNICODE_PATH_SEP)
  227. return NULL;
  228. pwszRestOfPath = wcschr( &pwszEntryPath[1], UNICODE_PATH_SEP );
  229. if (pwszRestOfPath == NULL)
  230. return NULL;
  231. pwszRestOfPath = wcschr( &pwszRestOfPath[1], UNICODE_PATH_SEP );
  232. if (pwszRestOfPath != NULL)
  233. wcscat(pwszFTDfsPath, pwszRestOfPath );
  234. }
  235. #if DBG
  236. if (DfsSvcVerbose)
  237. DbgPrint("FormFTDfsEntryPath(%ws->%ws)\n", pwszEntryPath, pwszFTDfsPath);
  238. #endif
  239. return( pwszFTDfsPath );
  240. }
  241. //+----------------------------------------------------------------------------
  242. //
  243. // Function: FormStdDfsEntryPath
  244. //
  245. // Synopsis: When the NetDfsXXX APIs are used to administer an StdDfs, the
  246. // entry path passed in may be of the form \somename\dfsname.
  247. // The first component must be normalized if possible
  248. // to the computer name.
  249. //
  250. // Arguments: [pwszEntryPath] -- The entry path to normalize
  251. //
  252. // Returns: If successfully normalized the entry path, returns a pointer to
  253. // the newly allocated entry path, else NULL
  254. //
  255. //-----------------------------------------------------------------------------
  256. LPWSTR
  257. FormStdDfsEntryPath(
  258. IN LPWSTR pwszEntryPath)
  259. {
  260. LPWSTR pwszStdDfsPath;
  261. LPWSTR pwszRestOfPath;
  262. if (pwszComputerName == NULL || pwszDfsRootName == NULL)
  263. return NULL;
  264. if (pwszEntryPath[0] == UNICODE_PATH_SEP &&
  265. pwszEntryPath[1] == UNICODE_PATH_SEP) {
  266. pwszEntryPath++;
  267. }
  268. pwszStdDfsPath = new WCHAR [
  269. wcslen(pwszEntryPath) +
  270. wcslen(UNICODE_PATH_SEP_STR) +
  271. wcslen(pwszComputerName) ];
  272. if (pwszStdDfsPath != NULL) {
  273. wcscpy(pwszStdDfsPath, UNICODE_PATH_SEP_STR);
  274. wcscat(pwszStdDfsPath, pwszComputerName);
  275. //
  276. // Skip past the first two backslashes of the input parameter
  277. //
  278. ASSERT(pwszEntryPath[0] == UNICODE_PATH_SEP);
  279. pwszRestOfPath = wcschr( &pwszEntryPath[1], UNICODE_PATH_SEP );
  280. if (pwszRestOfPath != NULL)
  281. wcscat(pwszStdDfsPath, pwszRestOfPath );
  282. }
  283. #if DBG
  284. if (DfsSvcVerbose)
  285. DbgPrint("FormStdDfsEntryPath(%ws->%ws)\n", pwszEntryPath, pwszStdDfsPath);
  286. #endif
  287. return( pwszStdDfsPath );
  288. }
  289. //+----------------------------------------------------------------------------
  290. //
  291. // Function: GetDfsVolumeFromPath
  292. //
  293. // Synopsis: Given a volume EntryPath, returns a CDfsVolume for that
  294. // volume.
  295. //
  296. // Arguments: [pwszEntryPath] -- EntryPath for which CDfsVolume is
  297. // desired.
  298. // [fExactMatch] -- If TRUE, this call will succeed only if
  299. // a volume object's EntryPath exactly matches
  300. // pwszEntryPath.
  301. // [ppCDfsVolume] -- On successful return, contains pointer to
  302. // newly allocated CDfsVolume for the EntryPath.
  303. //
  304. // Returns: [S_OK] -- Successfully returning new CDfsVolume.
  305. //
  306. // [E_OUTOFMEMORY] -- Out of memory creating new object.
  307. //
  308. // [DFS_E_NO_SUCH_VOLUME] -- Unable to find volume with
  309. // given EntryPath.
  310. //
  311. //-----------------------------------------------------------------------------
  312. DWORD
  313. GetDfsVolumeFromPath(
  314. LPWSTR pwszEntryPath,
  315. BOOLEAN fExactMatch,
  316. CDfsVolume **ppCDfsVolume)
  317. {
  318. DWORD dwErr;
  319. CDfsVolume *pCDfsVolume = NULL;
  320. LPWSTR pwszVolumeObject = NULL;
  321. dwErr = GetVolObjForPath( pwszEntryPath, fExactMatch, &pwszVolumeObject );
  322. if (dwErr == ERROR_SUCCESS) {
  323. pCDfsVolume = new CDfsVolume();
  324. if (pCDfsVolume != NULL) {
  325. dwErr = pCDfsVolume->Load( pwszVolumeObject, 0 );
  326. if (dwErr != ERROR_SUCCESS) {
  327. pCDfsVolume->Release();
  328. pCDfsVolume = NULL;
  329. }
  330. } else {
  331. dwErr = ERROR_OUTOFMEMORY;
  332. }
  333. delete [] pwszVolumeObject;
  334. }
  335. *ppCDfsVolume = pCDfsVolume;
  336. return( dwErr );
  337. }
  338. //+----------------------------------------------------------------------------
  339. //
  340. // Function: NetrDfsManagerGetVersion
  341. //
  342. // Synopsis: Returns the version of this server side implementation.
  343. //
  344. // Arguments: None.
  345. //
  346. // Returns: The version number.
  347. //
  348. //-----------------------------------------------------------------------------
  349. DWORD
  350. NetrDfsManagerGetVersion()
  351. {
  352. DWORD Version = 2;
  353. DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetVersion_Start, LOGNOTHING);
  354. #if DBG
  355. if (DfsSvcVerbose)
  356. DbgPrint("NetrDfsGetVersion()\n");
  357. #endif
  358. DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetVersion_End, LOGULONG(Version));
  359. return( Version );
  360. }
  361. //+----------------------------------------------------------------------------
  362. //
  363. // Function: NetrDfsAdd (Obsolete)
  364. //
  365. //-----------------------------------------------------------------------------
  366. extern "C" NET_API_STATUS
  367. NetrDfsAdd(
  368. IN LPWSTR DfsEntryPath,
  369. IN LPWSTR ServerName,
  370. IN LPWSTR ShareName,
  371. IN LPWSTR Comment,
  372. IN DWORD Flags)
  373. {
  374. NET_API_STATUS status = ERROR_SUCCESS;
  375. DFSM_TRACE_NORM(EVENT, NetrDfsAdd_Start,
  376. LOGSTATUS(status)
  377. LOGWSTR(DfsEntryPath)
  378. LOGWSTR(ServerName)
  379. LOGWSTR(ShareName));
  380. if (!AccessCheckRpcClient()) {
  381. status = ERROR_ACCESS_DENIED;
  382. }
  383. else if (ulDfsManagerType == DFS_MANAGER_FTDFS){
  384. status = ERROR_NOT_SUPPORTED;
  385. }
  386. else {
  387. status = NetrDfsAdd2(
  388. DfsEntryPath,
  389. NULL,
  390. ServerName,
  391. ShareName,
  392. Comment,
  393. Flags,
  394. NULL);
  395. }
  396. DFSM_TRACE_NORM(EVENT, NetrDfsAdd_End,
  397. LOGSTATUS(status)
  398. LOGWSTR(DfsEntryPath)
  399. LOGWSTR(ServerName)
  400. LOGWSTR(ShareName));
  401. return status;
  402. }
  403. //+----------------------------------------------------------------------------
  404. //
  405. // Function: NetrDfsAdd2
  406. //
  407. // Synopsis: Adds a volume/replica/link to this Dfs.
  408. //
  409. // Arguments: [DfsEntryPath] -- Entry Path of volume/link to be created, or
  410. // to which a replica should be added.
  411. // [DcName] -- Name of Dc to use
  412. // [ServerName] -- Name of server backing the volume.
  413. // [ShareName] -- Name of share on ServerName backing the volume.
  414. // [Comment] -- Comment associated with this volume, only used
  415. // when DFS_ADD_VOLUME is specified.
  416. // [Flags] -- If DFS_ADD_VOLUME, a new volume will be created.
  417. // If DFS_ADD_LINK, a new link to another Dfs will be
  418. // create. If 0, a replica will be added.
  419. // [ppRootList] -- On success, returns a list of roots that need to be
  420. // informed of the change in the DS object
  421. //
  422. // Returns: [NERR_Success] -- Operation succeeded.
  423. //
  424. // [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to a
  425. // existing Dfs volume.
  426. //
  427. // [NERR_DfsVolumeAlreadyExists] -- DFS_ADD_VOLUME was specified
  428. // and a volume with DfsEntryPath already exists.
  429. //
  430. // [NERR_DfsInternalCorruption] -- An internal database
  431. // corruption was encountered while executing this
  432. // operation.
  433. //
  434. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  435. //
  436. //-----------------------------------------------------------------------------
  437. extern "C" NET_API_STATUS
  438. NetrDfsAdd2(
  439. IN LPWSTR DfsEntryPath,
  440. IN LPWSTR DcName,
  441. IN LPWSTR ServerName,
  442. IN LPWSTR ShareName,
  443. IN LPWSTR Comment,
  444. IN DWORD Flags,
  445. IN PDFSM_ROOT_LIST *ppRootList)
  446. {
  447. NET_API_STATUS status = NERR_Success;
  448. CDfsVolume *pDfsVol = NULL;
  449. DFS_REPLICA_INFO replInfo;
  450. DWORD dwVersion;
  451. DWORD dwVolType;
  452. DWORD shareType = 0;
  453. DWORD dwErr;
  454. LPWSTR realShareName;
  455. BOOLEAN modifiedShareName = FALSE;
  456. LPDFS_SITELIST_INFO pSiteInfo;
  457. LPWSTR OrgDfsEntryPath = DfsEntryPath;
  458. #if DBG
  459. if (DfsSvcVerbose)
  460. DbgPrint("NetrDfsAdd2(%ws,%ws,%ws,%ws,%ws,%d,0x%x)\n",
  461. DfsEntryPath,
  462. DcName,
  463. ServerName,
  464. ShareName,
  465. Comment,
  466. Flags,
  467. ppRootList);
  468. #endif
  469. DFSM_TRACE_NORM(EVENT, NetrDfsAdd2_Start,
  470. LOGSTATUS(status)
  471. LOGWSTR(OrgDfsEntryPath)
  472. LOGWSTR(DcName)
  473. LOGWSTR(ServerName)
  474. LOGWSTR(ShareName));
  475. if (!AccessCheckRpcClient()) {
  476. status = ERROR_ACCESS_DENIED;
  477. goto cleanup;
  478. }
  479. //
  480. // Validate the input arguments...
  481. //
  482. if ( (Flags & ~(DFS_ADD_VOLUME | DFS_RESTORE_VOLUME)) != 0) {
  483. status = ERROR_INVALID_PARAMETER;
  484. goto cleanup;
  485. }
  486. if (DfsEntryPath == NULL || DfsEntryPath[0] != UNICODE_PATH_SEP){
  487. status = ERROR_INVALID_PARAMETER;
  488. goto cleanup;
  489. }
  490. #if 0 // Broken for DNS names
  491. DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
  492. #endif
  493. #if DBG
  494. if (DfsSvcVerbose) {
  495. DbgPrint(" 0:DfsEntryPath=[%ws]\n", DfsEntryPath);
  496. DbgPrint(" 0:ServerName=[%ws]\n", ServerName);
  497. DbgPrint(" 0:ShareName=[%ws]\n", ShareName);
  498. }
  499. #endif
  500. if (DfsEntryPath != NULL) {
  501. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  502. DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
  503. else if (ulDfsManagerType == DFS_MANAGER_SERVER)
  504. DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
  505. if (DfsEntryPath == NULL) {
  506. status = ERROR_OUTOFMEMORY;
  507. goto cleanup;
  508. }
  509. }
  510. #if DBG
  511. if (DfsSvcVerbose) {
  512. DbgPrint(" 1:ServerName=[%ws]\n", ServerName);
  513. DbgPrint(" 1:ShareName=[%ws]\n", ShareName);
  514. }
  515. #endif
  516. if (DfsEntryPath == NULL ||
  517. ServerName == NULL ||
  518. ShareName == NULL) {
  519. if (DfsEntryPath != NULL && DfsEntryPath != OrgDfsEntryPath) {
  520. delete [] DfsEntryPath;
  521. }
  522. status = ERROR_INVALID_PARAMETER;
  523. goto cleanup;
  524. }
  525. if (ServerName[0] == UNICODE_NULL ||
  526. ShareName[0] == UNICODE_NULL) {
  527. if (DfsEntryPath != OrgDfsEntryPath) {
  528. delete [] DfsEntryPath;
  529. }
  530. status = ERROR_INVALID_PARAMETER;
  531. goto cleanup;
  532. }
  533. ENTER_DFSM_OPERATION;
  534. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  535. if (DcName != NULL)
  536. DfsManagerSetDcName(DcName);
  537. LdapIncrementBlob();
  538. }
  539. //
  540. // We next determine whether this is going to be an interdomain link or
  541. // not. While doing so, we'll also check for certain cases of cyclical
  542. // references.
  543. //
  544. if (I_NetDfsIsThisADomainName(ServerName) == ERROR_SUCCESS) {
  545. if (ulDfsManagerType == DFS_MANAGER_FTDFS &&
  546. pwszDfsRootName != NULL &&
  547. (_wcsicmp( ServerName, pwszDfsRootName) == 0)){
  548. status = NERR_DfsCyclicalName;
  549. DFSM_TRACE_HIGH(ERROR, NetrDfsAdd2_Error1,
  550. LOGSTATUS(status)
  551. LOGWSTR(ServerName)
  552. LOGWSTR(ShareName));
  553. }
  554. else
  555. dwVolType = DFS_VOL_TYPE_REFERRAL_SVC | DFS_VOL_TYPE_INTER_DFS;
  556. } else if (Flags & DFS_RESTORE_VOLUME) {
  557. dwVolType = DFS_VOL_TYPE_DFS;
  558. shareType = 0;
  559. } else {
  560. //
  561. // Server name passed in is a real server. See if what kind of share
  562. // we are talking about.
  563. //
  564. PSHARE_INFO_1005 shi1005;
  565. realShareName = wcschr(ShareName, UNICODE_PATH_SEP);
  566. if (realShareName != NULL) {
  567. *realShareName = UNICODE_NULL;
  568. modifiedShareName = TRUE;
  569. }
  570. status = NetShareGetInfo(
  571. ServerName,
  572. ShareName,
  573. 1005,
  574. (PBYTE *) &shi1005);
  575. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, NetrDfsAdd2_Error_NetShareGetInfo,
  576. LOGSTATUS(status)
  577. LOGWSTR(ServerName)
  578. LOGWSTR(ShareName));
  579. if (modifiedShareName)
  580. *realShareName = UNICODE_PATH_SEP;
  581. if (status == NERR_Success) {
  582. shareType = shi1005->shi1005_flags;
  583. NetApiBufferFree( shi1005 );
  584. }
  585. if (status != NERR_NetNameNotFound)
  586. status = NERR_Success;
  587. if (status == NERR_Success) {
  588. if (shareType & SHI1005_FLAGS_DFS_ROOT) {
  589. //
  590. // If this is a server based Dfs, make sure we are not creating
  591. // a cyclical link to our root share. Since there is only one
  592. // share per server that can be a Dfs Root, it is sufficient to
  593. // see if the machine names match.
  594. //
  595. if (ulDfsManagerType == DFS_MANAGER_SERVER &&
  596. pwszDfsRootName != NULL &&
  597. (_wcsicmp( ServerName, pwszDfsRootName) == 0)) {
  598. status = NERR_DfsCyclicalName;
  599. DFSM_TRACE_HIGH(ERROR, NetrDfsAdd2_Error2,
  600. LOGSTATUS(status)
  601. LOGWSTR(ServerName)
  602. LOGWSTR(ShareName));
  603. }
  604. else
  605. dwVolType = DFS_VOL_TYPE_REFERRAL_SVC |
  606. DFS_VOL_TYPE_INTER_DFS;
  607. } else {
  608. dwVolType = DFS_VOL_TYPE_DFS;
  609. }
  610. }
  611. }
  612. //
  613. // Great, the parameters look semi-reasonable, lets do the work.
  614. //
  615. if (status == NERR_Success) {
  616. if ((Flags & DFS_ADD_VOLUME) == 0) {
  617. status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
  618. } else {
  619. //
  620. // Add volume or link case, so we don't want an exact match.
  621. // Note that if the Dfs Volume returned does indeed match exactly,
  622. // its ok, because the subsequent CreateChild operation will fail.
  623. //
  624. status = GetDfsVolumeFromPath( DfsEntryPath, FALSE, &pDfsVol );
  625. }
  626. }
  627. if (status != ERROR_SUCCESS) {
  628. pDfsVol = NULL;
  629. }
  630. if (status == ERROR_SUCCESS) {
  631. //
  632. // Create a DFS_REPLICA_INFO struct for this server-share...
  633. //
  634. ZeroMemory( &replInfo, sizeof(replInfo) );
  635. #if DBG
  636. if (DfsSvcVerbose) {
  637. DbgPrint(" 2:ServerName=[%ws]\n", ServerName);
  638. DbgPrint(" 2:ShareName=[%ws]\n", ShareName);
  639. }
  640. #endif
  641. replInfo.ulReplicaType = DFS_STORAGE_TYPE_NONDFS;
  642. replInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
  643. replInfo.pwszServerName = ServerName;
  644. replInfo.pwszShareName = ShareName;
  645. //
  646. // and carry out the Add operation.
  647. //
  648. if ((Flags & DFS_ADD_VOLUME) != 0) {
  649. status = pDfsVol->CreateChild(
  650. DfsEntryPath,
  651. dwVolType,
  652. &replInfo,
  653. Comment,
  654. DFS_NORMAL_FORCE);
  655. } else {
  656. status = pDfsVol->AddReplica( &replInfo, 0 );
  657. }
  658. if (status == NERR_Success) {
  659. //
  660. // Find out the list of covered sites
  661. // Note we use dwErr as the return code,
  662. // because we don't care if this fails - a downlevel
  663. // server won't respond.
  664. //
  665. pSiteInfo = NULL;
  666. dwErr = I_NetDfsManagerReportSiteInfo(
  667. ServerName,
  668. &pSiteInfo);
  669. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR, NetrDfsAdd2_Error_I_NetDfsManagerReportSiteInfo,
  670. LOGSTATUS(dwErr)
  671. LOGWSTR(ServerName)
  672. LOGWSTR(ShareName));
  673. //
  674. // Create a SiteTable object with those sites
  675. //
  676. if (dwErr == ERROR_SUCCESS) {
  677. if (pSiteInfo->cSites > 0) {
  678. //
  679. // AddRef the site table, then put the site info in, then
  680. // Release it. This will cause it to be written to the
  681. // appropriate store (ldap or registry).
  682. //
  683. pDfsmSites->AddRef();
  684. pDfsmSites->AddOrUpdateSiteInfo(
  685. ServerName,
  686. pSiteInfo->cSites,
  687. &pSiteInfo->Site[0]);
  688. pDfsmSites->Release();
  689. }
  690. NetApiBufferFree(pSiteInfo);
  691. }
  692. }
  693. }
  694. //
  695. // This writes the dfs-link info back
  696. // to
  697. // (1) the registry if stddfs
  698. // or
  699. // (2) the in-memory unmarshalled pkt blob which
  700. // will still need to go to the DS.
  701. //
  702. if (pDfsVol != NULL) {
  703. pDfsVol->Release();
  704. }
  705. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  706. // if we can't write to the DS we get an error
  707. // but don't mask any previous errors...
  708. NET_API_STATUS NewStatus;
  709. NewStatus = LdapDecrementBlob();
  710. if(status == NERR_Success){
  711. status = NewStatus;
  712. }
  713. }
  714. EXIT_DFSM_OPERATION;
  715. //
  716. // Create list of roots to redirect to this DC
  717. //
  718. if (status == NERR_Success &&
  719. DcName != NULL &&
  720. ulDfsManagerType == DFS_MANAGER_FTDFS
  721. ) {
  722. DfspCreateRootList(
  723. DfsEntryPath,
  724. DcName,
  725. ppRootList);
  726. }
  727. if (DfsEntryPath != OrgDfsEntryPath) {
  728. delete [] DfsEntryPath;
  729. }
  730. cleanup:
  731. #if DBG
  732. if (DfsSvcVerbose)
  733. DbgPrint("NetrDfsAdd2 returning %d\n", status);
  734. #endif
  735. DFSM_TRACE_NORM(EVENT, NetrDfsAdd2_End,
  736. LOGSTATUS(status)
  737. LOGWSTR(OrgDfsEntryPath)
  738. LOGWSTR(DcName)
  739. LOGWSTR(ServerName)
  740. LOGWSTR(ShareName));
  741. return( status );
  742. }
  743. //+----------------------------------------------------------------------------
  744. //
  745. // Function: NetrDfsAddFtRoot
  746. //
  747. // Synopsis: Creates a new FtDfs, or joins a Server into an FtDfs at the root
  748. //
  749. // Arguments: [ServerName] -- Name of server backing the volume.
  750. // [DcName] -- DC to use
  751. // [RootShare] -- Name of share on ServerName backing the volume.
  752. // [FtDfsName] -- The Name of the FtDfs to create/join
  753. // [Comment] -- Comment associated with this root.
  754. // [Flags] -- Flags for the operation
  755. // [ppRootList] -- On success, returns a list of roots that need to be
  756. // informed of the change in the DS object
  757. //
  758. // Returns: [NERR_Success] -- Operation succeeded.
  759. //
  760. // [NERR_DfsInternalCorruption] -- An internal database
  761. // corruption was encountered while executing this
  762. // operation.
  763. //
  764. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  765. //
  766. //-----------------------------------------------------------------------------
  767. extern "C" NET_API_STATUS
  768. NetrDfsAddFtRoot(
  769. IN LPWSTR ServerName,
  770. IN LPWSTR DcName,
  771. IN LPWSTR RootShare,
  772. IN LPWSTR FtDfsName,
  773. IN LPWSTR Comment,
  774. IN LPWSTR ConfigDN,
  775. IN BOOLEAN NewFtDfs,
  776. IN DWORD Flags,
  777. IN PDFSM_ROOT_LIST *ppRootList)
  778. {
  779. DWORD dwErr = ERROR_SUCCESS;
  780. ULONG i;
  781. WCHAR wszFullObjectName[MAX_PATH];
  782. WCHAR wszComputerName[MAX_PATH];
  783. WCHAR wszDomainName[MAX_PATH];
  784. HKEY hkey;
  785. DFS_NAME_CONVENTION NameType;
  786. PDFSM_ROOT_LIST pRootList = NULL;
  787. #if DBG
  788. if (DfsSvcVerbose)
  789. DbgPrint("NetrDfsAddFtRoot(%ws,%ws,%ws,%ws,%ws,%ws,0x%x,0x%x)\n",
  790. ServerName,
  791. DcName,
  792. RootShare,
  793. FtDfsName,
  794. Comment,
  795. ConfigDN,
  796. NewFtDfs,
  797. Flags);
  798. #endif
  799. DFSM_TRACE_NORM(EVENT, NetrDfsAddFtRoot_Start,
  800. LOGSTATUS(dwErr)
  801. LOGWSTR(ServerName)
  802. LOGWSTR(DcName)
  803. LOGWSTR(RootShare)
  804. LOGWSTR(FtDfsName)
  805. LOGWSTR(ConfigDN));
  806. if (!AccessCheckRpcClient()) {
  807. dwErr = ERROR_ACCESS_DENIED;
  808. goto cleanup;
  809. }
  810. //
  811. // Validate the input arguments...
  812. //
  813. if (
  814. ServerName == NULL ||
  815. DcName == NULL ||
  816. RootShare == NULL ||
  817. FtDfsName == NULL ||
  818. Comment == NULL ||
  819. ConfigDN == NULL
  820. ) {
  821. dwErr = ERROR_INVALID_PARAMETER;
  822. goto cleanup;
  823. }
  824. if (
  825. ServerName[0] == UNICODE_NULL ||
  826. DcName[0] == UNICODE_NULL ||
  827. RootShare[0] == UNICODE_NULL ||
  828. FtDfsName[0] == UNICODE_NULL ||
  829. ConfigDN[0] == UNICODE_NULL
  830. ) {
  831. dwErr = ERROR_INVALID_PARAMETER;
  832. goto cleanup;
  833. }
  834. //
  835. // Get our computer and domain names
  836. //
  837. NameType = DFS_NAMETYPE_DNS;
  838. dwErr = GetDomAndComputerName( wszDomainName, wszComputerName, &NameType);
  839. if (dwErr != ERROR_SUCCESS){
  840. goto cleanup;
  841. //return dwErr;
  842. }
  843. //
  844. // Ensure the syntax of FtDfsName is reasonable
  845. //
  846. if( wcslen( FtDfsName ) > NNLEN ||
  847. wcscspn( FtDfsName, ILLEGAL_NAME_CHARS_STR ) != wcslen( FtDfsName ) ) {
  848. dwErr = ERROR_INVALID_NAME;
  849. goto cleanup;
  850. }
  851. ENTER_DFSM_OPERATION;
  852. //
  853. // Already a root?
  854. //
  855. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  856. if (dwErr != ERROR_SUCCESS) {
  857. DfsManagerSetDcName(DcName);
  858. LdapIncrementBlob();
  859. //
  860. // Update pKT (blob) attribute
  861. //
  862. dwErr = SetupFtDfs(
  863. wszComputerName,
  864. wszDomainName,
  865. RootShare,
  866. FtDfsName,
  867. Comment,
  868. ConfigDN,
  869. NewFtDfs,
  870. Flags);
  871. #if DBG
  872. if (DfsSvcVerbose)
  873. DbgPrint("SetupFtDfs() returned %d\n", dwErr);
  874. #endif
  875. if (dwErr == ERROR_SUCCESS) {
  876. //
  877. // Reset dfs
  878. //
  879. DfsmStopDfs();
  880. DfsmResetPkt();
  881. DfsmInitLocalPartitions();
  882. InitializeDfsManager();
  883. DfsmStartDfs();
  884. DfsmPktFlushCache();
  885. } else {
  886. //
  887. // Something went wrong - remove all the stuff we set up
  888. //
  889. if (*ppRootList != NULL) {
  890. pRootList = *ppRootList;
  891. for (i = 0; i< pRootList->cEntries; i++)
  892. if (pRootList->Entry[i].ServerShare != NULL)
  893. MIDL_user_free(pRootList->Entry[i].ServerShare);
  894. MIDL_user_free(pRootList);
  895. *ppRootList = NULL;
  896. }
  897. wcscpy(wszFullObjectName, LDAP_VOLUMES_DIR);
  898. wcscat(wszFullObjectName, DOMAIN_ROOT_VOL);
  899. DfsManagerRemoveService(
  900. wszFullObjectName,
  901. wszComputerName);
  902. if (*ppRootList != NULL) {
  903. pRootList = *ppRootList;
  904. for (i = 0; i < pRootList->cEntries; i++)
  905. if (pRootList->Entry[i].ServerShare != NULL)
  906. MIDL_user_free(pRootList->Entry[i].ServerShare);
  907. MIDL_user_free(pRootList);
  908. *ppRootList = NULL;
  909. }
  910. DfsRemoveRoot();
  911. DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER);
  912. //
  913. // Tell dfs.sys to discard all state
  914. //
  915. DfsmStopDfs();
  916. DfsmResetPkt();
  917. DfsmStartDfs();
  918. DfsmPktFlushCache();
  919. }
  920. {
  921. // don't mask the previous errors!!!!
  922. DWORD dwErr2;
  923. dwErr2 = LdapDecrementBlob();
  924. if (dwErr == ERROR_SUCCESS) {
  925. dwErr = dwErr2;
  926. }
  927. }
  928. if (dwErr == ERROR_SUCCESS) {
  929. //
  930. // Everything went okay.
  931. // Update remoteServerName attribute
  932. //
  933. dwErr = DfspCreateFtDfsDsObj(
  934. wszComputerName,
  935. DcName,
  936. RootShare,
  937. FtDfsName,
  938. ppRootList);
  939. #if DBG
  940. if (DfsSvcVerbose)
  941. DbgPrint("DfspCreateFtDfsDsObj() returned %d\n", dwErr);
  942. #endif
  943. }
  944. } else {
  945. RegCloseKey(hkey);
  946. dwErr = ERROR_ALREADY_EXISTS;
  947. }
  948. EXIT_DFSM_OPERATION;
  949. cleanup:
  950. #if DBG
  951. if (DfsSvcVerbose)
  952. DbgPrint("NetrDfsAddFtRoot returning %d\n", dwErr);
  953. #endif
  954. DFSM_TRACE_NORM(EVENT, NetrDfsAddFtRoot_End,
  955. LOGSTATUS(dwErr)
  956. LOGWSTR(ServerName)
  957. LOGWSTR(DcName)
  958. LOGWSTR(RootShare)
  959. LOGWSTR(FtDfsName)
  960. LOGWSTR(ConfigDN));
  961. return dwErr;
  962. }
  963. //+----------------------------------------------------------------------------
  964. //
  965. // Function: NetrDfsGetDcAddress
  966. //
  967. // Synopsis: Gets the DC to go to so that we can create an FtDfs object for
  968. // this server.
  969. //
  970. // Arguments: [ServerName] -- Name of server backing the volume.
  971. // [DcName] -- Dc to use
  972. // [IsRoot] -- TRUE if this server is a Dfs root, FALSE otherwise
  973. // [Timeout] -- Timeout, in sec, that the server will stay with this DC
  974. //
  975. // Returns: [NERR_Success] -- Operation succeeded.
  976. //
  977. // [NERR_DfsInternalCorruption] -- An internal database
  978. // corruption was encountered while executing this
  979. // operation.
  980. //
  981. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  982. //
  983. //-----------------------------------------------------------------------------
  984. extern "C" NET_API_STATUS
  985. NetrDfsGetDcAddress(
  986. IN LPWSTR ServerName,
  987. IN OUT LPWSTR *DcName,
  988. IN OUT BOOLEAN *IsRoot,
  989. IN OUT ULONG *Timeout)
  990. {
  991. DWORD dwErr = ERROR_SUCCESS;
  992. HKEY hkey;
  993. WCHAR *wszDCName;
  994. #if DBG
  995. if (DfsSvcVerbose)
  996. DbgPrint("NetrDfsGetDcAddress(%ws)\n", ServerName);
  997. #endif
  998. DFSM_TRACE_NORM(EVENT, NetrDfsGetDcAddress_Start,
  999. LOGSTATUS(dwErr)
  1000. LOGWSTR(ServerName));
  1001. if (!AccessCheckRpcClient()) {
  1002. dwErr = ERROR_ACCESS_DENIED;
  1003. goto cleanup;
  1004. }
  1005. //
  1006. // Validate the input arguments...
  1007. //
  1008. if (
  1009. ServerName == NULL ||
  1010. DcName == NULL ||
  1011. IsRoot == NULL ||
  1012. Timeout == NULL
  1013. ) {
  1014. dwErr = ERROR_INVALID_PARAMETER;
  1015. goto cleanup;
  1016. }
  1017. if (ServerName[0] == UNICODE_NULL) {
  1018. dwErr = ERROR_INVALID_PARAMETER;
  1019. goto cleanup;
  1020. }
  1021. ENTER_DFSM_OPERATION;
  1022. //
  1023. // Fill in root flag
  1024. //
  1025. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  1026. if (dwErr == ERROR_SUCCESS) {
  1027. RegCloseKey(hkey);
  1028. *IsRoot = TRUE;
  1029. } else {
  1030. *IsRoot = FALSE;
  1031. }
  1032. #if DBG
  1033. if (DfsSvcVerbose)
  1034. DbgPrint("IsRoot=%ws\n", *IsRoot == TRUE ? L"TRUE" : L"FALSE");
  1035. #endif
  1036. dwErr = ERROR_SUCCESS;
  1037. if (pwszDSMachineName == NULL) {
  1038. dwErr = GetDcName( NULL, 1, &wszDCName );
  1039. if (dwErr == ERROR_SUCCESS) {
  1040. DfsManagerSetDcName(&wszDCName[2]);
  1041. }
  1042. }
  1043. if (dwErr == ERROR_SUCCESS) {
  1044. *DcName = (LPWSTR) MIDL_user_allocate((wcslen(pwszDSMachineName)+1) * sizeof(WCHAR));
  1045. if (*DcName != NULL) {
  1046. wcscpy(*DcName,pwszDSMachineName);
  1047. } else {
  1048. dwErr = ERROR_OUTOFMEMORY;
  1049. }
  1050. }
  1051. *Timeout = DcLockIntervalInMs / 1000;
  1052. EXIT_DFSM_OPERATION;
  1053. cleanup:
  1054. #if DBG
  1055. if (DfsSvcVerbose)
  1056. DbgPrint("NetrDfsGetDcAddress returning %d\n", dwErr);
  1057. #endif
  1058. DFSM_TRACE_NORM(EVENT, NetrDfsGetDcAddress_End,
  1059. LOGSTATUS(dwErr)
  1060. LOGWSTR(ServerName)
  1061. LOGWSTR(*DcName)
  1062. LOGBOOLEAN(*IsRoot)
  1063. LOGULONG(*Timeout)
  1064. );
  1065. return dwErr;
  1066. }
  1067. //+----------------------------------------------------------------------------
  1068. //
  1069. // Function: NetrDfsSetDcAddress
  1070. //
  1071. // Synopsis: Sets the DC to go to for the dfs blob
  1072. //
  1073. // Arguments: [ServerName] -- Name of server backing the volume.
  1074. // [DcName] -- Dc to use
  1075. // [Timeout] -- Time, in sec, to stay with that DC
  1076. //
  1077. // Returns: [NERR_Success] -- Operation succeeded.
  1078. //
  1079. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  1080. //
  1081. //-----------------------------------------------------------------------------
  1082. extern "C" NET_API_STATUS
  1083. NetrDfsSetDcAddress(
  1084. IN LPWSTR ServerName,
  1085. IN LPWSTR DcName,
  1086. IN ULONG Timeout,
  1087. IN DWORD Flags)
  1088. {
  1089. NET_API_STATUS status = ERROR_SUCCESS;
  1090. #if DBG
  1091. if (DfsSvcVerbose)
  1092. DbgPrint("NetrDfsSetDcAddress(%ws,%ws,%d,0x%x)\n",
  1093. ServerName,
  1094. DcName,
  1095. Timeout,
  1096. Flags);
  1097. #endif
  1098. DFSM_TRACE_NORM(EVENT, NetrDfsSetDcAddress_Start,
  1099. LOGSTATUS(status)
  1100. LOGWSTR(ServerName)
  1101. LOGWSTR(DcName));
  1102. if (!AccessCheckRpcClient()) {
  1103. status = ERROR_ACCESS_DENIED;
  1104. goto cleanup;
  1105. }
  1106. //
  1107. // Validate the input arguments...
  1108. //
  1109. if (ServerName == NULL || DcName == NULL) {
  1110. status = ERROR_INVALID_PARAMETER;
  1111. goto cleanup;
  1112. }
  1113. if (ServerName[0] == UNICODE_NULL || DcName[0] == UNICODE_NULL) {
  1114. status = ERROR_INVALID_PARAMETER;
  1115. goto cleanup;
  1116. }
  1117. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  1118. ENTER_DFSM_OPERATION;
  1119. DfsManagerSetDcName(DcName);
  1120. if ((Flags & NET_DFS_SETDC_TIMEOUT) != 0) {
  1121. DcLockIntervalInMs = Timeout * 1000;
  1122. }
  1123. EXIT_DFSM_OPERATION;
  1124. if (Flags & NET_DFS_SETDC_INITPKT) {
  1125. SetEvent(hSyncEvent);
  1126. }
  1127. }
  1128. cleanup:
  1129. #if DBG
  1130. if (DfsSvcVerbose)
  1131. DbgPrint("NetrDfsSetDcAddress returning SUCCESS\n");
  1132. #endif
  1133. DFSM_TRACE_NORM(EVENT, NetrDfsSetDcAddress_End,
  1134. LOGSTATUS(status)
  1135. LOGWSTR(ServerName)
  1136. LOGWSTR(DcName));
  1137. return ERROR_SUCCESS;
  1138. }
  1139. //+----------------------------------------------------------------------------
  1140. //
  1141. // Function: NetrDfsFlushFtTable
  1142. //
  1143. // Synopsis: Flushes an FtDfs entry from the FtDfs cache
  1144. //
  1145. // Arguments: [DcName] -- Dc to use
  1146. // [FtDfsName] -- Name of FtDfs
  1147. //
  1148. // Returns: [NERR_Success] -- Operation succeeded.
  1149. //
  1150. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  1151. //
  1152. //-----------------------------------------------------------------------------
  1153. extern "C" NET_API_STATUS
  1154. NetrDfsFlushFtTable(
  1155. IN LPWSTR DcName,
  1156. IN LPWSTR FtDfsName)
  1157. {
  1158. ULONG Size;
  1159. DWORD dwErr = ERROR_SUCCESS;
  1160. NTSTATUS Status;
  1161. PDFS_DELETE_SPECIAL_INFO_ARG pSpcDelArg;
  1162. OBJECT_ATTRIBUTES objectAttributes;
  1163. IO_STATUS_BLOCK IoStatus;
  1164. HANDLE dfsHandle = NULL;
  1165. UNICODE_STRING SrvName;
  1166. DFSM_TRACE_NORM(EVENT, NetrDfsFlushFtTable_Start,
  1167. LOGSTATUS(Status)
  1168. LOGWSTR(DcName)
  1169. LOGWSTR(FtDfsName));
  1170. if (!AccessCheckRpcClient()) {
  1171. Status = ERROR_ACCESS_DENIED;
  1172. goto cleanup;
  1173. }
  1174. //
  1175. // Validate the input arguments...
  1176. //
  1177. if (DcName == NULL || FtDfsName == NULL) {
  1178. Status = ERROR_INVALID_PARAMETER;
  1179. goto cleanup;
  1180. }
  1181. if (DcName[0] == UNICODE_NULL || FtDfsName[0] == UNICODE_NULL) {
  1182. Status = ERROR_INVALID_PARAMETER;
  1183. goto cleanup;
  1184. }
  1185. Size = sizeof(DFS_DELETE_SPECIAL_INFO_ARG) +
  1186. wcslen(FtDfsName) * sizeof(WCHAR);
  1187. pSpcDelArg = (PDFS_DELETE_SPECIAL_INFO_ARG) malloc(Size);
  1188. if (pSpcDelArg != NULL) {
  1189. WCHAR *wCp;
  1190. RtlZeroMemory(pSpcDelArg, Size);
  1191. wCp = (WCHAR *)((PCHAR)pSpcDelArg + sizeof(DFS_DELETE_SPECIAL_INFO_ARG));
  1192. pSpcDelArg->SpecialName.Buffer = (PWCHAR)sizeof(DFS_DELETE_SPECIAL_INFO_ARG);
  1193. pSpcDelArg->SpecialName.Length = wcslen(FtDfsName) * sizeof(WCHAR);
  1194. pSpcDelArg->SpecialName.MaximumLength = pSpcDelArg->SpecialName.Length;
  1195. RtlCopyMemory(wCp, FtDfsName, pSpcDelArg->SpecialName.Length);
  1196. ENTER_DFSM_OPERATION;
  1197. RtlInitUnicodeString(&SrvName, DFS_SERVER_NAME);
  1198. InitializeObjectAttributes(
  1199. &objectAttributes,
  1200. &SrvName,
  1201. OBJ_CASE_INSENSITIVE,
  1202. NULL,
  1203. NULL
  1204. );
  1205. Status = NtCreateFile(
  1206. &dfsHandle,
  1207. SYNCHRONIZE | FILE_WRITE_DATA,
  1208. &objectAttributes,
  1209. &IoStatus,
  1210. NULL,
  1211. FILE_ATTRIBUTE_NORMAL,
  1212. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1213. FILE_OPEN_IF,
  1214. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  1215. NULL,
  1216. 0
  1217. );
  1218. DFSM_TRACE_ERROR_HIGH(Status, ALL_ERROR, NetrDfsFlushFtTable_Error_NtCreateFile,
  1219. LOGSTATUS(Status)
  1220. LOGWSTR(DcName)
  1221. LOGWSTR(FtDfsName));
  1222. if (NT_SUCCESS(Status)) {
  1223. NtFsControlFile(
  1224. dfsHandle,
  1225. NULL, // Event,
  1226. NULL, // ApcRoutine,
  1227. NULL, // ApcContext,
  1228. &IoStatus,
  1229. FSCTL_DFS_DELETE_FTDFS_INFO,
  1230. pSpcDelArg,
  1231. Size,
  1232. NULL,
  1233. 0);
  1234. NtClose(dfsHandle);
  1235. }
  1236. free(pSpcDelArg);
  1237. if (!NT_SUCCESS(Status)) {
  1238. dwErr = ERROR_NOT_FOUND;
  1239. }
  1240. EXIT_DFSM_OPERATION;
  1241. } else {
  1242. dwErr = ERROR_OUTOFMEMORY;
  1243. }
  1244. cleanup:
  1245. DFSM_TRACE_NORM(EVENT, NetrDfsFlushFtTable_Start,
  1246. LOGSTATUS(Status)
  1247. LOGWSTR(DcName)
  1248. LOGWSTR(FtDfsName));
  1249. return dwErr;
  1250. }
  1251. //+----------------------------------------------------------------------------
  1252. //
  1253. // Function: NetrDfsAddStdRoot
  1254. //
  1255. // Synopsis: Creates a new Std Dfs
  1256. //
  1257. // Arguments: [ServerName] -- Name of server backing the volume.
  1258. // [RootShare] -- Name of share on ServerName backing the volume.
  1259. // [Comment] -- Comment associated with this root.
  1260. // [Flags] -- Flags for the operation
  1261. //
  1262. // Returns: [NERR_Success] -- Operation succeeded.
  1263. //
  1264. // [NERR_DfsInternalCorruption] -- An internal database
  1265. // corruption was encountered while executing this
  1266. // operation.
  1267. //
  1268. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  1269. //
  1270. //-----------------------------------------------------------------------------
  1271. extern "C" NET_API_STATUS
  1272. NetrDfsAddStdRoot(
  1273. IN LPWSTR ServerName,
  1274. IN LPWSTR RootShare,
  1275. IN LPWSTR Comment,
  1276. IN DWORD Flags)
  1277. {
  1278. WCHAR wszComputerName[MAX_PATH+1];
  1279. DWORD dwErr = ERROR_SUCCESS;
  1280. HKEY hkey;
  1281. DFS_NAME_CONVENTION NameType;
  1282. DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRoot_Start,
  1283. LOGSTATUS(dwErr)
  1284. LOGWSTR(ServerName)
  1285. LOGWSTR(RootShare));
  1286. if (!AccessCheckRpcClient()) {
  1287. dwErr = ERROR_ACCESS_DENIED;
  1288. goto cleanup;
  1289. }
  1290. //
  1291. // Validate the input arguments...
  1292. //
  1293. if (ServerName == NULL || RootShare == NULL) {
  1294. dwErr = ERROR_INVALID_PARAMETER;
  1295. goto cleanup;
  1296. }
  1297. if (ServerName[0] == UNICODE_NULL || RootShare[0] == UNICODE_NULL) {
  1298. dwErr = ERROR_INVALID_PARAMETER;
  1299. goto cleanup;
  1300. }
  1301. //
  1302. // Get our computer name
  1303. //
  1304. NameType = DFS_NAMETYPE_EITHER;
  1305. // NameType = DFS_NAMETYPE_NETBIOS;
  1306. dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
  1307. if (dwErr != ERROR_SUCCESS){
  1308. goto cleanup;
  1309. //return dwErr;
  1310. }
  1311. ENTER_DFSM_OPERATION;
  1312. //
  1313. // Already a root?
  1314. //
  1315. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  1316. if (dwErr != ERROR_SUCCESS) {
  1317. dwErr = SetupStdDfs(
  1318. wszComputerName,
  1319. RootShare,
  1320. Comment,
  1321. Flags,
  1322. NULL);
  1323. if (dwErr == ERROR_SUCCESS) {
  1324. //
  1325. // Reset dfs
  1326. //
  1327. DfsmStopDfs();
  1328. DfsmResetPkt();
  1329. DfsmInitLocalPartitions();
  1330. InitializeDfsManager();
  1331. DfsmStartDfs();
  1332. DfsmPktFlushCache();
  1333. }
  1334. } else {
  1335. RegCloseKey(hkey);
  1336. dwErr = ERROR_ALREADY_EXISTS;
  1337. }
  1338. EXIT_DFSM_OPERATION;
  1339. cleanup:
  1340. DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRoot_End,
  1341. LOGSTATUS(dwErr)
  1342. LOGWSTR(ServerName)
  1343. LOGWSTR(RootShare));
  1344. return dwErr;
  1345. }
  1346. //+----------------------------------------------------------------------------
  1347. //
  1348. // Function: NetrDfsAddStdRootForced
  1349. //
  1350. // Synopsis: Creates a new Std Dfs
  1351. //
  1352. // Arguments: [ServerName] -- Name of server backing the volume.
  1353. // [RootShare] -- Name of share on ServerName backing the volume.
  1354. // [Comment] -- Comment associated with this root.
  1355. // [Share] -- drive:\dir behind the share
  1356. //
  1357. // Returns: [NERR_Success] -- Operation succeeded.
  1358. //
  1359. // [NERR_DfsInternalCorruption] -- An internal database
  1360. // corruption was encountered while executing this
  1361. // operation.
  1362. //
  1363. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  1364. //
  1365. //-----------------------------------------------------------------------------
  1366. extern "C" NET_API_STATUS
  1367. NetrDfsAddStdRootForced(
  1368. IN LPWSTR ServerName,
  1369. IN LPWSTR RootShare,
  1370. IN LPWSTR Comment,
  1371. IN LPWSTR Share)
  1372. {
  1373. WCHAR wszComputerName[MAX_PATH+1];
  1374. DWORD dwErr = ERROR_SUCCESS;
  1375. HKEY hkey;
  1376. DFS_NAME_CONVENTION NameType;
  1377. DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRootForced_Start,
  1378. LOGSTATUS(dwErr)
  1379. LOGWSTR(ServerName)
  1380. LOGWSTR(RootShare)
  1381. LOGWSTR(Share));
  1382. if (!AccessCheckRpcClient()) {
  1383. dwErr = ERROR_ACCESS_DENIED;
  1384. goto cleanup;
  1385. }
  1386. //
  1387. // Validate the input arguments...
  1388. //
  1389. if (ServerName == NULL || RootShare == NULL || Share == NULL) {
  1390. dwErr = ERROR_INVALID_PARAMETER;
  1391. goto cleanup;
  1392. }
  1393. if (ServerName[0] == UNICODE_NULL || RootShare[0] == UNICODE_NULL || Share[0] == UNICODE_NULL) {
  1394. dwErr = ERROR_INVALID_PARAMETER;
  1395. goto cleanup;
  1396. }
  1397. //
  1398. // Get our computer name
  1399. //
  1400. NameType = DFS_NAMETYPE_EITHER;
  1401. dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
  1402. if (dwErr != ERROR_SUCCESS){
  1403. goto cleanup;
  1404. //return dwErr;
  1405. }
  1406. ENTER_DFSM_OPERATION;
  1407. //
  1408. // Already a root?
  1409. //
  1410. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  1411. if (dwErr != ERROR_SUCCESS) {
  1412. dwErr = SetupStdDfs(
  1413. wszComputerName,
  1414. RootShare,
  1415. Comment,
  1416. 1,
  1417. Share);
  1418. if (dwErr == ERROR_SUCCESS) {
  1419. //
  1420. // Reset dfs
  1421. //
  1422. DfsmStopDfs();
  1423. DfsmResetPkt();
  1424. DfsmInitLocalPartitions();
  1425. InitializeDfsManager();
  1426. DfsmStartDfs();
  1427. DfsmPktFlushCache();
  1428. }
  1429. } else {
  1430. RegCloseKey(hkey);
  1431. dwErr = ERROR_ALREADY_EXISTS;
  1432. }
  1433. EXIT_DFSM_OPERATION;
  1434. cleanup:
  1435. DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRootForced_End,
  1436. LOGSTATUS(dwErr)
  1437. LOGWSTR(ServerName)
  1438. LOGWSTR(RootShare)
  1439. LOGWSTR(Share));
  1440. return dwErr;
  1441. }
  1442. //+----------------------------------------------------------------------------
  1443. //
  1444. // Function: NetrDfsRemove (Obsolete)
  1445. //
  1446. //-----------------------------------------------------------------------------
  1447. extern "C" NET_API_STATUS
  1448. NetrDfsRemove(
  1449. IN LPWSTR DfsEntryPath,
  1450. IN LPWSTR ServerName,
  1451. IN LPWSTR ShareName)
  1452. {
  1453. NET_API_STATUS status = ERROR_SUCCESS;
  1454. DFSM_TRACE_NORM(EVENT, NetrDfsRemove_Start,
  1455. LOGSTATUS(status)
  1456. LOGWSTR(DfsEntryPath)
  1457. LOGWSTR(ServerName)
  1458. LOGWSTR(ShareName));
  1459. if (!AccessCheckRpcClient()) {
  1460. status = ERROR_ACCESS_DENIED;
  1461. goto cleanup;
  1462. }
  1463. if (ulDfsManagerType == DFS_MANAGER_FTDFS){
  1464. status = ERROR_NOT_SUPPORTED;
  1465. goto cleanup;
  1466. }
  1467. status = NetrDfsRemove2(
  1468. DfsEntryPath,
  1469. NULL,
  1470. ServerName,
  1471. ShareName,
  1472. NULL);
  1473. goto cleanup;
  1474. cleanup:
  1475. DFSM_TRACE_NORM(EVENT, NetrDfsRemove_End,
  1476. LOGSTATUS(status)
  1477. LOGWSTR(DfsEntryPath)
  1478. LOGWSTR(ServerName)
  1479. LOGWSTR(ShareName));
  1480. return status;
  1481. }
  1482. //+----------------------------------------------------------------------------
  1483. //
  1484. // Function: NetrDfsRemove2
  1485. //
  1486. // Synopsis: Deletes a volume/replica/link from the Dfs.
  1487. //
  1488. // Arguments: [DfsEntryPath] -- Entry path of the volume to operate on.
  1489. // [DcName] -- Name of Dc to use
  1490. // [ServerName] -- If specified, indicates the replica of the
  1491. // volume to operate on.
  1492. // [ShareName] -- If specified, indicates the share on the
  1493. // server to operate on.
  1494. // [Flags] -- Flags for the operation
  1495. // [ppRootList] -- On success, returns a list of roots that need to be
  1496. // informed of the change in the DS object
  1497. //
  1498. // Returns: [NERR_Success] -- Operation successful.
  1499. //
  1500. // [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to
  1501. // a valid entry path.
  1502. //
  1503. // [NERR_DfsNotALeafVolume] -- Unable to delete the volume
  1504. // because it is not a leaf volume.
  1505. //
  1506. // [NERR_DfsInternalCorruption] -- Internal database corruption
  1507. // encountered while executing operation.
  1508. //
  1509. // [ERROR_INVALID_PARAMETER] -- One of the input parameters is
  1510. // incorrect.
  1511. //
  1512. //-----------------------------------------------------------------------------
  1513. extern "C" NET_API_STATUS
  1514. NetrDfsRemove2(
  1515. IN LPWSTR DfsEntryPath,
  1516. IN LPWSTR DcName,
  1517. IN LPWSTR ServerName,
  1518. IN LPWSTR ShareName,
  1519. IN PDFSM_ROOT_LIST *ppRootList)
  1520. {
  1521. NET_API_STATUS status = ERROR_SUCCESS;
  1522. CDfsVolume *pDfsVol = NULL;
  1523. DFS_REPLICA_INFO replInfo;
  1524. BOOLEAN fRemoveReplica = FALSE;
  1525. LPWSTR OrgDfsEntryPath = DfsEntryPath;
  1526. DWORD dwErr;
  1527. #if DBG
  1528. if (DfsSvcVerbose)
  1529. DbgPrint("NetrDfsRemove2(%ws,%ws,%ws,%ws,0x%x)\n",
  1530. DfsEntryPath,
  1531. DcName,
  1532. ServerName,
  1533. ShareName,
  1534. ppRootList);
  1535. #endif
  1536. DFSM_TRACE_NORM(EVENT, NetrDfsRemove2_Start,
  1537. LOGSTATUS(status)
  1538. LOGWSTR(OrgDfsEntryPath)
  1539. LOGWSTR(DcName)
  1540. LOGWSTR(ServerName)
  1541. LOGWSTR(ShareName));
  1542. if (!AccessCheckRpcClient()){
  1543. status = ERROR_ACCESS_DENIED;
  1544. goto cleanup;
  1545. }
  1546. //
  1547. // Validate the input arguments...
  1548. //
  1549. #if 0 // Broken for DNS names
  1550. DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
  1551. #endif
  1552. if (DfsEntryPath != NULL) {
  1553. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  1554. DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
  1555. else if (ulDfsManagerType == DFS_MANAGER_SERVER)
  1556. DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
  1557. if (DfsEntryPath == NULL){
  1558. status = ERROR_OUTOFMEMORY;
  1559. goto cleanup;
  1560. }
  1561. }
  1562. if (DfsEntryPath == NULL) {
  1563. status = ERROR_INVALID_PARAMETER;
  1564. goto cleanup;
  1565. }
  1566. //
  1567. // If ServerName is present, it must be valid.
  1568. //
  1569. if (ServerName != NULL && ServerName[0] == UNICODE_NULL) {
  1570. if (DfsEntryPath != OrgDfsEntryPath) {
  1571. delete [] DfsEntryPath;
  1572. }
  1573. status = ERROR_INVALID_PARAMETER;
  1574. goto cleanup;
  1575. }
  1576. //
  1577. // If ShareName is present, it must be valid.
  1578. //
  1579. if (ShareName != NULL && ShareName[0] == UNICODE_NULL) {
  1580. if (DfsEntryPath != OrgDfsEntryPath) {
  1581. delete [] DfsEntryPath;
  1582. }
  1583. status = ERROR_INVALID_PARAMETER;
  1584. goto cleanup;
  1585. }
  1586. //
  1587. // If ShareName is present, ServerName must be present.
  1588. //
  1589. if (ShareName != NULL && ServerName == NULL) {
  1590. if (DfsEntryPath != OrgDfsEntryPath) {
  1591. delete [] DfsEntryPath;
  1592. }
  1593. status = ERROR_INVALID_PARAMETER;
  1594. goto cleanup;
  1595. }
  1596. ENTER_DFSM_OPERATION;
  1597. //
  1598. // Great, the parameters look semi-reasonable, lets do the work.
  1599. //
  1600. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  1601. if (DcName != NULL)
  1602. DfsManagerSetDcName(DcName);
  1603. LdapIncrementBlob();
  1604. }
  1605. ZeroMemory( &replInfo, sizeof(replInfo) );
  1606. status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
  1607. if (status != ERROR_SUCCESS) {
  1608. pDfsVol = NULL;
  1609. }
  1610. if (status == ERROR_SUCCESS && ServerName != NULL && ShareName != NULL) {
  1611. LPWSTR pwszShare;
  1612. replInfo.ulReplicaState = 0;
  1613. replInfo.ulReplicaType = 0;
  1614. replInfo.pwszServerName = ServerName;
  1615. replInfo.pwszShareName = ShareName;
  1616. fRemoveReplica = TRUE;
  1617. }
  1618. if (status == ERROR_SUCCESS) {
  1619. //
  1620. // See whether we should delete a replica or the volume
  1621. //
  1622. if (fRemoveReplica) {
  1623. status = pDfsVol->RemoveReplica( &replInfo, DFS_OVERRIDE_FORCE );
  1624. if (status == NERR_DfsCantRemoveLastServerShare) {
  1625. status = pDfsVol->Delete( DFS_OVERRIDE_FORCE );
  1626. }
  1627. } else {
  1628. status = pDfsVol->Delete( DFS_OVERRIDE_FORCE );
  1629. }
  1630. }
  1631. if (pDfsVol != NULL) {
  1632. pDfsVol->Release();
  1633. }
  1634. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  1635. status = LdapDecrementBlob();
  1636. EXIT_DFSM_OPERATION;
  1637. //
  1638. // Create list of roots to redirect to this DC
  1639. //
  1640. if (status == NERR_Success &&
  1641. DcName != NULL &&
  1642. ulDfsManagerType == DFS_MANAGER_FTDFS
  1643. ) {
  1644. DfspCreateRootList(
  1645. DfsEntryPath,
  1646. DcName,
  1647. ppRootList);
  1648. }
  1649. if (DfsEntryPath != OrgDfsEntryPath) {
  1650. delete [] DfsEntryPath;
  1651. }
  1652. cleanup:
  1653. #if DBG
  1654. if (DfsSvcVerbose)
  1655. DbgPrint("NetrDfsRemove2 returning %d\n", status);
  1656. #endif
  1657. DFSM_TRACE_NORM(EVENT, NetrDfsRemove2_End,
  1658. LOGSTATUS(status)
  1659. LOGWSTR(OrgDfsEntryPath)
  1660. LOGWSTR(DcName)
  1661. LOGWSTR(ServerName)
  1662. LOGWSTR(ShareName));
  1663. return( status );
  1664. }
  1665. //+----------------------------------------------------------------------------
  1666. //
  1667. // Function: NetrDfsRemoveFtRoot
  1668. //
  1669. // Synopsis: Deletes a root from an FtDfs.
  1670. //
  1671. // Arguments: [ServerName] -- The server to remove.
  1672. // [DcName] -- DC to use
  1673. // [RootShare] -- The Root share hosting the Dfs/FtDfs
  1674. // [FtDfsName] -- The FtDfs to remove the root from.
  1675. // [Flags] -- Flags for the operation
  1676. // [ppRootList] -- On success, returns a list of roots that need to be
  1677. // informed of the change in the DS object
  1678. //
  1679. // Returns: [NERR_Success] -- Operation successful.
  1680. //
  1681. // [NERR_DfsInternalCorruption] -- Internal database corruption
  1682. // encountered while executing operation.
  1683. //
  1684. // [ERROR_INVALID_PARAMETER] -- One of the input parameters is
  1685. // incorrect.
  1686. //
  1687. //-----------------------------------------------------------------------------
  1688. extern "C" NET_API_STATUS
  1689. NetrDfsRemoveFtRoot(
  1690. IN LPWSTR ServerName,
  1691. IN LPWSTR DcName,
  1692. IN LPWSTR RootShare,
  1693. IN LPWSTR FtDfsName,
  1694. IN DWORD Flags,
  1695. IN PDFSM_ROOT_LIST *ppRootList)
  1696. {
  1697. DWORD dwErr = ERROR_SUCCESS;
  1698. DWORD dwErr2 = ERROR_SUCCESS;
  1699. DWORD cbData;
  1700. DWORD dwType;
  1701. HKEY hkey;
  1702. WCHAR wszRootShare[MAX_PATH];
  1703. WCHAR wszFTDfs[MAX_PATH];
  1704. WCHAR wszFullObjectName[MAX_PATH];
  1705. WCHAR wszComputerName[MAX_PATH];
  1706. DFS_NAME_CONVENTION NameType;
  1707. #if DBG
  1708. if (DfsSvcVerbose)
  1709. DbgPrint("NetrDfsRemoveFtRoot(%ws,%ws,%ws,%ws,0x%x)\n",
  1710. ServerName,
  1711. DcName,
  1712. RootShare,
  1713. FtDfsName,
  1714. Flags);
  1715. #endif
  1716. DFSM_TRACE_NORM(EVENT, NetrDfsRemoveFtRoot_Start,
  1717. LOGSTATUS(dwErr)
  1718. LOGWSTR(ServerName)
  1719. LOGWSTR(DcName)
  1720. LOGWSTR(RootShare)
  1721. LOGWSTR(FtDfsName));
  1722. if (!AccessCheckRpcClient()) {
  1723. dwErr = ERROR_ACCESS_DENIED;
  1724. goto cleanup;
  1725. }
  1726. //
  1727. // Validate the input arguments...
  1728. //
  1729. if (
  1730. ServerName == NULL ||
  1731. DcName == NULL ||
  1732. RootShare == NULL ||
  1733. FtDfsName == NULL
  1734. ) {
  1735. dwErr = ERROR_INVALID_PARAMETER;
  1736. goto cleanup;
  1737. }
  1738. if (
  1739. ServerName[0] == UNICODE_NULL ||
  1740. DcName[0] == UNICODE_NULL ||
  1741. RootShare[0] == UNICODE_NULL ||
  1742. FtDfsName[0] == UNICODE_NULL
  1743. ) {
  1744. dwErr = ERROR_INVALID_PARAMETER;
  1745. goto cleanup;
  1746. }
  1747. //
  1748. // Get our computer name
  1749. //
  1750. NameType = DFS_NAMETYPE_DNS;
  1751. dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
  1752. if (dwErr != ERROR_SUCCESS){
  1753. goto cleanup;
  1754. //return dwErr;
  1755. }
  1756. if ((Flags & DFS_FORCE_REMOVE) == 0) {
  1757. ENTER_DFSM_OPERATION;
  1758. //
  1759. // Update remoteServerName attribute
  1760. //
  1761. dwErr = DfspRemoveFtDfsDsObj(
  1762. wszComputerName,
  1763. DcName,
  1764. RootShare,
  1765. FtDfsName,
  1766. ppRootList);
  1767. if (dwErr == ERROR_SUCCESS) {
  1768. LdapIncrementBlob();
  1769. DfsManagerSetDcName(DcName);
  1770. //
  1771. // We need to be a root to remove a root...
  1772. //
  1773. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  1774. }
  1775. //
  1776. // Check RootName and FtDfsName
  1777. //
  1778. if (dwErr == ERROR_SUCCESS) {
  1779. cbData = sizeof(wszRootShare);
  1780. dwErr = RegQueryValueEx(
  1781. hkey,
  1782. ROOT_SHARE_VALUE_NAME,
  1783. NULL,
  1784. &dwType,
  1785. (PBYTE) wszRootShare,
  1786. &cbData);
  1787. if (dwErr != ERROR_SUCCESS ||
  1788. dwType != REG_SZ ||
  1789. _wcsicmp(wszRootShare, RootShare) != 0
  1790. ) {
  1791. dwErr = ERROR_INVALID_PARAMETER;
  1792. }
  1793. } else {
  1794. hkey = NULL;
  1795. }
  1796. if (dwErr == ERROR_SUCCESS) {
  1797. cbData = sizeof(wszFTDfs);
  1798. dwErr = RegQueryValueEx(
  1799. hkey,
  1800. FTDFS_VALUE_NAME,
  1801. NULL,
  1802. &dwType,
  1803. (PBYTE) wszFTDfs,
  1804. &cbData);
  1805. if (dwErr != ERROR_SUCCESS ||
  1806. dwType != REG_SZ ||
  1807. _wcsicmp(wszFTDfs, FtDfsName) != 0
  1808. ) {
  1809. dwErr = ERROR_INVALID_PARAMETER;
  1810. }
  1811. }
  1812. //
  1813. // Update pKT (blob) attribute
  1814. //
  1815. if (dwErr == ERROR_SUCCESS) {
  1816. wcscpy(wszFullObjectName, LDAP_VOLUMES_DIR);
  1817. wcscat(wszFullObjectName, DOMAIN_ROOT_VOL);
  1818. dwErr = DfsManagerRemoveService(
  1819. wszFullObjectName,
  1820. wszComputerName);
  1821. if (dwErr == NERR_DfsCantRemoveLastServerShare) {
  1822. dwErr = ERROR_SUCCESS;
  1823. }
  1824. }
  1825. if (dwErr == ERROR_SUCCESS) {
  1826. dwErr = DfsRemoveRoot();
  1827. if (dwErr == ERROR_SUCCESS) {
  1828. //
  1829. // Reinit the service, back to non-ldap
  1830. //
  1831. DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER);
  1832. //
  1833. // Tell dfs.sys to discard all state
  1834. //
  1835. RegCloseKey(hkey);
  1836. hkey = NULL;
  1837. DfsmStopDfs();
  1838. DfsmResetPkt();
  1839. DfsmStartDfs();
  1840. DfsmPktFlushCache();
  1841. }
  1842. }
  1843. if (hkey != NULL) {
  1844. RegCloseKey(hkey);
  1845. }
  1846. dwErr2 = LdapDecrementBlob();
  1847. // don't mask more important errors.
  1848. if(dwErr == ERROR_SUCCESS) {
  1849. dwErr = dwErr2;
  1850. }
  1851. EXIT_DFSM_OPERATION;
  1852. } else {
  1853. ENTER_DFSM_OPERATION;
  1854. //
  1855. // We're forcefully removing a root. We'd better be a DC!!
  1856. //
  1857. //
  1858. // Update remoteServerName attribute
  1859. //
  1860. dwErr = DfspRemoveFtDfsDsObj(
  1861. ServerName,
  1862. DcName,
  1863. RootShare,
  1864. FtDfsName,
  1865. ppRootList);
  1866. //
  1867. // Update pKT (blob) attribute
  1868. //
  1869. if (dwErr == ERROR_SUCCESS) {
  1870. dwErr = DfsManagerRemoveServiceForced(
  1871. ServerName,
  1872. DcName,
  1873. FtDfsName);
  1874. }
  1875. EXIT_DFSM_OPERATION;
  1876. }
  1877. cleanup:
  1878. #if DBG
  1879. if (DfsSvcVerbose)
  1880. DbgPrint("NetrDfsRemoveFtRoot returning %d\n", dwErr);
  1881. #endif
  1882. DFSM_TRACE_NORM(EVENT, NetrDfsRemoveFtRoot_End,
  1883. LOGSTATUS(dwErr)
  1884. LOGWSTR(ServerName)
  1885. LOGWSTR(DcName)
  1886. LOGWSTR(RootShare)
  1887. LOGWSTR(FtDfsName));
  1888. return dwErr;
  1889. }
  1890. //+----------------------------------------------------------------------------
  1891. //
  1892. // Function: NetrDfsRemoveStdRoot
  1893. //
  1894. // Synopsis: Deletes a Dfs root
  1895. //
  1896. // Arguments: [ServerName] -- The server to remove.
  1897. // [RootShare] -- The Root share hosting the Dfs/FtDfs
  1898. // [Flags] -- Flags for the operation
  1899. //
  1900. // Returns: [NERR_Success] -- Operation successful.
  1901. //
  1902. // [NERR_DfsInternalCorruption] -- Internal database corruption
  1903. // encountered while executing operation.
  1904. //
  1905. // [ERROR_INVALID_PARAMETER] -- One of the input parameters is
  1906. // incorrect.
  1907. //
  1908. //-----------------------------------------------------------------------------
  1909. extern "C" NET_API_STATUS
  1910. NetrDfsRemoveStdRoot(
  1911. IN LPWSTR ServerName,
  1912. IN LPWSTR RootShare,
  1913. IN DWORD Flags)
  1914. {
  1915. DWORD dwErr = ERROR_SUCCESS;
  1916. DWORD cbData;
  1917. DWORD dwType;
  1918. HKEY hkey;
  1919. WCHAR wszRootShare[MAX_PATH];
  1920. DFSM_TRACE_NORM(EVENT, NetrDfsRemoveStdRoot_Start,
  1921. LOGSTATUS(dwErr)
  1922. LOGWSTR(ServerName)
  1923. LOGWSTR(RootShare));
  1924. if (!AccessCheckRpcClient()) {
  1925. dwErr = ERROR_ACCESS_DENIED;
  1926. goto cleanup;
  1927. }
  1928. //
  1929. // Validate the input arguments...
  1930. //
  1931. if (ServerName == NULL) {
  1932. dwErr = ERROR_INVALID_PARAMETER;
  1933. goto cleanup;
  1934. }
  1935. if (ServerName[0] == UNICODE_NULL) {
  1936. dwErr = ERROR_INVALID_PARAMETER;
  1937. goto cleanup;
  1938. }
  1939. if (RootShare == NULL) {
  1940. dwErr = ERROR_INVALID_PARAMETER;
  1941. goto cleanup;
  1942. }
  1943. if (RootShare[0] == UNICODE_NULL) {
  1944. dwErr = ERROR_INVALID_PARAMETER;
  1945. goto cleanup;
  1946. }
  1947. ENTER_DFSM_OPERATION;
  1948. //
  1949. // We need to be a root to remove a root...
  1950. //
  1951. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
  1952. //
  1953. // Check RootName
  1954. //
  1955. if (dwErr == ERROR_SUCCESS) {
  1956. cbData = sizeof(wszRootShare);
  1957. dwErr = RegQueryValueEx(
  1958. hkey,
  1959. ROOT_SHARE_VALUE_NAME,
  1960. NULL,
  1961. &dwType,
  1962. (PBYTE) wszRootShare,
  1963. &cbData);
  1964. if (dwErr != ERROR_SUCCESS ||
  1965. dwType != REG_SZ ||
  1966. _wcsicmp(wszRootShare, RootShare) != 0
  1967. ) {
  1968. dwErr = ERROR_INVALID_PARAMETER;
  1969. }
  1970. } else {
  1971. hkey = NULL;
  1972. }
  1973. if (dwErr == ERROR_SUCCESS) {
  1974. //
  1975. // Remove registry stuff (DfsHost and volumes)
  1976. //
  1977. dwErr = DfsRemoveRoot();
  1978. if (dwErr == ERROR_SUCCESS) {
  1979. //
  1980. // Reinit the service
  1981. //
  1982. DfsReInitGlobals(pwszComputerName, DFS_MANAGER_SERVER);
  1983. //
  1984. // Tell dfs.sys to discard all state
  1985. //
  1986. RegCloseKey(hkey);
  1987. hkey = NULL;
  1988. DfsmStopDfs();
  1989. DfsmResetPkt();
  1990. DfsmStartDfs();
  1991. DfsmPktFlushCache();
  1992. }
  1993. }
  1994. if (hkey != NULL) {
  1995. RegCloseKey(hkey);
  1996. }
  1997. EXIT_DFSM_OPERATION;
  1998. cleanup:
  1999. DFSM_TRACE_NORM(EVENT, NetrDfsRemoveStdRoot_End,
  2000. LOGSTATUS(dwErr)
  2001. LOGWSTR(ServerName)
  2002. LOGWSTR(RootShare));
  2003. return dwErr;
  2004. }
  2005. //+----------------------------------------------------------------------------
  2006. //
  2007. // Function: NetrDfsSetInfo (Obsolete)
  2008. //
  2009. //-----------------------------------------------------------------------------
  2010. extern "C" NET_API_STATUS
  2011. NetrDfsSetInfo(
  2012. IN LPWSTR DfsEntryPath,
  2013. IN LPWSTR ServerName,
  2014. IN LPWSTR ShareName,
  2015. IN DWORD Level,
  2016. IN LPDFS_INFO_STRUCT DfsInfo)
  2017. {
  2018. if (!AccessCheckRpcClient())
  2019. return( ERROR_ACCESS_DENIED );
  2020. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2021. return( ERROR_NOT_SUPPORTED );
  2022. return NetrDfsSetInfo2(
  2023. DfsEntryPath,
  2024. NULL,
  2025. ServerName,
  2026. ShareName,
  2027. Level,
  2028. DfsInfo,
  2029. NULL);
  2030. }
  2031. //+----------------------------------------------------------------------------
  2032. //
  2033. // Function: NetrDfsSetInfo2
  2034. //
  2035. // Synopsis: Sets the comment, volume state, or replica state.
  2036. //
  2037. // Arguments: [DfsEntryPath] -- Entry Path of the volume for which info is
  2038. // to be set.
  2039. // [ServerName] -- If specified, the name of the server whose
  2040. // state is to be set.
  2041. // [ShareName] -- If specified, the name of the share on
  2042. // ServerName whose state is to be set.
  2043. // [Level] -- Level of DfsInfo
  2044. // [DfsInfo] -- The actual Dfs info.
  2045. //
  2046. // Returns: [NERR_Success] -- Operation completed successfully.
  2047. //
  2048. // [ERROR_INVALID_LEVEL] -- Level != 100 , 101, or 102
  2049. //
  2050. // [ERROR_INVALID_PARAMETER] -- DfsEntryPath invalid, or
  2051. // ShareName specified without ServerName.
  2052. //
  2053. // [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to
  2054. // a valid Dfs volume.
  2055. //
  2056. // [NERR_DfsNoSuchShare] -- The indicated ServerName/ShareName do
  2057. // not support this Dfs volume.
  2058. //
  2059. // [NERR_DfsInternalCorruption] -- Internal database corruption
  2060. // encountered while executing operation.
  2061. //
  2062. //-----------------------------------------------------------------------------
  2063. extern "C" NET_API_STATUS
  2064. NetrDfsSetInfo2(
  2065. IN LPWSTR DfsEntryPath,
  2066. IN LPWSTR DcName,
  2067. IN LPWSTR ServerName,
  2068. IN LPWSTR ShareName,
  2069. IN DWORD Level,
  2070. IN LPDFS_INFO_STRUCT DfsInfo,
  2071. IN PDFSM_ROOT_LIST *ppRootList)
  2072. {
  2073. NET_API_STATUS status = ERROR_SUCCESS;
  2074. NET_API_STATUS netStatus;
  2075. CDfsVolume *pDfsVol = NULL;
  2076. LPWSTR pwszShare = NULL;
  2077. BOOLEAN fSetReplicaState;
  2078. LPWSTR OrgDfsEntryPath = DfsEntryPath;
  2079. DFSM_TRACE_NORM(EVENT, NetrDfsSetInfo2_Start,
  2080. LOGSTATUS(status)
  2081. LOGWSTR(OrgDfsEntryPath)
  2082. LOGWSTR(DcName)
  2083. LOGWSTR(ServerName)
  2084. LOGWSTR(ShareName));
  2085. #if DBG
  2086. if (DfsSvcVerbose) {
  2087. DbgPrint("NetrDfsSetInfo2(%ws,%ws,%ws,%ws,%d,0x%x\n",
  2088. DfsEntryPath,
  2089. DcName,
  2090. ServerName,
  2091. ShareName,
  2092. Level,
  2093. ppRootList);
  2094. if (Level == 100) {
  2095. DbgPrint(",Comment=%ws)\n", DfsInfo->DfsInfo100->Comment);
  2096. } else if (Level == 101) {
  2097. DbgPrint(",State=0x%x)\n", DfsInfo->DfsInfo101->State);
  2098. } else if (Level == 102) {
  2099. DbgPrint(",Timeout=0x%x)\n", DfsInfo->DfsInfo102->Timeout);
  2100. } else {
  2101. DbgPrint(")\n");
  2102. }
  2103. }
  2104. #endif
  2105. if (!AccessCheckRpcClient()) {
  2106. status = ERROR_ACCESS_DENIED;
  2107. goto cleanup;
  2108. }
  2109. //
  2110. // Validate the input parameters...
  2111. //
  2112. #if 0 // Broken for DNS names
  2113. DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
  2114. #endif
  2115. if (DfsEntryPath != NULL) {
  2116. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2117. DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
  2118. else if (ulDfsManagerType == DFS_MANAGER_SERVER)
  2119. DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
  2120. if (DfsEntryPath == NULL){
  2121. status = ERROR_OUTOFMEMORY;
  2122. goto cleanup;
  2123. }
  2124. }
  2125. if (DfsEntryPath == NULL) {
  2126. status = ERROR_INVALID_PARAMETER;
  2127. goto cleanup;
  2128. }
  2129. if (DfsInfo == NULL || DfsInfo->DfsInfo100 == NULL) {
  2130. if (DfsEntryPath != OrgDfsEntryPath) {
  2131. delete [] DfsEntryPath;
  2132. }
  2133. status = ERROR_INVALID_PARAMETER;
  2134. goto cleanup;
  2135. }
  2136. if (!(Level >= 100 && Level <= 102)) {
  2137. if (DfsEntryPath != OrgDfsEntryPath) {
  2138. delete [] DfsEntryPath;
  2139. }
  2140. status = ERROR_INVALID_LEVEL;
  2141. goto cleanup;
  2142. }
  2143. ENTER_DFSM_OPERATION;
  2144. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  2145. if (DcName != NULL)
  2146. DfsManagerSetDcName(DcName);
  2147. LdapIncrementBlob();
  2148. }
  2149. //
  2150. // Try to get the Dfs Volume for DfsEntryPath
  2151. //
  2152. status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
  2153. if (status == ERROR_SUCCESS) {
  2154. //
  2155. // Do the right thing based on Level...
  2156. //
  2157. if (Level == 100) {
  2158. //
  2159. // Set the volume Comment
  2160. //
  2161. if (DfsInfo->DfsInfo100->Comment != NULL)
  2162. status = pDfsVol->SetComment(DfsInfo->DfsInfo100->Comment);
  2163. else
  2164. status = pDfsVol->SetComment(L"");
  2165. } else if (Level == 101) {
  2166. //
  2167. // Set the volume state
  2168. //
  2169. if (ServerName == NULL && ShareName == NULL) {
  2170. fSetReplicaState = FALSE;
  2171. } else if (ServerName != NULL && ServerName[0] != UNICODE_NULL &&
  2172. ShareName != NULL && ShareName[0] != UNICODE_NULL) {
  2173. fSetReplicaState = TRUE;
  2174. } else {
  2175. status = ERROR_INVALID_PARAMETER;
  2176. DFSM_TRACE_HIGH(ERROR, NetrDfsSetInfo2_Error1,
  2177. LOGSTATUS(status)
  2178. LOGWSTR(DcName)
  2179. LOGWSTR(ServerName)
  2180. LOGWSTR(ShareName));
  2181. }
  2182. if (status == ERROR_SUCCESS) {
  2183. if (fSetReplicaState) {
  2184. status = pDfsVol->SetReplicaState(
  2185. ServerName,
  2186. ShareName,
  2187. DfsInfo->DfsInfo101->State);
  2188. } else {
  2189. status = pDfsVol->SetVolumeState(DfsInfo->DfsInfo101->State);
  2190. }
  2191. }
  2192. if (pwszShare != NULL) {
  2193. delete [] pwszShare;
  2194. }
  2195. } else if (Level == 102) {
  2196. //
  2197. // Set the volume timeout
  2198. //
  2199. status = pDfsVol->SetVolumeTimeout(DfsInfo->DfsInfo102->Timeout);
  2200. }
  2201. }
  2202. if (pDfsVol != NULL) {
  2203. pDfsVol->Release();
  2204. }
  2205. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2206. status = LdapDecrementBlob();
  2207. EXIT_DFSM_OPERATION;
  2208. //
  2209. // Create list of roots to redirect to this DC
  2210. //
  2211. if (status == NERR_Success &&
  2212. DcName != NULL &&
  2213. ulDfsManagerType == DFS_MANAGER_FTDFS
  2214. ) {
  2215. DfspCreateRootList(
  2216. DfsEntryPath,
  2217. DcName,
  2218. ppRootList);
  2219. }
  2220. if (DfsEntryPath != OrgDfsEntryPath) {
  2221. delete [] DfsEntryPath;
  2222. }
  2223. cleanup:
  2224. #if DBG
  2225. if (DfsSvcVerbose)
  2226. DbgPrint("NetrDfsSetInfo2 returning %d\n", status);
  2227. #endif
  2228. DFSM_TRACE_NORM(EVENT, NetrDfsSetInfo2_End,
  2229. LOGSTATUS(status)
  2230. LOGWSTR(OrgDfsEntryPath)
  2231. LOGWSTR(DcName)
  2232. LOGWSTR(ServerName)
  2233. LOGWSTR(ShareName));
  2234. return( status );
  2235. }
  2236. //+----------------------------------------------------------------------------
  2237. //
  2238. // Function: NetrDfsGetInfo
  2239. //
  2240. // Synopsis: Server side implementation of the NetDfsGetInfo.
  2241. //
  2242. // Arguments: [DfsEntryPath] -- Entry Path of volume for which info is
  2243. // requested.
  2244. //
  2245. // [ServerName] -- Name of server which supports this volume
  2246. // and for which info is requested.
  2247. //
  2248. // [ShareName] -- Name of share on ServerName which supports this
  2249. // volume.
  2250. //
  2251. // [Level] -- Level of Info requested.
  2252. //
  2253. // [DfsInfo] -- On successful return, contains a pointer to the
  2254. // requested DFS_INFO_x struct.
  2255. //
  2256. // Returns: [NERR_Success] -- If successfully returned requested info.
  2257. //
  2258. // [NERR_DfsNoSuchVolume] -- If DfsEntryPath does not
  2259. // corresponds to a valid volume.
  2260. //
  2261. // [NERR_DfsInternalCorruption] -- Corruption encountered in
  2262. // internal database.
  2263. //
  2264. // [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for
  2265. // info.
  2266. //
  2267. // [ERROR_INVALID_PARAMETER] -- DfsInfo was NULL on entry, or
  2268. // ShareName specified without ServerName, or
  2269. // DfsEntryPath was NULL on entry.
  2270. //
  2271. // [ERROR_INVALID_LEVEL] -- Level != 1,2,3,4, or 100
  2272. //
  2273. //-----------------------------------------------------------------------------
  2274. extern "C" NET_API_STATUS
  2275. NetrDfsGetInfo(
  2276. IN LPWSTR DfsEntryPath,
  2277. IN LPWSTR ServerName,
  2278. IN LPWSTR ShareName,
  2279. IN DWORD Level,
  2280. OUT LPDFS_INFO_STRUCT DfsInfo)
  2281. {
  2282. NET_API_STATUS status = ERROR_SUCCESS;
  2283. LPDFS_INFO_3 pInfo;
  2284. CDfsVolume *pDfsVol;
  2285. DWORD cbInfo;
  2286. LPWSTR OrgDfsEntryPath = DfsEntryPath;
  2287. DFSM_TRACE_NORM(EVENT, NetrDfsGetInfo_Start,
  2288. LOGSTATUS(status)
  2289. LOGWSTR(DfsEntryPath)
  2290. LOGWSTR(ServerName)
  2291. LOGWSTR(ShareName));
  2292. #if DBG
  2293. if (DfsSvcVerbose)
  2294. DbgPrint("NetrDfsGetInfo(%ws,%ws,%ws,%d)\n",
  2295. DfsEntryPath,
  2296. ServerName,
  2297. ShareName,
  2298. Level);
  2299. #endif
  2300. IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsGetInfo(L=%d)\n", Level));
  2301. //
  2302. // Validate the input parameters...
  2303. //
  2304. #if 0 // Broken for DNS names
  2305. DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
  2306. #endif
  2307. if (DfsEntryPath != NULL) {
  2308. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2309. DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
  2310. else if (ulDfsManagerType == DFS_MANAGER_SERVER)
  2311. DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
  2312. if (DfsEntryPath == NULL) {
  2313. status = ERROR_OUTOFMEMORY;
  2314. goto cleanup;
  2315. }
  2316. }
  2317. if (DfsEntryPath == NULL) {
  2318. status = ERROR_INVALID_PARAMETER;
  2319. goto cleanup;
  2320. }
  2321. if (DfsInfo == NULL) {
  2322. if (DfsEntryPath != OrgDfsEntryPath) {
  2323. delete [] DfsEntryPath;
  2324. }
  2325. status = ERROR_INVALID_PARAMETER;
  2326. goto cleanup;
  2327. }
  2328. if (!(Level >= 1 && Level <= 4) && Level != 100) {
  2329. if (DfsEntryPath != OrgDfsEntryPath) {
  2330. delete [] DfsEntryPath;
  2331. }
  2332. status = ERROR_INVALID_LEVEL;
  2333. goto cleanup;
  2334. }
  2335. if (ServerName == NULL && ShareName != NULL) {
  2336. if (DfsEntryPath != OrgDfsEntryPath) {
  2337. delete [] DfsEntryPath;
  2338. }
  2339. status = ERROR_INVALID_PARAMETER;
  2340. goto cleanup;
  2341. }
  2342. //
  2343. // Now, get the info...
  2344. //
  2345. if (Level <= 3) {
  2346. pInfo = (LPDFS_INFO_3) MIDL_user_allocate(sizeof(DFS_INFO_3));
  2347. } else {
  2348. pInfo = (LPDFS_INFO_3) MIDL_user_allocate(sizeof(DFS_INFO_4));
  2349. }
  2350. if (pInfo == NULL) {
  2351. if (DfsEntryPath != OrgDfsEntryPath) {
  2352. delete [] DfsEntryPath;
  2353. }
  2354. status = ERROR_NOT_ENOUGH_MEMORY;
  2355. goto cleanup;
  2356. }
  2357. ENTER_DFSM_OPERATION;
  2358. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2359. LdapIncrementBlob();
  2360. status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
  2361. if (status == ERROR_SUCCESS) {
  2362. status = pDfsVol->GetNetInfo(Level, pInfo, &cbInfo );
  2363. pDfsVol->Release();
  2364. }
  2365. if (status == ERROR_SUCCESS) {
  2366. DfsInfo->DfsInfo3 = pInfo;
  2367. } else if (status != NERR_DfsNoSuchVolume) {
  2368. status = NERR_DfsInternalCorruption;
  2369. }
  2370. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  2371. NET_API_STATUS TempStatus;
  2372. TempStatus = LdapDecrementBlob();
  2373. // only mask the status if we haven't already seen an error.
  2374. if(status == ERROR_SUCCESS) {
  2375. status = TempStatus;
  2376. }
  2377. }
  2378. EXIT_DFSM_OPERATION;
  2379. if (DfsEntryPath != OrgDfsEntryPath) {
  2380. delete [] DfsEntryPath;
  2381. }
  2382. cleanup:
  2383. #if DBG
  2384. if (DfsSvcVerbose)
  2385. DbgPrint("NetrDfsGetInfo returning %d\n", status);
  2386. #endif
  2387. DFSM_TRACE_NORM(EVENT, NetrDfsGetInfo_End,
  2388. LOGSTATUS(status)
  2389. LOGWSTR(DfsEntryPath)
  2390. LOGWSTR(ServerName)
  2391. LOGWSTR(ShareName));
  2392. return( status );
  2393. }
  2394. //+----------------------------------------------------------------------------
  2395. //
  2396. // Function: NetrDfsEnum
  2397. //
  2398. // Synopsis: The server side implementation of the NetDfsEnum public API
  2399. //
  2400. // Arguments: [Level] -- The level of info struct desired.
  2401. // [PrefMaxLen] -- Preferred maximum length of output buffer.
  2402. // 0xffffffff means no limit.
  2403. // [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
  2404. // structs will be returned.
  2405. // [ResumeHandle] -- If 0, the enumeration will begin from the
  2406. // start. On return, the resume handle will be an opaque
  2407. // cookie that can be passed in on subsequent calls to
  2408. // resume the enumeration.
  2409. //
  2410. // Returns: [NERR_Success] -- Successfully retrieved info.
  2411. //
  2412. // [NERR_DfsInternalCorruption] -- Internal Dfs database is
  2413. // corrupt.
  2414. //
  2415. // [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
  2416. // NULL on entry.
  2417. //
  2418. // [ERROR_INVALID_LEVEL] -- If Level != 1,2, 4 or 200
  2419. //
  2420. // [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
  2421. // on *ResumeHandle value.
  2422. //
  2423. // [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
  2424. // condition while constructing info.
  2425. //
  2426. //-----------------------------------------------------------------------------
  2427. extern "C" NET_API_STATUS
  2428. NetrDfsEnum(
  2429. IN DWORD Level,
  2430. IN DWORD PrefMaxLen,
  2431. IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
  2432. IN OUT LPDWORD ResumeHandle)
  2433. {
  2434. NET_API_STATUS status = ERROR_SUCCESS;
  2435. DWORD i, cEntriesToRead, cbInfoSize, cbOneInfoSize, cbTotalSize;
  2436. LPBYTE pBuffer;
  2437. DFSM_TRACE_NORM(EVENT, NetrDfsEnum_Start,
  2438. LOGSTATUS(status));
  2439. IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsEnum(L=%d)\n", Level));
  2440. #if DBG
  2441. if (DfsSvcVerbose)
  2442. DbgPrint("NetrDfsEnum(%d,0x%x)\n",
  2443. Level,
  2444. PrefMaxLen);
  2445. #endif
  2446. //
  2447. // Validate the Out parameters before we die...
  2448. //
  2449. if (DfsEnum == NULL ||
  2450. DfsEnum->DfsInfoContainer.DfsInfo1Container == NULL ||
  2451. ResumeHandle == NULL) {
  2452. #if DBG
  2453. if (DfsSvcVerbose)
  2454. DbgPrint("NetrDfsEnum returning ERROR_INVALID_PARAMETER\n");
  2455. #endif
  2456. if (DfsEventLog > 1) {
  2457. LogWriteMessage(
  2458. NET_DFS_ENUM,
  2459. ERROR_INVALID_PARAMETER,
  2460. 0,
  2461. NULL);
  2462. }
  2463. status = ERROR_INVALID_PARAMETER;
  2464. goto cleanup;
  2465. }
  2466. //
  2467. // Validate the Info Level...
  2468. //
  2469. if (!(Level >= 1 && Level <= 4) && Level != 200) {
  2470. #if DBG
  2471. if (DfsSvcVerbose)
  2472. DbgPrint("NetrDfsEnum returning ERROR_INVALID_LEVEL\n");
  2473. #endif
  2474. if (DfsEventLog > 1) {
  2475. LogWriteMessage(
  2476. NET_DFS_ENUM,
  2477. ERROR_INVALID_LEVEL,
  2478. 0,
  2479. NULL);
  2480. }
  2481. status = ERROR_INVALID_LEVEL;
  2482. goto cleanup;
  2483. }
  2484. ENTER_DFSM_OPERATION;
  2485. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2486. LdapIncrementBlob();
  2487. //
  2488. // Handle level 200 as a special case
  2489. //
  2490. if (Level == 200) {
  2491. status = NetrDfsEnum200(
  2492. Level,
  2493. PrefMaxLen,
  2494. DfsEnum,
  2495. ResumeHandle);
  2496. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2497. status = LdapDecrementBlob();
  2498. EXIT_DFSM_OPERATION;
  2499. #if DBG
  2500. if (DfsSvcVerbose) {
  2501. DbgPrint("NetrDfsEnum200 returned %d\n", status);
  2502. DbgPrint("NetrDfsEnum returning %d\n", status);
  2503. }
  2504. #endif
  2505. if (DfsEventLog > 1) {
  2506. LogWriteMessage(
  2507. NET_DFS_ENUM,
  2508. status,
  2509. 0,
  2510. NULL);
  2511. }
  2512. //return( status );
  2513. goto cleanup;
  2514. }
  2515. //
  2516. // Sanity check the ResumeHandle...
  2517. //
  2518. if (pDfsmStorageDirectory == NULL ||
  2519. (*ResumeHandle) >= pDfsmStorageDirectory->GetNumEntries()) {
  2520. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2521. status = LdapDecrementBlob();
  2522. EXIT_DFSM_OPERATION;
  2523. #if DBG
  2524. if (DfsSvcVerbose)
  2525. DbgPrint("NetrDfsEnum returning ERROR_NO_MORE_ITEMS\n");
  2526. #endif
  2527. if (DfsEventLog > 1) {
  2528. LogWriteMessage(
  2529. NET_DFS_ENUM,
  2530. ERROR_NO_MORE_ITEMS,
  2531. 0,
  2532. NULL);
  2533. }
  2534. status = ERROR_NO_MORE_ITEMS;
  2535. goto cleanup;
  2536. }
  2537. switch (Level) {
  2538. case 1:
  2539. cbInfoSize = sizeof(DFS_INFO_1);
  2540. break;
  2541. case 2:
  2542. cbInfoSize = sizeof(DFS_INFO_2);
  2543. break;
  2544. case 3:
  2545. cbInfoSize = sizeof(DFS_INFO_3);
  2546. break;
  2547. case 4:
  2548. cbInfoSize = sizeof(DFS_INFO_4);
  2549. break;
  2550. default:
  2551. EXIT_DFSM_OPERATION;
  2552. status = ERROR_INVALID_LEVEL;
  2553. goto cleanup;
  2554. }
  2555. if (PrefMaxLen == ~0) {
  2556. cEntriesToRead = pDfsmStorageDirectory->GetNumEntries();
  2557. } else {
  2558. cEntriesToRead = min( pDfsmStorageDirectory->GetNumEntries(),
  2559. PrefMaxLen / cbInfoSize );
  2560. }
  2561. #if DBG
  2562. if (DfsSvcVerbose)
  2563. DbgPrint("NetrDfsEnum: cEntriesToRead = %d\n", cEntriesToRead);
  2564. #endif
  2565. pBuffer = (LPBYTE) MIDL_user_allocate( cEntriesToRead * cbInfoSize );
  2566. if (pBuffer == NULL) {
  2567. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2568. status = LdapDecrementBlob();
  2569. EXIT_DFSM_OPERATION;
  2570. #if DBG
  2571. if (DfsSvcVerbose)
  2572. DbgPrint("NetrDfsEnum returning ERROR_NOT_ENOUGH_MEMORY\n");
  2573. #endif
  2574. if (DfsEventLog > 1) {
  2575. LogWriteMessage(
  2576. NET_DFS_ENUM,
  2577. ERROR_NOT_ENOUGH_MEMORY,
  2578. 0,
  2579. NULL);
  2580. }
  2581. status = ERROR_NOT_ENOUGH_MEMORY;
  2582. goto cleanup;
  2583. }
  2584. //
  2585. // Now, we sit in a loop and get the info
  2586. //
  2587. for (i = 0, cbTotalSize = 0, status = NERR_Success;
  2588. (i < cEntriesToRead) &&
  2589. (cbTotalSize < PrefMaxLen);
  2590. i++) {
  2591. status = DfspGetOneEnumInfo(
  2592. i,
  2593. Level,
  2594. pBuffer,
  2595. &cbOneInfoSize,
  2596. ResumeHandle);
  2597. #if DBG
  2598. if (DfsSvcVerbose)
  2599. DbgPrint("DfspGetOneEnumInfo returned %d\n", status);
  2600. #endif
  2601. if (status == ERROR_NO_MORE_ITEMS || status != NERR_Success)
  2602. break;
  2603. cbTotalSize += (cbInfoSize + cbOneInfoSize);
  2604. cbOneInfoSize = 0;
  2605. }
  2606. if (status == NERR_Success || status == ERROR_NO_MORE_ITEMS) {
  2607. DfsEnum->Level = Level;
  2608. DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = i;
  2609. if (i > 0) {
  2610. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer =
  2611. (LPDFS_INFO_1) pBuffer;
  2612. status = ERROR_SUCCESS;
  2613. } else {
  2614. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
  2615. MIDL_user_free( pBuffer );
  2616. }
  2617. } else {
  2618. for (; i > 0; i--) {
  2619. DfspFreeOneEnumInfo(i-1, Level, pBuffer);
  2620. //
  2621. // 333596. Fix memory leak.
  2622. //
  2623. MIDL_user_free( pBuffer );
  2624. }
  2625. }
  2626. if (ulDfsManagerType == DFS_MANAGER_FTDFS)
  2627. status = LdapDecrementBlob();
  2628. EXIT_DFSM_OPERATION;
  2629. #if DBG
  2630. if (DfsSvcVerbose)
  2631. DbgPrint("NetrDfsEnum returning %d\n", status);
  2632. #endif
  2633. if (DfsEventLog > 1) {
  2634. LogWriteMessage(
  2635. NET_DFS_ENUM,
  2636. status,
  2637. 0,
  2638. NULL);
  2639. }
  2640. cleanup:
  2641. DFSM_TRACE_NORM(EVENT, NetrDfsEnum_End,
  2642. LOGSTATUS(status));
  2643. return( status );
  2644. }
  2645. //+----------------------------------------------------------------------------
  2646. //
  2647. // Function: NetrDfsEnum200
  2648. //
  2649. // Synopsis: Handles level 200 for NetrDfsEnum, server-side implementation
  2650. //
  2651. // Arguments: [Level] -- The level of info struct desired.
  2652. // [PrefMaxLen] -- Preferred maximum length of output buffer.
  2653. // 0xffffffff means no limit.
  2654. // [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
  2655. // structs will be returned.
  2656. // [ResumeHandle] -- If 0, the enumeration will begin from the
  2657. // start. On return, the resume handle will be an opaque
  2658. // cookie that can be passed in on subsequent calls to
  2659. // resume the enumeration.
  2660. //
  2661. // Returns: [NERR_Success] -- Successfully retrieved info.
  2662. //
  2663. // [NERR_DfsInternalCorruption] -- Internal Dfs database is
  2664. // corrupt.
  2665. //
  2666. // [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
  2667. // NULL on entry.
  2668. //
  2669. // [ERROR_INVALID_LEVEL] -- If Level != 200
  2670. //
  2671. // [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
  2672. // on *ResumeHandle value.
  2673. //
  2674. // [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
  2675. // condition while constructing info.
  2676. //
  2677. //-----------------------------------------------------------------------------
  2678. NET_API_STATUS
  2679. NetrDfsEnum200(
  2680. IN DWORD Level,
  2681. IN DWORD PrefMaxLen,
  2682. IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
  2683. IN OUT LPDWORD ResumeHandle)
  2684. {
  2685. NET_API_STATUS status = ERROR_SUCCESS;
  2686. ULONG i;
  2687. ULONG cEntriesToRead;
  2688. ULONG cEntriesRead;
  2689. ULONG cbInfoSize;
  2690. ULONG cbThisInfoSize;
  2691. ULONG cbTotalSize;
  2692. ULONG cList;
  2693. LPWSTR *List = NULL;
  2694. PDFS_INFO_200 pDfsInfo200;
  2695. PBYTE pBuffer;
  2696. #if DBG
  2697. if (DfsSvcVerbose)
  2698. DbgPrint("NetrDfsEnum200(%d,%d)\n", Level, PrefMaxLen);
  2699. #endif
  2700. if (Level != 200) {
  2701. status = ERROR_INVALID_LEVEL;
  2702. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error1, LOGSTATUS(status));
  2703. goto AllDone;
  2704. }
  2705. if (pwszDomainName == NULL) {
  2706. status = ERROR_DOMAIN_CONTROLLER_NOT_FOUND;
  2707. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error2, LOGSTATUS(status));
  2708. goto AllDone;
  2709. }
  2710. cbInfoSize = sizeof(DFS_INFO_200);
  2711. //
  2712. // Get the list of FtDfs roots in the domain
  2713. //
  2714. status = DfsGetFtServersFromDs(
  2715. NULL,
  2716. pwszDomainName,
  2717. NULL,
  2718. &List);
  2719. IDfsVolInlineDebOut((DEB_TRACE, "DfsGetFtServersFromDs returned %d\n", status));
  2720. if (status != ERROR_SUCCESS)
  2721. goto AllDone;
  2722. if (List == NULL) {
  2723. status = ERROR_NO_MORE_ITEMS;
  2724. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error3, LOGSTATUS(status));
  2725. goto AllDone;
  2726. }
  2727. //
  2728. // Build the results array
  2729. //
  2730. if (status == NOERROR) {
  2731. status = NERR_Success;
  2732. //
  2733. // Count # entries returned
  2734. //
  2735. for (cList = 0; List[cList]; cList++) {
  2736. NOTHING;
  2737. }
  2738. #if DBG
  2739. if (DfsSvcVerbose) {
  2740. DbgPrint("List has %d items\n", cList);
  2741. for (i = 0; i < cList; i++)
  2742. DbgPrint("%d: %ws\n", i, List[i]);
  2743. }
  2744. #endif
  2745. if (*ResumeHandle >= cList) {
  2746. status = ERROR_NO_MORE_ITEMS;
  2747. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error4, LOGSTATUS(status));
  2748. goto AllDone;
  2749. }
  2750. //
  2751. // Size & allocate the results array
  2752. //
  2753. if (PrefMaxLen == ~0) {
  2754. cEntriesToRead = cList;
  2755. } else {
  2756. cEntriesToRead = min(cList, PrefMaxLen / cbInfoSize);
  2757. }
  2758. pBuffer = (LPBYTE) MIDL_user_allocate(cEntriesToRead * cbInfoSize);
  2759. if (pBuffer == NULL) {
  2760. status = ERROR_NOT_ENOUGH_MEMORY;
  2761. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error5, LOGSTATUS(status));
  2762. }
  2763. }
  2764. //
  2765. // Load the results array, starting at the resume handle
  2766. //
  2767. if (status == NERR_Success) {
  2768. pDfsInfo200 = (LPDFS_INFO_200)pBuffer;
  2769. cbTotalSize = cEntriesRead = 0;
  2770. for (i = *ResumeHandle; (i < cEntriesToRead) && (status == NERR_Success); i++) {
  2771. cbThisInfoSize = (wcslen(List[i]) + 1) * sizeof(WCHAR);
  2772. //
  2773. // Quit if this element would cause us to exceed PrefmaxLen
  2774. //
  2775. if (cbTotalSize + cbInfoSize + cbThisInfoSize > PrefMaxLen) {
  2776. break;
  2777. }
  2778. pDfsInfo200->FtDfsName = (LPWSTR) MIDL_user_allocate(cbThisInfoSize);
  2779. if (pDfsInfo200 != NULL) {
  2780. wcscpy(pDfsInfo200->FtDfsName, List[i]);
  2781. cbTotalSize += cbInfoSize + cbThisInfoSize;
  2782. } else {
  2783. status = ERROR_NOT_ENOUGH_MEMORY;
  2784. DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error6, LOGSTATUS(status));
  2785. }
  2786. pDfsInfo200++;
  2787. cEntriesRead++;
  2788. }
  2789. *ResumeHandle = i;
  2790. }
  2791. if (status == NERR_Success) {
  2792. //
  2793. // Everything worked
  2794. //
  2795. DfsEnum->Level = Level;
  2796. DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = cEntriesRead;
  2797. if (cEntriesRead > 0) {
  2798. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = (LPDFS_INFO_1) pBuffer;
  2799. status = ERROR_SUCCESS;
  2800. } else {
  2801. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
  2802. MIDL_user_free( pBuffer );
  2803. }
  2804. } else {
  2805. //
  2806. // We're going to return an error, so free all the MIDL_user_allocate's
  2807. // we made to hold FtDfsName's
  2808. //
  2809. for (i = cEntriesRead; i > 0; i--) {
  2810. pDfsInfo200 = (LPDFS_INFO_200) (pBuffer + (i-1) * sizeof(DFS_INFO_200));
  2811. if (pDfsInfo200->FtDfsName != NULL) {
  2812. MIDL_user_free(pDfsInfo200->FtDfsName);
  2813. }
  2814. }
  2815. MIDL_user_free( pBuffer );
  2816. }
  2817. NetApiBufferFree( List );
  2818. AllDone:
  2819. #if DBG
  2820. if (DfsSvcVerbose)
  2821. DbgPrint("NetrDfsEnum200 returning %d\n", status);
  2822. #endif
  2823. return status;
  2824. }
  2825. //+----------------------------------------------------------------------------
  2826. //
  2827. // Function: NetrDfsEnumEx
  2828. //
  2829. // Synopsis: The DC implementation of the NetDfsEnum public API
  2830. //
  2831. // Arguments: [DfsName] -- The Dfs to enumerate (\\domainname\ftdfsname)
  2832. // [Level] -- The level of info struct desired.
  2833. // [PrefMaxLen] -- Preferred maximum length of output buffer.
  2834. // 0xffffffff means no limit.
  2835. // [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
  2836. // structs will be returned.
  2837. // [ResumeHandle] -- If 0, the enumeration will begin from the
  2838. // start. On return, the resume handle will be an opaque
  2839. // cookie that can be passed in on subsequent calls to
  2840. // resume the enumeration.
  2841. //
  2842. // Returns: [NERR_Success] -- Successfully retrieved info.
  2843. //
  2844. // [NERR_DfsInternalCorruption] -- Internal Dfs database is
  2845. // corrupt.
  2846. //
  2847. // [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
  2848. // NULL on entry.
  2849. //
  2850. // [ERROR_INVALID_LEVEL] -- If Level != 1,2, 4 or 200
  2851. //
  2852. // [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
  2853. // on *ResumeHandle value.
  2854. //
  2855. // [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
  2856. // condition while constructing info.
  2857. //
  2858. //-----------------------------------------------------------------------------
  2859. extern "C" NET_API_STATUS
  2860. NetrDfsEnumEx(
  2861. IN LPWSTR DfsName,
  2862. IN DWORD Level,
  2863. IN DWORD PrefMaxLen,
  2864. IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
  2865. IN OUT LPDWORD ResumeHandle)
  2866. {
  2867. DWORD dwErr = ERROR_SUCCESS;
  2868. DFS_VOLUME_LIST DfsVolList;
  2869. ULONG cbBlob = 0;
  2870. BYTE *pBlob = NULL;
  2871. LPWSTR wszFtDfsName;
  2872. DWORD i;
  2873. DWORD cEntriesToRead;
  2874. DWORD cbInfoSize;
  2875. DWORD cbOneInfoSize;
  2876. DWORD cbTotalSize;
  2877. LPBYTE pBuffer;
  2878. DFSM_TRACE_NORM(EVENT, NetrDfsEnumEx_Start,
  2879. LOGSTATUS(dwErr)
  2880. LOGWSTR(DfsName));
  2881. IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsEnumEx(%ws,%d)\n", DfsName, Level));
  2882. #if DBG
  2883. if (DfsSvcVerbose)
  2884. DbgPrint("NetrDfsEnumEx(%ws,%d,0x%x)\n",
  2885. DfsName,
  2886. Level,
  2887. PrefMaxLen);
  2888. #endif
  2889. RtlZeroMemory(&DfsVolList, sizeof(DFS_VOLUME_LIST));
  2890. //
  2891. // Validate the Out parameters
  2892. //
  2893. if (DfsEnum == NULL
  2894. ||
  2895. DfsEnum->DfsInfoContainer.DfsInfo1Container == NULL
  2896. ||
  2897. ResumeHandle == NULL
  2898. ) {
  2899. #if DBG
  2900. if (DfsSvcVerbose)
  2901. DbgPrint("NetrDfsEnumEx returning ERROR_INVALID_PARAMETER\n");
  2902. #endif
  2903. if (DfsEventLog > 1) {
  2904. LogWriteMessage(
  2905. NET_DFS_ENUMEX,
  2906. ERROR_INVALID_PARAMETER,
  2907. 0,
  2908. NULL);
  2909. }
  2910. dwErr = ERROR_INVALID_PARAMETER;
  2911. goto cleanup;
  2912. }
  2913. //
  2914. // Validate the Info Level...
  2915. //
  2916. if (!(Level >= 1 && Level <= 4) && Level != 200) {
  2917. #if DBG
  2918. if (DfsSvcVerbose)
  2919. DbgPrint("NetrDfsEnumEx returning ERROR_INVALID_LEVEL\n");
  2920. #endif
  2921. if (DfsEventLog > 1) {
  2922. LogWriteMessage(
  2923. NET_DFS_ENUMEX,
  2924. ERROR_INVALID_LEVEL,
  2925. 0,
  2926. NULL);
  2927. }
  2928. dwErr = ERROR_INVALID_LEVEL;
  2929. goto cleanup;
  2930. }
  2931. ENTER_DFSM_OPERATION;
  2932. //
  2933. // Handle level 200 as a special case
  2934. //
  2935. if (Level == 200) {
  2936. dwErr = NetrDfsEnum200(
  2937. Level,
  2938. PrefMaxLen,
  2939. DfsEnum,
  2940. ResumeHandle);
  2941. #if DBG
  2942. if (DfsSvcVerbose)
  2943. DbgPrint("NetrDfsEnum200 returned %d\n", dwErr);
  2944. #endif
  2945. goto Cleanup;
  2946. }
  2947. for (wszFtDfsName = DfsName;
  2948. *wszFtDfsName != UNICODE_PATH_SEP && *wszFtDfsName != UNICODE_NULL;
  2949. wszFtDfsName++) {
  2950. NOTHING;
  2951. }
  2952. if (*wszFtDfsName != UNICODE_PATH_SEP) {
  2953. dwErr = ERROR_INVALID_PARAMETER;
  2954. goto Cleanup;
  2955. }
  2956. wszFtDfsName++;
  2957. if (*wszFtDfsName == UNICODE_NULL) {
  2958. dwErr = ERROR_INVALID_PARAMETER;
  2959. goto Cleanup;
  2960. }
  2961. //
  2962. // Get blob from Ds
  2963. //
  2964. dwErr = DfsGetDsBlob(
  2965. wszFtDfsName,
  2966. pwszComputerName,
  2967. &cbBlob,
  2968. &pBlob);
  2969. if (dwErr != ERROR_SUCCESS)
  2970. goto Cleanup;
  2971. //
  2972. // Unserialize it
  2973. //
  2974. dwErr = DfsGetVolList(
  2975. cbBlob,
  2976. pBlob,
  2977. &DfsVolList);
  2978. if (dwErr != ERROR_SUCCESS)
  2979. goto Cleanup;
  2980. #if DBG
  2981. if (DfsSvcVerbose)
  2982. DfsDumpVolList(&DfsVolList);
  2983. #endif
  2984. //
  2985. // Sanity check the ResumeHandle...
  2986. //
  2987. if ((*ResumeHandle) >= DfsVolList.VolCount) {
  2988. dwErr = ERROR_NO_MORE_ITEMS;
  2989. goto Cleanup;
  2990. }
  2991. switch (Level) {
  2992. case 1:
  2993. cbInfoSize = sizeof(DFS_INFO_1);
  2994. break;
  2995. case 2:
  2996. cbInfoSize = sizeof(DFS_INFO_2);
  2997. break;
  2998. case 3:
  2999. cbInfoSize = sizeof(DFS_INFO_3);
  3000. break;
  3001. case 4:
  3002. cbInfoSize = sizeof(DFS_INFO_4);
  3003. break;
  3004. default:
  3005. ASSERT(FALSE && "Invalid Info Level");
  3006. break;
  3007. }
  3008. if (PrefMaxLen == ~0) {
  3009. cEntriesToRead = DfsVolList.VolCount;
  3010. } else {
  3011. cEntriesToRead = min(DfsVolList.VolCount, PrefMaxLen/cbInfoSize);
  3012. }
  3013. #if DBG
  3014. if (DfsSvcVerbose)
  3015. DbgPrint("NetrDfsEnumEx: cEntriesToRead = %d\n", cEntriesToRead);
  3016. #endif
  3017. pBuffer = (LPBYTE) MIDL_user_allocate( cEntriesToRead * cbInfoSize );
  3018. if (pBuffer == NULL) {
  3019. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  3020. goto Cleanup;
  3021. }
  3022. //
  3023. // Now, we sit in a loop and get the info
  3024. //
  3025. for (i = 0, cbTotalSize = 0, dwErr = ERROR_SUCCESS;
  3026. (i < cEntriesToRead) && (cbTotalSize < PrefMaxLen);
  3027. i++
  3028. ) {
  3029. dwErr = DfspGetOneEnumInfoEx(
  3030. &DfsVolList,
  3031. i,
  3032. Level,
  3033. pBuffer,
  3034. &cbOneInfoSize);
  3035. if (dwErr == ERROR_NO_MORE_ITEMS || dwErr != ERROR_SUCCESS)
  3036. break;
  3037. cbTotalSize += cbInfoSize + cbOneInfoSize;
  3038. cbOneInfoSize = 0;
  3039. }
  3040. if (dwErr == ERROR_SUCCESS || dwErr == ERROR_NO_MORE_ITEMS) {
  3041. DfsEnum->Level = Level;
  3042. DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = cEntriesToRead;
  3043. if (i > 0) {
  3044. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = (LPDFS_INFO_1) pBuffer;
  3045. dwErr = ERROR_SUCCESS;
  3046. } else {
  3047. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
  3048. MIDL_user_free( pBuffer );
  3049. }
  3050. } else {
  3051. for (; i > 0; i--) {
  3052. DfspFreeOneEnumInfo(i-1, Level, pBuffer);
  3053. }
  3054. }
  3055. Cleanup:
  3056. EXIT_DFSM_OPERATION;
  3057. if (pBlob != NULL)
  3058. free(pBlob);
  3059. if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL)
  3060. DfsFreeVolList(&DfsVolList);
  3061. #if DBG
  3062. if (DfsSvcVerbose & 0x80000000) {
  3063. DbgPrint("===============\n");
  3064. DbgPrint("Level: %d\n", DfsEnum->Level);
  3065. DbgPrint("EntriesRead=%d\n", DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead);
  3066. for (i = 0; i < DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead; i++) {
  3067. if (Level == 1) {
  3068. DbgPrint("Entry %d: %ws\n",
  3069. i+1,
  3070. DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer[i].EntryPath);
  3071. } else if (Level == 3) {
  3072. DbgPrint("Entry %d: %ws\n",
  3073. i+1,
  3074. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].EntryPath);
  3075. }
  3076. if (Level == 3) {
  3077. ULONG j;
  3078. DbgPrint("\tComment: [%ws]\n",
  3079. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Comment,
  3080. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].State,
  3081. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].NumberOfStorages);
  3082. for (j = 0;
  3083. j < DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].NumberOfStorages;
  3084. j++
  3085. ) {
  3086. DbgPrint("\t\t[0x%x][\\\\%ws\\%ws]\n",
  3087. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].State,
  3088. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].ServerName,
  3089. DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].ShareName);
  3090. }
  3091. }
  3092. }
  3093. DbgPrint("===============\n");
  3094. }
  3095. if (DfsSvcVerbose)
  3096. DbgPrint("NetrDfsEnumEx returning %d\n", dwErr);
  3097. #endif
  3098. if (DfsEventLog > 1) {
  3099. LogWriteMessage(
  3100. NET_DFS_ENUMEX,
  3101. dwErr,
  3102. 0,
  3103. NULL);
  3104. }
  3105. cleanup:
  3106. DFSM_TRACE_NORM(EVENT, NetrDfsEnumEx_End,
  3107. LOGSTATUS(dwErr)
  3108. LOGWSTR(DfsName));
  3109. return( dwErr );
  3110. }
  3111. //+----------------------------------------------------------------------------
  3112. //
  3113. // Function: NetrDfsMove
  3114. //
  3115. // Synopsis: Moves a leaf volume to a different parent.
  3116. //
  3117. // Arguments: [DfsEntryPath] -- Current entry path of Dfs volume.
  3118. //
  3119. // [NewEntryPath] -- New entry path of Dfs volume.
  3120. //
  3121. // Returns:
  3122. //
  3123. //-----------------------------------------------------------------------------
  3124. extern "C" NET_API_STATUS
  3125. NetrDfsMove(
  3126. IN LPWSTR DfsEntryPath,
  3127. IN LPWSTR NewDfsEntryPath)
  3128. {
  3129. NET_API_STATUS status = ERROR_NOT_SUPPORTED;
  3130. CDfsVolume *pDfsVol = NULL;
  3131. LPWSTR OrgDfsEntryPath = DfsEntryPath;
  3132. LPWSTR OrgNewDfsEntryPath = NewDfsEntryPath;
  3133. DFSM_TRACE_NORM(EVENT, NetrDfsMove_Start,
  3134. LOGSTATUS(status)
  3135. LOGWSTR(DfsEntryPath)
  3136. LOGWSTR(NewDfsEntryPath));
  3137. if (!AccessCheckRpcClient())
  3138. status = ERROR_ACCESS_DENIED;
  3139. DFSM_TRACE_NORM(EVENT, NetrDfsMove_End,
  3140. LOGSTATUS(status)
  3141. LOGWSTR(DfsEntryPath)
  3142. LOGWSTR(NewDfsEntryPath));
  3143. return( status );
  3144. }
  3145. //+----------------------------------------------------------------------------
  3146. //
  3147. // Function: NetrDfsRename
  3148. //
  3149. // Synopsis: Moves a leaf volume to a different parent.
  3150. //
  3151. // Arguments: [Path] -- Current path along the entry path of a Dfs volume.
  3152. //
  3153. // [NewPath] -- New path for current path.
  3154. //
  3155. // Returns:
  3156. //
  3157. //-----------------------------------------------------------------------------
  3158. extern "C" NET_API_STATUS
  3159. NetrDfsRename(
  3160. IN LPWSTR Path,
  3161. IN LPWSTR NewPath)
  3162. {
  3163. NET_API_STATUS status = ERROR_NOT_SUPPORTED;
  3164. CDfsVolume *pDfsVol;
  3165. LPWSTR OrgPath = Path;
  3166. LPWSTR OrgNewPath = NewPath;
  3167. DFSM_TRACE_NORM(EVENT, NetrDfsRename_Start,
  3168. LOGSTATUS(status)
  3169. LOGWSTR(Path)
  3170. LOGWSTR(NewPath));
  3171. if (!AccessCheckRpcClient())
  3172. status = ERROR_ACCESS_DENIED;
  3173. DFSM_TRACE_NORM(EVENT, NetrDfsRename_End,
  3174. LOGSTATUS(status)
  3175. LOGWSTR(Path)
  3176. LOGWSTR(NewPath));
  3177. return( status );
  3178. }
  3179. //+----------------------------------------------------------------------------
  3180. //
  3181. // Function: NetrDfsManagerGetConfigInfo
  3182. //
  3183. // Synopsis: RPC Interface method that returns the config info for a
  3184. // Dfs volume for a given server
  3185. //
  3186. // Arguments: [wszServer] -- Name of server requesting the info. This
  3187. // server is assumed to be requesting the info for
  3188. // verification of its local volume knowledge.
  3189. // [wszLocalVolumeEntryPath] -- Entry path of local volume.
  3190. // [idLocalVolume] -- The guid of the local volume.
  3191. // [ppRelationInfo] -- The relation info is allocated and
  3192. // returned here.
  3193. //
  3194. // Returns: [ERROR_SUCCESS] -- Successfully returning relation info
  3195. //
  3196. // [NERR_DfsNoSuchVolume] -- Did not find LocalVolumeEntryPath
  3197. //
  3198. // [NERR_DfsNoSuchShare] -- The server name passed in does not
  3199. // support this local volume.
  3200. //
  3201. // [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for info.
  3202. //
  3203. //-----------------------------------------------------------------------------
  3204. extern "C" DWORD
  3205. NetrDfsManagerGetConfigInfo(
  3206. IN LPWSTR wszServer,
  3207. IN LPWSTR wszLocalVolumeEntryPath,
  3208. IN GUID idLocalVolume,
  3209. OUT LPDFSM_RELATION_INFO *ppRelationInfo)
  3210. {
  3211. DWORD dwErr = ERROR_SUCCESS;
  3212. DFS_PKT_ENTRY_ID EntryId;
  3213. DFS_PKT_RELATION_INFO DfsRelationInfo;
  3214. CDfsVolume *pDfsVol;
  3215. #if DBG
  3216. if (DfsSvcVerbose)
  3217. DbgPrint("NetrDfsManagerGetConfigInfo(%ws,%ws)\n",
  3218. wszServer,
  3219. wszLocalVolumeEntryPath);
  3220. #endif
  3221. DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetConfigInfo_Start,
  3222. LOGSTATUS(dwErr)
  3223. LOGWSTR(wszServer)
  3224. LOGWSTR(wszLocalVolumeEntryPath));
  3225. if (ppRelationInfo == NULL) {
  3226. dwErr = ERROR_INVALID_PARAMETER;
  3227. goto cleanup;
  3228. }
  3229. ENTER_DFSM_OPERATION;
  3230. EntryId.Uid = idLocalVolume;
  3231. RtlInitUnicodeString( &EntryId.Prefix, wszLocalVolumeEntryPath );
  3232. EntryId.ShortPrefix.Length = EntryId.ShortPrefix.MaximumLength = 0;
  3233. EntryId.ShortPrefix.Buffer = NULL;
  3234. dwErr = GetPktCacheRelationInfo( &EntryId, &DfsRelationInfo );
  3235. if (dwErr == ERROR_SUCCESS) {
  3236. //
  3237. // Well, we have the relation info, see if this server is a valid
  3238. // server for this volume.
  3239. //
  3240. dwErr = GetDfsVolumeFromPath( wszLocalVolumeEntryPath, TRUE, &pDfsVol );
  3241. if (dwErr == ERROR_SUCCESS) {
  3242. if ( pDfsVol->IsValidService(wszServer) ) {
  3243. dwErr = DfspAllocateRelationInfo(
  3244. &DfsRelationInfo,
  3245. ppRelationInfo );
  3246. } else {
  3247. dwErr = NERR_DfsNoSuchShare;
  3248. }
  3249. pDfsVol->Release();
  3250. } else {
  3251. dwErr = NERR_DfsNoSuchVolume;
  3252. }
  3253. DeallocateCacheRelationInfo( DfsRelationInfo );
  3254. } else {
  3255. dwErr = NERR_DfsInternalError;
  3256. }
  3257. EXIT_DFSM_OPERATION;
  3258. cleanup:
  3259. #if DBG
  3260. if (DfsSvcVerbose)
  3261. DbgPrint("NetrDfsManagerGetConfigInfo returning %d\n", dwErr);
  3262. #endif
  3263. DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetConfigInfo_End,
  3264. LOGSTATUS(dwErr)
  3265. LOGWSTR(wszServer)
  3266. LOGWSTR(wszLocalVolumeEntryPath));
  3267. return( dwErr );
  3268. }
  3269. //+----------------------------------------------------------------------------
  3270. //
  3271. // Function: NetrDfsManagerSendSiteInfo
  3272. //
  3273. // Synopsis: RPC Interface method that reports the site information for a
  3274. // Dfs storage server.
  3275. //
  3276. // Arguments: [wszServer] -- Name of server sending the info.
  3277. // [pSiteInfo] -- The site info is here.
  3278. //
  3279. // Returns: [ERROR_SUCCESS] -- Successfull
  3280. //
  3281. // [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for info.
  3282. //
  3283. //-----------------------------------------------------------------------------
  3284. extern "C" DWORD
  3285. NetrDfsManagerSendSiteInfo(
  3286. IN LPWSTR wszServer,
  3287. IN LPDFS_SITELIST_INFO pSiteInfo)
  3288. {
  3289. DWORD dwErr = ERROR_SUCCESS;
  3290. ULONG i;
  3291. DFSM_TRACE_NORM(EVENT, NetrDfsManagerSendSiteInfo_Start,
  3292. LOGSTATUS(dwErr)
  3293. LOGWSTR(wszServer));
  3294. if (!AccessCheckRpcClient()) {
  3295. dwErr = ERROR_ACCESS_DENIED;
  3296. goto cleanup;
  3297. }
  3298. ENTER_DFSM_OPERATION;
  3299. //
  3300. // Update the Site table
  3301. //
  3302. IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsGetInfo()\n", 0));
  3303. pDfsmSites->AddRef();
  3304. dwErr = pDfsmSites->AddOrUpdateSiteInfo(
  3305. wszServer,
  3306. pSiteInfo->cSites,
  3307. &pSiteInfo->Site[0]);
  3308. pDfsmSites->Release();
  3309. EXIT_DFSM_OPERATION;
  3310. cleanup:
  3311. DFSM_TRACE_NORM(EVENT, NetrDfsManagerSendSiteInfo_End,
  3312. LOGSTATUS(dwErr)
  3313. LOGWSTR(wszServer));
  3314. return( dwErr );
  3315. }
  3316. //+----------------------------------------------------------------------------
  3317. //
  3318. // Function: NetrDfsManagerInitialize
  3319. //
  3320. // Synopsis: Reinitializes the service
  3321. //
  3322. // Arguments: [ServerName] -- Name of server
  3323. // [Flags] -- Flags for the operation
  3324. //
  3325. // Returns: [NERR_Success] -- Operation succeeded.
  3326. //
  3327. // [ERROR_OUTOFMEMORY] -- Out of memory condition.
  3328. //
  3329. //-----------------------------------------------------------------------------
  3330. extern "C" NET_API_STATUS
  3331. NetrDfsManagerInitialize(
  3332. IN LPWSTR ServerName,
  3333. IN DWORD Flags)
  3334. {
  3335. DWORD dwErr = ERROR_SUCCESS;
  3336. DFSM_TRACE_NORM(EVENT, NetrDfsManagerInitialize_Start,
  3337. LOGSTATUS(dwErr)
  3338. LOGWSTR(ServerName));
  3339. #if DBG
  3340. if (DfsSvcVerbose)
  3341. DbgPrint("NetrDfsManagerInitialize(%ws,%d)\n",
  3342. ServerName,
  3343. Flags);
  3344. #endif
  3345. if (!AccessCheckRpcClient()) {
  3346. dwErr = ERROR_ACCESS_DENIED;
  3347. goto cleanup;
  3348. }
  3349. ENTER_DFSM_OPERATION;
  3350. #if DBG
  3351. GetDebugSwitches();
  3352. #endif
  3353. GetConfigSwitches();
  3354. //
  3355. // If we are a DomDfs, simply doing the LdapIncrementBlob will
  3356. // be enough. If the DS blob has changed, then we will note that
  3357. // and fully reinitialize everything.
  3358. //
  3359. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  3360. LdapIncrementBlob();
  3361. dwErr = LdapDecrementBlob();
  3362. } else {
  3363. if (pDfsmStorageDirectory != NULL)
  3364. delete pDfsmStorageDirectory;
  3365. if (pDfsmSites != NULL)
  3366. delete pDfsmSites;
  3367. pDfsmSites = new CSites(LDAP_VOLUMES_DIR SITE_ROOT, &dwErr);
  3368. pDfsmStorageDirectory = new CStorageDirectory( &dwErr );
  3369. DfsmMarkStalePktEntries();
  3370. InitializeDfsManager();
  3371. DfsmFlushStalePktEntries();
  3372. }
  3373. DfsmPktFlushCache();
  3374. EXIT_DFSM_OPERATION;
  3375. dwErr = NERR_Success;
  3376. cleanup:
  3377. #if DBG
  3378. if (DfsSvcVerbose)
  3379. DbgPrint("NetrDfsManagerInitialize returning %d\n", dwErr);
  3380. #endif
  3381. DFSM_TRACE_NORM(EVENT, NetrDfsManagerInitialize_End,
  3382. LOGSTATUS(dwErr)
  3383. LOGWSTR(ServerName));
  3384. return dwErr;
  3385. }
  3386. //+----------------------------------------------------------------------------
  3387. //
  3388. // Function: DfspGetOneEnumInfo
  3389. //
  3390. // Synopsis: Helper routine to read one info dfs info into an enum array.
  3391. //
  3392. // Arguments: [i] -- Index of the array element to fill.
  3393. // [Level] -- Info Level to fill with.
  3394. // [InfoArray] -- The array to use; only the ith member will be
  3395. // filled.
  3396. // [InfoSize] -- On successful return, size in bytes of info.
  3397. // [ResumeHandle] -- Handle to indicate the information to fill.
  3398. //
  3399. // Returns:
  3400. //
  3401. //-----------------------------------------------------------------------------
  3402. NET_API_STATUS
  3403. DfspGetOneEnumInfo(
  3404. DWORD i,
  3405. DWORD Level,
  3406. LPBYTE InfoArray,
  3407. LPDWORD InfoSize,
  3408. LPDWORD ResumeHandle)
  3409. {
  3410. NET_API_STATUS status;
  3411. LPWSTR wszObject;
  3412. CDfsVolume *pDfsVolume;
  3413. LPDFS_INFO_3 pDfsInfo;
  3414. //
  3415. // Get the object name for the object indicated in ResumeHandle. i == 0
  3416. // means that this is the first time this function is being called for
  3417. // this enum, so we are forced to get object name by index. If i > 0, then
  3418. // we can get the object name by using the "get next" capability of
  3419. // CStorageDirectory::GetObjectByIndex.
  3420. //
  3421. if (pDfsmStorageDirectory == NULL) {
  3422. return(ERROR_NO_MORE_ITEMS);
  3423. }
  3424. if (i == 0) {
  3425. status = pDfsmStorageDirectory->GetObjectByIndex(*ResumeHandle, &wszObject);
  3426. } else {
  3427. status = pDfsmStorageDirectory->GetObjectByIndex((DWORD)~0, &wszObject);
  3428. }
  3429. if (status != ERROR_SUCCESS)
  3430. return( status );
  3431. #if DBG
  3432. if (DfsSvcVerbose)
  3433. DbgPrint("DfspGetOneEnumInfo(%d,%d)\n", i, Level);
  3434. #endif
  3435. pDfsVolume = new CDfsVolume();
  3436. #if DBG
  3437. if (DfsSvcVerbose)
  3438. DbgPrint(" pDfsVolume = 0x%x\n", pDfsVolume);
  3439. #endif
  3440. if (pDfsVolume != NULL) {
  3441. status = pDfsVolume->Load(wszObject, 0);
  3442. #if DBG
  3443. if (DfsSvcVerbose)
  3444. DbgPrint(" pDfsVolume->Load returned %d\n", status);
  3445. #endif
  3446. if (status == ERROR_SUCCESS) {
  3447. switch (Level) {
  3448. case 1:
  3449. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_1));
  3450. break;
  3451. case 2:
  3452. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_2));
  3453. break;
  3454. case 3:
  3455. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_3));
  3456. break;
  3457. case 4:
  3458. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_4));
  3459. break;
  3460. default:
  3461. ASSERT( FALSE && "Invalid Info Level" );
  3462. break;
  3463. }
  3464. status = pDfsVolume->GetNetInfo(Level, pDfsInfo, InfoSize);
  3465. #if DBG
  3466. if (DfsSvcVerbose)
  3467. DbgPrint(" pDfsVolume->GetNetInfo returned %d\n", status);
  3468. #endif
  3469. }
  3470. pDfsVolume->Release();
  3471. if (status == ERROR_SUCCESS) {
  3472. (*ResumeHandle)++;
  3473. } else {
  3474. status = NERR_DfsInternalCorruption;
  3475. DFSM_TRACE_HIGH(ERROR, DfspGetOneEnumInfo_Error1, LOGSTATUS(status));
  3476. }
  3477. } else {
  3478. status = ERROR_NOT_ENOUGH_MEMORY;
  3479. DFSM_TRACE_HIGH(ERROR, DfspGetOneEnumInfo_Error2, LOGSTATUS(status));
  3480. }
  3481. delete [] wszObject;
  3482. return( status );
  3483. }
  3484. //+----------------------------------------------------------------------------
  3485. //
  3486. // Function: DfspGetOneEnumInfoEx
  3487. //
  3488. // Synopsis: Helper routine to read one info dfs info into an enum array.
  3489. //
  3490. // Arguments: [pDfsVolList] pointer to DFS_VOLUME_LIST to use
  3491. // [i] -- Index of the array element to fill.
  3492. // [Level] -- Info Level to fill with.
  3493. // [InfoArray] -- The array to use; only the ith member will be
  3494. // filled.
  3495. // [InfoSize] -- On successful return, size in bytes of info.
  3496. //
  3497. // Returns:
  3498. //
  3499. //-----------------------------------------------------------------------------
  3500. DWORD
  3501. DfspGetOneEnumInfoEx(
  3502. PDFS_VOLUME_LIST pDfsVolList,
  3503. DWORD i,
  3504. DWORD Level,
  3505. LPBYTE InfoArray,
  3506. LPDWORD InfoSize)
  3507. {
  3508. DWORD dwErr = ERROR_SUCCESS;
  3509. LPWSTR wszObject;
  3510. LPDFS_INFO_3 pDfsInfo;
  3511. #if DBG
  3512. if (DfsSvcVerbose)
  3513. DbgPrint("DfspGetOneEnumInfoEx(%d,%d)\n", i, Level);
  3514. #endif
  3515. if (pDfsVolList == NULL || i >= pDfsVolList->VolCount) {
  3516. dwErr = ERROR_NO_MORE_ITEMS;
  3517. goto AllDone;
  3518. }
  3519. switch (Level) {
  3520. case 1:
  3521. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_1));
  3522. break;
  3523. case 2:
  3524. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_2));
  3525. break;
  3526. case 3:
  3527. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_3));
  3528. break;
  3529. case 4:
  3530. pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_4));
  3531. break;
  3532. default:
  3533. // 447489. fix prefix bug.
  3534. return ERROR_INVALID_LEVEL;
  3535. }
  3536. dwErr = GetNetInfoEx(&pDfsVolList->Volumes[i], Level, pDfsInfo, InfoSize);
  3537. AllDone:
  3538. #if DBG
  3539. if (DfsSvcVerbose)
  3540. DbgPrint("DfspGetOneEnumInfoEx returning %d\n", dwErr);
  3541. #endif
  3542. return( dwErr );
  3543. }
  3544. //+----------------------------------------------------------------------------
  3545. //
  3546. // Function: DfspFreeOneEnumInfo
  3547. //
  3548. // Synopsis: Worker routine to free one DFS_INFO_x struct as allocated
  3549. // by DfspGetOneEnumInfo. Useful for cleanup in case of error.
  3550. //
  3551. // Arguments: [Idx] -- Index of the array element to free.
  3552. // [Level] -- Level of info to free.
  3553. // [InfoArray] -- The array to use; only the members of the ith
  3554. // element will be freed.
  3555. //
  3556. // Returns: Nothing
  3557. //
  3558. //-----------------------------------------------------------------------------
  3559. VOID
  3560. DfspFreeOneEnumInfo(
  3561. DWORD Idx,
  3562. DWORD Level,
  3563. LPBYTE InfoArray)
  3564. {
  3565. LPDFS_INFO_3 pDfsInfo;
  3566. LPDFS_INFO_4 pDfsInfo4;
  3567. ULONG i;
  3568. switch (Level) {
  3569. case 1:
  3570. pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_1));
  3571. break;
  3572. case 2:
  3573. pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_2));
  3574. break;
  3575. case 3:
  3576. pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_3));
  3577. break;
  3578. case 4:
  3579. pDfsInfo4 = (LPDFS_INFO_4) (InfoArray + Idx * sizeof(DFS_INFO_4));
  3580. break;
  3581. default:
  3582. //
  3583. // 447480. prefix bug. return if unknown level.
  3584. return;
  3585. }
  3586. if (Level == 4) {
  3587. if (pDfsInfo4->EntryPath != NULL) {
  3588. MIDL_user_free(pDfsInfo4->EntryPath);
  3589. }
  3590. if (pDfsInfo4->Comment != NULL) {
  3591. MIDL_user_free(pDfsInfo4->Comment);
  3592. }
  3593. if (pDfsInfo4->Storage != NULL) {
  3594. for (i = 0; i < pDfsInfo4->NumberOfStorages; i++) {
  3595. if (pDfsInfo4->Storage[i].ServerName != NULL)
  3596. MIDL_user_free(pDfsInfo4->Storage[i].ServerName);
  3597. if (pDfsInfo4->Storage[i].ShareName != NULL)
  3598. MIDL_user_free(pDfsInfo4->Storage[i].ShareName);
  3599. }
  3600. MIDL_user_free(pDfsInfo4->Storage);
  3601. }
  3602. return;
  3603. }
  3604. //
  3605. // Cleanup the Level 1 stuff.
  3606. //
  3607. if (pDfsInfo->EntryPath != NULL)
  3608. MIDL_user_free(pDfsInfo->EntryPath);
  3609. //
  3610. // Cleanup the Level 2 stuff if needed.
  3611. //
  3612. if (Level > 1 && pDfsInfo->Comment != NULL)
  3613. MIDL_user_free(pDfsInfo->Comment);
  3614. //
  3615. // Cleanup the Level 3 stuff if needed.
  3616. //
  3617. if (Level > 2 && pDfsInfo->Storage != NULL) {
  3618. for (i = 0; i < pDfsInfo->NumberOfStorages; i++) {
  3619. if (pDfsInfo->Storage[i].ServerName != NULL)
  3620. MIDL_user_free(pDfsInfo->Storage[i].ServerName);
  3621. if (pDfsInfo->Storage[i].ShareName != NULL)
  3622. MIDL_user_free(pDfsInfo->Storage[i].ShareName);
  3623. }
  3624. MIDL_user_free(pDfsInfo->Storage);
  3625. }
  3626. }
  3627. //+----------------------------------------------------------------------------
  3628. //
  3629. // Function: DfsManagerCreateVolumeObject
  3630. //
  3631. // Synopsis: Bootstrap routine to create a volume object directly (ie,
  3632. // without having to call DfsCreateChildVolume on a parent
  3633. // volume)
  3634. //
  3635. // Arguments: [pwszObjectName] -- Name of the volume object.
  3636. // [pwszPrefix] -- Entry Path of dfs volume.
  3637. // [pwszServer] -- Name of server supporting dfs volume.
  3638. // [pwszShare] -- Name of share on server supporting dfs volume.
  3639. // [pwszComment] -- Comment for dfs volume.
  3640. // [guidVolume] -- Id of dfs volume.
  3641. //
  3642. // Returns:
  3643. //
  3644. //-----------------------------------------------------------------------------
  3645. extern "C" DWORD
  3646. DfsManagerCreateVolumeObject(
  3647. IN LPWSTR pwszObjectName,
  3648. IN LPWSTR pwszPrefix,
  3649. IN LPWSTR pwszServer,
  3650. IN LPWSTR pwszShare,
  3651. IN LPWSTR pwszComment,
  3652. IN GUID *guidVolume)
  3653. {
  3654. DWORD dwErr;
  3655. DWORD dwStatus;
  3656. CDfsVolume *pCDfsVolume;
  3657. DFS_REPLICA_INFO replicaInfo;
  3658. LPDFS_SITELIST_INFO pSiteInfo;
  3659. pCDfsVolume = new CDfsVolume();
  3660. if (pCDfsVolume != NULL) {
  3661. replicaInfo.ulReplicaType = DFS_STORAGE_TYPE_DFS;
  3662. replicaInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
  3663. replicaInfo.pwszServerName = pwszServer;
  3664. replicaInfo.pwszShareName = pwszShare;
  3665. dwErr = pCDfsVolume->CreateObject(
  3666. pwszObjectName,
  3667. pwszPrefix,
  3668. DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC,
  3669. &replicaInfo,
  3670. pwszComment,
  3671. guidVolume);
  3672. //
  3673. // Create the site table object in the DS or registry
  3674. //
  3675. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  3676. dwErr = LdapCreateObject(
  3677. LDAP_VOLUMES_DIR SITE_ROOT);
  3678. } else {
  3679. // registry stuff instead
  3680. dwErr = RegCreateObject(
  3681. VOLUMES_DIR SITE_ROOT);
  3682. }
  3683. if (dwErr == ERROR_SUCCESS) {
  3684. //
  3685. // Find out the list of covered sites
  3686. // We continue even if this fails (standalone, no TCP/IP)
  3687. //
  3688. pSiteInfo = NULL;
  3689. dwStatus = I_NetDfsManagerReportSiteInfo(
  3690. pwszServer,
  3691. &pSiteInfo);
  3692. DFSM_TRACE_ERROR_HIGH(dwStatus, ALL_ERROR, DfsManagerCreateVolumeObject_Error_I_NetDfsManagerReportSiteInfo,
  3693. LOGSTATUS(dwStatus)
  3694. LOGWSTR(pwszObjectName)
  3695. LOGWSTR(pwszPrefix)
  3696. LOGWSTR(pwszServer)
  3697. LOGWSTR(pwszShare));
  3698. //
  3699. // Create a SiteTable object with those sites
  3700. //
  3701. if (dwStatus == ERROR_SUCCESS) {
  3702. if (pSiteInfo->cSites > 0) {
  3703. //
  3704. // AddRef the site table, then put the site info in, then
  3705. // Release it. This will cause it to be written to the
  3706. // appropriate store (ldap or registry).
  3707. //
  3708. pDfsmSites->AddRef();
  3709. pDfsmSites->AddOrUpdateSiteInfo(
  3710. pwszServer,
  3711. pSiteInfo->cSites,
  3712. &pSiteInfo->Site[0]);
  3713. pDfsmSites->Release();
  3714. }
  3715. NetApiBufferFree(pSiteInfo);
  3716. }
  3717. }
  3718. pCDfsVolume->Release();
  3719. } else {
  3720. dwErr = ERROR_OUTOFMEMORY;
  3721. }
  3722. return( dwErr );
  3723. }
  3724. //+----------------------------------------------------------------------------
  3725. //
  3726. // Function: DfsManagerSetDcName
  3727. //
  3728. // Synopsis: Sets the DC we should first attempt to connect to.
  3729. //
  3730. // Arguments: [pwszDCName] -- Name of the DC
  3731. //
  3732. // Returns: ERROR_SUCCESS
  3733. //
  3734. //-----------------------------------------------------------------------------
  3735. extern "C" DWORD
  3736. DfsManagerSetDcName(
  3737. IN LPWSTR pwszDCName)
  3738. {
  3739. if (pwszDSMachineName != NULL) {
  3740. if (wcscmp(pwszDSMachineName, pwszDCName) != 0) {
  3741. wcscpy(wszDSMachineName, pwszDCName);
  3742. pwszDSMachineName = wszDSMachineName;
  3743. if (pLdapConnection != NULL) {
  3744. if (DfsSvcLdap)
  3745. DbgPrint("DfsManagerSetDcName:ldap_unbind()\n");
  3746. ldap_unbind(pLdapConnection);
  3747. pLdapConnection = NULL;
  3748. }
  3749. }
  3750. } else {
  3751. wcscpy(wszDSMachineName, pwszDCName);
  3752. pwszDSMachineName = wszDSMachineName;
  3753. }
  3754. return ERROR_SUCCESS;
  3755. }
  3756. //+----------------------------------------------------------------------------
  3757. //
  3758. // Function: DfsManagerAddService
  3759. //
  3760. // Synopsis: Bootstrap routine for adding a service to an existing volume
  3761. // object. Used to set up additional root servers in an FTDfs
  3762. // setup.
  3763. //
  3764. // Arguments: [pwszFullObjectName] -- Name of the volume object.
  3765. // [pwszServer] -- Name of server to add.
  3766. // [pwszShare] -- Name of share.
  3767. //
  3768. // Returns:
  3769. //
  3770. //-----------------------------------------------------------------------------
  3771. extern "C" DWORD
  3772. DfsManagerAddService(
  3773. IN LPWSTR pwszFullObjectName,
  3774. IN LPWSTR pwszServer,
  3775. IN LPWSTR pwszShare,
  3776. OUT GUID *guidVolume)
  3777. {
  3778. DWORD dwErr;
  3779. DWORD dwStatus;
  3780. CDfsVolume *pCDfsVolume;
  3781. DFS_REPLICA_INFO replicaInfo;
  3782. LPDFS_SITELIST_INFO pSiteInfo;
  3783. pCDfsVolume = new CDfsVolume();
  3784. if (pCDfsVolume != NULL) {
  3785. dwErr = pCDfsVolume->Load( pwszFullObjectName, 0 );
  3786. if (dwErr == ERROR_SUCCESS) {
  3787. replicaInfo.ulReplicaType = DFS_STORAGE_TYPE_DFS;
  3788. replicaInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
  3789. replicaInfo.pwszServerName = pwszServer;
  3790. replicaInfo.pwszShareName = pwszShare;
  3791. dwErr = pCDfsVolume->AddReplicaToObj( &replicaInfo );
  3792. if (dwErr == ERROR_SUCCESS) {
  3793. pCDfsVolume->GetObjectID( guidVolume );
  3794. }
  3795. }
  3796. if (dwErr == ERROR_SUCCESS) {
  3797. //
  3798. // Find out the list of covered sites
  3799. // We continue even if this fails (standalone, no TCP/IP)
  3800. //
  3801. pSiteInfo = NULL;
  3802. dwStatus = I_NetDfsManagerReportSiteInfo(
  3803. pwszServer,
  3804. &pSiteInfo);
  3805. DFSM_TRACE_ERROR_HIGH(dwStatus, ALL_ERROR, DfsManagerAddService_Error_I_NetDfsManagerReportSiteInfo,
  3806. LOGSTATUS(dwStatus)
  3807. LOGWSTR(pwszFullObjectName)
  3808. LOGWSTR(pwszServer)
  3809. LOGWSTR(pwszShare));
  3810. //
  3811. // Create a SiteTable object with those sites
  3812. //
  3813. if (dwStatus == ERROR_SUCCESS) {
  3814. if (pSiteInfo->cSites > 0) {
  3815. //
  3816. // AddRef the site table, then put the site info in, then
  3817. // Release it. This will cause it to be written to the
  3818. // appropriate store (ldap or registry).
  3819. //
  3820. pDfsmSites->AddRef();
  3821. pDfsmSites->AddOrUpdateSiteInfo(
  3822. pwszServer,
  3823. pSiteInfo->cSites,
  3824. &pSiteInfo->Site[0]);
  3825. pDfsmSites->Release();
  3826. }
  3827. NetApiBufferFree(pSiteInfo);
  3828. }
  3829. }
  3830. pCDfsVolume->Release();
  3831. } else {
  3832. dwErr = ERROR_OUTOFMEMORY;
  3833. }
  3834. return( dwErr );
  3835. }
  3836. //+----------------------------------------------------------------------------
  3837. //
  3838. // Function: DfsManagerRemoveService
  3839. //
  3840. // Synopsis: Bootstrap routine for removing a service from an existing
  3841. // volume object. Used to remove root servers in an FTDfs
  3842. // setup.
  3843. //
  3844. // Arguments: [pwszFullObjectName] -- Name of the volume object.
  3845. // [pwszServer] -- Name of server to remove.
  3846. //
  3847. // Returns:
  3848. //
  3849. //-----------------------------------------------------------------------------
  3850. DWORD
  3851. DfsManagerRemoveService(
  3852. IN LPWSTR pwszFullObjectName,
  3853. IN LPWSTR pwszServer)
  3854. {
  3855. DWORD dwErr;
  3856. CDfsVolume *pCDfsVolume;
  3857. pCDfsVolume = new CDfsVolume();
  3858. if (pCDfsVolume != NULL) {
  3859. dwErr = pCDfsVolume->Load( pwszFullObjectName, 0 );
  3860. if (dwErr == ERROR_SUCCESS) {
  3861. dwErr = pCDfsVolume->RemoveReplicaFromObj( pwszServer );
  3862. }
  3863. pCDfsVolume->Release();
  3864. } else {
  3865. dwErr = ERROR_OUTOFMEMORY;
  3866. }
  3867. return( dwErr );
  3868. }
  3869. //+----------------------------------------------------------------------------
  3870. //
  3871. // Function: DfsManagerRemoveServiceForced
  3872. //
  3873. // Synopsis: Routine for removing a service from an existing
  3874. // volume object in the DS. Used to remove root servers in an FTDfs
  3875. // setup, even if the server is not up.
  3876. //
  3877. // Arguments: [wszServerName] -- Name of server to remove
  3878. // [wszDCName] -- Name of DC to use
  3879. // [wszFtDfsName] -- Name of the FtDfs
  3880. //
  3881. // Returns:
  3882. //
  3883. //-----------------------------------------------------------------------------
  3884. DWORD
  3885. DfsManagerRemoveServiceForced(
  3886. LPWSTR wszServerName,
  3887. LPWSTR wszDCName,
  3888. LPWSTR wszFtDfsName)
  3889. {
  3890. DWORD dwErr = ERROR_SUCCESS;
  3891. DFS_VOLUME_LIST DfsVolList;
  3892. ULONG cbBlob = 0;
  3893. BYTE *pBlob = NULL;
  3894. #if DBG
  3895. if (DfsSvcVerbose)
  3896. DbgPrint("DfsManagerRemoveServiceForced(%ws,%ws,%ws)\n",
  3897. wszServerName,
  3898. wszDCName,
  3899. wszFtDfsName);
  3900. #endif
  3901. RtlZeroMemory(&DfsVolList, sizeof(DFS_VOLUME_LIST));
  3902. //
  3903. // Get blob from Ds
  3904. //
  3905. dwErr = DfsGetDsBlob(
  3906. wszFtDfsName,
  3907. wszDCName,
  3908. &cbBlob,
  3909. &pBlob);
  3910. if (dwErr != ERROR_SUCCESS)
  3911. goto Cleanup;
  3912. //
  3913. // Unserialize it
  3914. //
  3915. dwErr = DfsGetVolList(
  3916. cbBlob,
  3917. pBlob,
  3918. &DfsVolList);
  3919. if (dwErr != ERROR_SUCCESS)
  3920. goto Cleanup;
  3921. //
  3922. // Free the blob
  3923. //
  3924. free(pBlob);
  3925. pBlob = NULL;
  3926. #if DBG
  3927. if (DfsSvcVerbose)
  3928. DfsDumpVolList(&DfsVolList);
  3929. #endif
  3930. //
  3931. // Remove the root/server/machine
  3932. //
  3933. dwErr = DfsRemoveRootReplica(&DfsVolList, wszServerName);
  3934. if (dwErr != ERROR_SUCCESS)
  3935. goto Cleanup;
  3936. #if DBG
  3937. if (DfsSvcVerbose)
  3938. DfsDumpVolList(&DfsVolList);
  3939. #endif
  3940. //
  3941. // Serialize it
  3942. //
  3943. dwErr = DfsPutVolList(
  3944. &cbBlob,
  3945. &pBlob,
  3946. &DfsVolList);
  3947. if (dwErr != ERROR_SUCCESS)
  3948. goto Cleanup;
  3949. //
  3950. // Update the DS
  3951. //
  3952. dwErr = DfsPutDsBlob(
  3953. wszFtDfsName,
  3954. wszDCName,
  3955. cbBlob,
  3956. pBlob);
  3957. //
  3958. // Free the volume list we created
  3959. //
  3960. DfsFreeVolList(&DfsVolList);
  3961. Cleanup:
  3962. if (pBlob != NULL)
  3963. free(pBlob);
  3964. if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL)
  3965. DfsFreeVolList(&DfsVolList);
  3966. #if DBG
  3967. if (DfsSvcVerbose)
  3968. DbgPrint("DfsManagerRemoveServiceForced returning %d\n", dwErr);
  3969. #endif
  3970. return( dwErr );
  3971. }
  3972. //+----------------------------------------------------------------------------
  3973. //
  3974. // Function: DfspAllocateRelationInfo
  3975. //
  3976. // Synopsis: Allocates and fills a RPC compliant DFSM_RELATION_INFO struct
  3977. //
  3978. // Arguments: [pDfsRelationInfo] -- The DFS_PKT_RELATION_INFO to use as a
  3979. // the source.
  3980. // [ppRelationInfo] -- On successful return, pointer to allocated
  3981. // DFSM_RELATION_INFO.
  3982. //
  3983. // Returns: [ERROR_SUCCESS] -- Successfully returning RelationInfo
  3984. //
  3985. // [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate RelationInfo
  3986. //
  3987. //-----------------------------------------------------------------------------
  3988. DWORD
  3989. DfspAllocateRelationInfo(
  3990. IN PDFS_PKT_RELATION_INFO pDfsRelationInfo,
  3991. OUT LPDFSM_RELATION_INFO *ppRelationInfo)
  3992. {
  3993. LPDFSM_RELATION_INFO pRelationInfo;
  3994. DWORD i, cbSize, dwErr;
  3995. LPDFSM_ENTRY_ID pEntryId;
  3996. LPWSTR pwszEntryPath;
  3997. cbSize = sizeof(DFSM_RELATION_INFO);
  3998. for (i = 0; i < pDfsRelationInfo->SubordinateIdCount; i++) {
  3999. cbSize += sizeof(DFSM_ENTRY_ID) +
  4000. pDfsRelationInfo->SubordinateIdList[i].Prefix.Length +
  4001. sizeof(UNICODE_NULL);
  4002. }
  4003. pRelationInfo = (LPDFSM_RELATION_INFO) MIDL_user_allocate( cbSize );
  4004. if (pRelationInfo != NULL) {
  4005. pRelationInfo->cSubordinates = pDfsRelationInfo->SubordinateIdCount;
  4006. pEntryId = &pRelationInfo->eid[0];
  4007. pwszEntryPath = (LPWSTR)
  4008. (((PBYTE) pRelationInfo) +
  4009. sizeof(DFSM_RELATION_INFO) +
  4010. (pDfsRelationInfo->SubordinateIdCount
  4011. * sizeof(DFSM_ENTRY_ID)));
  4012. for (i = 0;
  4013. i < pDfsRelationInfo->SubordinateIdCount;
  4014. i++, pEntryId++) {
  4015. pEntryId->idSubordinate =
  4016. pDfsRelationInfo->SubordinateIdList[i].Uid;
  4017. pEntryId->wszSubordinate = pwszEntryPath;
  4018. CopyMemory(
  4019. pwszEntryPath,
  4020. pDfsRelationInfo->SubordinateIdList[i].Prefix.Buffer,
  4021. pDfsRelationInfo->SubordinateIdList[i].Prefix.Length);
  4022. pwszEntryPath +=
  4023. pDfsRelationInfo->SubordinateIdList[i].Prefix.Length /
  4024. sizeof(WCHAR);
  4025. *pwszEntryPath = UNICODE_NULL;
  4026. pwszEntryPath++;
  4027. }
  4028. *ppRelationInfo = pRelationInfo;
  4029. dwErr = ERROR_SUCCESS;
  4030. } else {
  4031. dwErr = ERROR_OUTOFMEMORY;
  4032. }
  4033. return( dwErr );
  4034. }
  4035. //+----------------------------------------------------------------------------
  4036. //
  4037. // Function: GetDomAndComputerName
  4038. //
  4039. // Synopsis: Retrieves the domain and computer name of the local machine
  4040. //
  4041. // Arguments: [wszDomain] -- On successful return, contains name of domain.
  4042. // If this parameter is NULL on entry, the domain name is
  4043. // not returned.
  4044. //
  4045. // [wszComputer] -- On successful return, contains name of
  4046. // computer. If this parameter is NULL on entry, the
  4047. // computer name is not returned.
  4048. //
  4049. // Returns: [ERROR_SUCCESS] -- Successfully returning names.
  4050. //
  4051. // Win32 Error from calling NetWkstaGetInfo
  4052. //
  4053. //-----------------------------------------------------------------------------
  4054. DWORD
  4055. GetDomAndComputerName(
  4056. LPWSTR wszDomain OPTIONAL,
  4057. LPWSTR wszComputer OPTIONAL,
  4058. PDFS_NAME_CONVENTION pNameType)
  4059. {
  4060. DWORD dwErrNetBios = ERROR_SUCCESS;
  4061. DWORD dwErrDns = ERROR_SUCCESS;
  4062. PWKSTA_INFO_100 wkstaInfo = NULL;
  4063. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL;
  4064. DWORD Idx = 0;
  4065. DFS_NAME_CONVENTION NameType = *pNameType;
  4066. #if DBG
  4067. if (DfsSvcVerbose)
  4068. DbgPrint("GetDomAndComputerName(0x%x,0x%x,%ws)\n",
  4069. wszDomain,
  4070. wszComputer,
  4071. NameType == DFS_NAMETYPE_NETBIOS ? L"DFS_NAMETYPE_NETBIOS" :
  4072. NameType == DFS_NAMETYPE_DNS ? L"DFS_NAMETYPE_DNS" :
  4073. L"DFS_NAMETYPE_EITHER");
  4074. #endif
  4075. //
  4076. // Force Netbios only unless DfsDnsConfig != 0
  4077. //
  4078. if (DfsDnsConfig == 0) {
  4079. NameType = DFS_NAMETYPE_NETBIOS;
  4080. }
  4081. if (NameType == DFS_NAMETYPE_NETBIOS || NameType == DFS_NAMETYPE_EITHER) {
  4082. dwErrNetBios = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo );
  4083. if (dwErrNetBios == ERROR_SUCCESS) {
  4084. if (wszDomain)
  4085. wcscpy(wszDomain, wkstaInfo->wki100_langroup);
  4086. if (wszComputer)
  4087. wcscpy(wszComputer, wkstaInfo->wki100_computername);
  4088. NetApiBufferFree( wkstaInfo );
  4089. }
  4090. if (dwErrNetBios == ERROR_SUCCESS)
  4091. *pNameType = DFS_NAMETYPE_NETBIOS;
  4092. if (NameType == DFS_NAMETYPE_NETBIOS) {
  4093. #if DBG
  4094. if (DfsSvcVerbose)
  4095. DbgPrint("GetDomAndComputerName:NETBIOS:%ws,%ws\n", wszDomain, wszComputer);
  4096. #endif
  4097. return dwErrNetBios;
  4098. }
  4099. }
  4100. if (NameType == DFS_NAMETYPE_DNS || NameType == DFS_NAMETYPE_EITHER) {
  4101. if (wszDomain) {
  4102. //
  4103. // Get our machine name and type/role.
  4104. //
  4105. dwErrDns = DsRoleGetPrimaryDomainInformation(
  4106. NULL,
  4107. DsRolePrimaryDomainInfoBasic,
  4108. (PBYTE *)&pPrimaryDomainInfo);
  4109. if (dwErrDns == ERROR_SUCCESS) {
  4110. if (pPrimaryDomainInfo->DomainNameDns != NULL) {
  4111. if (wcslen(pPrimaryDomainInfo->DomainNameDns) < MAX_PATH) {
  4112. wcscpy(wszDomain, pPrimaryDomainInfo->DomainNameDns);
  4113. } else {
  4114. dwErrDns = ERROR_NOT_ENOUGH_MEMORY;
  4115. }
  4116. }
  4117. }
  4118. if (pPrimaryDomainInfo != NULL) {
  4119. DsRoleFreeMemory(pPrimaryDomainInfo);
  4120. pPrimaryDomainInfo = NULL;
  4121. }
  4122. }
  4123. if (wszComputer && dwErrDns == ERROR_SUCCESS) {
  4124. Idx = MAX_PATH;
  4125. if (!GetComputerNameEx(
  4126. ComputerNameDnsFullyQualified,
  4127. wszComputer,
  4128. &Idx))
  4129. dwErrDns = GetLastError();
  4130. }
  4131. if (dwErrDns == ERROR_SUCCESS)
  4132. *pNameType = DFS_NAMETYPE_DNS;
  4133. if (NameType == DFS_NAMETYPE_DNS) {
  4134. #if DBG
  4135. if (DfsSvcVerbose)
  4136. DbgPrint("GetDomAndComputerName:DNS:%ws,%ws\n", wszDomain, wszComputer);
  4137. #endif
  4138. return dwErrDns;
  4139. }
  4140. }
  4141. //
  4142. // NameType must be DFS_NAMETYPE_EITHER
  4143. //
  4144. if (*pNameType == DFS_NAMETYPE_DNS) {
  4145. #if DBG
  4146. if (DfsSvcVerbose)
  4147. DbgPrint("GetDomAndComputerName:EITHER(DNS)%ws,%ws\n", wszDomain, wszComputer);
  4148. #endif
  4149. return dwErrDns;
  4150. }
  4151. #if DBG
  4152. if (DfsSvcVerbose)
  4153. DbgPrint("GetDomAndComputerName:EITHER(NETBIOS)%ws,%ws\n", wszDomain, wszComputer);
  4154. #endif
  4155. return dwErrNetBios;
  4156. }
  4157. // ====================================================================
  4158. // MIDL allocate and free
  4159. // ====================================================================
  4160. PVOID
  4161. MIDL_user_allocate(size_t len)
  4162. {
  4163. return malloc(len);
  4164. }
  4165. VOID
  4166. MIDL_user_free(void * ptr)
  4167. {
  4168. free(ptr);
  4169. }