/*++ 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 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 '. 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 '. 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; }