windows-nt/Source/XPSP1/NT/com/svcdlls/trksvcs/itrkadmn/frcown.cpp

956 lines
27 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// FrcOwn.cpp : Implementation of CForceOwnership
#include "pch.cxx"
#pragma hdrstop
#define TRKDATA_ALLOCATE
#include <trklib.hxx>
#include <trksvr.hxx>
#undef TRKDATA_ALLOCATE
#include "stdafx.h"
#include "ITrkAdmn.h"
#include "FrcOwn.h"
STDMETHODIMP
CTrkForceOwnership::Volumes(BSTR bstrUncPath, long scope )
{
HRESULT hr = S_OK;
HANDLE hFile = NULL;
CVolumeId volid;
CMachineId mcid( (LPWSTR) bstrUncPath );
CRpcClientBinding rc;
CPCVolumes cpcVolumes( &mcid, &_voltab, &_refreshSequenceStorage );
TRpcPipeControl< TRK_VOLUME_TRACKING_INFORMATION_PIPE,
TRK_VOLUME_TRACKING_INFORMATION,
CPCVolumes
> cpipeVolumes( &cpcVolumes );
rc.Initialize( mcid );
if( TRKINFOSCOPE_VOLUME == scope )
{
NTSTATUS status;
IO_STATUS_BLOCK Iosb;
FILE_FS_OBJECTID_INFORMATION fsobOID;
status = TrkCreateFile( bstrUncPath, SYNCHRONIZE | FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
FILE_OPEN_NO_RECALL, NULL, &hFile );
if( !NT_SUCCESS(status) )
{
hFile = NULL;
TrkLog((TRKDBG_ERROR, TEXT("Couldn't open volume %s"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
status = NtQueryVolumeInformationFile( hFile, &Iosb, &fsobOID, sizeof(fsobOID),
FileFsObjectIdInformation );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_VOLUME_TRACKING_INFORMATION volinfo;
volinfo.volindex = -1;
cpcVolumes.Push( &volinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed NtQueryVolumeInformationFile (%s)"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
volid.Load( &volid, fsobOID );
NtClose( hFile );
hFile = NULL;
}
else if( TRKINFOSCOPE_MACHINE != scope )
{
TrkLog((TRKDBG_ERROR, TEXT("Bad scope to CTrkForceOwnership::VolumeStatus (%l)"), scope ));
TrkRaiseWin32Error( ERROR_INVALID_PARAMETER );
}
RpcTryExcept
{
hr = GetVolumeTrackingInformation( rc, volid, static_cast<TrkInfoScope>(scope), cpipeVolumes );
if( SUCCEEDED(hr) && SUCCEEDED(cpcVolumes.GetHResult()) )
hr = TriggerVolumeClaims( rc, cpcVolumes.Count(), cpcVolumes.GetVolIds() );
}
RpcExcept( BreakOnDebuggableException() )
{
hr = RpcExceptionCode();
}
RpcEndExcept;
Exit:
if( NULL != hFile )
NtClose( hFile );
return( hr );
}
STDMETHODIMP
CTrkForceOwnership::Files(BSTR bstrUncPath, long scope)
{
HRESULT hr = E_FAIL;
HANDLE hFile = NULL;
CPCFiles cpcFiles( &_idt );
TRpcPipeControl< TRK_FILE_TRACKING_INFORMATION_PIPE,
TRK_FILE_TRACKING_INFORMATION,
CPCFiles
> cpipeFiles( &cpcFiles);
CMachineId mcid( (LPWSTR) bstrUncPath );
CRpcClientBinding rc;
__try
{
NTSTATUS status;
CDomainRelativeObjId droidCurrent, droidBirth;
if( TRKINFOSCOPE_ONE_FILE == scope )
{
// BUGBUG P2: Optimize this; we don't need droidBirth
status = GetDroids( bstrUncPath, &droidCurrent, &droidBirth, RGO_READ_OBJECTID );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_FILE_TRACKING_INFORMATION fileinfo;
_tcscpy( fileinfo.tszFilePath, TEXT("") );
fileinfo.hr = HRESULT_FROM_NT( status );
cpcFiles.Push( &fileinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed GetDroids (%s)"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
}
else if( TRKINFOSCOPE_VOLUME == scope )
{
NTSTATUS status;
IO_STATUS_BLOCK Iosb;
FILE_FS_OBJECTID_INFORMATION fsobOID;
CVolumeId volid;
status = TrkCreateFile( bstrUncPath, SYNCHRONIZE | FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
FILE_OPEN_NO_RECALL, NULL, &hFile );
if( !NT_SUCCESS(status) )
{
hFile = NULL;
TrkLog((TRKDBG_ERROR, TEXT("Couldn't open volume %s"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
status = NtQueryVolumeInformationFile( hFile, &Iosb, &fsobOID, sizeof(fsobOID),
FileFsObjectIdInformation );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_FILE_TRACKING_INFORMATION fileinfo;
_tcscpy( fileinfo.tszFilePath, TEXT("") );
fileinfo.hr = HRESULT_FROM_NT( status );
cpcFiles.Push( &fileinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed NtQueryVolumeInformationFile (%s)"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
volid.Load( &volid, fsobOID );
droidCurrent = CDomainRelativeObjId( volid, CObjId() );
NtClose( hFile );
hFile = NULL;
}
else if( TRKINFOSCOPE_MACHINE != scope )
{
TrkLog((TRKDBG_ERROR, TEXT("Bad scope to CTrkForceOwnership::FileStatus (%d)"), scope ));
TrkRaiseWin32Error( ERROR_INVALID_PARAMETER );
}
rc.Initialize( mcid );
RpcTryExcept
{
hr = GetFileTrackingInformation( rc, droidCurrent, static_cast<TrkInfoScope>(scope), cpipeFiles );
}
RpcExcept( BreakOnDebuggableException() )
{
hr = HRESULT_FROM_WIN32( RpcExceptionCode() );
}
RpcEndExcept;
if( FAILED(hr) ) goto Exit;
}
__except( BreakOnDebuggableException() )
{
hr = GetExceptionCode();
}
Exit:
if( NULL != hFile )
NtClose( hFile );
return( hr );
}
STDMETHODIMP
CTrkForceOwnership::VolumeStatus(BSTR bstrUncPath, long scope,
VARIANT *pvarlongVolIndex, VARIANT *pvarbstrVolId, VARIANT *pvarlongStatus)
{
HRESULT hr = E_FAIL;
HANDLE hFile = NULL;
SAFEARRAYBOUND sabound;
CVolumeId volid;
// Determine the machine ID
CMachineId mcid( (LPWSTR) bstrUncPath );
CRpcClientBinding rc;
// This is used by the RPC server to pull the bstrUncPath
CPCPath cpcPath( bstrUncPath );
TRpcPipeControl< TCHAR_PIPE, TCHAR, CPCPath> cpipePath( &cpcPath );
// This is used by the RPC server to push the volume information
CPCVolumeStatus cpcVolumeStatus( &_voltab );
TRpcPipeControl< TRK_VOLUME_TRACKING_INFORMATION_PIPE, TRK_VOLUME_TRACKING_INFORMATION, CPCVolumeStatus
> cpipeVolumeStatus( &cpcVolumeStatus );
__try
{
NTSTATUS status;
// Initialize the outputs
VariantInit( pvarlongVolIndex );
VariantInit( pvarbstrVolId );
VariantInit( pvarlongStatus );
// Initialize the pipe callback
cpcVolumeStatus.Initialize( &mcid, pvarlongVolIndex, pvarbstrVolId, pvarlongStatus );
// Connect to the workstation in question
rc.Initialize( mcid );
if( TRKINFOSCOPE_VOLUME == scope )
{
IO_STATUS_BLOCK Iosb;
FILE_FS_OBJECTID_INFORMATION fsobOID;
status = TrkCreateFile( bstrUncPath, SYNCHRONIZE | FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
FILE_OPEN_NO_RECALL, NULL, &hFile );
if( !NT_SUCCESS(status) )
{
hFile = NULL;
TrkLog((TRKDBG_ERROR, TEXT("Couldn't open volume %s"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
status = NtQueryVolumeInformationFile( hFile, &Iosb, &fsobOID, sizeof(fsobOID),
FileFsObjectIdInformation );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_VOLUME_TRACKING_INFORMATION volinfo;
volinfo.volindex = -1;
cpcVolumeStatus.Push( &volinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed NtQueryVolumeInformationFile (%s)"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
volid.Load( &volid, fsobOID );
NtClose( hFile );
hFile = NULL;
}
else if( TRKINFOSCOPE_MACHINE != scope )
{
TrkLog((TRKDBG_ERROR, TEXT("Bad scope to CTrkForceOwnership::VolumeStatus (%l)"), scope ));
TrkRaiseWin32Error( ERROR_INVALID_PARAMETER );
}
RpcTryExcept
{
hr = GetVolumeTrackingInformation( rc, volid, static_cast<TrkInfoScope>(scope), cpipeVolumeStatus );
}
RpcExcept( BreakOnDebuggableException() )
{
hr = HRESULT_FROM_WIN32( RpcExceptionCode() );
}
RpcEndExcept;
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed call to GetVolumeTrackInformation")));
TrkRaiseException( hr );
}
if( FAILED(cpcVolumeStatus.GetHResult()) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed in VolumeStatus pipe callback")));
TrkRaiseException( cpcVolumeStatus.GetHResult() );
}
// Truncate the safearrays
cpcVolumeStatus.Compact();
}
__except( BreakOnDebuggableException() )
{
cpcVolumeStatus.UnInitialize();
hr = GetExceptionCode();
}
Exit:
if( FAILED(hr) )
{
VariantClear( pvarlongVolIndex );
VariantClear( pvarbstrVolId );
VariantClear( pvarlongStatus );
}
if( NULL != hFile )
NtClose( hFile );
return( hr );
}
void
CPCVolumeStatus::Initialize( CMachineId *pmcid, VARIANT *pvarlongVolIndex, VARIANT *pvarbstrVolId, VARIANT *pvarlongStatus )
{
_pmcid = pmcid;
_pvarlongVolIndex = pvarlongVolIndex;
_pvarbstrVolId = pvarbstrVolId;
_pvarlongStatus = pvarlongStatus;
_iArrays = 0;
_hr = S_OK;
_sabound.lLbound = 0;
_sabound.cElements = NUM_VOLUMES;
_fInitialized = TRUE;
_pvarlongVolIndex->parray = SafeArrayCreate( VT_I4, 1, &_sabound );
if( NULL == _pvarlongVolIndex->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarlongVolIndex->vt = VT_I4 | VT_ARRAY;
_pvarbstrVolId->parray = SafeArrayCreate( VT_BSTR, 1, &_sabound );
if( NULL == _pvarbstrVolId->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarbstrVolId->vt = VT_BSTR | VT_ARRAY;
_pvarlongStatus->parray = SafeArrayCreate( VT_I4, 1, &_sabound );
if( NULL == _pvarlongStatus->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarlongStatus->vt = VT_I4 | VT_ARRAY;
}
void
CPCVolumeStatus::UnInitialize()
{
// Nothing to do, the Variants are cleaned by the caller
return;
}
void
CPCVolumeStatus::Push( TRK_VOLUME_TRACKING_INFORMATION *pVolInfo, unsigned long cElems )
{
TrkLog(( TRKDBG_ADMIN, TEXT("CPCVolumeStatus received %d elements"), cElems ));
HRESULT hr = S_OK;
HRESULT hrGet;
ULONG iElem = 0;
BSTR bstrVolId = NULL;
__try
{
for( iElem = 0; iElem < cElems; iElem++ )
{
CMachineId mcidCheck;
CVolumeSecret volsecCheck;
SequenceNumber seqCheck;
CVolumeId volNULL;
TCHAR tszVolId[ 40 ];
TCHAR *ptszVolId = tszVolId;
long VolOwnership = OBJOWN_UNKNOWN;
if( pVolInfo[iElem].volume != volNULL )
hrGet = _pvoltab->GetVolumeInfo( pVolInfo[iElem].volume, &mcidCheck, &volsecCheck, &seqCheck );
if( _iArrays >= static_cast<LONG>(_sabound.cElements) )
{
TrkAssert( !TEXT("Not yet implemented") );
// BUGBUG: do a SafeArrayReDim
return;
}
TrkAssert( sizeof(long) == sizeof(pVolInfo[iElem].volindex) );
hr = SafeArrayPutElement( _pvarlongVolIndex->parray, &_iArrays, &pVolInfo[iElem].volindex );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElement")));
TrkRaiseException( hr );
}
// BUGBUG: Add a Serialize(BSTR) method to CVolumeId
pVolInfo[iElem].volume.Stringize( ptszVolId );
bstrVolId = SysAllocString( tszVolId );
if( NULL == bstrVolId )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SysAllocString")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
hr = SafeArrayPutElement( _pvarbstrVolId->parray, &_iArrays, bstrVolId );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElement")));
TrkRaiseException( hr );
}
if( S_OK != hrGet )
{
VolOwnership = OBJOWN_DOESNT_EXIST;
}
else if( mcidCheck == *_pmcid )
{
VolOwnership = OBJOWN_OWNED;
}
else if( volNULL == pVolInfo[iElem].volume )
{
VolOwnership = OBJOWN_NO_ID;
}
else
{
VolOwnership = OBJOWN_NOT_OWNED;
}
hr = SafeArrayPutElement( _pvarlongStatus->parray, &_iArrays, &VolOwnership );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElemnt")));
TrkRaiseException( hr );
}
SysFreeString( bstrVolId ); bstrVolId = NULL;
_iArrays++;
}
}
__except( BreakOnDebuggableException() )
{
hr = GetExceptionCode();
}
Exit:
if( FAILED(hr) )
{
if( NULL != bstrVolId )
SysFreeString( bstrVolId );
if( !FAILED(_hr) )
_hr = hr;
}
return;
}
void
CPCVolumeStatus::Compact()
{
HRESULT hr = S_OK;
_sabound.cElements = _iArrays;
hr = SafeArrayRedim( _pvarlongVolIndex->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
hr = SafeArrayRedim( _pvarbstrVolId->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
hr = SafeArrayRedim( _pvarlongStatus->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
}
void
CPCVolumes::Push( TRK_VOLUME_TRACKING_INFORMATION *pVolInfo, unsigned long cElems )
{
TrkLog(( TRKDBG_ADMIN, TEXT("CPCVolumeStatus received %d elements"), cElems ));
HRESULT hr = S_OK;
ULONG iElem = 0;
__try
{
for( iElem = 0; iElem < cElems; iElem++ )
{
hr = _pvoltab->SetMachine( pVolInfo[iElem].volume, *_pmcid );
if( TRK_S_VOLUME_NOT_FOUND == hr )
_pvoltab->CreateVolume(
pVolInfo[iElem].volume,
*_pmcid,
CVolumeSecret(),
_pRefreshSequenceStorage->GetSequenceNumber() );
// BUGBUG P1: Handle this error
TrkAssert( SUCCEEDED(hr) );
_rgvolid[ _cVolIds++ ] = pVolInfo[iElem].volume;
}
}
__except( BreakOnDebuggableException() )
{
hr = GetExceptionCode();
}
if( FAILED(hr) )
{
if( !FAILED(_hr) )
_hr = hr;
}
return;
}
void
CPCFiles::Push( TRK_FILE_TRACKING_INFORMATION *pFileInfo, unsigned long cElems )
{
ULONG iFile;
__try
{
// BUGBUG P2: Instead of a loop, batch these up
for( iFile = 0; iFile < cElems; iFile++ )
{
_pidt->Delete( pFileInfo[iFile].droidBirth );
TrkVerify( _pidt->Add( pFileInfo[iFile].droidBirth, pFileInfo[iFile].droidLast,
pFileInfo[iFile].droidBirth ));
}
}
__except( BreakOnDebuggableException() )
{
TrkLog(( TRKDBG_ERROR, TEXT("CPCFiles::Push had an exception (%08x)"), GetExceptionCode() ));
}
}
void
CPCFileStatus::Push( TRK_FILE_TRACKING_INFORMATION *pFileInfo, unsigned long cElems )
{
TrkLog(( TRKDBG_ADMIN, TEXT("CPCFileStatus received %d elements"), cElems ));
HRESULT hr = S_OK;
ULONG iElem = 0;
BSTR bstr = NULL;
__try
{
for( iElem = 0; iElem < cElems; iElem++ )
{
BOOL fExistsInTable = FALSE;
BOOL fAtBirthplace = FALSE;
CDomainRelativeObjId droidBirthCheck;
CDomainRelativeObjId droidNowCheck;
const CDomainRelativeObjId droidNULL;
TCHAR tszDroid[ MAX_PATH ];
long FileOwnership;
if( droidNULL == pFileInfo[iElem].droidBirth
||
pFileInfo[iElem].droidBirth == pFileInfo[iElem].droidLast )
{
fAtBirthplace = TRUE;
}
else
{
fExistsInTable = _pidt->Query( pFileInfo[iElem].droidBirth, &droidNowCheck, &droidBirthCheck );
}
if( _iArrays >= static_cast<LONG>(_sabound.cElements) )
{
TrkAssert( !TEXT("Not yet impelemented") );
// BUGBUG: do a SafeArrayReDim
return;
}
bstr = SysAllocString( pFileInfo[iElem].tszFilePath );
if( NULL == bstr )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SysAllocString")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
hr = SafeArrayPutElement( _pvarrgbstrFileName->parray, &_iArrays, bstr );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElement")));
TrkRaiseException( hr );
}
SysFreeString( bstr ); bstr = NULL;
// BUGBUG: Add a Serialize(BSTR) method to CDroid
pFileInfo[iElem].droidBirth.Stringize( tszDroid, sizeof(tszDroid) );
bstr = SysAllocString( tszDroid );
if( NULL == bstr )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SysAllocString")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
hr = SafeArrayPutElement( _pvarrgbstrFileId->parray, &_iArrays, bstr );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElement")));
TrkRaiseException( hr );
}
if( fAtBirthplace )
FileOwnership = OBJOWN_OWNED;
else if( !fExistsInTable )
FileOwnership = OBJOWN_DOESNT_EXIST;
else if( droidNowCheck == pFileInfo[iElem].droidLast
&&
droidBirthCheck == pFileInfo[iElem].droidBirth )
FileOwnership = OBJOWN_OWNED;
else
FileOwnership = OBJOWN_NOT_OWNED;
hr = SafeArrayPutElement( _pvarrglongStatus->parray, &_iArrays, &FileOwnership );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayPutElemnt")));
TrkRaiseException( hr );
}
_iArrays++;
}
}
__except( BreakOnDebuggableException() )
{
hr = GetExceptionCode();
}
Exit:
if( FAILED(hr) )
{
if( NULL != bstr )
SysFreeString( bstr );
if( !FAILED(_hr) )
_hr = hr;
}
return;
}
void
CPCFileStatus::Initialize( CMachineId *pmcid, VARIANT *pvarrgbstrFileName,
VARIANT *pvarrgbstrFileId, VARIANT *pvarrglongStatus )
{
_pmcid = pmcid;
_pvarrgbstrFileName = pvarrgbstrFileName;
_pvarrgbstrFileId = pvarrgbstrFileId;
_pvarrglongStatus = pvarrglongStatus;
_iArrays = 0;
_hr = S_OK;
_sabound.lLbound = 0;
_sabound.cElements = 10;
_fInitialized = TRUE;
_pvarrgbstrFileName->parray = SafeArrayCreate( VT_BSTR, 1, &_sabound );
if( NULL == _pvarrgbstrFileName->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarrgbstrFileName->vt = VT_BSTR | VT_ARRAY;
_pvarrgbstrFileId->parray = SafeArrayCreate( VT_BSTR, 1, &_sabound );
if( NULL == _pvarrgbstrFileId->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarrgbstrFileId->vt = VT_BSTR | VT_ARRAY;
_pvarrglongStatus->parray = SafeArrayCreate( VT_I4, 1, &_sabound );
if( NULL == _pvarrglongStatus->parray )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed SafeArrayCreate")));
TrkRaiseWin32Error( E_OUTOFMEMORY );
}
_pvarrglongStatus->vt = VT_I4 | VT_ARRAY;
} // CPCFileStatus::Initialize
void
CPCFileStatus::Compact()
{
HRESULT hr = S_OK;
_sabound.cElements = _iArrays;
hr = SafeArrayRedim( _pvarrgbstrFileName->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
hr = SafeArrayRedim( _pvarrgbstrFileId->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
hr = SafeArrayRedim( _pvarrglongStatus->parray, &_sabound );
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't redim safearray")));
TrkRaiseException( hr );
}
}
STDMETHODIMP CTrkForceOwnership::FileStatus(BSTR bstrUncPath, long scope,
VARIANT * pvarrgbstrFileName, VARIANT *pvarrgbstrFileId, VARIANT * pvarrglongStatus)
{
HRESULT hr = E_FAIL;
SAFEARRAYBOUND sabound;
HANDLE hFile = NULL;
// Determine the machine ID
CMachineId mcid( (LPWSTR) bstrUncPath );
CRpcClientBinding rc;
// This is used by the RPC server to push the volume information
CPCFileStatus cpcFileStatus( &_idt );
TRpcPipeControl< TRK_FILE_TRACKING_INFORMATION_PIPE, TRK_FILE_TRACKING_INFORMATION, CPCFileStatus
> cpipeFileStatus( &cpcFileStatus );
__try
{
NTSTATUS status;
// Initialize the outputs
VariantInit( pvarrgbstrFileName );
VariantInit( pvarrgbstrFileId );
VariantInit( pvarrglongStatus );
CDomainRelativeObjId droidCurrent, droidBirth;
// Initialize the pipe callback
cpcFileStatus.Initialize( &mcid, pvarrgbstrFileName, pvarrgbstrFileId, pvarrglongStatus );
if( TRKINFOSCOPE_ONE_FILE == scope )
{
// BUGBUG P2: Optimize this; we don't need droidBirth
status = GetDroids( bstrUncPath, &droidCurrent, &droidBirth, RGO_READ_OBJECTID );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_FILE_TRACKING_INFORMATION fileinfo;
_tcscpy( fileinfo.tszFilePath, TEXT("") );
fileinfo.hr = HRESULT_FROM_NT( status );
cpcFileStatus.Push( &fileinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed GetDroids (%s)"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
}
else if( TRKINFOSCOPE_VOLUME == scope )
{
NTSTATUS status;
IO_STATUS_BLOCK Iosb;
FILE_FS_OBJECTID_INFORMATION fsobOID;
CVolumeId volid;
status = TrkCreateFile( bstrUncPath, SYNCHRONIZE | FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
FILE_OPEN_NO_RECALL, NULL, &hFile );
if( !NT_SUCCESS(status) )
{
hFile = NULL;
TrkLog((TRKDBG_ERROR, TEXT("Couldn't open volume %s"), bstrUncPath ));
TrkRaiseNtStatus( status );
}
status = NtQueryVolumeInformationFile( hFile, &Iosb, &fsobOID, sizeof(fsobOID),
FileFsObjectIdInformation );
if( STATUS_OBJECT_NAME_NOT_FOUND == status )
{
TRK_FILE_TRACKING_INFORMATION fileinfo;
_tcscpy( fileinfo.tszFilePath, TEXT("") );
fileinfo.hr = HRESULT_FROM_NT( status );
cpcFileStatus.Push( &fileinfo, 1 );
hr = S_OK;
goto Exit;
}
else if( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed NtQueryVolumeInformationFile (%s)"), bstrUncPath));
TrkRaiseNtStatus( status );
}
volid.Load( &volid, fsobOID );
droidCurrent = CDomainRelativeObjId( volid, CObjId() );
NtClose( hFile );
hFile = NULL;
}
else if( TRKINFOSCOPE_MACHINE != scope )
{
TrkLog((TRKDBG_ERROR, TEXT("Bad scope to CTrkForceOwnership::FileStatus (%d)"), scope ));
TrkRaiseWin32Error( ERROR_INVALID_PARAMETER );
}
// Connect to the workstation in question
rc.Initialize( mcid );
// Get the volume status info
RpcTryExcept
{
hr = GetFileTrackingInformation( rc, droidCurrent, static_cast<TrkInfoScope>(scope), cpipeFileStatus );
}
RpcExcept( BreakOnDebuggableException() )
{
hr = HRESULT_FROM_WIN32( RpcExceptionCode() );
}
RpcEndExcept;
if( FAILED(hr) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed call to GetFileTrackInformation")));
TrkRaiseException( hr );
}
if( FAILED(cpcFileStatus.GetHResult()) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed in FileStatus pipe callback")));
TrkRaiseException( cpcFileStatus.GetHResult() );
}
// Truncate the safearrays
cpcFileStatus.Compact();
}
__except( BreakOnDebuggableException() )
{
cpcFileStatus.UnInitialize();
hr = GetExceptionCode();
}
Exit:
if( NULL != hFile )
NtClose( hFile );
if( FAILED(hr) )
{
VariantClear( pvarrgbstrFileName );
VariantClear( pvarrgbstrFileId );
VariantClear( pvarrglongStatus );
}
return( hr );
}