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

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
reparse.c
Abstract:
This file contains code for commands that affect
reparse points.
Author:
Wesley Witt [wesw] 1-March-2000
Revision History:
--*/
#include <precomp.h>
INT
ReparseHelp(
IN INT argc,
IN PWSTR argv[]
)
{
DisplayMsg( MSG_USAGE_REPARSEPOINT );
return EXIT_CODE_SUCCESS;
}
//
// This is the definition of the DATA portion of the SIS reparse buffer.
//
#define SIS_REPARSE_BUFFER_FORMAT_VERSION 5
typedef struct _SIS_REPARSE_BUFFER {
ULONG ReparsePointFormatVersion;
ULONG Reserved;
//
// The id of the common store file.
//
GUID CSid;
//
// The index of this link file.
//
LARGE_INTEGER LinkIndex;
//
// The file ID of the link file.
//
LARGE_INTEGER LinkFileNtfsId;
//
// The file ID of the common store file.
//
LARGE_INTEGER CSFileNtfsId;
//
// A "131 hash" checksum of the contents of the
// common store file.
//
LARGE_INTEGER CSChecksum;
//
// A "131 hash" checksum of this structure.
// N.B. Must be last.
//
LARGE_INTEGER Checksum;
} SIS_REPARSE_BUFFER, *PSIS_REPARSE_BUFFER;
INT
DisplaySISReparsePointData(
PREPARSE_DATA_BUFFER ReparseData
)
/*++
Routine Description:
This routine displays the SIS reparse data
Arguments:
Return Value:
None
--*/
{
PSIS_REPARSE_BUFFER sisRp;
WCHAR csID[40];
//
// Point to the SIS unique portion of the buffer
//
sisRp = (PSIS_REPARSE_BUFFER)&ReparseData->GenericReparseBuffer.DataBuffer;
DisplayMsg( MSG_SIS_REPARSE_INFO,
sisRp->ReparsePointFormatVersion,
Guid2Str( &sisRp->CSid, csID, sizeof(csID) ),
sisRp->LinkIndex.HighPart,
sisRp->LinkIndex.LowPart,
sisRp->LinkFileNtfsId.HighPart,
sisRp->LinkFileNtfsId.LowPart,
sisRp->CSFileNtfsId.HighPart,
sisRp->CSFileNtfsId.LowPart,
sisRp->CSChecksum.HighPart,
sisRp->CSChecksum.LowPart,
sisRp->Checksum.HighPart,
sisRp->Checksum.LowPart);
return EXIT_CODE_SUCCESS;
}
//
// Placeholder data - all versions unioned together
//
#define RP_RESV_SIZE 52
typedef struct _RP_PRIVATE_DATA {
CHAR reserved[RP_RESV_SIZE]; // Must be 0
ULONG bitFlags; // bitflags indicating status of the segment
LARGE_INTEGER migrationTime; // When migration occurred
GUID hsmId;
GUID bagId;
LARGE_INTEGER fileStart;
LARGE_INTEGER fileSize;
LARGE_INTEGER dataStart;
LARGE_INTEGER dataSize;
LARGE_INTEGER fileVersionId;
LARGE_INTEGER verificationData;
ULONG verificationType;
ULONG recallCount;
LARGE_INTEGER recallTime;
LARGE_INTEGER dataStreamStart;
LARGE_INTEGER dataStreamSize;
ULONG dataStream;
ULONG dataStreamCRCType;
LARGE_INTEGER dataStreamCRC;
} RP_PRIVATE_DATA, *PRP_PRIVATE_DATA;
typedef struct _RP_DATA {
GUID vendorId; // Unique HSM vendor ID -- This is first to match REPARSE_GUID_DATA_BUFFER
ULONG qualifier; // Used to checksum the data
ULONG version; // Version of the structure
ULONG globalBitFlags; // bitflags indicating status of the file
ULONG numPrivateData; // number of private data entries
GUID fileIdentifier; // Unique file ID
RP_PRIVATE_DATA data; // Vendor specific data
} RP_DATA, *PRP_DATA;
INT
DisplayRISReparsePointData(
PREPARSE_DATA_BUFFER ReparseData
)
/*++
Routine Description:
This routine displays the SIS reparse data
Arguments:
Return Value:
None
--*/
{
PRP_DATA risRp;
WCHAR vendorID[40];
WCHAR fileID[40];
WCHAR hsmID[40];
WCHAR bagID[40];
WCHAR migrationTime[32];
WCHAR recallTime[32];
//
// Point to the SIS unique portion of the buffer
//
risRp = (PRP_DATA)&ReparseData->GenericReparseBuffer.DataBuffer;
DisplayMsg( MSG_RIS_REPARSE_INFO,
Guid2Str( &risRp->vendorId, vendorID, sizeof(vendorID) ),
risRp->qualifier,
risRp->version,
risRp->globalBitFlags,
risRp->numPrivateData,
Guid2Str( &risRp->fileIdentifier, fileID, sizeof(fileID) ),
risRp->data.bitFlags,
FileTime2String( &risRp->data.migrationTime, migrationTime, sizeof(migrationTime) ),
Guid2Str( &risRp->data.hsmId, hsmID, sizeof(hsmID) ),
Guid2Str( &risRp->data.bagId, bagID, sizeof(bagID) ),
risRp->data.fileStart.HighPart,
risRp->data.fileStart.LowPart,
risRp->data.fileSize.HighPart,
risRp->data.fileSize.LowPart,
risRp->data.dataStart.HighPart,
risRp->data.dataStart.LowPart,
risRp->data.dataSize.HighPart,
risRp->data.dataSize.LowPart,
risRp->data.fileVersionId.HighPart,
risRp->data.fileVersionId.LowPart,
risRp->data.verificationData.HighPart,
risRp->data.verificationData.LowPart,
risRp->data.verificationType,
risRp->data.recallCount,
FileTime2String( &risRp->data.recallTime, recallTime, sizeof(recallTime) ),
risRp->data.dataStreamStart.HighPart,
risRp->data.dataStreamStart.LowPart,
risRp->data.dataStreamSize.HighPart,
risRp->data.dataStreamSize.LowPart,
risRp->data.dataStream,
risRp->data.dataStreamCRCType,
risRp->data.dataStreamCRC.HighPart,
risRp->data.dataStreamCRC.LowPart );
return EXIT_CODE_SUCCESS;
}
INT
DisplayMountPointData(
PREPARSE_DATA_BUFFER ReparseData
)
/*++
Routine Description:
This routine displays the SIS reparse data
Arguments:
Return Value:
None
--*/
{
//
// Display offset and length values
//
DisplayMsg( MSG_MOUNT_POINT_INFO,
ReparseData->MountPointReparseBuffer.SubstituteNameOffset,
ReparseData->MountPointReparseBuffer.SubstituteNameLength,
ReparseData->MountPointReparseBuffer.PrintNameOffset,
ReparseData->MountPointReparseBuffer.PrintNameLength);
//
// Display Name Substitue name if there is one
//
if (ReparseData->MountPointReparseBuffer.SubstituteNameLength > 0) {
DisplayMsg( MSG_MOUNT_POINT_SUBSTITUE_NAME,
(ReparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)),
&ReparseData->MountPointReparseBuffer.PathBuffer[ReparseData->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]);
}
//
// Display PRINT NAME if there is one
//
if (ReparseData->MountPointReparseBuffer.PrintNameLength > 0) {
DisplayMsg( MSG_MOUNT_POINT_PRINT_NAME,
(ReparseData->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR)),
&ReparseData->MountPointReparseBuffer.PathBuffer[ReparseData->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)]);
}
return EXIT_CODE_SUCCESS;
}
VOID
DisplayGenericReparseData(
UCHAR *ReparseData,
DWORD DataSize
)
/*++
Routine Description:
This routine displays the SIS reparse data
Arguments:
Return Value:
None
--*/
{
ULONG i, j;
WCHAR Buf[17];
WCHAR CharBuf[3 + 1];
OutputMessage( L"\r\n" );
DisplayMsg( MSG_REPARSE_DATA_LENGTH, DataSize );
if (DataSize > 0) {
DisplayMsg( MSG_GETREPARSE_DATA );
for (i = 0; i < DataSize; i += 16 ) {
swprintf( Buf, L"%04x: ", i );
OutputMessage( Buf );
for (j = 0; j < 16 && j + i < DataSize; j++) {
UCHAR c = ReparseData[ i + j ];
if (c >= 0x20 && c <= 0x7F) {
Buf[j] = c;
} else {
Buf[j] = L'.';
}
swprintf( CharBuf, L" %02x", c );
OutputMessage( CharBuf );
if (j == 7)
OutputMessage( L" " );
}
Buf[j] = L'\0';
for ( ; j < 16; j++ ) {
OutputMessage( L" " );
if (j == 7)
OutputMessage( L" " );
}
OutputMessage( L" " );
OutputMessage( Buf );
OutputMessage( L"\r\n" );
}
}
}
INT
GetReparsePoint(
IN INT argc,
IN PWSTR argv[]
)
/*++
Routine Description:
This routine gets the reparse point for the file specified.
Arguments:
argc - The argument count.
argv - Array of Strings of the form :
' fscutl getrp <pathname>'.
Return Value:
None
--*/
{
PWSTR Filename = NULL;
HANDLE FileHandle = INVALID_HANDLE_VALUE;
PREPARSE_DATA_BUFFER lpOutBuffer = NULL;
BOOL Status;
HRESULT Result;
DWORD BytesReturned;
ULONG ulMask;
WCHAR Buffer[256];
LPWSTR GuidStr;
INT ExitCode = EXIT_CODE_SUCCESS;
#define MAX_REPARSE_DATA 0x4000
try {
if (argc != 1) {
DisplayMsg( MSG_USAGE_GETREPARSE );
if (argc != 0) {
ExitCode = EXIT_CODE_FAILURE;
}
leave;
}
Filename = GetFullPath( argv[0] );
if (!Filename) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
if (!IsVolumeLocalNTFS( Filename[0] )) {
DisplayMsg( MSG_NTFS_REQUIRED );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
lpOutBuffer = (PREPARSE_DATA_BUFFER) malloc ( MAX_REPARSE_DATA );
if (lpOutBuffer == NULL) {
DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
FileHandle = CreateFile(
Filename,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if (FileHandle == INVALID_HANDLE_VALUE) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
Status = DeviceIoControl(
FileHandle,
FSCTL_GET_REPARSE_POINT,
NULL,
0,
(LPVOID) lpOutBuffer,
MAX_REPARSE_DATA,
&BytesReturned,
(LPOVERLAPPED)NULL
);
if (!Status) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
DisplayMsg( MSG_GETREPARSE_TAGVAL, lpOutBuffer->ReparseTag );
if (IsReparseTagMicrosoft( lpOutBuffer->ReparseTag )) {
DisplayMsg( MSG_TAG_MICROSOFT );
}
if (IsReparseTagNameSurrogate( lpOutBuffer->ReparseTag )) {
DisplayMsg( MSG_TAG_NAME_SURROGATE );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_SYMBOLIC_LINK) {
DisplayMsg( MSG_TAG_SYMBOLIC_LINK );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
DisplayMsg( MSG_TAG_MOUNT_POINT );
ExitCode = DisplayMountPointData( lpOutBuffer );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_HSM) {
DisplayMsg( MSG_TAG_HSM );
ExitCode = DisplayRISReparsePointData( lpOutBuffer );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_SIS) {
DisplayMsg( MSG_TAG_SIS );
ExitCode = DisplaySISReparsePointData( lpOutBuffer );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_FILTER_MANAGER) {
DisplayMsg( MSG_TAG_FILTER_MANAGER );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_DFS) {
DisplayMsg( MSG_TAG_DFS );
}
//
// This is an unknown tag, display the data
//
if (IsReparseTagMicrosoft( lpOutBuffer->ReparseTag )) {
//
// Display Microsoft tag data, note that these do NOT use
// the GUID form of the buffer
//
DisplayGenericReparseData( lpOutBuffer->GenericReparseBuffer.DataBuffer,
lpOutBuffer->ReparseDataLength );
} else {
//
// Display NON-Microsoft tag data, note that these DO use
// the GUID form of the buffer
//
PREPARSE_GUID_DATA_BUFFER nmReparseData = (PREPARSE_GUID_DATA_BUFFER)lpOutBuffer;
Result = StringFromIID( &nmReparseData->ReparseGuid, &GuidStr );
if (Result != S_OK) {
DisplayErrorMsg( Result );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
DisplayMsg( MSG_GETREPARSE_GUID, GuidStr );
DisplayGenericReparseData( nmReparseData->GenericReparseBuffer.DataBuffer,
nmReparseData->ReparseDataLength );
CoTaskMemFree(GuidStr);
}
} finally {
if (FileHandle != INVALID_HANDLE_VALUE) {
CloseHandle( FileHandle );
}
free( lpOutBuffer );
free( Filename );
}
return ExitCode;
}
INT
DeleteReparsePoint(
IN INT argc,
IN PWSTR argv[]
)
/*++
Routine Description:
This routine deletes the reparse point associated with
the file specified.
Arguments:
argc - The argument count.
argv - Array of Strings of the form :
' fscutl delrp <pathname>'.
Return Value:
None
--*/
{
BOOL Status;
PWSTR Filename = NULL;
HANDLE FileHandle = INVALID_HANDLE_VALUE;
PREPARSE_GUID_DATA_BUFFER lpInOutBuffer = NULL;
DWORD nInOutBufferSize;
DWORD BytesReturned;
INT ExitCode = EXIT_CODE_SUCCESS;
try {
if (argc != 1) {
DisplayMsg( MSG_DELETE_REPARSE );
if (argc != 0) {
ExitCode = EXIT_CODE_FAILURE;
}
leave;
}
Filename = GetFullPath( argv[0] );
if (!Filename) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
if (!IsVolumeLocalNTFS( Filename[0] )) {
DisplayMsg( MSG_NTFS_REQUIRED );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
nInOutBufferSize = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + MAX_REPARSE_DATA;
lpInOutBuffer = (PREPARSE_GUID_DATA_BUFFER) malloc ( nInOutBufferSize );
if (lpInOutBuffer == NULL) {
DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
FileHandle = CreateFile(
Filename,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if (FileHandle == INVALID_HANDLE_VALUE) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
Status = DeviceIoControl(
FileHandle,
FSCTL_GET_REPARSE_POINT,
NULL,
0,
(LPVOID) lpInOutBuffer,
nInOutBufferSize,
&BytesReturned,
(LPOVERLAPPED)NULL
);
if (!Status) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
leave;
}
lpInOutBuffer->ReparseDataLength = 0;
Status = DeviceIoControl(
FileHandle,
FSCTL_DELETE_REPARSE_POINT,
(LPVOID) lpInOutBuffer,
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,
NULL,
0,
&BytesReturned,
(LPOVERLAPPED)NULL
);
if (!Status) {
DisplayError();
ExitCode = EXIT_CODE_FAILURE;
}
} finally {
if (FileHandle != INVALID_HANDLE_VALUE) {
CloseHandle( FileHandle );
}
free( lpInOutBuffer );
free( Filename );
}
return ExitCode;
}