Source code of Windows XP (NT5)
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.

729 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: dlproxy.cxx
  7. //
  8. // Contents: Proxy class which is used by the Daemon process
  9. // to communicate with the CI process.
  10. //
  11. // History: 1-30-96 srikants Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #include <dmnproxy.hxx>
  17. #include <memser.hxx>
  18. #include <memdeser.hxx>
  19. #include <sizeser.hxx>
  20. #include <ciole.hxx>
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Member: CFilterStoreValueLayout::Init
  24. //
  25. // History: 1-30-96 srikants Created
  26. //
  27. //----------------------------------------------------------------------------
  28. SCODE CFilterStoreValueLayout::Init( ULONG cbMax, WORKID widFake,
  29. CFullPropSpec const & ps,
  30. CStorageVariant const & var )
  31. {
  32. _sig5 = eFilterSig5;
  33. _cbMax = cbMax - FIELD_OFFSET( CFilterStoreValueLayout, _ab );
  34. _widFake = widFake;
  35. CSizeSerStream sizeSer;
  36. _fSuccess = FALSE;
  37. ps.Marshall( sizeSer );
  38. var.Marshall( sizeSer );
  39. if ( sizeSer.Size() > _cbMax )
  40. {
  41. return STATUS_BUFFER_TOO_SMALL;
  42. }
  43. _cb = sizeSer.Size();
  44. CMemSerStream ser( GetBuffer(), _cb );
  45. ps.Marshall( ser );
  46. var.Marshall( ser );
  47. ser.AcqBuf();
  48. return S_OK;
  49. } //Init
  50. //+---------------------------------------------------------------------------
  51. //
  52. // Member: CFilterStoreSecurityLayout::Init
  53. //
  54. // Synopsis: Initialize a buffer for the FilterStoreSecurity call
  55. //
  56. // Arguments: [cbMax] - size in bytes of [this]
  57. // [widFake] - fake WORKID of file to apply security to
  58. // [pSD] - pointer to a self-relative security descriptor
  59. // [cbSD] - size in bytes of [pSD]
  60. //
  61. // History: 06 Feb 96 AlanW Created
  62. //
  63. //----------------------------------------------------------------------------
  64. void CFilterStoreSecurityLayout::Init( ULONG cbMax,
  65. WORKID widFake,
  66. PSECURITY_DESCRIPTOR pSD,
  67. ULONG cbSD )
  68. {
  69. _sig8 = (ULONG) eFilterSig8;
  70. _cbMax = cbMax - FIELD_OFFSET( CFilterStoreSecurityLayout, _ab );
  71. _widFake = widFake;
  72. _fSuccess = FALSE;
  73. _sdid = 0;
  74. if ( cbSD > _cbMax )
  75. {
  76. THROW( CException( STATUS_BUFFER_TOO_SMALL ) );
  77. }
  78. _cb = cbSD;
  79. RtlCopyMemory( &_ab, pSD, cbSD );
  80. } //Init
  81. //+---------------------------------------------------------------------------
  82. //
  83. // Member: CFilterStoreValueLayout::Get
  84. //
  85. // History: 1-30-96 srikants Created
  86. //
  87. //----------------------------------------------------------------------------
  88. void CFilterStoreValueLayout::Get( WORKID & widFake, CFullPropSpec & ps,
  89. CStorageVariant & var )
  90. {
  91. Win4Assert( IsValid() );
  92. widFake = _widFake;
  93. CMemDeSerStream deSer( GetBuffer(), _cb );
  94. // It's a little slow to do this, but it doesn't dominate filter time.
  95. CFullPropSpec psLocal( deSer );
  96. CStorageVariant varLocal( deSer );
  97. ps = psLocal;
  98. var = varLocal;
  99. } //Get
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Member: CFPSToPROPIDLayout::Init, public
  103. //
  104. // Synopsis: Initialize buffer for transfer (FPSToPROPID operation)
  105. //
  106. // Arguments: [cbMax] -- Size of buffer used in later marshalling
  107. // [fps] -- Propspec to be marshalled
  108. //
  109. // History: 30-Dec-1997 KyleP Created
  110. //
  111. //----------------------------------------------------------------------------
  112. void CFPSToPROPIDLayout::Init( ULONG cbMax, CFullPropSpec const & fps )
  113. {
  114. _sig6 = eFilterSig6;
  115. _cbMax = cbMax - FIELD_OFFSET( CFPSToPROPIDLayout, _ab );
  116. //
  117. // Serialize the pidmap
  118. //
  119. CSizeSerStream sizeSer;
  120. fps.Marshall( sizeSer );
  121. if ( sizeSer.Size() > _cbMax )
  122. {
  123. THROW( CException( STATUS_BUFFER_TOO_SMALL ) );
  124. }
  125. Win4Assert( cbMax >= sizeof(PROPID) );
  126. _cb = sizeSer.Size();
  127. CMemSerStream ser( GetBuffer(), _cb );
  128. fps.Marshall( ser );
  129. } //Init
  130. //+---------------------------------------------------------------------------
  131. //
  132. // Member: CGenericCiProxy::CGenericCiProxy
  133. //
  134. // Synopsis: Constructor for the proxy object used by Ci Daemon Process
  135. // to communicate with ContentIndex (in a different process).
  136. //
  137. // History: 2-02-96 srikants Created
  138. //
  139. // Notes: All the above handles are of the objects created by the
  140. // parent CI process with an "inheritable" attribute. The handles
  141. // are communicated to the daemon process as command line args
  142. // and used here.
  143. //
  144. //----------------------------------------------------------------------------
  145. CGenericCiProxy::CGenericCiProxy(
  146. CSharedNameGen & nameGen,
  147. DWORD dwMemSize,
  148. DWORD parentId )
  149. :_mutex( nameGen.GetMutexName() ),
  150. _sharedMem( nameGen.GetSharedMemName(), dwMemSize ),
  151. _evtCi( 0, nameGen.GetCiEventName() ),
  152. _evtDaemon( 0, nameGen.GetDaemonEventName() ),
  153. _cHandles(2)
  154. {
  155. _pLayout = (CFilterSharedMemLayout *) _sharedMem.Map();
  156. Win4Assert( _pLayout->IsValid() );
  157. _aWait[iDaemon] = _evtDaemon.GetHandle();
  158. HANDLE hParent = OpenProcess( SYNCHRONIZE, FALSE, parentId );
  159. if ( 0 == hParent )
  160. {
  161. DWORD dwError = GetLastError();
  162. ciDebugOut(( DEB_ERROR,
  163. "Failed to get parent process handle. Error %d\n",
  164. dwError ));
  165. THROW( CException( HRESULT_FROM_WIN32(dwError) ) );
  166. }
  167. _aWait[iParent] = hParent;
  168. _evtDaemon.Reset();
  169. } //CGenericCiProxy
  170. CGenericCiProxy::~CGenericCiProxy()
  171. {
  172. CloseHandle( _aWait[iParent] );
  173. } //~CGenericCiProxy
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Member: CGenericCiProxy::_WaitForResponse
  177. //
  178. // Synopsis: Waits on the parent handle and the work done event. If the
  179. // parent handle signals, then an exception will be thrown.
  180. //
  181. // History: 2-02-96 srikants Created
  182. // 18-Dec-97 KLam Added call to CCIOle::FlushIdle when wait
  183. // times out.
  184. //----------------------------------------------------------------------------
  185. void CGenericCiProxy::_WaitForResponse()
  186. {
  187. const DWORD dwWSTimeout = 20000;
  188. DWORD dwTimeout = TRUE ? dwWSTimeout : INFINITE;
  189. BOOL fFirstIdle = TRUE;
  190. do
  191. {
  192. //
  193. // Since ill-behaved filters and anything that uses mshtml creates
  194. // windows, we have to process messages or broadcast messages
  195. // will hang.
  196. //
  197. DWORD status = MsgWaitForMultipleObjects( _cHandles, // num handles
  198. _aWait, // array of handles
  199. FALSE, // wake up if any is set
  200. dwTimeout, // Timeout
  201. QS_ALLEVENTS );
  202. DWORD iStatus = status - WAIT_OBJECT_0;
  203. if ( iStatus == _cHandles )
  204. {
  205. // Deal with the window message for this thread.
  206. MSG msg;
  207. while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
  208. {
  209. TranslateMessage( &msg );
  210. DispatchMessage( &msg );
  211. }
  212. }
  213. else if ( WAIT_TIMEOUT == status )
  214. {
  215. // Throw away IFilters we haven't used in awhile
  216. CCiOle::FlushIdle();
  217. if ( fFirstIdle )
  218. {
  219. //
  220. // Unload dlls like mshtml that get dragged in via thumbmail
  221. // generation.
  222. //
  223. CoFreeUnusedLibraries();
  224. // Throw ourselves out of the working set.
  225. SetProcessWorkingSetSize( GetCurrentProcess(), -1, -1 );
  226. dwTimeout = 2 * 60 * 1000;
  227. fFirstIdle = FALSE;
  228. }
  229. }
  230. else if ( WAIT_FAILED == status )
  231. {
  232. DWORD dwError = GetLastError();
  233. ciDebugOut(( DEB_ERROR, "Daemon - WaitFailed. Error %d\n", dwError ));
  234. THROW( CException() );
  235. }
  236. else if ( iParent == iStatus )
  237. {
  238. ciDebugOut(( DEB_ERROR, "Daemon - Parent process died abruptly\n" ));
  239. THROW( CException( STATUS_NOT_FOUND ) );
  240. }
  241. else
  242. {
  243. Win4Assert( iDaemon == iStatus );
  244. _evtDaemon.Reset();
  245. break;
  246. }
  247. }
  248. while( TRUE );
  249. } //_WaitForResponse
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Member: CGenericCiProxy::FilterReady
  253. //
  254. // History: 1-30-96 srikants Created
  255. //
  256. //----------------------------------------------------------------------------
  257. SCODE CGenericCiProxy::FilterReady( BYTE * docBuffer, ULONG & cb,
  258. ULONG cMaxDocs )
  259. {
  260. ProbeForParentProcess();
  261. Win4Assert( _pLayout );
  262. {
  263. CIPLock lock(_mutex);
  264. CFilterReadyLayout & data = _pLayout->GetFilterReady();
  265. data.Init( _pLayout->GetMaxVarDataSize(), cb, cMaxDocs );
  266. _LokGiveWork( CFilterSharedMemLayout::eFilterReady );
  267. }
  268. _WaitForResponse();
  269. SCODE status;
  270. {
  271. CIPLock lock(_mutex);
  272. CFilterReadyLayout & data = _pLayout->GetFilterReady();
  273. Win4Assert( data.IsValid() );
  274. status = _pLayout->GetStatus();
  275. if ( NT_SUCCESS(status) )
  276. {
  277. if ( data.GetCount() <= cb )
  278. {
  279. cb = data.GetCount();
  280. RtlCopyMemory( docBuffer, data.GetBuffer(), cb );
  281. }
  282. else
  283. {
  284. // need more memory
  285. cb = data.GetCount();
  286. }
  287. }
  288. else
  289. {
  290. THROW( CException(status) );
  291. }
  292. }
  293. return status;
  294. }
  295. //+---------------------------------------------------------------------------
  296. //
  297. // Member: CGenericCiProxy::FilterDataReady
  298. //
  299. // History: 1-30-96 srikants Created
  300. //
  301. //----------------------------------------------------------------------------
  302. SCODE CGenericCiProxy::FilterDataReady( BYTE const * pEntryBuf, ULONG cb )
  303. {
  304. ProbeForParentProcess();
  305. Win4Assert( _pLayout );
  306. {
  307. CIPLock lock(_mutex);
  308. CFilterDataLayout & data = _pLayout->GetFilterDataReady();
  309. data.Init( pEntryBuf, cb );
  310. _LokGiveWork( CFilterSharedMemLayout::eFilterDataReady );
  311. }
  312. _WaitForResponse();
  313. SCODE status;
  314. {
  315. CIPLock lock(_mutex);
  316. CFilterDataLayout & data = _pLayout->GetFilterDataReady();
  317. Win4Assert( data.IsValid() );
  318. status = _pLayout->GetStatus();
  319. }
  320. return status;
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Member: CGenericCiProxy::FilterMore
  325. //
  326. // History: 1-30-96 srikants Created
  327. //
  328. //----------------------------------------------------------------------------
  329. SCODE CGenericCiProxy::FilterMore( STATUS const * aStatus, ULONG cStatus )
  330. {
  331. ProbeForParentProcess();
  332. Win4Assert( _pLayout );
  333. {
  334. CIPLock lock(_mutex);
  335. CFilterMoreDoneLayout & data = _pLayout->GetFilterMore();
  336. data.Init( aStatus, cStatus );
  337. _LokGiveWork( CFilterSharedMemLayout::eFilterMore );
  338. }
  339. _WaitForResponse();
  340. SCODE status;
  341. {
  342. CIPLock lock(_mutex);
  343. CFilterMoreDoneLayout & data = _pLayout->GetFilterMore();
  344. Win4Assert( data.IsValid() );
  345. status = _pLayout->GetStatus();
  346. }
  347. return status;
  348. }
  349. //+---------------------------------------------------------------------------
  350. //
  351. // Member: CGenericCiProxy::FilterDone
  352. //
  353. // History: 1-30-96 srikants Created
  354. //
  355. //----------------------------------------------------------------------------
  356. SCODE CGenericCiProxy::FilterDone( STATUS const * aStatus, ULONG cStatus )
  357. {
  358. ProbeForParentProcess();
  359. Win4Assert( _pLayout );
  360. {
  361. CIPLock lock(_mutex);
  362. CFilterMoreDoneLayout & data = _pLayout->GetFilterDone();
  363. data.Init( aStatus, cStatus );
  364. _LokGiveWork( CFilterSharedMemLayout::eFilterDone );
  365. }
  366. _WaitForResponse();
  367. SCODE status;
  368. {
  369. CIPLock lock(_mutex);
  370. CFilterMoreDoneLayout & data = _pLayout->GetFilterDone();
  371. Win4Assert( data.IsValid() );
  372. status = _pLayout->GetStatus();
  373. }
  374. return status;
  375. }
  376. //+---------------------------------------------------------------------------
  377. //
  378. // Member: CGenericCiProxy::FilterStoreValue
  379. //
  380. // History: 1-30-96 srikants Created
  381. //
  382. //----------------------------------------------------------------------------
  383. SCODE CGenericCiProxy::FilterStoreValue( WORKID widFake,
  384. CFullPropSpec const & ps,
  385. CStorageVariant const & var,
  386. BOOL & fCanStore )
  387. {
  388. ProbeForParentProcess();
  389. Win4Assert( _pLayout );
  390. {
  391. CIPLock lock(_mutex);
  392. CFilterStoreValueLayout & data = _pLayout->GetFilterStoreValueLayout();
  393. SCODE sc = data.Init( _pLayout->GetMaxVarDataSize(), widFake, ps, var );
  394. if ( S_OK != sc )
  395. {
  396. fCanStore = TRUE; // We are not sure if this property can be stored
  397. // or not in the cache - err on the assumption that
  398. // it can be stored.
  399. return sc;
  400. }
  401. _LokGiveWork( CFilterSharedMemLayout::eFilterStoreValue );
  402. }
  403. _WaitForResponse();
  404. SCODE status;
  405. {
  406. CIPLock lock(_mutex);
  407. CFilterStoreValueLayout & data = _pLayout->GetFilterStoreValueLayout();
  408. Win4Assert( data.IsValid() );
  409. fCanStore = data.GetStatus();
  410. status = _pLayout->GetStatus();
  411. }
  412. return status;
  413. }
  414. //+---------------------------------------------------------------------------
  415. //
  416. // Member: CGenericCiProxy::FilterStoreSecurity
  417. //
  418. // History: 06 Feb 96 AlanW Created
  419. //
  420. //----------------------------------------------------------------------------
  421. SCODE CGenericCiProxy::FilterStoreSecurity( WORKID widFake,
  422. PSECURITY_DESCRIPTOR pSD,
  423. ULONG cbSD,
  424. BOOL & fCanStore )
  425. {
  426. ProbeForParentProcess();
  427. Win4Assert( _pLayout );
  428. {
  429. CIPLock lock(_mutex);
  430. CFilterStoreSecurityLayout & data =
  431. _pLayout->GetFilterStoreSecurityLayout();
  432. data.Init( _pLayout->GetMaxVarDataSize(), widFake, pSD, cbSD );
  433. _LokGiveWork( CFilterSharedMemLayout::eFilterStoreSecurity );
  434. }
  435. _WaitForResponse();
  436. SCODE status;
  437. {
  438. CIPLock lock(_mutex);
  439. CFilterStoreSecurityLayout & data = _pLayout->GetFilterStoreSecurityLayout();
  440. Win4Assert( data.IsValid() );
  441. fCanStore = data.GetStatus();
  442. status = _pLayout->GetStatus();
  443. }
  444. return status;
  445. } //FilterStoreSecurity
  446. //+---------------------------------------------------------------------------
  447. //
  448. // Member: CGenericCiProxy::FPSToPROPID, public
  449. //
  450. // Synopsis: Converts FULLPROPSPEC to PROPID
  451. //
  452. // Arguments: [fps] -- FULLPROPSPEC representing property
  453. // [pid] -- PROPID written here on success
  454. //
  455. // Returns: S_OK on success
  456. //
  457. // History: 29-Dec-1997 KyleP Created
  458. //
  459. //----------------------------------------------------------------------------
  460. SCODE CGenericCiProxy::FPSToPROPID( CFullPropSpec const & fps, PROPID & pid )
  461. {
  462. ProbeForParentProcess();
  463. Win4Assert( _pLayout );
  464. {
  465. CIPLock lock(_mutex);
  466. CFPSToPROPIDLayout & data = _pLayout->GetFPSToPROPID();
  467. data.Init( _pLayout->GetMaxVarDataSize(), fps );
  468. _LokGiveWork( CFilterSharedMemLayout::eFPSToPROPID );
  469. }
  470. _WaitForResponse();
  471. SCODE status = S_OK;
  472. {
  473. CIPLock lock(_mutex);
  474. CFPSToPROPIDLayout & data = _pLayout->GetFPSToPROPID();
  475. status = _pLayout->GetStatus();
  476. if ( SUCCEEDED(status) )
  477. {
  478. ULONG cb = data.GetCount();
  479. Win4Assert( data.IsValid() );
  480. pid = data.GetPROPID();
  481. }
  482. else
  483. {
  484. Win4Assert( STATUS_BUFFER_TOO_SMALL != status );
  485. THROW( CException(status) );
  486. }
  487. }
  488. return status;
  489. } //PidMapToPidRemap
  490. //+---------------------------------------------------------------------------
  491. //
  492. // Member: CGenericCiProxy::GetStartupData
  493. //
  494. // Synopsis: Retrieves the startup data from the main process. This will
  495. // be handed over to the client.
  496. //
  497. // History: 12-19-96 srikants Created
  498. //
  499. //----------------------------------------------------------------------------
  500. BYTE const * CGenericCiProxy::GetStartupData( GUID & clsidClientMgr,
  501. ULONG & cbData )
  502. {
  503. ProbeForParentProcess();
  504. Win4Assert( _pLayout );
  505. {
  506. CIPLock lock(_mutex);
  507. CFilterStartupDataLayout & data = _pLayout->GetStartupData();
  508. data.Init();
  509. _LokGiveWork( CFilterSharedMemLayout::eFilterStartupData );
  510. }
  511. _WaitForResponse();
  512. SCODE status;
  513. BYTE const * pbData = 0;
  514. {
  515. CIPLock lock(_mutex);
  516. CFilterStartupDataLayout & data = _pLayout->GetStartupData();
  517. Win4Assert( data.IsValid() );
  518. status = _pLayout->GetStatus();
  519. if ( S_OK == status )
  520. {
  521. pbData = data.GetData( cbData );
  522. clsidClientMgr = data.GetClientMgrCLSID();
  523. }
  524. }
  525. return pbData;
  526. }
  527. //+---------------------------------------------------------------------------
  528. //
  529. // Member: CGenericCiProxy::SetPriority
  530. //
  531. // Synopsis: Sets the priority class of the process and this thread's priority
  532. // based upon the values passed in.
  533. //
  534. // History: 12-19-96 srikants Created
  535. //
  536. //----------------------------------------------------------------------------
  537. void CGenericCiProxy::SetPriority( ULONG priClass, ULONG priThread )
  538. {
  539. SetPriorityClass( GetCurrentProcess(), priClass );
  540. SetThreadPriority( GetCurrentThread(), priThread );
  541. }
  542. //+---------------------------------------------------------------------------
  543. //
  544. // Member: CGenericCiProxy::GetEntryBuffer
  545. //
  546. // Synopsis: Returns the shared memory buffer that will be used by
  547. // the daemon to pass the "FilterDataReady".
  548. // This is an optimization to avoid data copying (128K) for
  549. // every call to "FilterDataReady".
  550. //
  551. // Arguments: [cb] - On output, will have the size of the buffer.
  552. //
  553. // History: 2-21-96 srikants Created
  554. //
  555. //----------------------------------------------------------------------------
  556. BYTE * CGenericCiProxy::GetEntryBuffer( ULONG & cbMax )
  557. {
  558. CIPLock lock(_mutex);
  559. CFilterDataLayout & data = _pLayout->GetFilterDataReady();
  560. cbMax = data.GetMaxSize();
  561. return data.GetBuffer();
  562. } //GetEntryBuffer
  563. //+---------------------------------------------------------------------------
  564. //
  565. // Member: CGenericCiProxy::ProbeForParentProcess
  566. //
  567. // Synopsis: Checks if the parent process (cisvc.exe) is still alive
  568. //
  569. // History: 12-Aug-97 SitaramR Created
  570. //
  571. //----------------------------------------------------------------------------
  572. void CGenericCiProxy::ProbeForParentProcess()
  573. {
  574. DWORD status = WaitForSingleObject( _aWait[iParent], 0 );
  575. if ( WAIT_FAILED == status )
  576. {
  577. DWORD dwError = GetLastError();
  578. ciDebugOut(( DEB_ERROR, "DLDaemon - WaitFailed. Error 0x%X\n", dwError ));
  579. THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
  580. }
  581. if ( WAIT_TIMEOUT == status )
  582. return;
  583. else
  584. {
  585. ciDebugOut(( DEB_ERROR, "DLDaemon - Parent process died abruptly\n" ));
  586. THROW( CException(FDAEMON_E_FATALERROR ) );
  587. }
  588. }