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

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: opendoc.cxx
  7. //
  8. // Contents: Code that encapsulates an opened file on a Nt volume
  9. //
  10. //----------------------------------------------------------------------------
  11. #include <pch.cxx>
  12. #pragma hdrstop
  13. #include <docname.hxx>
  14. #include <ciole.hxx>
  15. #include <opendoc.hxx>
  16. #include <statprop.hxx>
  17. #include <imprsnat.hxx>
  18. #include <dmnstart.hxx>
  19. #include <queryexp.hxx>
  20. #include <filterob.hxx>
  21. #include <ntopen.hxx>
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Class: CImpersonatedOpenOpLock
  25. //
  26. // Purpose: Opens the oplock by doing any necessary impersonation. If there
  27. // are multiple alternative user-ids, it will try until one
  28. // succeeds or there are no more choices.
  29. //
  30. // History: 1-24-97 srikants Created
  31. //
  32. //----------------------------------------------------------------------------
  33. class CImpersonatedOpenOpLock : public PImpersonatedWorkItem
  34. {
  35. public:
  36. CImpersonatedOpenOpLock( const CFunnyPath & funnyDoc,
  37. CImpersonateRemoteAccess * pRemoteAccess,
  38. BOOL fTakeOpLock )
  39. : PImpersonatedWorkItem( funnyDoc.GetActualPath() ),
  40. _funnyDoc(funnyDoc),
  41. _fTakeOpLock( fTakeOpLock ),
  42. _pRemoteAccess( pRemoteAccess ),
  43. _fSharingViolation(FALSE)
  44. {
  45. }
  46. BOOL DoIt(); // virtual
  47. void Open()
  48. {
  49. if ( _pRemoteAccess )
  50. {
  51. ImpersonateAndDoWork( *_pRemoteAccess );
  52. }
  53. else
  54. {
  55. BOOL fSuccess = DoIt();
  56. Win4Assert( fSuccess );
  57. }
  58. }
  59. CFilterOplock * Acquire()
  60. {
  61. return _oplock.Acquire();
  62. }
  63. BOOL IsSharingViolation() const
  64. {
  65. return _fSharingViolation;
  66. }
  67. BOOL IsOffline() const
  68. {
  69. return _oplock->IsOffline();
  70. }
  71. BOOL IsNotContentIndexed() const
  72. {
  73. return _oplock->IsNotContentIndexed();
  74. }
  75. private:
  76. const CFunnyPath & _funnyDoc;
  77. BOOL _fTakeOpLock;
  78. CImpersonateRemoteAccess * _pRemoteAccess;
  79. XPtr<CFilterOplock> _oplock;
  80. BOOL _fSharingViolation;
  81. };
  82. //+---------------------------------------------------------------------------
  83. //
  84. // Member: CImpersonatedOpenOpLock::DoIt
  85. //
  86. // Synopsis: The virtual "DoIt" method that does the work under the
  87. // impersonated context (if necessary).
  88. //
  89. // Returns: TRUE if successful.
  90. // FALSE if another impersonation must be tried
  91. // THROWS if there is a failure and no impersonation to be
  92. // tried.
  93. //
  94. // History: 1-24-97 srikants Created
  95. //
  96. //----------------------------------------------------------------------------
  97. BOOL CImpersonatedOpenOpLock::DoIt()
  98. {
  99. BOOL fStatus = TRUE;
  100. BOOL fTryAgain = TRUE;
  101. for (;;)
  102. {
  103. TRY
  104. {
  105. _oplock.Set( new CFilterOplock( _funnyDoc, _fTakeOpLock ) );
  106. break;
  107. }
  108. CATCH( CException, e )
  109. {
  110. NTSTATUS Status = e.GetErrorCode();
  111. //
  112. // If the path was a net path, we may have to use a different impersonation
  113. // to gain access. We try until there are no more impersonation choices left.
  114. //
  115. if ( _fNetPath && 0 != _pRemoteAccess &&
  116. IsRetryableError(Status) )
  117. {
  118. fStatus = FALSE;
  119. ciDebugOut(( DEB_WARN, "Trying another user-id for (%ws)\n",
  120. _funnyDoc.GetPath() ));
  121. }
  122. else
  123. {
  124. if ( fTryAgain && ::IsSharingViolation( Status ) )
  125. {
  126. _fSharingViolation = TRUE;
  127. _fTakeOpLock = FALSE;
  128. fTryAgain = FALSE;
  129. continue;
  130. }
  131. ciDebugOut(( DEB_IWARN, "Failed to filter (%ws). Error (0x%X)\n",
  132. _funnyDoc.GetPath(), e.GetErrorCode() ));
  133. RETHROW();
  134. }
  135. break;
  136. }
  137. END_CATCH
  138. }
  139. return fStatus;
  140. }
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Construction/Destruction
  144. //
  145. //----------------------------------------------------------------------------
  146. //+---------------------------------------------------------------------------
  147. //
  148. // Member: CCiCOpenedDoc::CCiCOpenedDoc
  149. //
  150. // Synopsis: Default constructor. We initialize the minimal set of
  151. // members to indicate an inactive document
  152. //
  153. // Arguments: None
  154. //
  155. //----------------------------------------------------------------------------
  156. CCiCOpenedDoc::CCiCOpenedDoc( CStorageFilterObject * pFilterObject,
  157. CClientDaemonWorker * pWorker,
  158. BOOL fTakeOpLock,
  159. BOOL fFailIfNotContentIndexed )
  160. :_RefCount( 1 ),
  161. _TypeOfStorage( eUnknown ),
  162. _llFileSize(0),
  163. _pWorker( pWorker),
  164. _pRemoteImpersonation(0),
  165. _pFilterObject( pFilterObject ),
  166. _fTakeOpLock( fTakeOpLock ),
  167. _fSharingViolation( FALSE ),
  168. _fFailIfNotContentIndexed( fFailIfNotContentIndexed )
  169. {
  170. if ( _pWorker )
  171. {
  172. _pRemoteImpersonation =
  173. new CImpersonateRemoteAccess( &(_pWorker->GetImpersonationCache()) );
  174. }
  175. }
  176. CCiCOpenedDoc::~CCiCOpenedDoc()
  177. {
  178. Win4Assert( 0 == _RefCount );
  179. Close();
  180. delete _pRemoteImpersonation;
  181. }
  182. //+---------------------------------------------------------------------------
  183. //
  184. // Member: CCiCOpenedDoc::_TooBigForDefault
  185. //
  186. // Synopsis: Checks if the given size is too big for using the default
  187. // filter.
  188. //
  189. // Arguments: [ll] - Size to check
  190. //
  191. // History: 1-24-97 srikants Created
  192. //
  193. //----------------------------------------------------------------------------
  194. inline BOOL CCiCOpenedDoc::_TooBigForDefault( LONGLONG const ll )
  195. {
  196. Win4Assert( 0 != _pWorker );
  197. return( ll > (_pWorker->GetRegParams().GetMaxFilesizeFiltered() * 1024) );
  198. }
  199. //+---------------------------------------------------------------------------
  200. //
  201. // Member: CCiCOpenedDoc::_GetFileSize
  202. //
  203. // Synopsis: Retrieves the size of the current file.
  204. //
  205. // History: 1-24-97 srikants Created
  206. //
  207. //----------------------------------------------------------------------------
  208. LONGLONG CCiCOpenedDoc::_GetFileSize()
  209. {
  210. Win4Assert( IsOpen( ) );
  211. IO_STATUS_BLOCK IoStatus;
  212. HANDLE FileHandle = _SafeOplock->GetFileHandle( );
  213. Win4Assert( INVALID_HANDLE_VALUE != FileHandle );
  214. FILE_STANDARD_INFORMATION stdInfo;
  215. NTSTATUS Status = NtQueryInformationFile( FileHandle, // File handle
  216. &IoStatus, // I/O Status
  217. &stdInfo, // Buffer
  218. sizeof( stdInfo ),// Buffer size
  219. FileStandardInformation );
  220. Win4Assert( STATUS_DATATYPE_MISALIGNMENT != Status );
  221. if ( !NT_SUCCESS(Status) )
  222. {
  223. ciDebugOut(( DEB_IERROR, "Error 0x%x querying file info\n",
  224. Status ));
  225. QUIETTHROW( CException( Status ));
  226. }
  227. return stdInfo.EndOfFile.QuadPart;
  228. }
  229. //+---------------------------------------------------------------------------
  230. //
  231. // IUnknown method implementations
  232. //
  233. //----------------------------------------------------------------------------
  234. //+---------------------------------------------------------------------------
  235. //
  236. // Member: CCiCOpenedDoc::QueryInterface
  237. //
  238. // Synopsis: Supports IID_IUnknown and IID_ICiCOpenedDoc
  239. //
  240. // Arguments: [riid] - desired interface id
  241. // [ppvObject] - output interface pointer
  242. //
  243. //----------------------------------------------------------------------------
  244. STDMETHODIMP CCiCOpenedDoc::QueryInterface(
  245. REFIID riid,
  246. void **ppvObject)
  247. {
  248. Win4Assert( 0 != ppvObject );
  249. if ( IID_ICiCOpenedDoc == riid )
  250. *ppvObject = (void *)((ICiCOpenedDoc *)this);
  251. else if ( IID_IUnknown == riid )
  252. *ppvObject = (void *)((IUnknown *)this);
  253. else
  254. {
  255. *ppvObject = 0;
  256. return E_NOINTERFACE;
  257. }
  258. AddRef();
  259. return S_OK;
  260. } // QueryInterface
  261. //+---------------------------------------------------------------------------
  262. //
  263. // Member: CCiCOpenedDoc::AddRef
  264. //
  265. //----------------------------------------------------------------------------
  266. STDMETHODIMP_(ULONG) CCiCOpenedDoc::AddRef()
  267. {
  268. return InterlockedIncrement( &_RefCount );
  269. } // AddRef
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Member: CCiCOpenedDoc::Release
  273. //
  274. //----------------------------------------------------------------------------
  275. STDMETHODIMP_(ULONG) CCiCOpenedDoc::Release()
  276. {
  277. Win4Assert( _RefCount != 0 );
  278. LONG RefCount = InterlockedDecrement( &_RefCount );
  279. if ( RefCount <= 0 )
  280. delete this;
  281. return (ULONG) RefCount;
  282. } // Release
  283. //+---------------------------------------------------------------------------
  284. //
  285. // ICiCOpenedDoc method implementations
  286. //
  287. //----------------------------------------------------------------------------
  288. //+---------------------------------------------------------------------------
  289. //
  290. // Member: CCiCOpenedDoc::Open
  291. //
  292. // Synopsis: Opens the specified file. In general, the caller
  293. // passes an implementation-specific blob of data to the
  294. // ICiCOpenedDoc interface. The selected implementation is
  295. // free to choose how it wants to interpret it. This
  296. // implementation considers it to be a lpwstr.
  297. //
  298. // Arguments: [pbDocName] - Pointer to, presumably, lpwstr
  299. // [cbDocName] - Length in BYTES, not characters, of the name
  300. //
  301. // Returns: S_OK if successful
  302. // FILTER_E_ALREADY_OPEN if there is already an open document
  303. // FILTER_E_UNREACHABLE if there is a net failure
  304. // FILTER_E_IN_USE if the document is in use by another proess
  305. // other errors as appropriate
  306. //
  307. //----------------------------------------------------------------------------
  308. SCODE CCiCOpenedDoc::Open ( BYTE const * pbDocName, ULONG cbDocName )
  309. {
  310. //
  311. // We cannot open if we're already open
  312. //
  313. if ( IsOpen() )
  314. {
  315. ciDebugOut(( DEB_IERROR, "CCiCOpenedDoc::Open - Document is already open\n" ));
  316. return FILTER_E_ALREADY_OPEN;
  317. }
  318. //
  319. // The docname (Path) is always null terminated. It is an empty string
  320. // for a deleted document.
  321. //
  322. if ( cbDocName <= 2 )
  323. return CI_E_NOT_FOUND;
  324. SCODE sc = S_OK;
  325. TRY
  326. {
  327. //
  328. // Safely construct each piece.
  329. //
  330. XInterface<CCiCDocName> LocalFileName( new CCiCDocName( (PWCHAR) pbDocName, cbDocName / sizeof( WCHAR )));
  331. _funnyFileName.SetPath( (const WCHAR*)pbDocName, (cbDocName/sizeof(WCHAR) - 1) );
  332. #if DBG || CIDBG
  333. //
  334. // Check that we haven't been asked to filter a file in a catalog.wci
  335. // directory.
  336. //
  337. const WCHAR * pwszComponent = (WCHAR *)pbDocName;
  338. while (pwszComponent = wcschr(pwszComponent+1, L'\\'))
  339. {
  340. Win4Assert ( _wcsnicmp( pwszComponent,
  341. L"\\catalog.wci\\",
  342. wcslen(L"\\catalog.wci\\" )) != 0 );
  343. }
  344. #endif // DBG || CIDBG
  345. //
  346. // We have to impersonate before accessing.
  347. //
  348. CImpersonatedOpenOpLock openDoc( _funnyFileName,
  349. _pRemoteImpersonation,
  350. _fTakeOpLock );
  351. openDoc.Open();
  352. //
  353. // Anything bad happen?
  354. //
  355. if ( openDoc.IsSharingViolation() )
  356. sc = FILTER_E_IN_USE;
  357. else if ( openDoc.IsOffline() )
  358. sc = FILTER_E_OFFLINE;
  359. else if ( _fFailIfNotContentIndexed && openDoc.IsNotContentIndexed() )
  360. {
  361. ciDebugOut(( DEB_ITRACE, "not indexing not-indexed file\n" ));
  362. sc = FILTER_E_IN_USE;
  363. }
  364. else
  365. {
  366. //
  367. // At this point, everything is correctly opened. We assign to the
  368. // members. This disconnects the objects from the safe pointers.
  369. //
  370. _FileName.Set( LocalFileName.Acquire( ));
  371. _SafeOplock.Set( openDoc.Acquire( ));
  372. _TypeOfStorage = eUnknown;
  373. }
  374. }
  375. CATCH ( CException, e )
  376. {
  377. //
  378. // Grab status code and convert to SCODE. Convert the status,
  379. // if possible, to a known class of SCODE that the caller might,
  380. // in some way, be able to deal with.
  381. //
  382. NTSTATUS Status = e.GetErrorCode( );
  383. if (::IsSharingViolation( Status ))
  384. {
  385. ciDebugOut(( DEB_IERROR, "CCiCOpenedDoc::Open - sharing violation - %x\n", Status ));
  386. sc = FILTER_E_IN_USE;
  387. _fSharingViolation = TRUE;
  388. }
  389. else if (IsNetDisconnect( Status ))
  390. {
  391. ciDebugOut(( DEB_ERROR, "CCiCOpenedDoc::Open - net disconnect - %x\n", Status ));
  392. sc = FILTER_E_UNREACHABLE;
  393. }
  394. else
  395. {
  396. ciDebugOut(( DEB_ITRACE, "CCiCOpenedDoc::Open - other error - %x\n", Status ));
  397. sc = Status;
  398. }
  399. }
  400. END_CATCH
  401. return sc;
  402. } //Open
  403. //+---------------------------------------------------------------------------
  404. //
  405. // Member: CCiCOpenedDoc::Close
  406. //
  407. // Synopsis: Terminate all access to a file
  408. //
  409. // Arguments: None.
  410. //
  411. // Returns: S_OK if successful
  412. // FILTER_E_NOT_OPEN if there is no document
  413. //
  414. //----------------------------------------------------------------------------
  415. STDMETHODIMP CCiCOpenedDoc::Close( void )
  416. {
  417. //
  418. // If there is no document open, reject this call
  419. //
  420. if ( !IsOpen() )
  421. return FILTER_E_NOT_OPEN;
  422. if ( 0 != _pWorker )
  423. _SafeOplock->MaybeSetLastAccessTime( _pWorker->GetRegParams().GetStompLastAccessDelay() );
  424. //
  425. // Release pointers
  426. //
  427. _Storage.Free();
  428. _SafeOplock.Free( );
  429. _FileName.Free( );
  430. _funnyFileName.Truncate(0);
  431. _llFileSize = 0;
  432. return S_OK;
  433. } //Close
  434. //+---------------------------------------------------------------------------
  435. //
  436. // Member: CCiCOpenedDoc::GetDocumentName
  437. //
  438. // Synopsis: Returns the interface to the document name, if open.
  439. //
  440. // Arguments: [ppIDocName] - Pointer to the returned document name
  441. //
  442. // Returns: S_OK if successful
  443. // FILTER_E_NOT_OPEN if document is not currently open
  444. //
  445. //----------------------------------------------------------------------------
  446. STDMETHODIMP CCiCOpenedDoc::GetDocumentName(
  447. ICiCDocName ** ppIDocName )
  448. {
  449. //
  450. // If there is no name, then we haven't opened a document yet.
  451. //
  452. if (!IsOpen( )) {
  453. return FILTER_E_NOT_OPEN;
  454. }
  455. //
  456. // Set up return pointer and reference interface
  457. //
  458. *ppIDocName = _FileName.GetPointer( );
  459. (*ppIDocName)->AddRef( );
  460. return S_OK;
  461. } // GetDocumentName
  462. void FunnyToNormalPath( const CFunnyPath & funnyPath,
  463. WCHAR * awcPath );
  464. SCODE ShellBindToItemByName(
  465. WCHAR const * pszFile,
  466. REFIID riid,
  467. void ** ppv );
  468. //+---------------------------------------------------------------------------
  469. //
  470. // Member: CCiCOpenedDoc::GetPropertySetStorage
  471. //
  472. // Synopsis: Returns the interface to the underlying IStorage if we have
  473. // a docfile.
  474. //
  475. // Returns: IStorage* of underlying docfile.
  476. // NULL if not a docfile or not open
  477. //
  478. // History: 06-Apr-1998 KyleP Use only for property set storage
  479. //
  480. //----------------------------------------------------------------------------
  481. IPropertySetStorage * CCiCOpenedDoc::GetPropertySetStorage()
  482. {
  483. // NTRAID#DB-NTBUG9-84131-2000/07/31-dlee Indexing Service contains workarounds for StgOpenStorage AV on > MAX_PATH paths
  484. if ( _funnyFileName.GetLength() >= MAX_PATH )
  485. {
  486. ciDebugOut(( DEB_WARN, "Not calling StgOpenStorage in CCiCOpenedDoc::GetPropertySetStorage for paths > MAX_PATH: \n(%ws)\n",
  487. _funnyFileName.GetPath() ));
  488. _TypeOfStorage = eOther;
  489. Win4Assert( _Storage.IsNull() );
  490. return _Storage.GetPointer( );
  491. }
  492. //
  493. // If we are open and we don't have a storage instance and we don't know
  494. // the type of storage
  495. //
  496. if (IsOpen() && _Storage.IsNull( ) && _TypeOfStorage == eUnknown)
  497. {
  498. //
  499. // Attempt to open docfile
  500. //
  501. Win4Assert( _Storage.IsNull() );
  502. Win4Assert( !_SafeOplock->IsOffline() );
  503. #if 0
  504. SCODE sc = StgOpenStorageEx( _funnyFileName.GetPath( ), // Path
  505. STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE, // Flags (BChapman said use these)
  506. STGFMT_ANY, // Format
  507. 0, // Reserved
  508. 0, // Reserved
  509. 0, // Reserved
  510. IID_IPropertySetStorage, // IID
  511. _Storage.GetQIPointer() );
  512. #else
  513. //
  514. // The shell expects the string not to change or go away until the
  515. // IPropertySetStorage is released, so make a copy of it.
  516. //
  517. FunnyToNormalPath( _funnyFileName, _awcPath );
  518. SCODE sc = ShellBindToItemByName( _awcPath,
  519. IID_IPropertySetStorage,
  520. _Storage.GetQIPointer() );
  521. #endif
  522. //
  523. // Set the type of storage based on what we found
  524. //
  525. if ( SUCCEEDED( sc ) )
  526. _TypeOfStorage = eDocfile;
  527. else
  528. {
  529. _TypeOfStorage = eOther;
  530. Win4Assert( _Storage.IsNull() );
  531. }
  532. }
  533. return _Storage.GetPointer( );
  534. } //GetPropertySetStorage
  535. //+---------------------------------------------------------------------------
  536. //
  537. // Member: CCiCOpenedDoc::GetStatPropertyEnum
  538. //
  539. // Synopsis: Return property storage for the "stat" (i.e., system storage)
  540. // property set. This property set is not really stored in normal
  541. // property storage but is faked out of Nt file information.
  542. //
  543. // Arguments: [ppIStatPropEnum] - pointer to the returned IPropertyStorage
  544. // interface
  545. //
  546. // Returns: S_OK -if successful
  547. // E_NOTIMPL if stat properties are not supported. This
  548. // implementation supports them.
  549. // FILTER_E_NOT_OPEN if there is no open document.
  550. // Other as appropriate
  551. //
  552. //----------------------------------------------------------------------------
  553. STDMETHODIMP CCiCOpenedDoc::GetStatPropertyEnum(
  554. IPropertyStorage **ppIStatPropEnum )
  555. {
  556. //
  557. // Make sure the document is open
  558. //
  559. if (!IsOpen( )) {
  560. ciDebugOut(( DEB_IERROR, "Document is not open\n" ));
  561. return FILTER_E_NOT_OPEN;
  562. }
  563. //
  564. // Return and interface
  565. //
  566. *ppIStatPropEnum = new CStatPropertyStorage( _SafeOplock->GetFileHandle( ),
  567. _funnyFileName.GetLength() );
  568. return S_OK;
  569. } // GetStatPropertyEnum
  570. //+---------------------------------------------------------------------------
  571. //
  572. // Member: CCiCOpenedDoc::GetPropertySetEnum
  573. //
  574. // Synopsis: Returns the docfile property set storage interface on the
  575. // current doc.
  576. //
  577. // Arguments: [ppIPropSetEnum] - returned pointer to the Docfile property
  578. // set storage
  579. //
  580. // Returns: S_OK if successful
  581. // FILTER_S_NO_PROPSETS if no property sets (beyond stat ones)
  582. // available on this document
  583. // FILTER_E_NOT_OPEN if the document is not currently open
  584. // Other as appropriate
  585. //
  586. //----------------------------------------------------------------------------
  587. STDMETHODIMP CCiCOpenedDoc::GetPropertySetEnum( IPropertySetStorage ** ppIPropSetEnum )
  588. {
  589. //
  590. // Make sure the document is open
  591. //
  592. if ( !IsOpen() )
  593. return FILTER_E_NOT_OPEN;
  594. //
  595. // Make sure the extra file handle in the oplock is closed
  596. //
  597. _SafeOplock->CloseFileHandle();
  598. //
  599. // Get the IStorage corresponding to this document
  600. //
  601. IPropertySetStorage * Storage = GetPropertySetStorage();
  602. //
  603. // If we couldn't get the IStorage, then we certainly
  604. // couldn't get the property set storage
  605. //
  606. if ( 0 == Storage )
  607. return FILTER_S_NO_PROPSETS;
  608. Storage->AddRef();
  609. *ppIPropSetEnum = Storage;
  610. return S_OK;
  611. }
  612. //+---------------------------------------------------------------------------
  613. //
  614. // Member: CCiCOpenedDoc::GetPropertyEnum
  615. //
  616. // Synopsis: Return the property storage for a particular property set
  617. //
  618. // Arguments: [GuidPropSet] - GUID of the property set whose property
  619. // storage is being requested
  620. // [ppIPropEnum] - returned pointer to property storage
  621. //
  622. // Returns: S_OK if successful
  623. // FILTER_E_NO_SUCH_PROPERTY - if property set with GUID not found
  624. // FILTER_E_NOT_OPEN if there is no open document
  625. //
  626. //----------------------------------------------------------------------------
  627. STDMETHODIMP CCiCOpenedDoc::GetPropertyEnum(
  628. REFFMTID refGuidPropSet,
  629. IPropertyStorage **ppIPropEnum )
  630. {
  631. //
  632. // Get the property set storage interface
  633. //
  634. IPropertySetStorage *PropSetStorage;
  635. SCODE sc = GetPropertySetEnum( &PropSetStorage );
  636. if (!SUCCEEDED( sc )) {
  637. return sc;
  638. }
  639. //
  640. // Attempt to open the named property set.
  641. //
  642. HRESULT hr = PropSetStorage->Open( refGuidPropSet,
  643. STGM_READ | STGM_SHARE_EXCLUSIVE, // BChapman said to use these
  644. ppIPropEnum );
  645. PropSetStorage->Release( );
  646. if (!SUCCEEDED( hr )) {
  647. return FILTER_E_NO_SUCH_PROPERTY;
  648. }
  649. return S_OK;
  650. } // GetPropertyEnum
  651. //+---------------------------------------------------------------------------
  652. //
  653. // Member: CCiCOpenedDoc::GetIFilter
  654. //
  655. // Synopsis: Return the appropriate filter bound to the document
  656. //
  657. // Arguments: [ppIFilter] - returned IFilter
  658. //
  659. // Returns: S_OK if successful
  660. // FILTER_E_NOT_OPEN if there is no open document
  661. // E_NOT_IMPL if not implemented
  662. // Other as appropriate
  663. //
  664. //----------------------------------------------------------------------------
  665. STDMETHODIMP CCiCOpenedDoc::GetIFilter(
  666. IFilter ** ppIFilter )
  667. {
  668. SCODE sc = S_OK;
  669. //
  670. // We can't do anything if the document is not opened yet.
  671. //
  672. if ( !IsOpen() || IsSharingViolation() )
  673. return FILTER_E_NOT_OPEN;
  674. //
  675. // Make sure the extra file handle in the oplock is closed
  676. //
  677. if ( INVALID_HANDLE_VALUE != _SafeOplock->GetFileHandle() )
  678. {
  679. _llFileSize = _GetFileSize();
  680. _SafeOplock->CloseFileHandle();
  681. }
  682. //
  683. // Call Ole to perform the binding
  684. //
  685. TRY
  686. {
  687. sc = CCiOle::BindIFilter( _funnyFileName.GetPath(), NULL, ppIFilter, FALSE );
  688. if ( FAILED(sc) )
  689. {
  690. // MK_E_CANTOPENFILE is returned by the office filter. It should be
  691. // fixed to return FILTER_E_ACCESS/FILTER_E_PASSWORD in case it is not able
  692. // to open a file for filtering. Once that is done, we can get rid
  693. // of MK_E_CANTOPENFILE condition
  694. if ( FILTER_E_ACCESS == sc ||
  695. ( MK_E_CANTOPENFILE == sc && ::IsSharingViolation( GetLastError() ))
  696. )
  697. {
  698. sc = FILTER_E_IN_USE ;
  699. }
  700. else if ( FILTER_E_PASSWORD == sc )
  701. {
  702. sc = FILTER_E_UNREACHABLE;
  703. }
  704. else if ( _pWorker->GetRegParams().FilterFilesWithUnknownExtensions() )
  705. {
  706. //
  707. // File with unknown extension. Does the registry say that we should
  708. // filter the file ?
  709. //
  710. ciDebugOut((DEB_IWARN, "Going to default filtering for %ws.\n",
  711. _FileName->GetPath( ) ));
  712. // TSTART(_drep->timerNoBind);
  713. //
  714. // Verify file is of appropriate size for default filtering.
  715. //
  716. if ( _TooBigForDefault( _llFileSize ) )
  717. {
  718. ciDebugOut(( DEB_IWARN,
  719. "%ws too large for default filtering\n",
  720. _FileName->GetPath( ) ));
  721. //
  722. // When this code was in CFilterDriver::Init we returned FILTER_E_TOO_BIG.
  723. // Now we don't want to do that. Properties should still be filtered.
  724. //
  725. //sc = FILTER_E_TOO_BIG;
  726. sc = LoadBinaryFilter( _funnyFileName.GetPath(), ppIFilter );
  727. }
  728. else
  729. {
  730. sc = LoadTextFilter( _funnyFileName.GetPath(), ppIFilter );
  731. }
  732. if ( FAILED(sc) )
  733. {
  734. if ( FILTER_E_ACCESS == sc )
  735. {
  736. sc = FILTER_E_IN_USE ;
  737. }
  738. else if ( FILTER_E_PASSWORD == sc )
  739. {
  740. sc = FILTER_E_UNREACHABLE;
  741. }
  742. }
  743. // TSTOP(_drep->timerNoBind);
  744. }
  745. }
  746. }
  747. CATCH ( CException, e )
  748. {
  749. sc = e.GetErrorCode();
  750. }
  751. END_CATCH
  752. if ( FAILED(sc) && 0 != _pFilterObject )
  753. _pFilterObject->ReportFilterLoadFailure( _FileName->GetPath(), sc );
  754. return sc;
  755. }
  756. //+---------------------------------------------------------------------------
  757. //
  758. // Member: CCiCOpenedDoc::GetSecurity
  759. //
  760. // Synopsis: Retrieves security
  761. //
  762. // Arguments: [pbData] - pointer to returned buffer containing security descriptor
  763. // [pcbData] - input: size of buffer
  764. // output: amount of buffer used, if successful, size needed
  765. // otherwise
  766. //
  767. // Returns: S_OK if successful
  768. // FILTER_E_NOT_OPEN if document not open
  769. // HRESULT_FROM_NT( STATUS_BUFFER_TOO_SMALL )
  770. //
  771. //----------------------------------------------------------------------------
  772. STDMETHODIMP CCiCOpenedDoc::GetSecurity(
  773. BYTE * pbData,
  774. ULONG * pcbData )
  775. {
  776. //
  777. // Verify that the file is open
  778. //
  779. if (!IsOpen( )) {
  780. return FILTER_E_NOT_OPEN;
  781. }
  782. //
  783. // If it is a network file, don't store security.
  784. //
  785. if ( _pRemoteImpersonation &&
  786. _pRemoteImpersonation->IsImpersonated() )
  787. {
  788. *pcbData = 0;
  789. return S_OK;
  790. }
  791. //
  792. // Attempt to get the security descriptor into the buffer
  793. //
  794. ULONG cbBuffer = *pcbData;
  795. NTSTATUS Status =
  796. NtQuerySecurityObject ( _SafeOplock->GetFileHandle(),
  797. OWNER_SECURITY_INFORMATION |
  798. GROUP_SECURITY_INFORMATION |
  799. DACL_SECURITY_INFORMATION,
  800. pbData,
  801. cbBuffer,
  802. pcbData );
  803. //
  804. // If we succeeded let caller know
  805. //
  806. if (NT_SUCCESS(Status))
  807. {
  808. *pcbData = GetSecurityDescriptorLength(pbData);
  809. return S_OK;
  810. }
  811. //
  812. // Map status for caller
  813. //
  814. if ( STATUS_BUFFER_TOO_SMALL == Status )
  815. return CI_E_BUFFERTOOSMALL;
  816. else return HRESULT_FROM_NT( Status );
  817. }
  818. //+---------------------------------------------------------------------------
  819. //
  820. // Member: CCiCOpenedDoc::IsInUseByAnotherProcess
  821. //
  822. // Synopsis: Tests to see if the document is wanted by another process
  823. //
  824. // Arguments: [pfInUse] - Returned flag, TRUE => someone wants this document
  825. //
  826. // Returns: S_OK if successful
  827. // FILTER_E_NOT_OPEN if document isn't open
  828. // E_NOTIMPL
  829. //
  830. //----------------------------------------------------------------------------
  831. STDMETHODIMP CCiCOpenedDoc::IsInUseByAnotherProcess(
  832. BOOL * pfInUse )
  833. {
  834. //
  835. // Verify that the file is open
  836. //
  837. if (!IsOpen( ) || IsSharingViolation() )
  838. {
  839. // If there was a sharing violation, then we never took the oplock.
  840. return FILTER_E_NOT_OPEN;
  841. }
  842. *pfInUse = _SafeOplock->IsOplockBroken( );
  843. return S_OK;
  844. }