Leaked source code of windows server 2003
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.

549 lines
15 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: dfsCompCheck.c
  6. //
  7. // Contents: Checks if the existing DFS root is compatible with Windows XP server.
  8. //
  9. // History: Aug. 8 2001, Author: navjotv, some code picked up from other dfs source code files.
  10. //
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include "dfsCompCheck.hxx"
  14. BOOLEAN
  15. IsNTFS(
  16. PFILE_FS_ATTRIBUTE_INFORMATION pInfo);
  17. LPWSTR DfsOldStandaloneChild = L"domainroot";
  18. LPWSTR DfsOldRegistryLocation = L"SOFTWARE\\Microsoft\\DfsHost\\volumes";
  19. LPWSTR DfsLogicalShareValueName = L"LogicalShare";
  20. LPWSTR DfsRootShareValueName = L"RootShare";
  21. //+-------------------------------------------------------------------------
  22. //
  23. // Function: CompatibilityCheck
  24. //
  25. // Arguments: CompatibilityCallback - function to call if a compatibility problem is found
  26. // Context
  27. //
  28. // Returns: TRUE on success
  29. // FALSE otherwise
  30. //
  31. //
  32. // Description: Check if existing DFS root will be supported after system upgarde.
  33. //
  34. //--------------------------------------------------------------------------
  35. BOOLEAN
  36. APIENTRY
  37. CompatibilityCheck(PCOMPAIBILITYCALLBACK CompatibilityCallback, LPVOID Context)
  38. {
  39. DFSSTATUS Status = ERROR_SUCCESS;
  40. NTSTATUS NtStatus = STATUS_SUCCESS;
  41. HKEY OldStandaloneDfsKey;
  42. BOOLEAN MachineContacted = FALSE;
  43. ULONG pAttribInfoSize;
  44. PFILE_FS_ATTRIBUTE_INFORMATION pAttribInfo = NULL;
  45. OBJECT_ATTRIBUTES ObjectAttributes;
  46. IO_STATUS_BLOCK IoStatusBlock;
  47. UNICODE_STRING DirectoryName;
  48. HANDLE DirHandle = NULL;
  49. UNICODE_STRING PhysicalShare;
  50. BOOLEAN ReturnVal = FALSE;
  51. COMPATIBILITY_ENTRY CompEntry;
  52. CompEntry.Description = L"The current DFS root hosted on this server will not be supported after this system upgrade";
  53. CompEntry.HtmlName = L"compdata\\dfsComp.htm";
  54. CompEntry.TextName = L"compdata\\dfsComp.txt";
  55. CompEntry.RegKeyName = NULL;
  56. CompEntry.RegValName = NULL;
  57. CompEntry.RegValDataSize = NULL;
  58. CompEntry.RegValData = NULL;
  59. CompEntry.SaveValue = NULL;
  60. CompEntry.Flags = 0x00000000;
  61. CompEntry.InfName = NULL;
  62. CompEntry.InfSection = NULL;
  63. printf("\n dfsCompCheck:: Entering CompatibilityCheck");
  64. Status = GetOldDfsRegistryKey( L"",
  65. FALSE,
  66. &MachineContacted,
  67. &OldStandaloneDfsKey );
  68. // If we cn open this registry key, then we know that this machine
  69. //has old style DFS.
  70. if (Status == ERROR_SUCCESS)
  71. {
  72. Status = GetRootPhysicalShare(OldStandaloneDfsKey,
  73. &PhysicalShare);
  74. if (Status == ERROR_SUCCESS)
  75. {
  76. Status = DfsGetSharePath(L"",
  77. PhysicalShare.Buffer,
  78. &DirectoryName);
  79. if ( (DirectoryName.Buffer == NULL) ||
  80. (DirectoryName.Length == 0) )
  81. {
  82. Status = ERROR_INVALID_PARAMETER;
  83. }
  84. ReleaseRootPhysicalShare(&PhysicalShare);
  85. if (Status == ERROR_SUCCESS)
  86. {
  87. //why MAX_PATH??
  88. pAttribInfoSize = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH;
  89. pAttribInfo = (PFILE_FS_ATTRIBUTE_INFORMATION) new BYTE [pAttribInfoSize];
  90. if (pAttribInfo != NULL)
  91. {
  92. InitializeObjectAttributes ( &ObjectAttributes,
  93. &DirectoryName,
  94. OBJ_CASE_INSENSITIVE, //Attributes
  95. NULL, //Root handle
  96. NULL ); //Security descriptor.
  97. NtStatus = NtOpenFile( &DirHandle,
  98. (ACCESS_MASK)FILE_LIST_DIRECTORY | SYNCHRONIZE,
  99. &ObjectAttributes,
  100. &IoStatusBlock,
  101. FILE_SHARE_READ | FILE_SHARE_WRITE,
  102. FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT );
  103. if (NtStatus == STATUS_SUCCESS)
  104. {
  105. //
  106. // Query for the basic information, which has the attributes.
  107. //
  108. NtStatus = NtQueryVolumeInformationFile( DirHandle,
  109. &IoStatusBlock,
  110. pAttribInfo,
  111. pAttribInfoSize,
  112. FileFsAttributeInformation );
  113. if (NtStatus == STATUS_SUCCESS)
  114. {
  115. //
  116. // If the attributes indicate reparse point, we have a reparse
  117. // point directory on our hands.
  118. //
  119. if ( (pAttribInfo->FileSystemAttributes & FILE_SUPPORTS_REPARSE_POINTS) == 0
  120. && !IsNTFS(pAttribInfo))
  121. {
  122. NtStatus = STATUS_NOT_SUPPORTED;
  123. CompatibilityCallback(&CompEntry, Context);
  124. ReturnVal = FALSE;
  125. }
  126. else
  127. {
  128. ReturnVal = TRUE;
  129. }
  130. }
  131. CloseHandle (DirHandle);
  132. delete [] pAttribInfo;
  133. }
  134. }
  135. }
  136. }
  137. }
  138. else
  139. {
  140. //Does not have old DFS
  141. ReturnVal = TRUE;
  142. }
  143. return ReturnVal;
  144. }
  145. //+-------------------------------------------------------------------------
  146. //
  147. // Function: GetOldStandaloneRegistryKey
  148. //
  149. // Arguments:
  150. //
  151. // Returns: SUCCESS or error
  152. //
  153. // Description: Checks if Old Standalone DFS registry key exists.
  154. //
  155. //
  156. //--------------------------------------------------------------------------
  157. static
  158. DFSSTATUS
  159. GetOldStandaloneRegistryKey( IN LPWSTR MachineName,
  160. BOOLEAN WritePermission,
  161. OUT BOOLEAN *pMachineContacted,
  162. OUT PHKEY pDfsRegKey )
  163. {
  164. DFSSTATUS Status;
  165. HKEY DfsKey;
  166. Status = GetOldDfsRegistryKey (MachineName,
  167. WritePermission,
  168. pMachineContacted,
  169. &DfsKey );
  170. if (Status == ERROR_SUCCESS)
  171. {
  172. Status = RegOpenKeyEx( DfsKey,
  173. DfsOldStandaloneChild,
  174. 0,
  175. KEY_READ | (WritePermission ? KEY_WRITE : 0),
  176. pDfsRegKey );
  177. RegCloseKey( DfsKey);
  178. }
  179. return Status;
  180. }
  181. //+-------------------------------------------------------------------------
  182. //
  183. // Function: GetOldDfsRegistryKey
  184. //
  185. // Arguments:
  186. //
  187. // Returns: SUCCESS or error
  188. //
  189. // Description: Checks if Old DFS registry key exists.
  190. //
  191. //
  192. //--------------------------------------------------------------------------
  193. static
  194. DFSSTATUS
  195. GetOldDfsRegistryKey( IN LPWSTR MachineName,
  196. BOOLEAN WritePermission,
  197. OUT BOOLEAN *pMachineContacted,
  198. OUT PHKEY pDfsRegKey )
  199. {
  200. return GetDfsRegistryKey (MachineName,
  201. DfsOldRegistryLocation,
  202. WritePermission,
  203. pMachineContacted,
  204. pDfsRegKey );
  205. }
  206. //+-------------------------------------------------------------------------
  207. //
  208. // Function: GetDfsRegistryKey
  209. //
  210. // Arguments:
  211. //
  212. // Returns: SUCCESS or error
  213. //
  214. // Description:
  215. // Function GetDfsRegistryKey: This function takes a Name as the input,
  216. // and looks up all DFS roots in that namespace.
  217. //
  218. //--------------------------------------------------------------------------
  219. static
  220. DFSSTATUS
  221. GetDfsRegistryKey( IN LPWSTR MachineName,
  222. IN LPWSTR LocationString,
  223. BOOLEAN WritePermission,
  224. OUT BOOLEAN *pMachineContacted,
  225. OUT PHKEY pDfsRegKey )
  226. {
  227. DFSSTATUS Status;
  228. HKEY RootKey;
  229. BOOLEAN Contacted = FALSE;
  230. LPWSTR UseMachineName = NULL;
  231. REGSAM DesiredAccess = KEY_READ;
  232. if (WritePermission == TRUE)
  233. {
  234. DesiredAccess |= KEY_WRITE;
  235. }
  236. if (IsEmptyString(MachineName) == FALSE) {
  237. UseMachineName = MachineName;
  238. }
  239. Status = RegConnectRegistry( UseMachineName,
  240. HKEY_LOCAL_MACHINE,
  241. &RootKey );
  242. if ( Status == ERROR_SUCCESS )
  243. {
  244. Contacted = TRUE;
  245. Status = RegOpenKeyEx( RootKey,
  246. LocationString,
  247. 0,
  248. DesiredAccess,
  249. pDfsRegKey );
  250. //
  251. // There appears to be a bug in the registry code. When
  252. // we connect to the local machine, the key that is returned
  253. // in the RegConnectRegistry is HKEY_LOCAL_MACHINE. If we
  254. // then attempt to close it here, it affects other threads
  255. // that are using this code: they get STATUS_INVALID_HANDLE
  256. // in some cases. So, dont close the key if it is
  257. // HKEY_LOCAL_MACHINE.
  258. //
  259. if (RootKey != HKEY_LOCAL_MACHINE)
  260. {
  261. RegCloseKey( RootKey );
  262. }
  263. }
  264. if (pMachineContacted != NULL)
  265. {
  266. *pMachineContacted = Contacted;
  267. }
  268. return Status;
  269. }
  270. //+-------------------------------------------------------------------------
  271. //
  272. // Function: GetRootPhysicalShare
  273. //
  274. // Arguments:
  275. //
  276. // Returns: SUCCESS or error
  277. //
  278. // Description: Gets the value of the DFS root share
  279. //
  280. //
  281. //--------------------------------------------------------------------------
  282. DFSSTATUS
  283. GetRootPhysicalShare(
  284. HKEY RootKey,
  285. PUNICODE_STRING pRootPhysicalShare )
  286. {
  287. DFSSTATUS Status;
  288. ULONG DataSize, DataType;
  289. LPWSTR DfsRootShare = NULL;
  290. Status = RegQueryInfoKey( RootKey, // Key
  291. NULL, // Class string
  292. NULL, // Size of class string
  293. NULL, // Reserved
  294. NULL, // # of subkeys
  295. NULL, // max size of subkey name
  296. NULL, // max size of class name
  297. NULL, // # of values
  298. NULL, // max size of value name
  299. &DataSize, // max size of value data,
  300. NULL, // security descriptor
  301. NULL ); // Last write time
  302. if (Status == ERROR_SUCCESS)
  303. {
  304. DfsRootShare = (LPWSTR) new BYTE [DataSize];
  305. if ( DfsRootShare == NULL )
  306. {
  307. Status = ERROR_NOT_ENOUGH_MEMORY;
  308. } else
  309. {
  310. Status = RegQueryValueEx( RootKey,
  311. DfsRootShareValueName,
  312. NULL,
  313. &DataType,
  314. (LPBYTE)DfsRootShare,
  315. &DataSize );
  316. }
  317. }
  318. if (Status == ERROR_SUCCESS)
  319. {
  320. if (DataType == REG_SZ)
  321. {
  322. RtlInitUnicodeString( pRootPhysicalShare, DfsRootShare );
  323. }
  324. else {
  325. Status = STATUS_INVALID_PARAMETER;
  326. }
  327. }
  328. if (Status != ERROR_SUCCESS)
  329. {
  330. if (DfsRootShare != NULL)
  331. {
  332. delete [] DfsRootShare;
  333. }
  334. }
  335. return Status;
  336. }
  337. //+-------------------------------------------------------------------------
  338. //
  339. // Function: ReleaseRootPhysicalShare
  340. //
  341. // Arguments:
  342. //
  343. // Returns:
  344. //
  345. // Description: Releases memory for pRootPhysicalShare->Buffer.
  346. //
  347. //
  348. //--------------------------------------------------------------------------
  349. VOID
  350. ReleaseRootPhysicalShare(
  351. PUNICODE_STRING pRootPhysicalShare )
  352. {
  353. delete [] pRootPhysicalShare->Buffer;
  354. }
  355. //+-------------------------------------------------------------------------
  356. //
  357. // Function: DfsGetSharePath
  358. //
  359. // Arguments: ServerName - the name of the server
  360. // ShareName - the name of the share
  361. // pPathName - the unicode string representing the NT name
  362. // of the local path representing the share
  363. //
  364. // Returns: SUCCESS or error
  365. //
  366. // Description: This routine takes a servername and a sharename, and
  367. // returns an NT pathname to the physical resource that is
  368. // backing the share name.
  369. //
  370. //--------------------------------------------------------------------------
  371. DFSSTATUS
  372. DfsGetSharePath(
  373. IN LPWSTR ServerName,
  374. IN LPWSTR ShareName,
  375. OUT PUNICODE_STRING pPathName )
  376. {
  377. LPWSTR UseServerName = NULL;
  378. ULONG InfoLevel = 2;
  379. PSHARE_INFO_2 pShareInfo;
  380. NET_API_STATUS NetStatus;
  381. DFSSTATUS Status;
  382. UNICODE_STRING NtSharePath;
  383. if (IsEmptyString(ServerName) == FALSE)
  384. {
  385. UseServerName = ServerName;
  386. }
  387. NetStatus = NetShareGetInfo( UseServerName,
  388. ShareName,
  389. InfoLevel,
  390. (LPBYTE *)&pShareInfo );
  391. if (NetStatus != ERROR_SUCCESS)
  392. {
  393. Status = (DFSSTATUS)NetStatus;
  394. return Status;
  395. }
  396. if( RtlDosPathNameToNtPathName_U(pShareInfo->shi2_path,
  397. &NtSharePath,
  398. NULL,
  399. NULL ) == TRUE )
  400. {
  401. Status = DfsCreateUnicodeString( pPathName,
  402. &NtSharePath );
  403. RtlFreeUnicodeString( &NtSharePath );
  404. }
  405. else {
  406. Status = ERROR_NOT_ENOUGH_MEMORY;
  407. }
  408. NetApiBufferFree( pShareInfo );
  409. return Status;
  410. }
  411. //+-------------------------------------------------------------------------
  412. //
  413. // Function: DfsCreateUnicodeString
  414. //
  415. // Arguments: pDest - the destination unicode string
  416. // pSrc - the source unicode string
  417. //
  418. // Returns: SUCCESS or error
  419. //
  420. // Description: This routine creates a new unicode string that is a copy
  421. // of the original. The copied unicode string has a buffer
  422. // that is null terminated, so the buffer can be used as a
  423. // normal string if necessary.
  424. //
  425. //--------------------------------------------------------------------------
  426. DFSSTATUS
  427. DfsCreateUnicodeString(
  428. PUNICODE_STRING pDest,
  429. PUNICODE_STRING pSrc )
  430. {
  431. LPWSTR NewString;
  432. NewString = (LPWSTR) malloc(pSrc->Length + sizeof(WCHAR));
  433. if ( NewString == NULL )
  434. {
  435. return ERROR_NOT_ENOUGH_MEMORY;
  436. }
  437. RtlCopyMemory( NewString, pSrc->Buffer, pSrc->Length);
  438. NewString[ pSrc->Length / sizeof(WCHAR)] = UNICODE_NULL;
  439. RtlInitUnicodeString( pDest, NewString );
  440. return ERROR_SUCCESS;
  441. }
  442. //+-------------------------------------------------------------------------
  443. //
  444. // Function: IsNTFS
  445. //
  446. // Arguments: pInfo
  447. //
  448. // Returns: True - if NTFS
  449. // False - if not NTFS
  450. //
  451. // Description: Checks if filesystem is NTFS
  452. //
  453. //--------------------------------------------------------------------------
  454. BOOLEAN
  455. IsNTFS(
  456. PFILE_FS_ATTRIBUTE_INFORMATION pInfo)
  457. {
  458. if (pInfo->FileSystemNameLength == 8 &&
  459. pInfo->FileSystemName[0] == 'N' &&
  460. pInfo->FileSystemName[1] == 'T' &&
  461. pInfo->FileSystemName[2] == 'F' &&
  462. pInfo->FileSystemName[3] == 'S')
  463. return TRUE;
  464. else
  465. return FALSE;
  466. }