/*++ Copyright (c) 2000 Microsoft Corporation Module Name: objectid.c Abstract: This file contains code for commands that affect object ids. Author: Wesley Witt [wesw] 1-March-2000 Revision History: --*/ #include INT ObjectIdHelp( IN INT argc, IN PWSTR argv[] ) { DisplayMsg( MSG_USAGE_OBJECTID ); return EXIT_CODE_SUCCESS; } VOID PrintObjectId( PFILE_OBJECTID_BUFFER lpOutBuffer ) { INT Index; DisplayMsg( MSG_OBJECTID_TEXT ); for ( Index = 0 ; Index < 16 ; Index++ ) { wprintf( L"%02x", lpOutBuffer->ObjectId[Index] ); } wprintf( L"\n" ); DisplayMsg( MSG_BIRTHVOLID_TEXT ); for ( Index = 0 ; Index < 16 ; Index++ ) { wprintf( L"%02x", lpOutBuffer->BirthVolumeId[Index] ); } wprintf( L"\n" ); DisplayMsg( MSG_BIRTHOBJECTID_TEXT ); for ( Index = 0 ; Index < 16 ; Index++ ) { wprintf( L"%02x", lpOutBuffer->BirthObjectId[Index] ); } wprintf( L"\n" ); DisplayMsg( MSG_DOMAINID_TEXT ); for ( Index = 0 ; Index < 16 ; Index++ ) { wprintf( L"%02x", lpOutBuffer->DomainId[Index] ); } wprintf( L"\n" ); } UCHAR GetNibbleValue( IN OUT PCWSTR *String ) { UCHAR v; WCHAR c; c = *(*String)++; c = (UCHAR) toupper( c ); if (isdigit( c )) { v = c - L'0'; } else if (isalpha( c ) && c <= L'F') { v = c - L'A' + 10; } else { (*String)--; return 0; } return v; } UCHAR GetByteValue( IN OUT PCWSTR *String ) { UCHAR v = GetNibbleValue( String ); v *= 16; v += GetNibbleValue( String ); return v; } BOOL ConvertStringToHexData( IN PCWSTR Arg, OUT PUCHAR Buffer ) { int i; for (i = 0; i < 16; i++) { Buffer[i] = GetByteValue( &Arg ); } return *Arg == L'\0'; } INT SetObjectId( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine sets the objectID for the file specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl setoid '. Return Value: None --*/ { PWSTR Filename = NULL; HANDLE FileHandle = INVALID_HANDLE_VALUE; PFILE_OBJECTID_BUFFER lpInBuffer = NULL; BOOL Status; DWORD nInBufferSize; DWORD BytesReturned; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 5) { DisplayMsg( MSG_USAGE_SETOBJECTID ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE; } leave; } Filename = GetFullPath( argv[4] ); if (!Filename) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (!IsVolumeLocalNTFS( Filename[0] )) { DisplayMsg( MSG_NTFS_REQUIRED ); ExitCode = EXIT_CODE_FAILURE; leave; } nInBufferSize = sizeof(FILE_OBJECTID_BUFFER); lpInBuffer = (PFILE_OBJECTID_BUFFER) malloc ( nInBufferSize ); if (lpInBuffer == NULL) { DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY ); ExitCode = EXIT_CODE_FAILURE; leave; } // // Convert the input strings into the correct data // if (!ConvertStringToHexData( argv[0], lpInBuffer->ObjectId) || !ConvertStringToHexData( argv[1], lpInBuffer->BirthVolumeId) || !ConvertStringToHexData( argv[2], lpInBuffer->BirthObjectId) || !ConvertStringToHexData( argv[3], lpInBuffer->DomainId)) { DisplayMsg( MSG_USAGE_SETOBJECTID ); ExitCode = EXIT_CODE_FAILURE; leave; } EnablePrivilege( SE_RESTORE_NAME ); FileHandle = CreateFile( Filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } Status = DeviceIoControl( FileHandle, FSCTL_SET_OBJECT_ID, (LPVOID) lpInBuffer, nInBufferSize, NULL, 0, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } free(lpInBuffer); free( Filename ); } return ExitCode; } INT GetObjectId( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine gets the objectID associated with the file specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl getoid '. Return Value: None --*/ { HANDLE FileHandle = INVALID_HANDLE_VALUE; PWSTR Filename = NULL; PFILE_OBJECTID_BUFFER lpOutBuffer = NULL; BOOL Status; DWORD nOutBufferSize; DWORD BytesReturned; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 1) { DisplayMsg( MSG_USAGE_GETOBJECTID ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE; } leave; } Filename = GetFullPath( argv[0] ); if (!Filename) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } if (!IsVolumeNTFS( Filename )) { DisplayMsg( MSG_NTFS_REQUIRED ); ExitCode = EXIT_CODE_FAILURE; leave; } nOutBufferSize = sizeof(FILE_OBJECTID_BUFFER); lpOutBuffer = (PFILE_OBJECTID_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_ATTRIBUTE_NORMAL, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } Status = DeviceIoControl( FileHandle, FSCTL_GET_OBJECT_ID, NULL, 0, (LPVOID) lpOutBuffer, nOutBufferSize, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { if (GetLastError( ) == ERROR_FILE_NOT_FOUND) { DisplayMsg( MSG_NO_OBJECT_ID ); } else { DisplayError(); ExitCode = EXIT_CODE_FAILURE; } leave; } PrintObjectId( lpOutBuffer ); } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } free(lpOutBuffer); free( Filename ); } return ExitCode; } INT CreateOrGetObjectId( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine gets the objectID for the file, if it exists, else creates an objectID and returns it. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl crgetoid '. Return Value: None --*/ { PWSTR Filename = NULL; HANDLE FileHandle = INVALID_HANDLE_VALUE; PFILE_OBJECTID_BUFFER lpOutBuffer = NULL; BOOL Status; DWORD nOutBufferSize; DWORD BytesReturned; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 1) { DisplayMsg( MSG_USAGE_CREATEOBJECTID ); 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 = sizeof(FILE_OBJECTID_BUFFER); lpOutBuffer = (PFILE_OBJECTID_BUFFER) malloc ( nOutBufferSize ); if (lpOutBuffer == NULL) { DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY ); ExitCode = EXIT_CODE_FAILURE; leave; } FileHandle = CreateFile( Filename, GENERIC_READ | 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; } Status = DeviceIoControl( FileHandle, FSCTL_CREATE_OR_GET_OBJECT_ID, NULL, 0, (LPVOID) lpOutBuffer, nOutBufferSize, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } PrintObjectId( lpOutBuffer ); } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } if (lpOutBuffer) { free(lpOutBuffer); } if (Filename) { free( Filename ); } } return ExitCode; } INT DeleteObjectId( IN INT argc, IN PWSTR argv[] ) /*++ Routine Description: This routine deletes the objectID associated with the file specified. Arguments: argc - The argument count. argv - Array of Strings of the form : ' fscutl deloid '. Return Value: None --*/ { HANDLE FileHandle = INVALID_HANDLE_VALUE; PWSTR Filename = NULL; BOOL Status; DWORD BytesReturned; INT ExitCode = EXIT_CODE_SUCCESS; try { if (argc != 1) { DisplayMsg( MSG_USAGE_DELETEOBJECTID ); if (argc != 0) { ExitCode = EXIT_CODE_FAILURE;} leave; } Filename = GetFullPath( argv[0] ); if (!Filename) { DisplayError(); if (argc != 0) { 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; } Status = DeviceIoControl( FileHandle, FSCTL_DELETE_OBJECT_ID, NULL, 0, NULL, 0, &BytesReturned, (LPOVERLAPPED)NULL ); if (!Status) { DisplayError(); ExitCode = EXIT_CODE_FAILURE; leave; } } finally { if (FileHandle != INVALID_HANDLE_VALUE) { CloseHandle( FileHandle ); } free( Filename ); } return ExitCode; }