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.
 
 
 
 
 
 

1022 lines
30 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: opendoc.cxx
//
// Contents: Code that encapsulates an opened file on a Nt volume
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <docname.hxx>
#include <ciole.hxx>
#include <opendoc.hxx>
#include <statprop.hxx>
#include <imprsnat.hxx>
#include <dmnstart.hxx>
#include <queryexp.hxx>
#include <filterob.hxx>
#include <ntopen.hxx>
//+---------------------------------------------------------------------------
//
// Class: CImpersonatedOpenOpLock
//
// Purpose: Opens the oplock by doing any necessary impersonation. If there
// are multiple alternative user-ids, it will try until one
// succeeds or there are no more choices.
//
// History: 1-24-97 srikants Created
//
//----------------------------------------------------------------------------
class CImpersonatedOpenOpLock : public PImpersonatedWorkItem
{
public:
CImpersonatedOpenOpLock( const CFunnyPath & funnyDoc,
CImpersonateRemoteAccess * pRemoteAccess,
BOOL fTakeOpLock )
: PImpersonatedWorkItem( funnyDoc.GetActualPath() ),
_funnyDoc(funnyDoc),
_fTakeOpLock( fTakeOpLock ),
_pRemoteAccess( pRemoteAccess ),
_fSharingViolation(FALSE)
{
}
BOOL DoIt(); // virtual
void Open()
{
if ( _pRemoteAccess )
{
ImpersonateAndDoWork( *_pRemoteAccess );
}
else
{
BOOL fSuccess = DoIt();
Win4Assert( fSuccess );
}
}
CFilterOplock * Acquire()
{
return _oplock.Acquire();
}
BOOL IsSharingViolation() const
{
return _fSharingViolation;
}
BOOL IsOffline() const
{
return _oplock->IsOffline();
}
BOOL IsNotContentIndexed() const
{
return _oplock->IsNotContentIndexed();
}
private:
const CFunnyPath & _funnyDoc;
BOOL _fTakeOpLock;
CImpersonateRemoteAccess * _pRemoteAccess;
XPtr<CFilterOplock> _oplock;
BOOL _fSharingViolation;
};
//+---------------------------------------------------------------------------
//
// Member: CImpersonatedOpenOpLock::DoIt
//
// Synopsis: The virtual "DoIt" method that does the work under the
// impersonated context (if necessary).
//
// Returns: TRUE if successful.
// FALSE if another impersonation must be tried
// THROWS if there is a failure and no impersonation to be
// tried.
//
// History: 1-24-97 srikants Created
//
//----------------------------------------------------------------------------
BOOL CImpersonatedOpenOpLock::DoIt()
{
BOOL fStatus = TRUE;
BOOL fTryAgain = TRUE;
for (;;)
{
TRY
{
_oplock.Set( new CFilterOplock( _funnyDoc, _fTakeOpLock ) );
break;
}
CATCH( CException, e )
{
NTSTATUS Status = e.GetErrorCode();
//
// If the path was a net path, we may have to use a different impersonation
// to gain access. We try until there are no more impersonation choices left.
//
if ( _fNetPath && 0 != _pRemoteAccess &&
IsRetryableError(Status) )
{
fStatus = FALSE;
ciDebugOut(( DEB_WARN, "Trying another user-id for (%ws)\n",
_funnyDoc.GetPath() ));
}
else
{
if ( fTryAgain && ::IsSharingViolation( Status ) )
{
_fSharingViolation = TRUE;
_fTakeOpLock = FALSE;
fTryAgain = FALSE;
continue;
}
ciDebugOut(( DEB_IWARN, "Failed to filter (%ws). Error (0x%X)\n",
_funnyDoc.GetPath(), e.GetErrorCode() ));
RETHROW();
}
break;
}
END_CATCH
}
return fStatus;
}
//+---------------------------------------------------------------------------
//
// Construction/Destruction
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::CCiCOpenedDoc
//
// Synopsis: Default constructor. We initialize the minimal set of
// members to indicate an inactive document
//
// Arguments: None
//
//----------------------------------------------------------------------------
CCiCOpenedDoc::CCiCOpenedDoc( CStorageFilterObject * pFilterObject,
CClientDaemonWorker * pWorker,
BOOL fTakeOpLock,
BOOL fFailIfNotContentIndexed )
:_RefCount( 1 ),
_TypeOfStorage( eUnknown ),
_llFileSize(0),
_pWorker( pWorker),
_pRemoteImpersonation(0),
_pFilterObject( pFilterObject ),
_fTakeOpLock( fTakeOpLock ),
_fSharingViolation( FALSE ),
_fFailIfNotContentIndexed( fFailIfNotContentIndexed )
{
if ( _pWorker )
{
_pRemoteImpersonation =
new CImpersonateRemoteAccess( &(_pWorker->GetImpersonationCache()) );
}
}
CCiCOpenedDoc::~CCiCOpenedDoc()
{
Win4Assert( 0 == _RefCount );
Close();
delete _pRemoteImpersonation;
}
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::_TooBigForDefault
//
// Synopsis: Checks if the given size is too big for using the default
// filter.
//
// Arguments: [ll] - Size to check
//
// History: 1-24-97 srikants Created
//
//----------------------------------------------------------------------------
inline BOOL CCiCOpenedDoc::_TooBigForDefault( LONGLONG const ll )
{
Win4Assert( 0 != _pWorker );
return( ll > (_pWorker->GetRegParams().GetMaxFilesizeFiltered() * 1024) );
}
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::_GetFileSize
//
// Synopsis: Retrieves the size of the current file.
//
// History: 1-24-97 srikants Created
//
//----------------------------------------------------------------------------
LONGLONG CCiCOpenedDoc::_GetFileSize()
{
Win4Assert( IsOpen( ) );
IO_STATUS_BLOCK IoStatus;
HANDLE FileHandle = _SafeOplock->GetFileHandle( );
Win4Assert( INVALID_HANDLE_VALUE != FileHandle );
FILE_STANDARD_INFORMATION stdInfo;
NTSTATUS Status = NtQueryInformationFile( FileHandle, // File handle
&IoStatus, // I/O Status
&stdInfo, // Buffer
sizeof( stdInfo ),// Buffer size
FileStandardInformation );
Win4Assert( STATUS_DATATYPE_MISALIGNMENT != Status );
if ( !NT_SUCCESS(Status) )
{
ciDebugOut(( DEB_IERROR, "Error 0x%x querying file info\n",
Status ));
QUIETTHROW( CException( Status ));
}
return stdInfo.EndOfFile.QuadPart;
}
//+---------------------------------------------------------------------------
//
// IUnknown method implementations
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::QueryInterface
//
// Synopsis: Supports IID_IUnknown and IID_ICiCOpenedDoc
//
// Arguments: [riid] - desired interface id
// [ppvObject] - output interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::QueryInterface(
REFIID riid,
void **ppvObject)
{
Win4Assert( 0 != ppvObject );
if ( IID_ICiCOpenedDoc == riid )
*ppvObject = (void *)((ICiCOpenedDoc *)this);
else if ( IID_IUnknown == riid )
*ppvObject = (void *)((IUnknown *)this);
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
} // QueryInterface
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::AddRef
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CCiCOpenedDoc::AddRef()
{
return InterlockedIncrement( &_RefCount );
} // AddRef
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::Release
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CCiCOpenedDoc::Release()
{
Win4Assert( _RefCount != 0 );
LONG RefCount = InterlockedDecrement( &_RefCount );
if ( RefCount <= 0 )
delete this;
return (ULONG) RefCount;
} // Release
//+---------------------------------------------------------------------------
//
// ICiCOpenedDoc method implementations
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::Open
//
// Synopsis: Opens the specified file. In general, the caller
// passes an implementation-specific blob of data to the
// ICiCOpenedDoc interface. The selected implementation is
// free to choose how it wants to interpret it. This
// implementation considers it to be a lpwstr.
//
// Arguments: [pbDocName] - Pointer to, presumably, lpwstr
// [cbDocName] - Length in BYTES, not characters, of the name
//
// Returns: S_OK if successful
// FILTER_E_ALREADY_OPEN if there is already an open document
// FILTER_E_UNREACHABLE if there is a net failure
// FILTER_E_IN_USE if the document is in use by another proess
// other errors as appropriate
//
//----------------------------------------------------------------------------
SCODE CCiCOpenedDoc::Open ( BYTE const * pbDocName, ULONG cbDocName )
{
//
// We cannot open if we're already open
//
if ( IsOpen() )
{
ciDebugOut(( DEB_IERROR, "CCiCOpenedDoc::Open - Document is already open\n" ));
return FILTER_E_ALREADY_OPEN;
}
//
// The docname (Path) is always null terminated. It is an empty string
// for a deleted document.
//
if ( cbDocName <= 2 )
return CI_E_NOT_FOUND;
SCODE sc = S_OK;
TRY
{
//
// Safely construct each piece.
//
XInterface<CCiCDocName> LocalFileName( new CCiCDocName( (PWCHAR) pbDocName, cbDocName / sizeof( WCHAR )));
_funnyFileName.SetPath( (const WCHAR*)pbDocName, (cbDocName/sizeof(WCHAR) - 1) );
#if DBG || CIDBG
//
// Check that we haven't been asked to filter a file in a catalog.wci
// directory.
//
const WCHAR * pwszComponent = (WCHAR *)pbDocName;
while (pwszComponent = wcschr(pwszComponent+1, L'\\'))
{
Win4Assert ( _wcsnicmp( pwszComponent,
L"\\catalog.wci\\",
wcslen(L"\\catalog.wci\\" )) != 0 );
}
#endif // DBG || CIDBG
//
// We have to impersonate before accessing.
//
CImpersonatedOpenOpLock openDoc( _funnyFileName,
_pRemoteImpersonation,
_fTakeOpLock );
openDoc.Open();
//
// Anything bad happen?
//
if ( openDoc.IsSharingViolation() )
sc = FILTER_E_IN_USE;
else if ( openDoc.IsOffline() )
sc = FILTER_E_OFFLINE;
else if ( _fFailIfNotContentIndexed && openDoc.IsNotContentIndexed() )
{
ciDebugOut(( DEB_ITRACE, "not indexing not-indexed file\n" ));
sc = FILTER_E_IN_USE;
}
else
{
//
// At this point, everything is correctly opened. We assign to the
// members. This disconnects the objects from the safe pointers.
//
_FileName.Set( LocalFileName.Acquire( ));
_SafeOplock.Set( openDoc.Acquire( ));
_TypeOfStorage = eUnknown;
}
}
CATCH ( CException, e )
{
//
// Grab status code and convert to SCODE. Convert the status,
// if possible, to a known class of SCODE that the caller might,
// in some way, be able to deal with.
//
NTSTATUS Status = e.GetErrorCode( );
if (::IsSharingViolation( Status ))
{
ciDebugOut(( DEB_IERROR, "CCiCOpenedDoc::Open - sharing violation - %x\n", Status ));
sc = FILTER_E_IN_USE;
_fSharingViolation = TRUE;
}
else if (IsNetDisconnect( Status ))
{
ciDebugOut(( DEB_ERROR, "CCiCOpenedDoc::Open - net disconnect - %x\n", Status ));
sc = FILTER_E_UNREACHABLE;
}
else
{
ciDebugOut(( DEB_ITRACE, "CCiCOpenedDoc::Open - other error - %x\n", Status ));
sc = Status;
}
}
END_CATCH
return sc;
} //Open
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::Close
//
// Synopsis: Terminate all access to a file
//
// Arguments: None.
//
// Returns: S_OK if successful
// FILTER_E_NOT_OPEN if there is no document
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::Close( void )
{
//
// If there is no document open, reject this call
//
if ( !IsOpen() )
return FILTER_E_NOT_OPEN;
if ( 0 != _pWorker )
_SafeOplock->MaybeSetLastAccessTime( _pWorker->GetRegParams().GetStompLastAccessDelay() );
//
// Release pointers
//
_Storage.Free();
_SafeOplock.Free( );
_FileName.Free( );
_funnyFileName.Truncate(0);
_llFileSize = 0;
return S_OK;
} //Close
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetDocumentName
//
// Synopsis: Returns the interface to the document name, if open.
//
// Arguments: [ppIDocName] - Pointer to the returned document name
//
// Returns: S_OK if successful
// FILTER_E_NOT_OPEN if document is not currently open
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetDocumentName(
ICiCDocName ** ppIDocName )
{
//
// If there is no name, then we haven't opened a document yet.
//
if (!IsOpen( )) {
return FILTER_E_NOT_OPEN;
}
//
// Set up return pointer and reference interface
//
*ppIDocName = _FileName.GetPointer( );
(*ppIDocName)->AddRef( );
return S_OK;
} // GetDocumentName
void FunnyToNormalPath( const CFunnyPath & funnyPath,
WCHAR * awcPath );
SCODE ShellBindToItemByName(
WCHAR const * pszFile,
REFIID riid,
void ** ppv );
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetPropertySetStorage
//
// Synopsis: Returns the interface to the underlying IStorage if we have
// a docfile.
//
// Returns: IStorage* of underlying docfile.
// NULL if not a docfile or not open
//
// History: 06-Apr-1998 KyleP Use only for property set storage
//
//----------------------------------------------------------------------------
IPropertySetStorage * CCiCOpenedDoc::GetPropertySetStorage()
{
// NTRAID#DB-NTBUG9-84131-2000/07/31-dlee Indexing Service contains workarounds for StgOpenStorage AV on > MAX_PATH paths
if ( _funnyFileName.GetLength() >= MAX_PATH )
{
ciDebugOut(( DEB_WARN, "Not calling StgOpenStorage in CCiCOpenedDoc::GetPropertySetStorage for paths > MAX_PATH: \n(%ws)\n",
_funnyFileName.GetPath() ));
_TypeOfStorage = eOther;
Win4Assert( _Storage.IsNull() );
return _Storage.GetPointer( );
}
//
// If we are open and we don't have a storage instance and we don't know
// the type of storage
//
if (IsOpen() && _Storage.IsNull( ) && _TypeOfStorage == eUnknown)
{
//
// Attempt to open docfile
//
Win4Assert( _Storage.IsNull() );
Win4Assert( !_SafeOplock->IsOffline() );
#if 0
SCODE sc = StgOpenStorageEx( _funnyFileName.GetPath( ), // Path
STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE, // Flags (BChapman said use these)
STGFMT_ANY, // Format
0, // Reserved
0, // Reserved
0, // Reserved
IID_IPropertySetStorage, // IID
_Storage.GetQIPointer() );
#else
//
// The shell expects the string not to change or go away until the
// IPropertySetStorage is released, so make a copy of it.
//
FunnyToNormalPath( _funnyFileName, _awcPath );
SCODE sc = ShellBindToItemByName( _awcPath,
IID_IPropertySetStorage,
_Storage.GetQIPointer() );
#endif
//
// Set the type of storage based on what we found
//
if ( SUCCEEDED( sc ) )
_TypeOfStorage = eDocfile;
else
{
_TypeOfStorage = eOther;
Win4Assert( _Storage.IsNull() );
}
}
return _Storage.GetPointer( );
} //GetPropertySetStorage
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetStatPropertyEnum
//
// Synopsis: Return property storage for the "stat" (i.e., system storage)
// property set. This property set is not really stored in normal
// property storage but is faked out of Nt file information.
//
// Arguments: [ppIStatPropEnum] - pointer to the returned IPropertyStorage
// interface
//
// Returns: S_OK -if successful
// E_NOTIMPL if stat properties are not supported. This
// implementation supports them.
// FILTER_E_NOT_OPEN if there is no open document.
// Other as appropriate
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetStatPropertyEnum(
IPropertyStorage **ppIStatPropEnum )
{
//
// Make sure the document is open
//
if (!IsOpen( )) {
ciDebugOut(( DEB_IERROR, "Document is not open\n" ));
return FILTER_E_NOT_OPEN;
}
//
// Return and interface
//
*ppIStatPropEnum = new CStatPropertyStorage( _SafeOplock->GetFileHandle( ),
_funnyFileName.GetLength() );
return S_OK;
} // GetStatPropertyEnum
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetPropertySetEnum
//
// Synopsis: Returns the docfile property set storage interface on the
// current doc.
//
// Arguments: [ppIPropSetEnum] - returned pointer to the Docfile property
// set storage
//
// Returns: S_OK if successful
// FILTER_S_NO_PROPSETS if no property sets (beyond stat ones)
// available on this document
// FILTER_E_NOT_OPEN if the document is not currently open
// Other as appropriate
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetPropertySetEnum( IPropertySetStorage ** ppIPropSetEnum )
{
//
// Make sure the document is open
//
if ( !IsOpen() )
return FILTER_E_NOT_OPEN;
//
// Make sure the extra file handle in the oplock is closed
//
_SafeOplock->CloseFileHandle();
//
// Get the IStorage corresponding to this document
//
IPropertySetStorage * Storage = GetPropertySetStorage();
//
// If we couldn't get the IStorage, then we certainly
// couldn't get the property set storage
//
if ( 0 == Storage )
return FILTER_S_NO_PROPSETS;
Storage->AddRef();
*ppIPropSetEnum = Storage;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetPropertyEnum
//
// Synopsis: Return the property storage for a particular property set
//
// Arguments: [GuidPropSet] - GUID of the property set whose property
// storage is being requested
// [ppIPropEnum] - returned pointer to property storage
//
// Returns: S_OK if successful
// FILTER_E_NO_SUCH_PROPERTY - if property set with GUID not found
// FILTER_E_NOT_OPEN if there is no open document
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetPropertyEnum(
REFFMTID refGuidPropSet,
IPropertyStorage **ppIPropEnum )
{
//
// Get the property set storage interface
//
IPropertySetStorage *PropSetStorage;
SCODE sc = GetPropertySetEnum( &PropSetStorage );
if (!SUCCEEDED( sc )) {
return sc;
}
//
// Attempt to open the named property set.
//
HRESULT hr = PropSetStorage->Open( refGuidPropSet,
STGM_READ | STGM_SHARE_EXCLUSIVE, // BChapman said to use these
ppIPropEnum );
PropSetStorage->Release( );
if (!SUCCEEDED( hr )) {
return FILTER_E_NO_SUCH_PROPERTY;
}
return S_OK;
} // GetPropertyEnum
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetIFilter
//
// Synopsis: Return the appropriate filter bound to the document
//
// Arguments: [ppIFilter] - returned IFilter
//
// Returns: S_OK if successful
// FILTER_E_NOT_OPEN if there is no open document
// E_NOT_IMPL if not implemented
// Other as appropriate
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetIFilter(
IFilter ** ppIFilter )
{
SCODE sc = S_OK;
//
// We can't do anything if the document is not opened yet.
//
if ( !IsOpen() || IsSharingViolation() )
return FILTER_E_NOT_OPEN;
//
// Make sure the extra file handle in the oplock is closed
//
if ( INVALID_HANDLE_VALUE != _SafeOplock->GetFileHandle() )
{
_llFileSize = _GetFileSize();
_SafeOplock->CloseFileHandle();
}
//
// Call Ole to perform the binding
//
TRY
{
sc = CCiOle::BindIFilter( _funnyFileName.GetPath(), NULL, ppIFilter, FALSE );
if ( FAILED(sc) )
{
// MK_E_CANTOPENFILE is returned by the office filter. It should be
// fixed to return FILTER_E_ACCESS/FILTER_E_PASSWORD in case it is not able
// to open a file for filtering. Once that is done, we can get rid
// of MK_E_CANTOPENFILE condition
if ( FILTER_E_ACCESS == sc ||
( MK_E_CANTOPENFILE == sc && ::IsSharingViolation( GetLastError() ))
)
{
sc = FILTER_E_IN_USE ;
}
else if ( FILTER_E_PASSWORD == sc )
{
sc = FILTER_E_UNREACHABLE;
}
else if ( _pWorker->GetRegParams().FilterFilesWithUnknownExtensions() )
{
//
// File with unknown extension. Does the registry say that we should
// filter the file ?
//
ciDebugOut((DEB_IWARN, "Going to default filtering for %ws.\n",
_FileName->GetPath( ) ));
// TSTART(_drep->timerNoBind);
//
// Verify file is of appropriate size for default filtering.
//
if ( _TooBigForDefault( _llFileSize ) )
{
ciDebugOut(( DEB_IWARN,
"%ws too large for default filtering\n",
_FileName->GetPath( ) ));
//
// When this code was in CFilterDriver::Init we returned FILTER_E_TOO_BIG.
// Now we don't want to do that. Properties should still be filtered.
//
//sc = FILTER_E_TOO_BIG;
sc = LoadBinaryFilter( _funnyFileName.GetPath(), ppIFilter );
}
else
{
sc = LoadTextFilter( _funnyFileName.GetPath(), ppIFilter );
}
if ( FAILED(sc) )
{
if ( FILTER_E_ACCESS == sc )
{
sc = FILTER_E_IN_USE ;
}
else if ( FILTER_E_PASSWORD == sc )
{
sc = FILTER_E_UNREACHABLE;
}
}
// TSTOP(_drep->timerNoBind);
}
}
}
CATCH ( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
if ( FAILED(sc) && 0 != _pFilterObject )
_pFilterObject->ReportFilterLoadFailure( _FileName->GetPath(), sc );
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::GetSecurity
//
// Synopsis: Retrieves security
//
// Arguments: [pbData] - pointer to returned buffer containing security descriptor
// [pcbData] - input: size of buffer
// output: amount of buffer used, if successful, size needed
// otherwise
//
// Returns: S_OK if successful
// FILTER_E_NOT_OPEN if document not open
// HRESULT_FROM_NT( STATUS_BUFFER_TOO_SMALL )
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::GetSecurity(
BYTE * pbData,
ULONG * pcbData )
{
//
// Verify that the file is open
//
if (!IsOpen( )) {
return FILTER_E_NOT_OPEN;
}
//
// If it is a network file, don't store security.
//
if ( _pRemoteImpersonation &&
_pRemoteImpersonation->IsImpersonated() )
{
*pcbData = 0;
return S_OK;
}
//
// Attempt to get the security descriptor into the buffer
//
ULONG cbBuffer = *pcbData;
NTSTATUS Status =
NtQuerySecurityObject ( _SafeOplock->GetFileHandle(),
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION,
pbData,
cbBuffer,
pcbData );
//
// If we succeeded let caller know
//
if (NT_SUCCESS(Status))
{
*pcbData = GetSecurityDescriptorLength(pbData);
return S_OK;
}
//
// Map status for caller
//
if ( STATUS_BUFFER_TOO_SMALL == Status )
return CI_E_BUFFERTOOSMALL;
else return HRESULT_FROM_NT( Status );
}
//+---------------------------------------------------------------------------
//
// Member: CCiCOpenedDoc::IsInUseByAnotherProcess
//
// Synopsis: Tests to see if the document is wanted by another process
//
// Arguments: [pfInUse] - Returned flag, TRUE => someone wants this document
//
// Returns: S_OK if successful
// FILTER_E_NOT_OPEN if document isn't open
// E_NOTIMPL
//
//----------------------------------------------------------------------------
STDMETHODIMP CCiCOpenedDoc::IsInUseByAnotherProcess(
BOOL * pfInUse )
{
//
// Verify that the file is open
//
if (!IsOpen( ) || IsSharingViolation() )
{
// If there was a sharing violation, then we never took the oplock.
return FILTER_E_NOT_OPEN;
}
*pfInUse = _SafeOplock->IsOplockBroken( );
return S_OK;
}