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.
 
 
 
 
 
 

389 lines
9.9 KiB

// Copyright (c) 1996-1999 Microsoft Corporation
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// File: fileops.hxx
//
// Contents: Definitions for OBJID and file operations
//
// Classes:
//
// Functions:
//
//
//
// History: 18-Nov-96 BillMo Created.
//
// Notes:
//
// Codework:
//
//--------------------------------------------------------------------------
unsigned
ConvertToNtPath(const TCHAR *ptszVolumePath, WCHAR *pwszNtPath, ULONG cwcBuf);
//+----------------------------------------------------------------------------
//
// CVolumeDeviceName
//
// This represents a "volume device name", as defined by the mount manager.
// Volume device names are of the form (but without the trailing whack). E.g.:
//
// "\\?\Volume{856d50da-d07e-11d2-9e72-806d6172696f}"
//
//+----------------------------------------------------------------------------
class CVolumeDeviceName
{
public:
// Create a volume device name from a zero-relative
// drive letter index.
CVolumeDeviceName( LONG iVol )
{
_stprintf( _tszPath, TEXT("\\\\.\\%c:"), iVol+TEXT('A') );
}
// Return the volume name..
operator const TCHAR*() const
{
return( _tszPath );
}
// Validate a zero-relative drive letter index.
static BOOL IsValid( LONG iVol )
{
if( 0 <= iVol && NUM_VOLUMES > iVol )
return( TRUE );
else
return( FALSE );
}
private:
TCHAR _tszPath[ MAX_PATH ];
};
//
// IsLocalObjectVolume
//
// Returns true of the volume supports object IDs (NTFS5).
//
BOOL IsLocalObjectVolume( const TCHAR *ptszVolumeName );
inline BOOL
IsLocalObjectVolume( LONG iVol )
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
TCHAR tszVolumeName[ MAX_PATH+1 ];
_tcscpy( tszVolumeName, CVolumeDeviceName(iVol) );
_tcscat( tszVolumeName, TEXT("\\") );
return( IsLocalObjectVolume( tszVolumeName ));
}
//
// IsSystemVolumeInformation
//
// Returns true if the path is somewhere under "\System Volume Information"
//
BOOL IsSystemVolumeInformation( const TCHAR *ptszPath );
HRESULT
MapLocalPathToUNC( RPC_BINDING_HANDLE IDL_handle,
const TCHAR *ptszLocalPath,
TCHAR *ptszUNC,
ULONG cbMaxUnc );
NTSTATUS
OpenFileById( const TCHAR *ptszVolumeDeviceName,
const CObjId &oid,
ACCESS_MASK AccessMask,
ULONG ShareAccess,
ULONG AdditionalCreateOptions,
HANDLE *ph);
inline NTSTATUS
OpenFileById( LONG iVol,
const CObjId &oid,
ACCESS_MASK AccessMask,
ULONG ShareAccess,
ULONG AdditionalCreateOptions,
HANDLE *ph)
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( OpenFileById( CVolumeDeviceName(iVol), oid,
AccessMask, ShareAccess, AdditionalCreateOptions, ph ));
}
NTSTATUS
OpenVolume( const TCHAR *ptszVolumeDeviceName, HANDLE * ph );
inline NTSTATUS
OpenVolume( LONG iVol, HANDLE * phVolume )
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( OpenVolume( CVolumeDeviceName(iVol), phVolume ));
}
NTSTATUS
CheckVolumeWriteProtection( const TCHAR *ptszVolumeDeviceName, BOOL *pfWriteProtected );
#define CCH_MAX_VOLUME_NAME 50 // \\?\Volume{96765fc3-9c72-11d1-b93d-000000000000}\
LONG
MapVolumeDeviceNameToIndex( TCHAR *ptszVolumeDeviceName );
NTSTATUS
SetVolId( const TCHAR *ptszVolumeDeviceName, const CVolumeId &volid );
inline NTSTATUS
SetVolId( LONG iVol, const CVolumeId &volid )
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( SetVolId( CVolumeDeviceName(iVol), volid ));
}
NTSTATUS
TrkCreateFile( const WCHAR *pwszCompleteDosPath,
ACCESS_MASK AccessMask,
ULONG Attributes,
ULONG ShareAccess,
ULONG CreationDisposition, // e.g. FILE_OPEN, FILE_OPEN_IF, etc
ULONG CreateOptions, // e.g. FILE_WRITE_THROUGH, FILE_OPEN_FOR_BACKUP_INTENT
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
HANDLE *ph);
NTSTATUS
FindLocalPath( IN const TCHAR *ptszVolumeDeviceName,
IN const CObjId &objid,
OUT CDomainRelativeObjId *pdroidBirth,
OUT TCHAR *ptszLocalPath );
inline NTSTATUS
FindLocalPath( IN ULONG iVol,
IN const CObjId &objid,
OUT CDomainRelativeObjId *pdroidBirth,
OUT TCHAR *ptszLocalPath )
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( FindLocalPath( CVolumeDeviceName(iVol), objid, pdroidBirth, ptszLocalPath ));
}
NTSTATUS
GetDroids( HANDLE hFile,
CDomainRelativeObjId *pdroidCurrent,
CDomainRelativeObjId *pdroidBirth,
RGO_ENUM rgoEnum );
NTSTATUS
GetDroids( const TCHAR *ptszFile,
CDomainRelativeObjId *pdroidCurrent,
CDomainRelativeObjId *pdroidBirth,
RGO_ENUM rgoEnum );
NTSTATUS
SetObjId( const HANDLE hFile,
CObjId objid,
const CDomainRelativeObjId &droidBirth );
NTSTATUS
SetObjId( const TCHAR *ptszFile,
CObjId objid,
const CDomainRelativeObjId &droidBirth );
NTSTATUS
MakeObjIdReborn(HANDLE hFile);
NTSTATUS
MakeObjIdReborn(const TCHAR *ptszVolumeDeviceName, const CObjId &objid);
inline NTSTATUS
MakeObjIdReborn(LONG iVol, const CObjId &objid)
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( MakeObjIdReborn( CVolumeDeviceName(iVol), objid ));
}
NTSTATUS
SetBirthId( HANDLE hFile,
const CDomainRelativeObjId &droidBirth );
NTSTATUS
SetBirthId( const TCHAR *ptszFile,
const CDomainRelativeObjId &droidBirth );
NTSTATUS
GetBirthId( IN HANDLE hFile, OUT CDomainRelativeObjId *pdroidBirth );
// This routine is inline because it doesn't get used in the production code,
// only in tests.
inline NTSTATUS
DelObjId(HANDLE hFile)
{
// -----------------
// Delete the Object ID
// -----------------
// Send the FSCTL
IO_STATUS_BLOCK IoStatus;
return NtFsControlFile(
hFile,
NULL,
NULL,
NULL,
&IoStatus,
FSCTL_DELETE_OBJECT_ID,
NULL, // in buffer
0, // in buffer size
NULL, // Out buffer
0); // Out buffer size
}
// This routine is inline because it doesn't get used in the production code,
// only in tests.
inline NTSTATUS
DelObjId(const TCHAR *ptszVolumeDeviceName, const CObjId &objid)
{
// --------------
// Initialization
// --------------
NTSTATUS status = STATUS_SUCCESS;
HANDLE hFile = NULL;
// -------------
// Open the file
// -------------
EnableRestorePrivilege();
status = OpenFileById(ptszVolumeDeviceName,
objid,
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_FOR_BACKUP_INTENT, // for FSCTL_DELETE_OBJECT_ID
&hFile);
if( !NT_SUCCESS(status) )
{
hFile = NULL;
TrkLog(( TRKDBG_ERROR, TEXT("Couldn't del objid, failed open (%08x)"),
status ));
goto Exit;
}
status = DelObjId( hFile );
if( !NT_SUCCESS(status) && STATUS_OBJECT_NAME_NOT_FOUND != status )
{
TrkLog(( TRKDBG_ERROR, TEXT("Couldn't delete file Object ID, failed delete (%08x)"),
status ));
goto Exit;
}
// ----
// Exit
// ----
Exit:
if( NULL != hFile )
NtClose( hFile );
return( status );
}
inline NTSTATUS
DelObjId(LONG iVol, const CObjId &objid)
{
if( !CVolumeDeviceName::IsValid(iVol) )
return( STATUS_OBJECT_PATH_NOT_FOUND );
return( DelObjId( CVolumeDeviceName(iVol), objid ));
}
//+----------------------------------------------------------------------------
//
// InterlockedCloseHandle
//
// This routine provides a thread-safe way to close a handle for code
// that isn't thread-safe. This is used by CloseVolumeHandles, since
// that routine can't take a lock.
//
//+----------------------------------------------------------------------------
inline void
InterlockedCloseHandle( HANDLE *ph, void* EmptyValue = NULL, BOOL fCancelIo = FALSE )
{
HANDLE h1 = NULL;
HANDLE h2 = NULL;
// Get the current value.
h1 = *ph;
// If the handle hasn't changed between the previous line and the
// following call, set it to null.
h2 = InterlockedCompareExchangePointer( (void**)ph,
(void*)EmptyValue,
h1 );
// If *ph was unchanged as of the previous
// call, we've got a local copy of it now, and we can safely close it.
if( h1 == h2
&&
EmptyValue != h1 )
{
// *ph is already NULL
if( fCancelIo )
{
TrkLog(( TRKDBG_MISC, TEXT("Canceling handle x%x"), h1 ));
CancelIo( h1 );
}
TrkLog(( TRKDBG_MISC, TEXT("Closing handle x%x"), h1 ));
NtClose( h1 );
}
}