// FrcOwn.cpp : Implementation of CForceOwnership #include "pch.cxx" #pragma hdrstop #define TRKDATA_ALLOCATE #include #include #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(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(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(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(_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(_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(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 ); }