/*++ Copyright (c) 2000 Microsoft Corporation Module Name: fsfile.c Abstract: This file contains code for commands that affect individual files. Author: Wesley Witt [wesw] 1-March-2000 Revision History: --*/ #include //---------------------------------- #include #include #include #include #define MAX_ALLOC_RANGES 32 // // Common command line args // #define ARG_OFFSET L"offset=" #define ARG_OFFSET_LEN 7 #define ARG_LENGTH L"length=" #define ARG_LENGTH_LEN 7 INT FileHelp( IN INT argc, IN PWSTR argv[] ) { DisplayMsg( MSG_USAGE_FILE ); return EXIT_CODE_SUCCESS; } INT FindFilesBySid( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine finds file owned by the user specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl findbysid '. Return Value: None --*/ { #define SID_MAX_LENGTH (FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES) HANDLE FileHandle = INVALID_HANDLE_VALUE; BOOL Status; struct { ULONG Restart; BYTE Sid[SID_MAX_LENGTH]; } InBuffer; DWORD nInBufferSize; DWORD BytesReturned; ULONG SidLength = sizeof( InBuffer.Sid ); WCHAR Domain[MAX_PATH]; ULONG DomainLength = sizeof( Domain ); SID_NAME_USE SidNameUse; DWORD nOutBufferSize; PBYTE lpOutBuffer; PFILE_NAME_INFORMATION FileNameInfo; ULONG Length; PWSTR Filename; ULONG Found = 0; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 2) { DisplayMsg( MSG_USAGE_FINDBYSID ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE; } leave; } Filename = GetFullPath( argv[1] ); if (!Filename) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (!IsVolumeLocalNTFS( Filename[0] )) { DisplayMsg( MSG_NTFS_REQUIRED ); ExitCode = EXIT_CODE_FAILURE; leave; } FileHandle = CreateFile( Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } nInBufferSize = sizeof(InBuffer); nOutBufferSize = 32768; lpOutBuffer = (PBYTE) malloc( nOutBufferSize ); if (lpOutBuffer == NULL) { DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY ); ExitCode = EXIT_CODE_FAILURE; leave; } memset( lpOutBuffer, 0, nOutBufferSize ); memset( &InBuffer, 0, sizeof(InBuffer) ); if (!LookupAccountName( NULL, argv[0], InBuffer.Sid, &SidLength, Domain, &DomainLength, &SidNameUse )) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } InBuffer.Restart = 1; do { Status = DeviceIoControl( FileHandle, FSCTL_FIND_FILES_BY_SID, &InBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } InBuffer.Restart = 0; FileNameInfo = (PFILE_NAME_INFORMATION) lpOutBuffer; while ((PBYTE)FileNameInfo < lpOutBuffer + BytesReturned) { Length = sizeof( FILE_NAME_INFORMATION ) - sizeof( WCHAR ) + FileNameInfo->FileNameLength; OutputMessageLength( FileNameInfo->FileName, FileNameInfo->FileNameLength / sizeof( WCHAR )); OutputMessage( L"\r\n" ); FileNameInfo = (PFILE_NAME_INFORMATION) Add2Ptr( FileNameInfo, QuadAlign( Length ) ); Found += 1; } } while (Status && BytesReturned); if (Found == 0) { DisplayMsg( MSG_FINDFILESBYSID_NONE ); } } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } free( lpOutBuffer ); free( Filename ); } return ExitCode; } INT SetZeroData( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine sets zero data for the range in the file specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl setzero offset= beyond= '. Return Value: None --*/ { HANDLE FileHandle = INVALID_HANDLE_VALUE; PWSTR Filename = NULL; PWSTR EndPtr; BOOL Status; PFILE_ZERO_DATA_INFORMATION lpInBuffer; DWORD nInBufferSize; DWORD BytesReturned; ULONGLONG Offset; ULONGLONG Length; ULONGLONG Beyond; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 3) { DisplayMsg( MSG_SETZERO_USAGE ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE; } leave; } Filename = GetFullPath( argv[2] ); if (!Filename) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (!IsVolumeLocalNTFS( Filename[0] )) { DisplayMsg( MSG_NTFS_REQUIRED ); ExitCode = EXIT_CODE_FAILURE; leave; } FileHandle = CreateFile( Filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (_wcsnicmp( argv[0], ARG_OFFSET, ARG_OFFSET_LEN)) { DisplayMsg( MSG_SETZERO_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } Offset = My_wcstoui64( argv[0] + ARG_OFFSET_LEN, &EndPtr, 0 ); if (UnsignedI64NumberCheck( Offset, EndPtr )) { DisplayMsg( MSG_SETZERO_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } if (_wcsnicmp( argv[1], ARG_LENGTH, ARG_LENGTH_LEN)) { DisplayMsg( MSG_SETZERO_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } Length = My_wcstoui64( argv[1] + ARG_LENGTH_LEN, &EndPtr, 0 ); if (UnsignedI64NumberCheck( Length, EndPtr )) { DisplayMsg( MSG_SETZERO_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } Beyond = Offset + Length; if (Beyond < Offset) { DisplayMsg( MSG_SETZERO_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } nInBufferSize = sizeof(FILE_ZERO_DATA_INFORMATION); lpInBuffer = (PFILE_ZERO_DATA_INFORMATION) malloc ( nInBufferSize ); if (lpInBuffer == NULL) { DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY ); ExitCode = EXIT_CODE_FAILURE; leave; } lpInBuffer->FileOffset.QuadPart = Offset; lpInBuffer->BeyondFinalZero.QuadPart = Beyond; Status = DeviceIoControl( FileHandle, FSCTL_SET_ZERO_DATA, (LPVOID) lpInBuffer, nInBufferSize, NULL, 0, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; } else { DisplayMsg( MSG_SET_ZERODATA ); } } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } if (Filename) { free( Filename ); } } return ExitCode; } INT QueryAllocatedRanges( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine scans for any allocated range within the range specified in the file specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl qryalcrnge offset= length= '. Return Value: None --*/ { HANDLE FileHandle = INVALID_HANDLE_VALUE; PWSTR Filename = NULL; PWSTR EndPtr; BOOL Status; PFILE_ALLOCATED_RANGE_BUFFER lpInBuffer = NULL; DWORD nInBufferSize; PFILE_ALLOCATED_RANGE_BUFFER *lpOutBuffer = NULL; PFILE_ALLOCATED_RANGE_BUFFER pBuffer; DWORD nOutBufferSize; DWORD BytesReturned; ULARGE_INTEGER Offset; ULARGE_INTEGER Length; INT NumberOfBuffers; INT Index; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 3) { DisplayMsg( MSG_ALLOCRANGE_USAGE ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE; } leave; } Filename = GetFullPath( argv[2] ); if (!Filename) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (!IsVolumeLocalNTFS( Filename[0] )) { DisplayMsg( MSG_NTFS_REQUIRED ); ExitCode = EXIT_CODE_FAILURE; leave; } Offset.QuadPart = Length.QuadPart = 0; if (_wcsnicmp( argv[0], ARG_OFFSET, ARG_OFFSET_LEN )) { DisplayMsg( MSG_ALLOCRANGE_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } Offset.QuadPart = My_wcstoui64( argv[0] + ARG_OFFSET_LEN, &EndPtr, 0 ); if (UnsignedI64NumberCheck( Offset.QuadPart, EndPtr)) { DisplayMsg( MSG_ALLOCRANGE_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } if (_wcsnicmp( argv[1], ARG_LENGTH, ARG_LENGTH_LEN )) { DisplayMsg( MSG_ALLOCRANGE_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } Length.QuadPart = My_wcstoui64( argv[1] + ARG_LENGTH_LEN, &EndPtr, 0 ); if (UnsignedI64NumberCheck( Length.QuadPart, EndPtr )) { DisplayMsg( MSG_ALLOCRANGE_USAGE ); ExitCode = EXIT_CODE_FAILURE; leave; } FileHandle = CreateFile( Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } nInBufferSize = sizeof(FILE_ALLOCATED_RANGE_BUFFER); lpInBuffer = (PFILE_ALLOCATED_RANGE_BUFFER) malloc ( nInBufferSize ); nOutBufferSize = sizeof(FILE_ALLOCATED_RANGE_BUFFER) * MAX_ALLOC_RANGES; lpOutBuffer = (PFILE_ALLOCATED_RANGE_BUFFER *) calloc ( MAX_ALLOC_RANGES, sizeof(FILE_ALLOCATED_RANGE_BUFFER) ); if (lpInBuffer == NULL || lpOutBuffer == NULL) { DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY ); ExitCode = EXIT_CODE_FAILURE; leave; } lpInBuffer->FileOffset.QuadPart = Offset.QuadPart; lpInBuffer->Length.QuadPart = Length.QuadPart; Status = DeviceIoControl( FileHandle, FSCTL_QUERY_ALLOCATED_RANGES, (LPVOID) lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } pBuffer = (PFILE_ALLOCATED_RANGE_BUFFER) lpOutBuffer ; NumberOfBuffers = (BytesReturned) / sizeof(FILE_ALLOCATED_RANGE_BUFFER); for ( Index=0; Index