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.

1046 lines
32 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: scmrot.hxx
  7. //
  8. // Contents: Implementation of classes for the ROT in the SCM
  9. //
  10. // Functions: RoundTo8 - round size to 8 byte boundary
  11. // CalcIfdSize - calculate size needed for marhaled interface
  12. // SizeMnkEqBufForRotEntry - calculate size for moniker eq buffer
  13. // AllocateAndCopy - create copy of a marshaled interface
  14. // GetEntryFromScmReg - convert SCMREGKEY to ROT entry ptr
  15. //
  16. // History: 20-Jan-95 Ricksa Created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "act.hxx"
  20. #if 0 // #ifdef _CHICAGO_
  21. CStaticPortableMutex CScmRot::_mxs; // mutex semaphore
  22. #endif
  23. //+-------------------------------------------------------------------------
  24. //
  25. // Function: RoundTo8
  26. //
  27. // Synopsis: Round size to next 8 byte boundary
  28. //
  29. // Arguments: [sizeToRound] - Size to round
  30. //
  31. // Returns: Input rounded to the next 8 byte boundary
  32. //
  33. // History: 20-Jan-95 Ricksa Created
  34. //
  35. //--------------------------------------------------------------------------
  36. inline size_t RoundTo8(size_t sizeToRound)
  37. {
  38. return (sizeToRound + 7) & ~7;
  39. }
  40. //+-------------------------------------------------------------------------
  41. //
  42. // Function: CalcIfdSize
  43. //
  44. // Synopsis: Calculate size required by a marshaled interface
  45. //
  46. // Arguments: [pifd] - interface whose size to calculate
  47. //
  48. // Returns: size required for interface
  49. //
  50. // Algorithm: Get size from the interface and round to next 8 bytes so
  51. // data packed following this buffer will be nicely aligned.
  52. //
  53. // History: 20-Jan-95 Ricksa Created
  54. //
  55. //--------------------------------------------------------------------------
  56. size_t CalcIfdSize(InterfaceData *pifd)
  57. {
  58. CairoleDebugOut((DEB_ROT, "%p _IN CalcIfdSize ( %p )\n", NULL,
  59. pifd));
  60. size_t sizeRet = RoundTo8(IFD_SIZE(pifd));
  61. CairoleDebugOut((DEB_ROT, "%p OUT CalcIfdSize ( %lx )\n", NULL,
  62. sizeRet));
  63. return sizeRet;
  64. }
  65. //+-------------------------------------------------------------------------
  66. //
  67. // Function: SizeMnkEqBufForRotEntry
  68. //
  69. // Synopsis: Calculate 8 byte aligned size for moniker equality buffer
  70. //
  71. // Arguments: [pmnkeqbuf] - Moniker equality buffer
  72. //
  73. // Returns: 8 byte aligned size of moniker buffer.
  74. //
  75. // Algorithm: Calculate size for the moniker equality buffer from input
  76. // buffer and then round to next 8 byte boundary
  77. //
  78. // History: 20-Jan-95 Ricksa Created
  79. //
  80. //--------------------------------------------------------------------------
  81. size_t SizeMnkEqBufForRotEntry(MNKEQBUF *pmnkeqbuf)
  82. {
  83. CairoleDebugOut((DEB_ROT, "%p _IN SizeMnkEqBufForRotEntry ( %p )\n", NULL,
  84. pmnkeqbuf));
  85. size_t sizeRet = RoundTo8((sizeof(MNKEQBUF) - 1) + pmnkeqbuf->cdwSize);
  86. CairoleDebugOut((DEB_ROT, "%p OUT SizeMnkEqBufForRotEntry ( %lx )\n", NULL,
  87. sizeRet));
  88. return sizeRet;
  89. }
  90. //+-------------------------------------------------------------------------
  91. //
  92. // Function: AllocateAndCopy
  93. //
  94. // Synopsis: Make a copy of the input marshaled interface
  95. //
  96. // Arguments: [pifdIn] - input marshaled interface.
  97. //
  98. // Returns: Copy of input marshaled interface.
  99. //
  100. // Algorithm: Calculate size required for marshaled interface. Allocate
  101. // memory for the interface and then copy input interface into
  102. // the new buffer.
  103. //
  104. // History: 20-Jan-95 Ricksa Created
  105. //
  106. //--------------------------------------------------------------------------
  107. InterfaceData *AllocateAndCopy(InterfaceData *pifdIn)
  108. {
  109. CairoleDebugOut((DEB_ROT, "%p _IN AllocateAndCopy ( %p )\n", NULL, pifdIn));
  110. DWORD dwSizeObj = CalcIfdSize(pifdIn);
  111. InterfaceData *pifd = (InterfaceData *) MIDL_user_allocate(dwSizeObj);
  112. if (pifd)
  113. {
  114. // Copy all the data. Remember that pifdIn was allocated rounded
  115. // to an 8 byte boundary so we will not run off the end of the
  116. // memory buffer
  117. memcpy(pifd, pifdIn, dwSizeObj);
  118. }
  119. CairoleDebugOut((DEB_ROT, "%p OUT AllocateAndCopy ( %lx )\n", NULL, pifd));
  120. return pifd;
  121. }
  122. //+-------------------------------------------------------------------------
  123. //
  124. // Function: GetEntryFromScmReg
  125. //
  126. // Synopsis: Convert SCMREGKEY into a pointer to a ROT entry if possible
  127. //
  128. // Arguments: [psrk] - Pointer to a SCMREGKEY
  129. //
  130. // Returns: NULL - psrk not valid
  131. // ROT entry for the given input key
  132. //
  133. // Algorithm: Take the pointer portion of the key and make sure that
  134. // it points to enough memory so that we can validate the
  135. // signiture in the object. Then validate the signiture in
  136. // the object and return a pointer to the object.
  137. //
  138. // History: 20-Jan-95 Ricksa Created
  139. //
  140. //--------------------------------------------------------------------------
  141. CScmRotEntry *GetEntryFromScmReg(SCMREGKEY *psrk)
  142. {
  143. CairoleDebugOut((DEB_ROT, "%p _IN GetEntryFromScmReg ( %p )\n",
  144. NULL, psrk));
  145. CScmRotEntry *psreRet = NULL;
  146. CScmRotEntry *psre = (CScmRotEntry *) psrk->dwEntryLoc;
  147. // Make sure pointer is pointer to valid memory - it s/b read write
  148. // memory since we allocated it and updated it.
  149. if (!IsBadReadPtr(psre, sizeof(*psre))
  150. && !IsBadWritePtr(psre, sizeof(*psre)))
  151. {
  152. // Make sure signitures are valid
  153. if (psre->IsValid(psrk->dwScmId))
  154. {
  155. psreRet = psre;
  156. }
  157. }
  158. CairoleDebugOut((DEB_ROT, "%p OUT GetEntryFromScmReg ( %lx )\n",
  159. NULL, psreRet));
  160. return psreRet;
  161. }
  162. //+-------------------------------------------------------------------------
  163. //
  164. // Member: CScmRotEntry::CScmRotEntry
  165. //
  166. // Synopsis: Create a ROT entry for a registration
  167. //
  168. // Arguments: [dwScmRotId] - signiture for item
  169. // [pmkeqbuf] - moniker equality buffer to use
  170. // [pfiletime] - file time to use
  171. // [dwProcessID] - process id to use
  172. // [pifdObject] - marshaled interface for the object
  173. // [pifdObjectName] - marshaled moniker for the object
  174. //
  175. // Algorithm: Initialize data and calcualte offsets into the object for
  176. // the variable length data.
  177. //
  178. // History: 20-Jan-95 Ricksa Created
  179. //
  180. //--------------------------------------------------------------------------
  181. CScmRotEntry::CScmRotEntry(
  182. DWORD dwScmRotId,
  183. MNKEQBUF *pmkeqbuf,
  184. FILETIME *pfiletime,
  185. DWORD dwProcessID,
  186. #if 1 // #ifndef _CHICAGO_
  187. CToken *pToken,
  188. #endif
  189. WCHAR *pwszWinstaDesktop,
  190. InterfaceData *pifdObject,
  191. InterfaceData *pifdObjectName)
  192. : _dwSig(SCMROT_SIG),
  193. _dwScmRotId(dwScmRotId),
  194. _dwProcessID(dwProcessID),
  195. _filetimeLastChange(*pfiletime),
  196. _pifdObject((InterfaceData *) &_ab[0])
  197. {
  198. CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::CScmRotEntry "
  199. "( %lx , %p , %p , %lx , %p , %p )\n", this, pmkeqbuf, pfiletime,
  200. dwProcessID, pifdObject, pifdObjectName));
  201. #ifndef _CHICAGO_
  202. _pToken = pToken;
  203. if ( _pToken )
  204. _pToken->AddRef();
  205. #endif
  206. // Copy data for object to preallocated area
  207. _pifdObject->ulCntData = pifdObject->ulCntData;
  208. memcpy(&_pifdObject->abData[0], &pifdObject->abData[0],
  209. _pifdObject->ulCntData);
  210. // Calculate the location of the equality buffer in the allocated data
  211. DWORD dwOffsetMnkEqBuf = CalcIfdSize(_pifdObject);
  212. _pmkeqbufKey = (MNKEQBUF *) &_ab[dwOffsetMnkEqBuf];
  213. // Copy data for moniker equality buffer into preallocated area
  214. _pmkeqbufKey->cdwSize = pmkeqbuf->cdwSize;
  215. memcpy(&_pmkeqbufKey->abEqData[0], &pmkeqbuf->abEqData[0],
  216. _pmkeqbufKey->cdwSize);
  217. // Calculate the location of the moniker name buffer
  218. _pifdObjectName = (InterfaceData *)
  219. &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey)];
  220. // Copy in the data for the moniker name
  221. _pifdObjectName->ulCntData = pifdObjectName->ulCntData;
  222. memcpy(&_pifdObjectName->abData[0], &pifdObjectName->abData[0],
  223. _pifdObjectName->ulCntData);
  224. if ( pwszWinstaDesktop )
  225. {
  226. _pwszWinstaDesktop = (WCHAR *)
  227. &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey) + CalcIfdSize(_pifdObjectName)];
  228. lstrcpyW( _pwszWinstaDesktop, pwszWinstaDesktop );
  229. }
  230. else
  231. {
  232. _pwszWinstaDesktop = NULL;
  233. }
  234. CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::CScmRotEntry \n",
  235. this));
  236. }
  237. //+-------------------------------------------------------------------------
  238. //
  239. // Member: CScmRotEntry::IsEqual
  240. //
  241. // Synopsis: Determine if input key is equal to the ROT entry's key
  242. //
  243. // Arguments: [pKey] - Key to use for the test
  244. // [cbKey] - Count of bytes in key
  245. //
  246. // Returns: TRUE - input key equals this object's key
  247. // FALSE - keys are not equal
  248. //
  249. // Algorithm: If the two sizes are equal then compare the actual data
  250. // buffers and return the result of that compare.
  251. //
  252. // History: 20-Jan-95 Ricksa Created
  253. //
  254. //--------------------------------------------------------------------------
  255. BOOL CScmRotEntry::IsEqual(LPVOID pKey, UINT cbKey)
  256. {
  257. CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::IsEqual "
  258. "( %p , %lx )\n", this, pKey, cbKey));
  259. BOOL fRet = FALSE;
  260. if (cbKey == _pmkeqbufKey->cdwSize)
  261. {
  262. fRet = memcmp(pKey, &_pmkeqbufKey->abEqData[0], cbKey) == 0;
  263. }
  264. CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::IsEqual ( %lx )\n",
  265. this, fRet));
  266. return fRet;
  267. }
  268. //+-------------------------------------------------------------------------
  269. //
  270. // Member: CScmRot::Register
  271. //
  272. // Synopsis: Add entry to the ROT
  273. //
  274. // Arguments: [pmkeqbuf] - moniker equality buffer to use
  275. // [pfiletime] - file time to use
  276. // [dwProcessID] - process id to use
  277. // [pifdObject] - marshaled interface for the object
  278. // [pifdObjectName] - marshaled moniker for the object
  279. //
  280. // Returns: NOERROR - successfully registered
  281. // E_OUTOFMEMORY
  282. //
  283. // Algorithm: Lock the ROT from all other threads. The create a new
  284. // entry and determine if there is an eqivalent entry in
  285. // the ROT. Calculate the hash value and then put the
  286. // entry into our hash table. Finally, build a registration
  287. // key to return to the caller.
  288. //
  289. // History: 20-Jan-95 Ricksa Created
  290. //
  291. //--------------------------------------------------------------------------
  292. HRESULT CScmRot::Register(
  293. #if 1 // #ifndef _CHICAGO_
  294. CProcess *pProcess,
  295. #endif
  296. WCHAR *pwszWinstaDesktop,
  297. MNKEQBUF *pmnkeqbuf,
  298. InterfaceData *pifdObject,
  299. InterfaceData *pifdObjectName,
  300. FILETIME *pfiletime,
  301. DWORD dwProcessID,
  302. WCHAR *pwszServerExe,
  303. SCMREGKEY *psrkRegister)
  304. {
  305. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Register "
  306. "( %p , %p , %p , %p , %lx , %p )\n", this, pmnkeqbuf, pifdObject,
  307. pifdObjectName, pfiletime, dwProcessID, psrkRegister));
  308. // Assume that there is a memory problem
  309. HRESULT hr = E_OUTOFMEMORY;
  310. CToken * pToken;
  311. pToken = pProcess->GetToken();
  312. if ( pwszServerExe )
  313. {
  314. HKEY hKey;
  315. LONG RegStatus;
  316. WCHAR wszAppid[40];
  317. DWORD Size;
  318. RegStatus = ERROR_SUCCESS;
  319. // The pwszServerExe string may contain an AppId string or
  320. // a module name. If it looks like a GUID string, we can bypass
  321. // the AppId lookup. Otherwise, we go to the Registry to
  322. if ( pwszServerExe[0] == L'{' )
  323. {
  324. // Use the given string as the AppId
  325. lstrcpyn(wszAppid, pwszServerExe, sizeof(wszAppid)/sizeof(WCHAR));
  326. }
  327. else
  328. {
  329. // Try to map the Exe name to an AppId
  330. if ( ! ghAppidMachine )
  331. RegStatus = OpenClassesRootKeys();
  332. if ( ERROR_SUCCESS == RegStatus )
  333. {
  334. RegStatus = RegOpenKeyEx( ghAppidMachine,
  335. pwszServerExe,
  336. NULL,
  337. KEY_READ,
  338. &hKey );
  339. }
  340. if ( ERROR_SUCCESS == RegStatus )
  341. {
  342. Size = sizeof(wszAppid);
  343. RegStatus = RegQueryValueEx( hKey,
  344. L"AppId",
  345. NULL,
  346. NULL,
  347. (BYTE *)wszAppid,
  348. &Size );
  349. RegCloseKey( hKey );
  350. }
  351. if ( RegStatus != ERROR_SUCCESS )
  352. return CO_E_WRONG_SERVER_IDENTITY;
  353. }
  354. CAppidData Appid( wszAppid, pToken );
  355. BOOL Access;
  356. Access = FALSE;
  357. // Load appid info from the matching side of the registry
  358. DWORD dwAppidFlags = 0;
  359. #if defined(_WIN64)
  360. dwAppidFlags = pProcess->Is64Bit() ? CAT_REG64_ONLY : CAT_REG32_ONLY;
  361. #endif
  362. hr = Appid.Load(dwAppidFlags);
  363. if ( S_OK == hr )
  364. Access = Appid.CertifyServer( pProcess );
  365. if ( ! Access )
  366. return CO_E_WRONG_SERVER_IDENTITY;
  367. //
  368. // NULL these to indicate that any client can connect to this
  369. // registration.
  370. //
  371. pwszWinstaDesktop = NULL;
  372. pToken = NULL;
  373. }
  374. // Lock for the duration of the call
  375. CPortableLock lck(_mxs);
  376. // Bump the id
  377. _dwIdCntr++;
  378. // Build a record to put into the table
  379. CScmRotEntry *psreNew = new(
  380. pwszWinstaDesktop ? (lstrlenW(pwszWinstaDesktop)+1)*sizeof(WCHAR) : 0,
  381. CalcIfdSize(pifdObject),
  382. SizeMnkEqBufForRotEntry(pmnkeqbuf),
  383. CalcIfdSize(pifdObjectName))
  384. CScmRotEntry(_dwIdCntr, pmnkeqbuf, pfiletime, dwProcessID,
  385. #ifndef _CHICAGO_
  386. pToken,
  387. #else
  388. NULL,
  389. #endif
  390. pwszWinstaDesktop, pifdObject, pifdObjectName);
  391. if (psreNew != NULL)
  392. {
  393. DWORD dwHash;
  394. CScmRotEntry * psreRunning;
  395. #ifndef _CHICAGO_
  396. psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
  397. #else
  398. psreRunning = GetRotEntry( NULL, pwszWinstaDesktop, pmnkeqbuf );
  399. #endif
  400. dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0);
  401. // Put record into the hash table
  402. _sht.SetAt(dwHash, psreNew);
  403. #if 1 // #ifndef _CHICAGO_
  404. // Update the hint table
  405. _rht.SetIndicator(dwHash);
  406. #endif // !_CHICAGO_
  407. // Build return value
  408. psreNew->SetScmRegKey(psrkRegister);
  409. // Map return result based on prior existence of the object.
  410. hr = (psreRunning == NULL)
  411. ? NOERROR : MK_S_MONIKERALREADYREGISTERED;
  412. }
  413. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Register "
  414. " ( %lx )\n", this, hr));
  415. return hr;
  416. }
  417. //+-------------------------------------------------------------------------
  418. //
  419. // Member: CScmRot::Revoke
  420. //
  421. // Synopsis: Remove entry from the ROT
  422. //
  423. // Arguments: [psrkRegister] - registration to revoke
  424. // [fServer] - whether this is the object server
  425. // [ppifdObject] - output marshaled interface (optional)
  426. // [ppifdName] - output marshaled moniker (optional)
  427. //
  428. // Returns: NOERROR - successfully removed.
  429. // E_INVALIDARG
  430. //
  431. // Algorithm: Convert SCMREGKEY to anentry in the ROT. Remove the
  432. // entry from the hash table. If this is the object server
  433. // for the entry, then return the marshaled interfaces
  434. // so the object server can release them.
  435. //
  436. // History: 20-Jan-95 Ricksa Created
  437. //
  438. //--------------------------------------------------------------------------
  439. HRESULT CScmRot::Revoke(
  440. SCMREGKEY *psrkRegister,
  441. BOOL fServer,
  442. InterfaceData **ppifdObject,
  443. InterfaceData **ppifdName)
  444. {
  445. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Revoke "
  446. "( %p , %lx , %p , %p )\n", this, fServer, ppifdObject, ppifdName));
  447. HRESULT hr = E_INVALIDARG;
  448. // Lock for the duration of the call
  449. CPortableLock lck(_mxs);
  450. // Verify registration key
  451. CScmRotEntry *psreToRemove = GetEntryFromScmReg(psrkRegister);
  452. if (psreToRemove != NULL)
  453. {
  454. // Get the has value
  455. DWORD dwHash = ScmRotHash(psreToRemove->Key(), psreToRemove->cKey(), 0);
  456. // Remove object from the list
  457. _sht.RemoveEntry(dwHash, psreToRemove);
  458. // Is this a server doing a revoke?
  459. if (fServer)
  460. {
  461. // Error handling here - suppose these allocations fail, what
  462. // can we do? The bottom line is nothing. This will cause a
  463. // memory leak in the server because they can't release the
  464. // marshaled data. However, this is assumed to be a rare
  465. // occurance and will really only cause the moniker to live
  466. // longer than it ought to which should not be too serious.
  467. *ppifdObject = AllocateAndCopy(psreToRemove->GetObject());
  468. *ppifdName = AllocateAndCopy(psreToRemove->GetMoniker());
  469. }
  470. // Free the entry
  471. delete psreToRemove;
  472. #if 1 // #ifndef _CHICAGO_
  473. // See if bucket is empty
  474. if (_sht.IsBucketEmpty(dwHash))
  475. {
  476. // Update the hint table.
  477. _rht.ClearIndicator(dwHash);
  478. }
  479. #endif // !_CHICAGO_
  480. hr = S_OK;
  481. }
  482. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Revoke "
  483. " ( %lx ) [ %p, %p ] \n", this, hr,
  484. (ppifdObject != NULL) ? *ppifdObject : NULL,
  485. (ppifdName != NULL) ? *ppifdName : NULL));
  486. return hr;
  487. }
  488. //+-------------------------------------------------------------------------
  489. //
  490. // Member: CScmRot::IsRunning
  491. //
  492. // Synopsis: Determine if there is a registered entry for an item
  493. //
  494. // Arguments: [pmnkeqbuf] - Moniker equality buffer to search for
  495. //
  496. // Returns: NOERROR - moniker is registered as running
  497. // S_FALSE - moniker is not running.
  498. //
  499. // Algorithm: Get the entry for the moniker equality buffer if there is
  500. // one. If there is one, then return NOERROR otherwise return
  501. // S_FALSE.
  502. //
  503. // History: 20-Jan-95 Ricksa Created
  504. //
  505. //--------------------------------------------------------------------------
  506. HRESULT CScmRot::IsRunning(
  507. #if 1 // #ifndef _CHICAGO_
  508. CToken *pToken,
  509. #endif
  510. WCHAR *pwszWinstaDesktop,
  511. MNKEQBUF *pmnkeqbuf)
  512. {
  513. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::IsRunning "
  514. "( %p )\n", this, pmnkeqbuf));
  515. // Lock for the duration of the call
  516. CPortableLock lck(_mxs);
  517. #if 1 // #ifndef _CHICAGO_
  518. CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
  519. #else
  520. CScmRotEntry *psreRunning = GetRotEntry(pwszWinstaDesktop, pmnkeqbuf);
  521. #endif
  522. HRESULT hr = (psreRunning != NULL) ? S_OK : S_FALSE;
  523. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::IsRunning "
  524. " ( %lx ) \n", this, hr));
  525. return hr;
  526. }
  527. //+-------------------------------------------------------------------------
  528. //
  529. // Member: CScmRot::GetObject
  530. //
  531. // Synopsis: Get running object for input
  532. //
  533. // Arguments: [dwProcessID] - process id of object (optional)
  534. // [pmnkeqbuf] - moniker equality buffer
  535. // [psrkRegister] - output registration id.
  536. // [ppifdObject] - marshaled interface for registration
  537. //
  538. // Returns: NOERROR - got object
  539. // MK_E_UNAVAILABLE - registration could not be found
  540. //
  541. // Algorithm: If not process ID is input, then search for the first
  542. // matching entry that we can find. Otherwise, search the
  543. // hash for the entry with both the same key and the same
  544. // process id.
  545. //
  546. // History: 20-Jan-95 Ricksa Created
  547. //
  548. //--------------------------------------------------------------------------
  549. HRESULT CScmRot::GetObject(
  550. #if 1 // #ifndef _CHICAGO_
  551. CToken *pToken,
  552. #endif
  553. WCHAR *pwszWinstaDesktop,
  554. DWORD dwProcessID,
  555. MNKEQBUF *pmnkeqbuf,
  556. SCMREGKEY *psrkRegister,
  557. InterfaceData **ppifdObject)
  558. {
  559. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetObject "
  560. "( %lx , %p , %p , %p )\n", this, dwProcessID, pmnkeqbuf, psrkRegister,
  561. ppifdObject));
  562. HRESULT hr = MK_E_UNAVAILABLE;
  563. // Lock for the duration of the call
  564. CPortableLock lck(_mxs);
  565. CScmRotEntry *psreRunning;
  566. if (dwProcessID == 0)
  567. {
  568. psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
  569. }
  570. else
  571. {
  572. // Special search based on process ID - get the head of the list
  573. // for the bucket
  574. psreRunning = (CScmRotEntry *) _sht.GetBucketList(
  575. ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0));
  576. // Search list for a matching entry
  577. while (psreRunning != NULL)
  578. {
  579. if ((psreRunning->GetProcessID() == dwProcessID)
  580. && psreRunning->IsEqual(&pmnkeqbuf->abEqData[0],
  581. pmnkeqbuf->cdwSize))
  582. {
  583. // We found a match so we are done.
  584. break;
  585. }
  586. // Try the next item in the bucket.
  587. psreRunning = (CScmRotEntry *) psreRunning->GetNext();
  588. }
  589. }
  590. if (psreRunning != NULL)
  591. {
  592. hr = E_OUTOFMEMORY;
  593. *ppifdObject = AllocateAndCopy(psreRunning->GetObject());
  594. if (*ppifdObject != NULL)
  595. {
  596. hr = NOERROR;
  597. }
  598. // Build return registration key
  599. psreRunning->SetScmRegKey(psrkRegister);
  600. }
  601. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetObject "
  602. " ( %lx ) [ %p ] \n", this, hr, *ppifdObject));
  603. return hr;
  604. }
  605. //+-------------------------------------------------------------------------
  606. //
  607. // Member: CScmRot::NoteChangeTime
  608. //
  609. // Synopsis: Set the time of last change for a ROT entry
  610. //
  611. // Arguments: [psrkRegister] - ID of entry to change
  612. // [pfiletime] - new time for the entry.
  613. //
  614. // Returns: NOERROR - time set
  615. // E_INVALIDARG - ROT entry could not be found
  616. //
  617. // Algorithm: Convert SCMREGKEY into a pointer to a ROT entry and then
  618. // update the time of that entry.
  619. //
  620. // History: 20-Jan-95 Ricksa Created
  621. //
  622. //--------------------------------------------------------------------------
  623. HRESULT CScmRot::NoteChangeTime(
  624. SCMREGKEY *psrkRegister,
  625. FILETIME *pfiletime)
  626. {
  627. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::NoteChangeTime "
  628. "( %p , %p )\n", this, psrkRegister, pfiletime));
  629. HRESULT hr = E_INVALIDARG;
  630. // Lock for the duration of the call
  631. CPortableLock lck(_mxs);
  632. CScmRotEntry *psre = GetEntryFromScmReg(psrkRegister);
  633. if (psre != NULL)
  634. {
  635. psre->SetTime(pfiletime);
  636. hr = S_OK;
  637. }
  638. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::NoteChangeTime "
  639. " ( %lx ) \n", this, hr));
  640. return hr;
  641. }
  642. //+-------------------------------------------------------------------------
  643. //
  644. // Member: CScmRot::GetTimeOfLastChange
  645. //
  646. // Synopsis: Get time of last change for a moniker in the ROT
  647. //
  648. // Arguments: [pmnkeqbuf] - Moniker equality buffer
  649. // [pfiletime] - Where to put the time
  650. //
  651. // Returns: NOERROR - got the time
  652. // MK_E_UNAVAILABLE - couldn't find an entry/
  653. //
  654. // Algorithm: Search the hash for an entry with the same moniker. If
  655. // found, then copy out the time.
  656. //
  657. // History: 20-Jan-95 Ricksa Created
  658. //
  659. //--------------------------------------------------------------------------
  660. HRESULT CScmRot::GetTimeOfLastChange(
  661. #if 1 // #ifndef _CHICAGO_
  662. CToken *pToken,
  663. #endif
  664. WCHAR *pwszWinstaDesktop,
  665. MNKEQBUF *pmnkeqbuf,
  666. FILETIME *pfiletime)
  667. {
  668. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetTimeOfLastChange "
  669. "( %p , %p )\n", this, pmnkeqbuf, pfiletime));
  670. HRESULT hr = MK_E_UNAVAILABLE;
  671. // Lock for the duration of the call
  672. CPortableLock lck(_mxs);
  673. #if 1 // #ifndef _CHICAGO_
  674. CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
  675. #else
  676. CScmRotEntry *psreRunning = GetRotEntry(pwszWinstaDesktop, pmnkeqbuf);
  677. #endif
  678. if (psreRunning != NULL)
  679. {
  680. psreRunning->GetTime(pfiletime);
  681. hr = S_OK;
  682. }
  683. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetTimeOfLastChange "
  684. " ( %lx ) \n", this, hr));
  685. return hr;
  686. }
  687. //+-------------------------------------------------------------------------
  688. //
  689. // Member: CScmRot::EnumRunning
  690. //
  691. // Synopsis: Get a list of all the monikers that are currently running
  692. //
  693. // Arguments: [ppMkIFList] - Where to put list of monikers running
  694. //
  695. // Returns: NOERROR - got list
  696. // E_OUTOFMEMORY - couldn't allocate space for the list
  697. //
  698. // Algorithm: Loop through the ROT copying out the marshaled moniker buffers
  699. //
  700. // History: 20-Jan-95 Ricksa Created
  701. //
  702. //--------------------------------------------------------------------------
  703. HRESULT CScmRot::EnumRunning(
  704. #if 1 // #ifndef _CHICAGO_
  705. CToken *pToken,
  706. #endif
  707. WCHAR *pwszWinstaDesktop,
  708. MkInterfaceList **ppMkIFList)
  709. {
  710. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::EnumRunning "
  711. "( %p )\n", this, ppMkIFList));
  712. HRESULT hr = E_OUTOFMEMORY;
  713. // Lock for the duration of the call
  714. CPortableLock lck(_mxs);
  715. *ppMkIFList = NULL;
  716. MkInterfaceList *pMkIFList = NULL;
  717. // This is the upper limit on how much space we'll need.
  718. DWORD dwSize = sizeof(MkInterfaceList) +
  719. (_sht.GetCount() - 1) * sizeof(InterfaceData *);
  720. // Allocate buffer
  721. pMkIFList = (MkInterfaceList *) MIDL_user_allocate(dwSize);
  722. // We use this to keep track fof the number of monikers we are returning
  723. DWORD dwOffset = 0;
  724. if (pMkIFList != NULL)
  725. {
  726. // Iterate list getting the pointers
  727. CScmHashIter shi(&_sht);
  728. CScmRotEntry *psre;
  729. while ((psre = (CScmRotEntry *) shi.GetNext()) != NULL)
  730. {
  731. InterfaceData *pifdForOutput;
  732. if ( psre->WinstaDesktop() &&
  733. (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) )
  734. continue;
  735. #ifndef _CHICAGO_
  736. if ( S_OK != pToken->MatchToken2(psre->Token(), FALSE) )
  737. continue;
  738. if ( gbSAFERROTChecksEnabled )
  739. {
  740. HRESULT hr = pToken->CompareSaferLevels(psre->Token());
  741. // S_FALSE: pToken is of lesser authorization, i.e., this
  742. // is untrusted code calling into trusted code.
  743. if (hr == S_FALSE)
  744. {
  745. DbgPrint("RPCSS: SCMROT: SAFER level did not match.\n");
  746. continue;
  747. }
  748. }
  749. #endif
  750. pifdForOutput = AllocateAndCopy(psre->GetMoniker());
  751. if (pifdForOutput == NULL)
  752. {
  753. goto Exit;
  754. }
  755. // Put copy in the array
  756. pMkIFList->apIFDList[dwOffset] = pifdForOutput;
  757. // We bump the count because it makes clean up easier
  758. dwOffset++;
  759. }
  760. // Teller caller and cleanup that everything went ok.
  761. hr = S_OK;
  762. // Set the output buffer to the buffer we have allocated.
  763. *ppMkIFList = pMkIFList;
  764. // Set the size of the object to return
  765. pMkIFList->dwSize = dwOffset;
  766. }
  767. Exit:
  768. if (FAILED(hr))
  769. {
  770. // We failed so clean up
  771. if (pMkIFList != NULL)
  772. {
  773. // Clean up the moniker interfaces that were allocated
  774. for (DWORD i = 0; i < dwOffset; i++)
  775. {
  776. MIDL_user_free(pMkIFList->apIFDList[i]);
  777. }
  778. // Clean up the table structure itself
  779. MIDL_user_free(pMkIFList);
  780. }
  781. }
  782. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::EnumRunning "
  783. " ( %lx ) [ %p ]\n", this, hr, *ppMkIFList));
  784. return hr;
  785. }
  786. //+-------------------------------------------------------------------------
  787. //
  788. // Member: CScmRot::GetRotEntry
  789. //
  790. // Synopsis: Search ROT for entry that matches the equality buffer input.
  791. //
  792. // Arguments: [pmnkeqbuf] - Moniker equality buffer to search for.
  793. //
  794. // Returns: NULL - no entry could be found
  795. // Pointer to ROT entry with matching key
  796. //
  797. // Algorithm: Calculate the hash value for the input buffer. The search
  798. // the hash table for the matching value.
  799. //
  800. // History: 20-Jan-95 Ricksa Created
  801. //
  802. //--------------------------------------------------------------------------
  803. CScmRotEntry *CScmRot::GetRotEntry(
  804. #if 1 // #ifndef _CHICAGO_
  805. CToken *pToken,
  806. #endif
  807. WCHAR *pwszWinstaDesktop,
  808. MNKEQBUF *pmnkeqbuf)
  809. {
  810. CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetRotEntry "
  811. "( %p )\n", this, pmnkeqbuf));
  812. DWORD dwHash;
  813. CScmRotEntry * psre;
  814. dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0);
  815. psre = (CScmRotEntry *) _sht.GetBucketList( dwHash );
  816. for ( ; psre != NULL; psre = (CScmRotEntry *) psre->GetNext() )
  817. {
  818. if ( psre->IsEqual(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize) )
  819. {
  820. //
  821. // Note that this routine is actually called during a Register
  822. // to see if there is a duplicate moniker and also during a
  823. // client Lookup. This makes things a little complicated.
  824. //
  825. // The winsta\desktop param can only be null in two instances.
  826. // + While doing a Register from a service or RunAs server. The
  827. // pToken will also be null.
  828. // + While doing a ROT lookup during a secure remote activation.
  829. // The pToken will be non-null. We only check that the SIDs
  830. // match in this case.
  831. //
  832. // During an usecure activation the pToken will be NULL. The
  833. // winsta/desktop will actually be "" in this case (see
  834. // Activation) to allow us to distinguish just this case.
  835. //
  836. // The ROT entry's winsta\desktop can be null if a service or RunAs
  837. // server registered a globally available object.
  838. //
  839. // Existing registration is globally available.
  840. if ( ! psre->WinstaDesktop() )
  841. break;
  842. //
  843. // NULL token and winsta/desktop means a server is doing a register
  844. // for a globally available object, return the match.
  845. // NULL token but non-null ("") winsta/desktop is a lookup from a
  846. // remote unsecure client, no match.
  847. //
  848. if ( ! pToken )
  849. {
  850. if ( ! pwszWinstaDesktop )
  851. break;
  852. else
  853. continue;
  854. }
  855. Win4Assert( psre->Token() );
  856. if ( pwszWinstaDesktop &&
  857. (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) )
  858. continue;
  859. // Check to make sure the token matches
  860. if(S_OK != pToken->MatchToken2(psre->Token(), FALSE))
  861. continue;
  862. // Check to make sure that the safer token matches
  863. if ( gbSAFERROTChecksEnabled )
  864. {
  865. HRESULT hr = pToken->CompareSaferLevels(psre->Token());
  866. // S_FALSE: pToken is of lesser authorization, i.e., this
  867. // is untrusted code calling into trusted code.
  868. if (hr == S_FALSE)
  869. {
  870. DbgPrint("RPCSS: SCMROT: SAFER level did not match.\n");
  871. continue;
  872. }
  873. }
  874. break;
  875. }
  876. }
  877. CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetRotEntry "
  878. " ( %p )\n", this, psre));
  879. return psre;
  880. }