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.

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