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.

666 lines
17 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1996, Microsoft Corporation
  4. //
  5. // File: localvol.cxx
  6. //
  7. // Contents: Code to validate local volume knowledge with the root server
  8. // of the Dfs
  9. //
  10. // Classes:
  11. //
  12. // Functions: DfsManagerValidateLocalVolumes
  13. //
  14. // DfspGetRemoteConfigInfo
  15. // DfspValidateLocalPartition
  16. // DfspPruneLocalPartition
  17. // StringToGuid
  18. //
  19. // History: April 29, 1996 Milans Created
  20. //
  21. //-----------------------------------------------------------------------------
  22. //#include <ntos.h>
  23. //#include <ntrtl.h>
  24. //#include <nturtl.h>
  25. //#include <dfsfsctl.h>
  26. //#include <windows.h>
  27. #include <headers.hxx>
  28. #pragma hdrstop
  29. #include <dsgetdc.h>
  30. #include "dfsmwml.h"
  31. extern "C" NET_API_STATUS
  32. NetDfsManagerGetConfigInfo(
  33. LPWSTR wszServer,
  34. LPWSTR wszLocalVolumeEntryPath,
  35. GUID guidLocalVolume,
  36. LPDFSM_RELATION_INFO *ppDfsmRelationInfo);
  37. extern "C" NET_API_STATUS
  38. NetDfsManagerSendSiteInfo(
  39. LPWSTR wszServer,
  40. LPWSTR wszLocalVolumeEntryPath,
  41. LPDFS_SITELIST_INFO pSiteInfo);
  42. DWORD
  43. DfspGetRemoteConfigInfo(
  44. LPWSTR wszLocalVolumeEntryPath,
  45. LPWSTR wszLocalVolumeGuid,
  46. LPDFSM_RELATION_INFO *ppDfsmRelationInfo);
  47. VOID
  48. DfspValidateLocalPartition(
  49. LPWSTR wszLocalVolumeEntryPath,
  50. LPWSTR wszLocalVolumeGuid,
  51. LPDFSM_RELATION_INFO pDfsmRelationInfo);
  52. VOID
  53. DfspPruneLocalPartition(
  54. LPWSTR wszLocalVolumeEntryPath,
  55. LPWSTR wszLocalVolumeGuid);
  56. VOID StringToGuid(
  57. IN PWSTR pwszGuid,
  58. OUT GUID *pGuid);
  59. BOOLEAN
  60. DfspGetCoveredSiteInfo(
  61. LPWSTR ServerName,
  62. LPDFS_SITELIST_INFO *ppSiteInfo);
  63. //+----------------------------------------------------------------------------
  64. //
  65. // Function: DfsManagerValidateLocalVolumes
  66. //
  67. // Synopsis: Validates the relation info of all local volumes with the
  68. // Dfs Root server
  69. //
  70. // Arguments: None
  71. //
  72. // Returns: TRUE if validation attempt succeeded, FALSE if could not
  73. // validate all local volumes
  74. //
  75. //-----------------------------------------------------------------------------
  76. extern "C" BOOLEAN
  77. DfsManagerValidateLocalVolumes()
  78. {
  79. DWORD dwErr, i;
  80. HKEY hkeyLv, hkeyThisLv;
  81. WCHAR wszLocalVolGuid[ 2 * sizeof(GUID) + 1 ];
  82. BOOLEAN fValidateNextVolume;
  83. BOOLEAN fHaveCoveredSiteInfo;
  84. LPDFS_SITELIST_INFO pSiteInfo = NULL;
  85. if (pwszComputerName == NULL)
  86. return FALSE;
  87. //
  88. // Get covered site info
  89. //
  90. fHaveCoveredSiteInfo = DfspGetCoveredSiteInfo(
  91. pwszComputerName,
  92. &pSiteInfo);
  93. //
  94. // For each local volume, ask the root for its relation info and then
  95. // fsctl it down to the driver so it can validate its relation info.
  96. //
  97. IDfsVolInlineDebOut((DEB_TRACE, "DfsManagerValidateLocalVolumes()\n"));
  98. dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES, &hkeyLv);
  99. if (dwErr != ERROR_SUCCESS) {
  100. if (fHaveCoveredSiteInfo == TRUE) {
  101. MIDL_user_free(pSiteInfo);
  102. }
  103. return( FALSE );
  104. }
  105. i = 0;
  106. do {
  107. WCHAR wszEntryPath[MAX_PATH + 1];
  108. LPDFSM_RELATION_INFO pDfsmRelationInfo;
  109. fValidateNextVolume = TRUE;
  110. //
  111. // Local volumes are stored with their stringized guids as key names
  112. //
  113. dwErr = RegEnumKey(
  114. hkeyLv,
  115. i,
  116. wszLocalVolGuid,
  117. sizeof(wszLocalVolGuid) );
  118. if (dwErr == ERROR_SUCCESS) {
  119. dwErr = RegOpenKey(hkeyLv, wszLocalVolGuid, &hkeyThisLv);
  120. if (dwErr == ERROR_SUCCESS) {
  121. DWORD cbBuffer = sizeof(wszEntryPath);
  122. DWORD dwType;
  123. dwErr = RegQueryValueEx(
  124. hkeyThisLv,
  125. REG_VALUE_ENTRY_PATH,
  126. NULL,
  127. &dwType,
  128. (LPBYTE) wszEntryPath,
  129. &cbBuffer);
  130. RegCloseKey( hkeyThisLv );
  131. }
  132. } else if (dwErr == ERROR_NO_MORE_ITEMS) {
  133. fValidateNextVolume = FALSE;
  134. }
  135. if (dwErr == ERROR_SUCCESS) {
  136. dwErr = DfspGetRemoteConfigInfo(
  137. wszEntryPath,
  138. wszLocalVolGuid,
  139. &pDfsmRelationInfo);
  140. switch (dwErr) {
  141. case ERROR_SUCCESS:
  142. DfspValidateLocalPartition(
  143. wszEntryPath,
  144. wszLocalVolGuid,
  145. pDfsmRelationInfo);
  146. NetApiBufferFree(pDfsmRelationInfo);
  147. break;
  148. case NERR_DfsNoSuchVolume:
  149. case NERR_DfsNoSuchShare:
  150. DfspPruneLocalPartition(
  151. wszEntryPath,
  152. wszLocalVolGuid);
  153. break;
  154. case ERROR_NOT_ENOUGH_MEMORY:
  155. break;
  156. default:
  157. fValidateNextVolume = FALSE;
  158. break;
  159. }
  160. //
  161. // Tell the root what sites we cover
  162. //
  163. if (fHaveCoveredSiteInfo == TRUE && pwszComputerName != NULL) {
  164. NetDfsManagerSendSiteInfo(
  165. pwszComputerName, // Who's sending this
  166. wszEntryPath, // The dfs root to send to
  167. pSiteInfo); // the site info itself
  168. }
  169. }
  170. i++;
  171. } while ( fValidateNextVolume );
  172. RegCloseKey( hkeyLv );
  173. if (fHaveCoveredSiteInfo == TRUE) {
  174. MIDL_user_free(pSiteInfo);
  175. }
  176. IDfsVolInlineDebOut((DEB_TRACE, "DfsManagerValidateLocalVolumes: i=%d on exit\n", i));
  177. return( TRUE );
  178. }
  179. BOOLEAN
  180. DfspGetCoveredSiteInfo(
  181. LPWSTR ServerName,
  182. LPDFS_SITELIST_INFO *ppSiteInfo)
  183. {
  184. DWORD status;
  185. LPWSTR ThisSite;
  186. LPWSTR CoveredSites = NULL;
  187. LPDFS_SITELIST_INFO pSiteInfo = NULL;
  188. ULONG Size;
  189. ULONG cSites;
  190. LPWSTR pSiteName;
  191. LPWSTR pNames;
  192. ULONG iSite;
  193. ULONG j;
  194. DWORD dwType;
  195. DWORD dwUnused;
  196. ULONG cbBuffer;
  197. HKEY hkey;
  198. BOOLEAN fUsingDefault = TRUE;
  199. status = RegOpenKey(
  200. HKEY_LOCAL_MACHINE,
  201. REG_KEY_COVERED_SITES,
  202. &hkey);
  203. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegOpenKey,
  204. LOGSTATUS(status)
  205. LOGWSTR(ServerName));
  206. if (status == ERROR_SUCCESS) {
  207. status = RegQueryInfoKey(
  208. hkey, // Key
  209. NULL, // Class string
  210. NULL, // Size of class string
  211. NULL, // Reserved
  212. &dwUnused, // # of subkeys
  213. &dwUnused, // max size of subkey name
  214. &dwUnused, // max size of class name
  215. &dwUnused, // # of values
  216. &dwUnused, // max size of value name
  217. &cbBuffer, // max size of value data,
  218. NULL, // security descriptor
  219. NULL); // Last write time
  220. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryInfoKey,
  221. LOGSTATUS(status)
  222. LOGWSTR(ServerName));
  223. //
  224. // Check if there's a value the same name as the servername passed in,
  225. // if so, use it. Else default to value REG_VALUE_COVERED_SITES.
  226. //
  227. if (status == ERROR_SUCCESS) {
  228. CoveredSites = (LPWSTR)MIDL_user_allocate(cbBuffer);
  229. if (CoveredSites != NULL) {
  230. status = RegQueryValueEx(
  231. hkey,
  232. ServerName,
  233. NULL,
  234. &dwType,
  235. (PUCHAR)CoveredSites,
  236. &cbBuffer);
  237. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryValueEx,
  238. LOGSTATUS(status)
  239. LOGWSTR(ServerName));
  240. if (status == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
  241. fUsingDefault = FALSE;
  242. } else {
  243. status = RegQueryValueEx(
  244. hkey,
  245. REG_VALUE_COVERED_SITES,
  246. NULL,
  247. &dwType,
  248. (PUCHAR)CoveredSites,
  249. &cbBuffer);
  250. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryValueEx2,
  251. LOGSTATUS(status)
  252. LOGWSTR(ServerName));
  253. if ( status != ERROR_SUCCESS || dwType != REG_MULTI_SZ) {
  254. MIDL_user_free(CoveredSites);
  255. CoveredSites = NULL;
  256. }
  257. }
  258. }
  259. }
  260. RegCloseKey( hkey );
  261. }
  262. //
  263. // Size the return buffer
  264. //
  265. Size = 0;
  266. for (cSites = 0, pNames = CoveredSites; pNames && *pNames; cSites++) {
  267. Size += (wcslen(pNames) + 1) * sizeof(WCHAR);
  268. pNames += wcslen(pNames) + 1;
  269. }
  270. //
  271. // Get site we belong to, if we're using the defaults
  272. //
  273. ThisSite = NULL;
  274. if (fUsingDefault == TRUE) {
  275. status = DsGetSiteName(NULL, &ThisSite);
  276. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_DsGetSiteName,
  277. LOGSTATUS(status)
  278. LOGWSTR(ServerName));
  279. if (status == NO_ERROR && ThisSite != NULL) {
  280. Size += (wcslen(ThisSite) + 1) * sizeof(WCHAR);
  281. cSites++;
  282. }
  283. }
  284. //
  285. // If no sites are configured, and we couldn't determine our site,
  286. // then we fail.
  287. //
  288. if (cSites == 0) {
  289. goto ErrorReturn;
  290. }
  291. Size += FIELD_OFFSET(DFS_SITELIST_INFO,Site[cSites]);
  292. pSiteInfo = (LPDFS_SITELIST_INFO)MIDL_user_allocate(Size);
  293. if (pSiteInfo == NULL) {
  294. goto ErrorReturn;
  295. }
  296. RtlZeroMemory(pSiteInfo, Size);
  297. pSiteInfo->cSites = cSites;
  298. pSiteName = (LPWSTR) ((PCHAR)pSiteInfo +
  299. sizeof(DFS_SITELIST_INFO) +
  300. sizeof(DFS_SITENAME_INFO) * (cSites - 1));
  301. //
  302. // Marshall the site strings into the buffer
  303. //
  304. iSite = 0;
  305. if (ThisSite != NULL) {
  306. wcscpy(pSiteName, ThisSite);
  307. pSiteInfo->Site[iSite].SiteFlags = DFS_SITE_PRIMARY;
  308. pSiteInfo->Site[iSite++].SiteName = pSiteName;
  309. pSiteName += wcslen(ThisSite) + 1;
  310. }
  311. for (pNames = CoveredSites; pNames && *pNames; pNames += wcslen(pNames) + 1) {
  312. wcscpy(pSiteName, pNames);
  313. pSiteInfo->Site[iSite++].SiteName = pSiteName;
  314. pSiteName += wcslen(pSiteName) + 1;
  315. }
  316. *ppSiteInfo = pSiteInfo;
  317. if (CoveredSites != NULL) {
  318. MIDL_user_free(CoveredSites);
  319. }
  320. return TRUE;
  321. ErrorReturn:
  322. //
  323. // Free anything we allocated
  324. //
  325. if (pSiteInfo != NULL) {
  326. MIDL_user_free(pSiteInfo);
  327. }
  328. if (CoveredSites != NULL) {
  329. MIDL_user_free(CoveredSites);
  330. }
  331. return FALSE;
  332. }
  333. //+----------------------------------------------------------------------------
  334. //
  335. // Function: DfspGetRemoteConfigInfo
  336. //
  337. // Synopsis: Gets the config info for a local volume from the Dfs root
  338. // server.
  339. //
  340. // Arguments: [wszLocalVolumeEntryPath] -- Entry path of local volume.
  341. //
  342. // [wszLocalVolumeGuid] -- Stringized guid of local volume.
  343. //
  344. // [ppDfsmRelationInfo] -- On successful return, contains pointer
  345. // to allocated DFSM_RELATION_INFO structure.
  346. //
  347. // Returns: Error code from NetDfsManagerGetConfigInfo or
  348. //
  349. //-----------------------------------------------------------------------------
  350. DWORD
  351. DfspGetRemoteConfigInfo(
  352. LPWSTR wszLocalVolumeEntryPath,
  353. LPWSTR wszLocalVolumeGuid,
  354. LPDFSM_RELATION_INFO *ppDfsmRelationInfo)
  355. {
  356. DWORD dwErr;
  357. GUID guidLocalVolume;
  358. if (pwszComputerName == NULL)
  359. return ERROR_INVALID_PARAMETER;
  360. StringToGuid( wszLocalVolumeGuid, &guidLocalVolume );
  361. dwErr = NetDfsManagerGetConfigInfo(
  362. pwszComputerName,
  363. wszLocalVolumeEntryPath,
  364. guidLocalVolume,
  365. ppDfsmRelationInfo);
  366. DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR, DfspGetRemoteConfigInfo_Error_NetDfsManagerGetConfigInfo,
  367. LOGSTATUS(dwErr)
  368. LOGWSTR(wszLocalVolumeEntryPath));
  369. return( dwErr );
  370. }
  371. //+----------------------------------------------------------------------------
  372. //
  373. // Function: DfspValidateLocalPartition
  374. //
  375. // Synopsis: Given a remote config info, this API will fsctl to the local
  376. // dfs driver to take actions and match up its local volume info
  377. // with the remote one.
  378. //
  379. // Arguments: [wszLocalVolumeEntryPath] -- local volume entry path to
  380. // validate
  381. // [wszLocalVolumeGuid] -- Guid of local volume to validate
  382. // [pDfsmRelationInfo] -- The DFSM_RELATION_INFO that this local
  383. // volume should have.
  384. //
  385. // Returns: Nothing
  386. //
  387. //-----------------------------------------------------------------------------
  388. VOID
  389. DfspValidateLocalPartition(
  390. LPWSTR wszLocalVolumeEntryPath,
  391. LPWSTR wszLocalVolumeGuid,
  392. LPDFSM_RELATION_INFO pDfsmRelationInfo)
  393. {
  394. DFS_PKT_RELATION_INFO DfsRelationInfo;
  395. DWORD i;
  396. //
  397. // Massage the DFSM_RELATION_INFO into a DFS_PKT_RELATION_INFO
  398. //
  399. StringToGuid( wszLocalVolumeGuid, &DfsRelationInfo.EntryId.Uid );
  400. RtlInitUnicodeString(
  401. &DfsRelationInfo.EntryId.Prefix,
  402. wszLocalVolumeEntryPath);
  403. RtlInitUnicodeString( &DfsRelationInfo.EntryId.ShortPrefix, NULL );
  404. DfsRelationInfo.SubordinateIdList =
  405. new DFS_PKT_ENTRY_ID[ pDfsmRelationInfo->cSubordinates ];
  406. if (DfsRelationInfo.SubordinateIdList == NULL)
  407. return;
  408. DfsRelationInfo.SubordinateIdCount = pDfsmRelationInfo->cSubordinates;
  409. for (i = 0; i < pDfsmRelationInfo->cSubordinates; i++) {
  410. DfsRelationInfo.SubordinateIdList[i].Uid =
  411. pDfsmRelationInfo->eid[i].idSubordinate;
  412. RtlInitUnicodeString(
  413. &DfsRelationInfo.SubordinateIdList[i].Prefix,
  414. pDfsmRelationInfo->eid[i].wszSubordinate);
  415. RtlInitUnicodeString(
  416. &DfsRelationInfo.SubordinateIdList[i].ShortPrefix,
  417. NULL);
  418. }
  419. PktValidateLocalVolumeInfo( &DfsRelationInfo );
  420. }
  421. //+----------------------------------------------------------------------------
  422. //
  423. // Function: DfspPruneLocalPartition
  424. //
  425. // Synopsis: Deletes a local volume that the root server says is an extra
  426. // volume.
  427. //
  428. // Arguments: [wszLocalVolumeEntryPath] -- local volume entry path to
  429. // delete
  430. // [wszLocalVolumeGuid] -- Guid of local volume to delete
  431. //
  432. // Returns: Nothing
  433. //
  434. //-----------------------------------------------------------------------------
  435. VOID
  436. DfspPruneLocalPartition(
  437. LPWSTR wszLocalVolumeEntryPath,
  438. LPWSTR wszLocalVolumeGuid)
  439. {
  440. DFS_PKT_ENTRY_ID EntryId;
  441. RtlZeroMemory(&EntryId, sizeof(EntryId));
  442. StringToGuid( wszLocalVolumeGuid, &EntryId.Uid );
  443. RtlInitUnicodeString( &EntryId.Prefix, wszLocalVolumeEntryPath );
  444. PktPruneLocalPartition( &EntryId );
  445. }
  446. //+----------------------------------------------------------------------------
  447. //
  448. // Function: StringToGuid
  449. //
  450. // Synopsis: Converts a 32 wchar null terminated string to a GUID.
  451. //
  452. // Arguments: [pwszGuid] -- the string to convert
  453. // [pGuid] -- Pointer to destination GUID.
  454. //
  455. // Returns: Nothing
  456. //
  457. //-----------------------------------------------------------------------------
  458. #define HEX_DIGIT_TO_INT(d, i) \
  459. ASSERT(((d) >= L'0' && (d) <= L'9') || \
  460. ((d) >= L'A' && (d) <= L'F')); \
  461. if ((d) <= L'9') { \
  462. i = (d) - L'0'; \
  463. } else { \
  464. i = (d) - L'A' + 10; \
  465. }
  466. VOID StringToGuid(
  467. IN PWSTR pwszGuid,
  468. OUT GUID *pGuid)
  469. {
  470. PBYTE pbBuffer = (PBYTE) pGuid;
  471. USHORT i, n;
  472. for (i = 0; i < sizeof(GUID); i++) {
  473. HEX_DIGIT_TO_INT(pwszGuid[2 * i], n);
  474. pbBuffer[i] = n << 4;
  475. HEX_DIGIT_TO_INT(pwszGuid[2 * i + 1], n);
  476. pbBuffer[i] |= n;
  477. }
  478. }