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.

664 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. reparse.c
  5. Abstract:
  6. This file contains code for commands that affect
  7. reparse points.
  8. Author:
  9. Wesley Witt [wesw] 1-March-2000
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. INT
  14. ReparseHelp(
  15. IN INT argc,
  16. IN PWSTR argv[]
  17. )
  18. {
  19. DisplayMsg( MSG_USAGE_REPARSEPOINT );
  20. return EXIT_CODE_SUCCESS;
  21. }
  22. //
  23. // This is the definition of the DATA portion of the SIS reparse buffer.
  24. //
  25. #define SIS_REPARSE_BUFFER_FORMAT_VERSION 5
  26. typedef struct _SIS_REPARSE_BUFFER {
  27. ULONG ReparsePointFormatVersion;
  28. ULONG Reserved;
  29. //
  30. // The id of the common store file.
  31. //
  32. GUID CSid;
  33. //
  34. // The index of this link file.
  35. //
  36. LARGE_INTEGER LinkIndex;
  37. //
  38. // The file ID of the link file.
  39. //
  40. LARGE_INTEGER LinkFileNtfsId;
  41. //
  42. // The file ID of the common store file.
  43. //
  44. LARGE_INTEGER CSFileNtfsId;
  45. //
  46. // A "131 hash" checksum of the contents of the
  47. // common store file.
  48. //
  49. LARGE_INTEGER CSChecksum;
  50. //
  51. // A "131 hash" checksum of this structure.
  52. // N.B. Must be last.
  53. //
  54. LARGE_INTEGER Checksum;
  55. } SIS_REPARSE_BUFFER, *PSIS_REPARSE_BUFFER;
  56. INT
  57. DisplaySISReparsePointData(
  58. PREPARSE_DATA_BUFFER ReparseData
  59. )
  60. /*++
  61. Routine Description:
  62. This routine displays the SIS reparse data
  63. Arguments:
  64. Return Value:
  65. None
  66. --*/
  67. {
  68. PSIS_REPARSE_BUFFER sisRp;
  69. WCHAR csID[40];
  70. //
  71. // Point to the SIS unique portion of the buffer
  72. //
  73. sisRp = (PSIS_REPARSE_BUFFER)&ReparseData->GenericReparseBuffer.DataBuffer;
  74. DisplayMsg( MSG_SIS_REPARSE_INFO,
  75. sisRp->ReparsePointFormatVersion,
  76. Guid2Str( &sisRp->CSid, csID, sizeof(csID) ),
  77. sisRp->LinkIndex.HighPart,
  78. sisRp->LinkIndex.LowPart,
  79. sisRp->LinkFileNtfsId.HighPart,
  80. sisRp->LinkFileNtfsId.LowPart,
  81. sisRp->CSFileNtfsId.HighPart,
  82. sisRp->CSFileNtfsId.LowPart,
  83. sisRp->CSChecksum.HighPart,
  84. sisRp->CSChecksum.LowPart,
  85. sisRp->Checksum.HighPart,
  86. sisRp->Checksum.LowPart);
  87. return EXIT_CODE_SUCCESS;
  88. }
  89. //
  90. // Placeholder data - all versions unioned together
  91. //
  92. #define RP_RESV_SIZE 52
  93. typedef struct _RP_PRIVATE_DATA {
  94. CHAR reserved[RP_RESV_SIZE]; // Must be 0
  95. ULONG bitFlags; // bitflags indicating status of the segment
  96. LARGE_INTEGER migrationTime; // When migration occurred
  97. GUID hsmId;
  98. GUID bagId;
  99. LARGE_INTEGER fileStart;
  100. LARGE_INTEGER fileSize;
  101. LARGE_INTEGER dataStart;
  102. LARGE_INTEGER dataSize;
  103. LARGE_INTEGER fileVersionId;
  104. LARGE_INTEGER verificationData;
  105. ULONG verificationType;
  106. ULONG recallCount;
  107. LARGE_INTEGER recallTime;
  108. LARGE_INTEGER dataStreamStart;
  109. LARGE_INTEGER dataStreamSize;
  110. ULONG dataStream;
  111. ULONG dataStreamCRCType;
  112. LARGE_INTEGER dataStreamCRC;
  113. } RP_PRIVATE_DATA, *PRP_PRIVATE_DATA;
  114. typedef struct _RP_DATA {
  115. GUID vendorId; // Unique HSM vendor ID -- This is first to match REPARSE_GUID_DATA_BUFFER
  116. ULONG qualifier; // Used to checksum the data
  117. ULONG version; // Version of the structure
  118. ULONG globalBitFlags; // bitflags indicating status of the file
  119. ULONG numPrivateData; // number of private data entries
  120. GUID fileIdentifier; // Unique file ID
  121. RP_PRIVATE_DATA data; // Vendor specific data
  122. } RP_DATA, *PRP_DATA;
  123. INT
  124. DisplayRISReparsePointData(
  125. PREPARSE_DATA_BUFFER ReparseData
  126. )
  127. /*++
  128. Routine Description:
  129. This routine displays the SIS reparse data
  130. Arguments:
  131. Return Value:
  132. None
  133. --*/
  134. {
  135. PRP_DATA risRp;
  136. WCHAR vendorID[40];
  137. WCHAR fileID[40];
  138. WCHAR hsmID[40];
  139. WCHAR bagID[40];
  140. WCHAR migrationTime[32];
  141. WCHAR recallTime[32];
  142. //
  143. // Point to the SIS unique portion of the buffer
  144. //
  145. risRp = (PRP_DATA)&ReparseData->GenericReparseBuffer.DataBuffer;
  146. DisplayMsg( MSG_RIS_REPARSE_INFO,
  147. Guid2Str( &risRp->vendorId, vendorID, sizeof(vendorID) ),
  148. risRp->qualifier,
  149. risRp->version,
  150. risRp->globalBitFlags,
  151. risRp->numPrivateData,
  152. Guid2Str( &risRp->fileIdentifier, fileID, sizeof(fileID) ),
  153. risRp->data.bitFlags,
  154. FileTime2String( &risRp->data.migrationTime, migrationTime, sizeof(migrationTime) ),
  155. Guid2Str( &risRp->data.hsmId, hsmID, sizeof(hsmID) ),
  156. Guid2Str( &risRp->data.bagId, bagID, sizeof(bagID) ),
  157. risRp->data.fileStart.HighPart,
  158. risRp->data.fileStart.LowPart,
  159. risRp->data.fileSize.HighPart,
  160. risRp->data.fileSize.LowPart,
  161. risRp->data.dataStart.HighPart,
  162. risRp->data.dataStart.LowPart,
  163. risRp->data.dataSize.HighPart,
  164. risRp->data.dataSize.LowPart,
  165. risRp->data.fileVersionId.HighPart,
  166. risRp->data.fileVersionId.LowPart,
  167. risRp->data.verificationData.HighPart,
  168. risRp->data.verificationData.LowPart,
  169. risRp->data.verificationType,
  170. risRp->data.recallCount,
  171. FileTime2String( &risRp->data.recallTime, recallTime, sizeof(recallTime) ),
  172. risRp->data.dataStreamStart.HighPart,
  173. risRp->data.dataStreamStart.LowPart,
  174. risRp->data.dataStreamSize.HighPart,
  175. risRp->data.dataStreamSize.LowPart,
  176. risRp->data.dataStream,
  177. risRp->data.dataStreamCRCType,
  178. risRp->data.dataStreamCRC.HighPart,
  179. risRp->data.dataStreamCRC.LowPart );
  180. return EXIT_CODE_SUCCESS;
  181. }
  182. INT
  183. DisplayMountPointData(
  184. PREPARSE_DATA_BUFFER ReparseData
  185. )
  186. /*++
  187. Routine Description:
  188. This routine displays the SIS reparse data
  189. Arguments:
  190. Return Value:
  191. None
  192. --*/
  193. {
  194. //
  195. // Display offset and length values
  196. //
  197. DisplayMsg( MSG_MOUNT_POINT_INFO,
  198. ReparseData->MountPointReparseBuffer.SubstituteNameOffset,
  199. ReparseData->MountPointReparseBuffer.SubstituteNameLength,
  200. ReparseData->MountPointReparseBuffer.PrintNameOffset,
  201. ReparseData->MountPointReparseBuffer.PrintNameLength);
  202. //
  203. // Display Name Substitue name if there is one
  204. //
  205. if (ReparseData->MountPointReparseBuffer.SubstituteNameLength > 0) {
  206. DisplayMsg( MSG_MOUNT_POINT_SUBSTITUE_NAME,
  207. (ReparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)),
  208. &ReparseData->MountPointReparseBuffer.PathBuffer[ReparseData->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]);
  209. }
  210. //
  211. // Display PRINT NAME if there is one
  212. //
  213. if (ReparseData->MountPointReparseBuffer.PrintNameLength > 0) {
  214. DisplayMsg( MSG_MOUNT_POINT_PRINT_NAME,
  215. (ReparseData->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR)),
  216. &ReparseData->MountPointReparseBuffer.PathBuffer[ReparseData->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)]);
  217. }
  218. return EXIT_CODE_SUCCESS;
  219. }
  220. VOID
  221. DisplayGenericReparseData(
  222. UCHAR *ReparseData,
  223. DWORD DataSize
  224. )
  225. /*++
  226. Routine Description:
  227. This routine displays the SIS reparse data
  228. Arguments:
  229. Return Value:
  230. None
  231. --*/
  232. {
  233. ULONG i, j;
  234. WCHAR Buf[17];
  235. WCHAR CharBuf[3 + 1];
  236. OutputMessage( L"\r\n" );
  237. DisplayMsg( MSG_REPARSE_DATA_LENGTH, DataSize );
  238. if (DataSize > 0) {
  239. DisplayMsg( MSG_GETREPARSE_DATA );
  240. for (i = 0; i < DataSize; i += 16 ) {
  241. swprintf( Buf, L"%04x: ", i );
  242. OutputMessage( Buf );
  243. for (j = 0; j < 16 && j + i < DataSize; j++) {
  244. UCHAR c = ReparseData[ i + j ];
  245. if (c >= 0x20 && c <= 0x7F) {
  246. Buf[j] = c;
  247. } else {
  248. Buf[j] = L'.';
  249. }
  250. swprintf( CharBuf, L" %02x", c );
  251. OutputMessage( CharBuf );
  252. if (j == 7)
  253. OutputMessage( L" " );
  254. }
  255. Buf[j] = L'\0';
  256. for ( ; j < 16; j++ ) {
  257. OutputMessage( L" " );
  258. if (j == 7)
  259. OutputMessage( L" " );
  260. }
  261. OutputMessage( L" " );
  262. OutputMessage( Buf );
  263. OutputMessage( L"\r\n" );
  264. }
  265. }
  266. }
  267. INT
  268. GetReparsePoint(
  269. IN INT argc,
  270. IN PWSTR argv[]
  271. )
  272. /*++
  273. Routine Description:
  274. This routine gets the reparse point for the file specified.
  275. Arguments:
  276. argc - The argument count.
  277. argv - Array of Strings of the form :
  278. ' fscutl getrp <pathname>'.
  279. Return Value:
  280. None
  281. --*/
  282. {
  283. PWSTR Filename = NULL;
  284. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  285. PREPARSE_DATA_BUFFER lpOutBuffer = NULL;
  286. BOOL Status;
  287. HRESULT Result;
  288. DWORD BytesReturned;
  289. ULONG ulMask;
  290. WCHAR Buffer[256];
  291. LPWSTR GuidStr;
  292. INT ExitCode = EXIT_CODE_SUCCESS;
  293. #define MAX_REPARSE_DATA 0x4000
  294. try {
  295. if (argc != 1) {
  296. DisplayMsg( MSG_USAGE_GETREPARSE );
  297. if (argc != 0) {
  298. ExitCode = EXIT_CODE_FAILURE;
  299. }
  300. leave;
  301. }
  302. Filename = GetFullPath( argv[0] );
  303. if (!Filename) {
  304. DisplayError();
  305. ExitCode = EXIT_CODE_FAILURE;
  306. leave;
  307. }
  308. if (!IsVolumeLocalNTFS( Filename[0] )) {
  309. DisplayMsg( MSG_NTFS_REQUIRED );
  310. ExitCode = EXIT_CODE_FAILURE;
  311. leave;
  312. }
  313. lpOutBuffer = (PREPARSE_DATA_BUFFER) malloc ( MAX_REPARSE_DATA );
  314. if (lpOutBuffer == NULL) {
  315. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  316. ExitCode = EXIT_CODE_FAILURE;
  317. leave;
  318. }
  319. FileHandle = CreateFile(
  320. Filename,
  321. GENERIC_READ,
  322. FILE_SHARE_READ | FILE_SHARE_WRITE,
  323. NULL,
  324. OPEN_EXISTING,
  325. FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
  326. NULL
  327. );
  328. if (FileHandle == INVALID_HANDLE_VALUE) {
  329. DisplayError();
  330. ExitCode = EXIT_CODE_FAILURE;
  331. leave;
  332. }
  333. Status = DeviceIoControl(
  334. FileHandle,
  335. FSCTL_GET_REPARSE_POINT,
  336. NULL,
  337. 0,
  338. (LPVOID) lpOutBuffer,
  339. MAX_REPARSE_DATA,
  340. &BytesReturned,
  341. (LPOVERLAPPED)NULL
  342. );
  343. if (!Status) {
  344. DisplayError();
  345. ExitCode = EXIT_CODE_FAILURE;
  346. leave;
  347. }
  348. DisplayMsg( MSG_GETREPARSE_TAGVAL, lpOutBuffer->ReparseTag );
  349. if (IsReparseTagMicrosoft( lpOutBuffer->ReparseTag )) {
  350. DisplayMsg( MSG_TAG_MICROSOFT );
  351. }
  352. if (IsReparseTagNameSurrogate( lpOutBuffer->ReparseTag )) {
  353. DisplayMsg( MSG_TAG_NAME_SURROGATE );
  354. }
  355. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_SYMBOLIC_LINK) {
  356. DisplayMsg( MSG_TAG_SYMBOLIC_LINK );
  357. }
  358. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
  359. DisplayMsg( MSG_TAG_MOUNT_POINT );
  360. ExitCode = DisplayMountPointData( lpOutBuffer );
  361. }
  362. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_HSM) {
  363. DisplayMsg( MSG_TAG_HSM );
  364. ExitCode = DisplayRISReparsePointData( lpOutBuffer );
  365. }
  366. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_SIS) {
  367. DisplayMsg( MSG_TAG_SIS );
  368. ExitCode = DisplaySISReparsePointData( lpOutBuffer );
  369. }
  370. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_FILTER_MANAGER) {
  371. DisplayMsg( MSG_TAG_FILTER_MANAGER );
  372. }
  373. if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_DFS) {
  374. DisplayMsg( MSG_TAG_DFS );
  375. }
  376. //
  377. // This is an unknown tag, display the data
  378. //
  379. if (IsReparseTagMicrosoft( lpOutBuffer->ReparseTag )) {
  380. //
  381. // Display Microsoft tag data, note that these do NOT use
  382. // the GUID form of the buffer
  383. //
  384. DisplayGenericReparseData( lpOutBuffer->GenericReparseBuffer.DataBuffer,
  385. lpOutBuffer->ReparseDataLength );
  386. } else {
  387. //
  388. // Display NON-Microsoft tag data, note that these DO use
  389. // the GUID form of the buffer
  390. //
  391. PREPARSE_GUID_DATA_BUFFER nmReparseData = (PREPARSE_GUID_DATA_BUFFER)lpOutBuffer;
  392. Result = StringFromIID( &nmReparseData->ReparseGuid, &GuidStr );
  393. if (Result != S_OK) {
  394. DisplayErrorMsg( Result );
  395. ExitCode = EXIT_CODE_FAILURE;
  396. leave;
  397. }
  398. DisplayMsg( MSG_GETREPARSE_GUID, GuidStr );
  399. DisplayGenericReparseData( nmReparseData->GenericReparseBuffer.DataBuffer,
  400. nmReparseData->ReparseDataLength );
  401. CoTaskMemFree(GuidStr);
  402. }
  403. } finally {
  404. if (FileHandle != INVALID_HANDLE_VALUE) {
  405. CloseHandle( FileHandle );
  406. }
  407. free( lpOutBuffer );
  408. free( Filename );
  409. }
  410. return ExitCode;
  411. }
  412. INT
  413. DeleteReparsePoint(
  414. IN INT argc,
  415. IN PWSTR argv[]
  416. )
  417. /*++
  418. Routine Description:
  419. This routine deletes the reparse point associated with
  420. the file specified.
  421. Arguments:
  422. argc - The argument count.
  423. argv - Array of Strings of the form :
  424. ' fscutl delrp <pathname>'.
  425. Return Value:
  426. None
  427. --*/
  428. {
  429. BOOL Status;
  430. PWSTR Filename = NULL;
  431. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  432. PREPARSE_GUID_DATA_BUFFER lpInOutBuffer = NULL;
  433. DWORD nInOutBufferSize;
  434. DWORD BytesReturned;
  435. INT ExitCode = EXIT_CODE_SUCCESS;
  436. try {
  437. if (argc != 1) {
  438. DisplayMsg( MSG_DELETE_REPARSE );
  439. if (argc != 0) {
  440. ExitCode = EXIT_CODE_FAILURE;
  441. }
  442. leave;
  443. }
  444. Filename = GetFullPath( argv[0] );
  445. if (!Filename) {
  446. DisplayError();
  447. ExitCode = EXIT_CODE_FAILURE;
  448. leave;
  449. }
  450. if (!IsVolumeLocalNTFS( Filename[0] )) {
  451. DisplayMsg( MSG_NTFS_REQUIRED );
  452. ExitCode = EXIT_CODE_FAILURE;
  453. leave;
  454. }
  455. nInOutBufferSize = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + MAX_REPARSE_DATA;
  456. lpInOutBuffer = (PREPARSE_GUID_DATA_BUFFER) malloc ( nInOutBufferSize );
  457. if (lpInOutBuffer == NULL) {
  458. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  459. ExitCode = EXIT_CODE_FAILURE;
  460. leave;
  461. }
  462. FileHandle = CreateFile(
  463. Filename,
  464. GENERIC_WRITE,
  465. FILE_SHARE_READ | FILE_SHARE_WRITE,
  466. NULL,
  467. OPEN_EXISTING,
  468. FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
  469. NULL
  470. );
  471. if (FileHandle == INVALID_HANDLE_VALUE) {
  472. DisplayError();
  473. ExitCode = EXIT_CODE_FAILURE;
  474. leave;
  475. }
  476. Status = DeviceIoControl(
  477. FileHandle,
  478. FSCTL_GET_REPARSE_POINT,
  479. NULL,
  480. 0,
  481. (LPVOID) lpInOutBuffer,
  482. nInOutBufferSize,
  483. &BytesReturned,
  484. (LPOVERLAPPED)NULL
  485. );
  486. if (!Status) {
  487. DisplayError();
  488. ExitCode = EXIT_CODE_FAILURE;
  489. leave;
  490. }
  491. lpInOutBuffer->ReparseDataLength = 0;
  492. Status = DeviceIoControl(
  493. FileHandle,
  494. FSCTL_DELETE_REPARSE_POINT,
  495. (LPVOID) lpInOutBuffer,
  496. REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,
  497. NULL,
  498. 0,
  499. &BytesReturned,
  500. (LPOVERLAPPED)NULL
  501. );
  502. if (!Status) {
  503. DisplayError();
  504. ExitCode = EXIT_CODE_FAILURE;
  505. }
  506. } finally {
  507. if (FileHandle != INVALID_HANDLE_VALUE) {
  508. CloseHandle( FileHandle );
  509. }
  510. free( lpInOutBuffer );
  511. free( Filename );
  512. }
  513. return ExitCode;
  514. }