windows-nt/Source/XPSP1/NT/base/fs/ntfs/fu/reparse.c
2020-09-26 16:20:57 +08:00

338 lines
7.9 KiB
C

/*++
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;
}
//
// Microsoft tags for reparse points.
//
#define MAX_REPARSE_DATA 0x1000
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_GUID_DATA_BUFFER lpOutBuffer = NULL;
BOOL Status;
DWORD nOutBufferSize;
DWORD BytesReturned;
ULONG ulMask;
WCHAR Buffer[256];
LPWSTR GuidStr;
INT ExitCode = EXIT_CODE_SUCCESS;
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;
}
nOutBufferSize = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + MAX_REPARSE_DATA;
lpOutBuffer = (PREPARSE_GUID_DATA_BUFFER) malloc ( nOutBufferSize );
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,
nOutBufferSize,
&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 );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_HSM) {
DisplayMsg( MSG_TAG_HSM );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_SIS) {
DisplayMsg( MSG_TAG_SIS );
}
if (lpOutBuffer->ReparseTag == IO_REPARSE_TAG_FILTER_MANAGER) {
DisplayMsg( MSG_TAG_FILTER_MANAGER );
}
Status = StringFromIID( &lpOutBuffer->ReparseGuid, &GuidStr );
if (Status != S_OK) {
DisplayErrorMsg( Status );
ExitCode = EXIT_CODE_FAILURE;
leave;
}
DisplayMsg( MSG_GETREPARSE_GUID, GuidStr, lpOutBuffer->ReparseDataLength );
if (lpOutBuffer->ReparseDataLength != 0) {
int i, j;
WCHAR Buf[17];
DisplayMsg( MSG_GETREPARSE_DATA );
for (i = 0; i < lpOutBuffer->ReparseDataLength; i += 16 ) {
wprintf( L"%04x: ", i );
for (j = 0; j < 16 && j + i < lpOutBuffer->ReparseDataLength; j++) {
UCHAR c = lpOutBuffer->GenericReparseBuffer.DataBuffer[ i + j ];
if (c >= 0x20 && c <= 0x7F) {
Buf[j] = c;
} else {
Buf[j] = L'.';
}
wprintf( L" %02x", c );
}
Buf[j] = L'\0';
for ( ; j < 16; j++ ) {
wprintf( L" " );
}
wprintf( L" %s\n", Buf );
}
}
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;
}