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.

1159 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: scmif.cxx
  7. //
  8. // Contents: Entry points for scm interface.
  9. //
  10. // Functions: StartObjectService
  11. // SvcActivateObject
  12. // SvcCreateActivateObject
  13. // ObjectServerStarted
  14. // StopServer
  15. //
  16. // History: 01-May-93 Ricksa Created
  17. // 31-Dec-93 ErikGav Chicago port
  18. //
  19. //--------------------------------------------------------------------------
  20. #include "act.hxx"
  21. extern void UpdateCOMPlusEnabled();
  22. //+-------------------------------------------------------------------------
  23. //
  24. // Function: Dummy1
  25. //
  26. // Synopsis: Needed for IDL hack. Never called.
  27. //
  28. // Arguments: [hRpc] - RPC handle
  29. // [orpcthis] - ORPC handle
  30. // [localthis] - ORPC call data
  31. // [orpcthat] - ORPC reply data
  32. //
  33. // Returns: HRESULT
  34. //
  35. // History: 14 Apr 95 AlexMit Created
  36. //
  37. //--------------------------------------------------------------------------
  38. extern "C" HRESULT DummyQueryInterfaceIOSCM(
  39. handle_t hRpc,
  40. ORPCTHIS *orpcthis,
  41. LOCALTHIS *localthis,
  42. ORPCTHAT *orpcthat,
  43. DWORD dummy )
  44. {
  45. CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
  46. orpcthat->flags = 0;
  47. orpcthat->extensions = NULL;
  48. return E_FAIL;
  49. }
  50. //+-------------------------------------------------------------------------
  51. //
  52. // Function: Dummy2
  53. //
  54. // Synopsis: Needed for IDL hack. Never called.
  55. //
  56. // Arguments: [hRpc] - RPC handle
  57. // [orpcthis] - ORPC handle
  58. // [localthis] - ORPC call data
  59. // [orpcthat] - ORPC reply data
  60. //
  61. // Returns: HRESULT
  62. //
  63. // History: 14 Apr 95 AlexMit Created
  64. //
  65. //--------------------------------------------------------------------------
  66. extern "C" HRESULT DummyAddRefIOSCM(
  67. handle_t hRpc,
  68. ORPCTHIS *orpcthis,
  69. LOCALTHIS *localthis,
  70. ORPCTHAT *orpcthat,
  71. DWORD dummy )
  72. {
  73. CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
  74. orpcthat->flags = 0;
  75. orpcthat->extensions = NULL;
  76. return E_FAIL;
  77. }
  78. //+-------------------------------------------------------------------------
  79. //
  80. // Function: Dummy3
  81. //
  82. // Synopsis: Needed for IDL hack. Never called.
  83. //
  84. // Arguments: [hRpc] - RPC handle
  85. // [orpcthis] - ORPC handle
  86. // [localthis] - ORPC call data
  87. // [orpcthat] - ORPC reply data
  88. //
  89. // Returns: HRESULT
  90. //
  91. // History: 14 Apr 95 AlexMit Created
  92. //
  93. //--------------------------------------------------------------------------
  94. extern "C" HRESULT DummyReleaseIOSCM(
  95. handle_t hRpc,
  96. ORPCTHIS *orpcthis,
  97. LOCALTHIS *localthis,
  98. ORPCTHAT *orpcthat,
  99. DWORD dummy )
  100. {
  101. CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
  102. orpcthat->flags = 0;
  103. orpcthat->extensions = NULL;
  104. return E_FAIL;
  105. }
  106. //+-------------------------------------------------------------------------
  107. //
  108. // Function: ServerRegisterClsid
  109. //
  110. // Synopsis: Notifies SCM that server is started for a class
  111. //
  112. // Arguments: [hRpc] - RPC handle
  113. // [phProcess] - context handle
  114. // [lpDeskTop] - caller's desktop
  115. // [pregin] - array of registration entries
  116. // [ppregout] - array of registration cookies to return
  117. // [rpcstat] - status code
  118. //
  119. // Returns: HRESULT
  120. //
  121. // History: 01-May-93 Ricksa Created
  122. //
  123. //--------------------------------------------------------------------------
  124. extern "C" HRESULT ServerRegisterClsid(
  125. handle_t hRpc,
  126. PHPROCESS phProcess,
  127. RegInput *pregin,
  128. RegOutput **ppregout,
  129. error_status_t *prpcstat)
  130. {
  131. RegOutput* pregout;
  132. CServerTableEntry* pClassTableEntry;
  133. CClsidData* pClsidData = NULL;
  134. DWORD Size, Entries, i;
  135. UCHAR ServerState;
  136. LONG Status;
  137. HRESULT hr = S_OK;
  138. CNamedObject** pRegisterEvents = NULL;
  139. // Parameter validation
  140. if (!prpcstat || !pregin || !ppregout)
  141. return E_INVALIDARG;
  142. *prpcstat = 0;
  143. *ppregout = NULL;
  144. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  145. if (!pProcess)
  146. return E_ACCESSDENIED;
  147. // Allocate an array of handles to hold the register events.
  148. pRegisterEvents = (CNamedObject**)alloca(sizeof(CNamedObject*) * pregin->dwSize);
  149. memset(pRegisterEvents, 0, sizeof(CNamedObject*) * pregin->dwSize);
  150. Size = sizeof(RegOutput) + (pregin->dwSize - 1) * sizeof(DWORD);
  151. *ppregout = (RegOutput *) PrivMemAlloc(Size);
  152. if (!(*ppregout))
  153. {
  154. return E_OUTOFMEMORY;
  155. }
  156. pregout = *ppregout;
  157. memset( pregout, 0, Size );
  158. pregout->dwSize = pregin->dwSize;
  159. Entries = pregin->dwSize;
  160. //
  161. // First loop, we add all of the registrations.
  162. //
  163. for ( i = 0; i < Entries; i++ )
  164. {
  165. pClsidData = 0;
  166. // This path taken by non-COM+ servers, ergo
  167. // no IComClassinfo
  168. (void) LookupClsidData(
  169. pregin->rginent[i].clsid,
  170. NULL,
  171. pProcess->GetToken(),
  172. LOAD_APPID,
  173. &pClsidData );
  174. //
  175. // Check that the caller is allowed to register this CLSID.
  176. //
  177. if ( pClsidData && ! pClsidData->CertifyServer( pProcess ) )
  178. {
  179. delete pClsidData;
  180. hr = CO_E_WRONG_SERVER_IDENTITY;
  181. break;
  182. }
  183. //
  184. // Get the register event for this clsid, to be signalled later on
  185. // in the second loop below. If we couldn't find a pClsidData for
  186. // this clsid, that's fine it just means it was a registration for
  187. // an unknown clsid (which is legal).
  188. //
  189. if (pClsidData)
  190. {
  191. pRegisterEvents[i] = pClsidData->ServerRegisterEvent();
  192. if (!pRegisterEvents[i])
  193. {
  194. delete pClsidData;
  195. hr = E_OUTOFMEMORY;
  196. break;
  197. }
  198. }
  199. ServerState = SERVERSTATE_SUSPENDED;
  200. // Note: REGCLS_SINGLEUSE is *not* a bitflag, it's zero!
  201. // Therefore, it is incompatible with all other flags
  202. if ( pregin->rginent[i].dwFlags == REGCLS_SINGLEUSE )
  203. ServerState |= SERVERSTATE_SINGLEUSE;
  204. if ( pregin->rginent[i].dwFlags & REGCLS_SURROGATE )
  205. ServerState |= SERVERSTATE_SURROGATE;
  206. pClassTableEntry = gpClassTable->GetOrCreate( pregin->rginent[i].clsid );
  207. if ( ! pClassTableEntry )
  208. hr = E_OUTOFMEMORY;
  209. if ( pClassTableEntry )
  210. {
  211. hr = pClassTableEntry->RegisterServer(
  212. pProcess,
  213. pregin->rginent[i].ipid,
  214. pClsidData,
  215. NULL,
  216. ServerState,
  217. &pregout->RegKeys[i] );
  218. pClassTableEntry->Release();
  219. }
  220. if ( pClsidData )
  221. {
  222. delete pClsidData;
  223. pClsidData = NULL;
  224. }
  225. if ( hr != S_OK )
  226. break;
  227. }
  228. //
  229. // If we encountered any errors then we remove any entries which were
  230. // successfully added.
  231. //
  232. // On success, we now signal all of the class table events.
  233. //
  234. // This loop restarts itself in removal mode if it encounters an errors
  235. // while trying to signal the register events.
  236. //
  237. for ( i = 0; i < Entries; i++ )
  238. {
  239. pClassTableEntry = gpClassTable->Lookup( pregin->rginent[i].clsid );
  240. if ( S_OK == hr )
  241. {
  242. ASSERT( pClassTableEntry );
  243. pClassTableEntry->UnsuspendServer( pregout->RegKeys[i] );
  244. //
  245. // Signal to waiting client (if any) that this clsid is registered
  246. //
  247. if (pRegisterEvents[i])
  248. {
  249. SetEvent(pRegisterEvents[i]->Handle());
  250. pRegisterEvents[i]->Release();
  251. pRegisterEvents[i] = NULL;
  252. }
  253. }
  254. if ( (hr != S_OK) && pregout->RegKeys[i] )
  255. {
  256. if ( pClassTableEntry )
  257. pClassTableEntry->RevokeServer( pProcess, pregout->RegKeys[i] );
  258. }
  259. if ( pClassTableEntry )
  260. pClassTableEntry->Release();
  261. }
  262. if ( hr != S_OK )
  263. memset( pregout->RegKeys, 0, pregout->dwSize * sizeof(DWORD) );
  264. //
  265. // Release all of the registration event handles
  266. //
  267. for (i = 0; i < Entries; i++)
  268. {
  269. if (pRegisterEvents[i])
  270. {
  271. pRegisterEvents[i]->Release();
  272. }
  273. }
  274. return hr;
  275. }
  276. //+-------------------------------------------------------------------------
  277. //
  278. // Function: ServerRevokeClsid
  279. //
  280. // Synopsis: Get notification that class server is stopping
  281. //
  282. // Arguments: [hRpc] - RPC handle
  283. // [prevcls] - list of classes/registrations to stop
  284. //
  285. // History: 01-May-93 Ricksa Created
  286. //
  287. //--------------------------------------------------------------------------
  288. extern "C" void ServerRevokeClsid(
  289. handle_t hRpc,
  290. PHPROCESS phProcess,
  291. RevokeClasses *prevcls,
  292. error_status_t *prpcstat)
  293. {
  294. CServerTableEntry* pClassTableEntry;
  295. RevokeEntry* prevent;
  296. DWORD Entries;
  297. // Parameter validation
  298. if (!prpcstat || !prevcls)
  299. return; // E_INVALIDARG
  300. *prpcstat = 0;
  301. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  302. if (!pProcess)
  303. return; // E_ACCESSDENIED
  304. Entries = prevcls->dwSize;
  305. prevent = prevcls->revent;
  306. for ( ; Entries--; prevent++ )
  307. {
  308. pClassTableEntry = gpClassTable->Lookup( prevent->clsid );
  309. if ( pClassTableEntry )
  310. {
  311. pClassTableEntry->RevokeServer( pProcess, prevent->dwReg );
  312. pClassTableEntry->Release();
  313. }
  314. }
  315. }
  316. void GetThreadID(
  317. handle_t hRpc,
  318. PHPROCESS phProcess,
  319. DWORD * pThreadID,
  320. error_status_t *prpcstat)
  321. {
  322. if (!CheckLocalSecurity(hRpc, phProcess))
  323. RpcRaiseException(ERROR_ACCESS_DENIED);
  324. // Parameter validation
  325. if (!pThreadID || !prpcstat)
  326. return;
  327. *prpcstat = 0;
  328. *pThreadID = InterlockedExchangeAdd((long *)&gNextThreadID,1);
  329. }
  330. //+-------------------------------------------------------------------------
  331. //
  332. // Function: UpdateActivationSettings
  333. //
  334. // Synopsis: Re-read default activation settings.
  335. //
  336. // Arguments: [hRpc] - RPC handle
  337. // [prpcstat] - communication status
  338. //
  339. //--------------------------------------------------------------------------
  340. extern void ComputeSecurity();
  341. extern "C" void UpdateActivationSettings(
  342. handle_t hRpc,
  343. PHPROCESS phProcess,
  344. error_status_t *prpcstat)
  345. {
  346. if (!CheckLocalSecurity(hRpc, phProcess))
  347. RpcRaiseException(ERROR_ACCESS_DENIED);
  348. // Parameter validation
  349. if (!prpcstat)
  350. return;
  351. *prpcstat = 0;
  352. ReadRemoteActivationKeys();
  353. ComputeSecurity();
  354. UpdateCOMPlusEnabled();
  355. }
  356. //+-------------------------------------------------------------------------
  357. //
  358. // Function: VerifyCallerIsAdministrator
  359. //
  360. // Synopsis: Verifies that the specified user is an administrator
  361. //
  362. // Returns: S_OK -- success, *pbAdmin is valid
  363. // other -- error occurred
  364. //
  365. // Arguments: [pToken] - token of the user
  366. // [pbAdmin] - out param denoting admin status
  367. //
  368. //--------------------------------------------------------------------------
  369. HRESULT VerifyCallerIsAdministrator(CToken* pToken, BOOL* pbAdmin)
  370. {
  371. BOOL fSuccess;
  372. PSID psidAdmin;
  373. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  374. // Allocate sid for Administrators
  375. fSuccess = AllocateAndInitializeSid(&SystemSidAuthority, 2,
  376. SECURITY_BUILTIN_DOMAIN_RID,
  377. DOMAIN_ALIAS_RID_ADMINS,
  378. 0, 0, 0, 0, 0, 0, &psidAdmin);
  379. if (!fSuccess)
  380. return HRESULT_FROM_WIN32(GetLastError());
  381. // Check that caller is an admin
  382. fSuccess = CheckTokenMembership(pToken->GetToken(), psidAdmin, pbAdmin);
  383. FreeSid(psidAdmin);
  384. if (!fSuccess)
  385. return HRESULT_FROM_WIN32(GetLastError());
  386. return S_OK;
  387. }
  388. //+-------------------------------------------------------------------------
  389. //
  390. // Function: EnableDisableDynamicIPTracking
  391. //
  392. // Synopsis: Writes a "Y" or "N" to the HKLM\Software\MS\Ole\
  393. // EnableSystemDynamicIPTracking string value, and sets the
  394. // global variable gbDynamicIPChangesEnabled accordingly.
  395. //
  396. // Arguments: [hRpc] - RPC handle
  397. // [phProcess] - context handle
  398. // [fEnable] - whether to enable or disable
  399. // [prpcstat] - communication status
  400. //
  401. //--------------------------------------------------------------------------
  402. extern "C"
  403. HRESULT EnableDisableDynamicIPTracking(
  404. handle_t hRpc,
  405. PHPROCESS phProcess,
  406. BOOL fEnable,
  407. error_status_t* prpcstat)
  408. {
  409. HRESULT hr = S_OK;
  410. BOOL bAdmin;
  411. ORSTATUS status;
  412. // Parameter validation
  413. if (!prpcstat)
  414. return E_INVALIDARG;
  415. *prpcstat = 0; // we got here so we are OK
  416. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  417. if (!pProcess)
  418. return E_ACCESSDENIED;
  419. // Get token for the caller
  420. CToken* pToken;
  421. status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
  422. if (status != ERROR_SUCCESS)
  423. return E_ACCESSDENIED;
  424. hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
  425. pToken->Release();
  426. if (FAILED(hr))
  427. return hr;
  428. if (!bAdmin)
  429. return E_ACCESSDENIED;
  430. SCMVDATEHEAP();
  431. hr = gAddrExclusionMgr.EnableDisableDynamicTracking(fEnable);
  432. SCMVDATEHEAP();
  433. return hr;
  434. }
  435. //+-------------------------------------------------------------------------
  436. //
  437. // Function: GetCurrentIPExclusionList
  438. //
  439. // Synopsis: Passes the contents of the current address exclusion list
  440. // back to the caller
  441. //
  442. // Arguments: [hRpc] - RPC handle
  443. // [phProcess] - context handle
  444. // [pdwNumStrings] - size of the pppszStrings array
  445. // [pppszStrings] - array of pointers to NULL-term'd strings
  446. // [prpcstat] - communication status
  447. //
  448. //--------------------------------------------------------------------------
  449. extern "C"
  450. HRESULT GetCurrentAddrExclusionList(
  451. handle_t hRpc,
  452. PHPROCESS phProcess,
  453. DWORD* pdwNumStrings,
  454. LPWSTR** pppszStrings,
  455. error_status_t* prpcstat)
  456. {
  457. HRESULT hr = S_OK;
  458. BOOL bAdmin;
  459. ORSTATUS status;
  460. // Parameter validation
  461. if (!prpcstat || !pppszStrings || !pppszStrings)
  462. return E_INVALIDARG;
  463. *prpcstat = 0; // we got here so we are OK
  464. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  465. if (!pProcess)
  466. return E_ACCESSDENIED;
  467. // Get token for the caller
  468. CToken* pToken;
  469. status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
  470. if (status != ERROR_SUCCESS)
  471. return E_ACCESSDENIED;
  472. hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
  473. pToken->Release();
  474. if (FAILED(hr))
  475. return hr;
  476. if (!bAdmin)
  477. return E_ACCESSDENIED;
  478. SCMVDATEHEAP();
  479. hr = gAddrExclusionMgr.GetExclusionList(
  480. pdwNumStrings,
  481. pppszStrings);
  482. SCMVDATEHEAP();
  483. return hr;
  484. }
  485. //+-------------------------------------------------------------------------
  486. //
  487. // Function: SetAddrExclusionList
  488. //
  489. // Synopsis: Re-sets the contents of the address exclusion list, and updates
  490. // all currently running processes with the new bindings.
  491. //
  492. // Arguments: [hRpc] - RPC handle
  493. // [phProcess] - context handle
  494. // [dwNumStrings] - size of the ppszStrings array
  495. // [ppszStrings] - array of pointers to NULL-term'd strings
  496. // [prpcstat] - communication status
  497. //
  498. //--------------------------------------------------------------------------
  499. extern "C"
  500. HRESULT SetAddrExclusionList(
  501. handle_t hRpc,
  502. PHPROCESS phProcess,
  503. DWORD dwNumStrings,
  504. LPWSTR* ppszStrings,
  505. error_status_t* prpcstat)
  506. {
  507. HRESULT hr = S_OK;
  508. BOOL bAdmin;
  509. ORSTATUS status;
  510. // Parameter validation
  511. if (!ppszStrings || !prpcstat)
  512. return E_INVALIDARG;
  513. *prpcstat = 0; // we got here so we are OK
  514. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  515. if (!pProcess)
  516. return E_ACCESSDENIED;
  517. // Get token for the caller
  518. CToken* pToken;
  519. status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
  520. if (status != ERROR_SUCCESS)
  521. return E_ACCESSDENIED;
  522. hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
  523. pToken->Release();
  524. if (FAILED(hr))
  525. return hr;
  526. if (!bAdmin)
  527. return E_ACCESSDENIED;
  528. SCMVDATEHEAP();
  529. hr = gAddrExclusionMgr.SetExclusionList(
  530. dwNumStrings,
  531. ppszStrings);
  532. SCMVDATEHEAP();
  533. return hr;
  534. }
  535. //+-------------------------------------------------------------------------
  536. //
  537. // Function: FlushSCMBindings
  538. //
  539. // Synopsis: Remove the specified machine bindings from our remote binding
  540. // handle cache
  541. //
  542. // Arguments: [hRpc] - RPC handle
  543. // [prpcstat] - communication status
  544. //
  545. //--------------------------------------------------------------------------
  546. extern "C"
  547. HRESULT FlushSCMBindings(
  548. handle_t hRpc,
  549. PHPROCESS phProcess,
  550. WCHAR* pszMachineName,
  551. error_status_t* prpcstat)
  552. {
  553. HRESULT hr;
  554. BOOL bAdmin;
  555. ORSTATUS status;
  556. // Parameter validation
  557. if (!pszMachineName || !prpcstat)
  558. return E_INVALIDARG;
  559. *prpcstat = 0; // we got here so we are OK
  560. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  561. if (!pProcess)
  562. return E_ACCESSDENIED;
  563. // Get token for the caller
  564. CToken* pToken;
  565. status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
  566. if (status != ERROR_SUCCESS)
  567. return E_ACCESSDENIED;
  568. hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
  569. pToken->Release();
  570. if (FAILED(hr))
  571. return hr;
  572. if (!bAdmin)
  573. return E_ACCESSDENIED;
  574. SCMVDATEHEAP();
  575. hr = gpRemoteMachineList->FlushSpecificBindings(pszMachineName);
  576. SCMVDATEHEAP();
  577. return hr;
  578. }
  579. //+-------------------------------------------------------------------------
  580. //
  581. // Function: RetireServer
  582. //
  583. // Synopsis: Marks the specified server as being no longer eligible for
  584. // component activations of any type. Currently only used
  585. // to support COM+'s process recycling feature.
  586. //
  587. // Arguments: [hRpc] - RPC handle
  588. // [pguidProcessIdentifier] - guid which identifies the server
  589. // [prpcstat] - communication status
  590. //
  591. //--------------------------------------------------------------------------
  592. extern "C"
  593. HRESULT RetireServer(
  594. handle_t hRpc,
  595. PHPROCESS phProcess,
  596. GUID* pguidProcessIdentifier,
  597. error_status_t* prpcstat)
  598. {
  599. // Parameter validation
  600. if (!pguidProcessIdentifier || !prpcstat)
  601. return E_INVALIDARG;
  602. *prpcstat = 0; // we got here so we are OK
  603. CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
  604. if (!pProcess)
  605. return E_ACCESSDENIED;
  606. // Get token for the caller
  607. CToken* pToken;
  608. ORSTATUS status;
  609. status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
  610. if (status != ERROR_SUCCESS)
  611. return E_ACCESSDENIED;
  612. // Make sure they're an administrator
  613. HRESULT hr;
  614. BOOL bAdmin;
  615. hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
  616. pToken->Release();
  617. if (FAILED(hr))
  618. return hr;
  619. if (!bAdmin)
  620. return E_ACCESSDENIED;
  621. // Okay, see if we know which process they're talking about
  622. gpProcessListLock->LockShared();
  623. hr = E_INVALIDARG; // review for better code when we don't find the process
  624. CBListIterator all_procs(gpProcessList);
  625. CProcess* pprocess;
  626. while (pprocess = (CProcess*)all_procs.Next())
  627. {
  628. if (*pprocess->GetGuidProcessIdentifier() == *pguidProcessIdentifier)
  629. {
  630. // Found it. Mark it as retired
  631. pprocess->Retire();
  632. hr = S_OK;
  633. break;
  634. }
  635. }
  636. gpProcessListLock->UnlockShared();
  637. return hr;
  638. }
  639. CWIPTable gWIPTbl; // global instance of the class
  640. CWIPTable * gpWIPTbl = &gWIPTbl;
  641. //+-------------------------------------------------------------------------
  642. //
  643. // Function: CopyDualStringArray
  644. //
  645. // Synopsis: makes a copy of the given string array
  646. //
  647. // History: 22-Jan-96 Rickhi Created
  648. //
  649. //--------------------------------------------------------------------------
  650. HRESULT CopyDualStringArray(DUALSTRINGARRAY *psa, DUALSTRINGARRAY **ppsaNew)
  651. {
  652. ULONG ulSize = sizeof(DUALSTRINGARRAY) + (psa->wNumEntries * sizeof(WCHAR));
  653. *ppsaNew = (DUALSTRINGARRAY *) PrivMemAlloc(ulSize);
  654. if (*ppsaNew == NULL)
  655. {
  656. return E_OUTOFMEMORY;
  657. }
  658. memcpy(*ppsaNew, psa, ulSize);
  659. return S_OK;
  660. }
  661. //+-------------------------------------------------------------------------
  662. //
  663. // Member: CWIPTable::AddEntry, public
  664. //
  665. // Synopsis: Adds a WIPEntry to the table.
  666. //
  667. // Arguments: [hWnd] - window handle
  668. // [pStd] - standard marshaled interface STDOBJREF
  669. // [pOxidInfo] - info needed to resolve the OXID
  670. // [pdwCookie] - cookie to return (to be placed on the window)
  671. //
  672. // History: 22-Jan-96 Rickhi Created
  673. //
  674. //--------------------------------------------------------------------------
  675. HRESULT CWIPTable::AddEntry(
  676. DWORD_PTR hWnd,
  677. STDOBJREF *pStd,
  678. OXID_INFO *pOxidInfo,
  679. ULONG sessId,
  680. void * creator,
  681. DWORD_PTR *pdwCookie
  682. )
  683. {
  684. // make a copy of the string array in the OxidInfo since MIDL will
  685. // delete it on the way back out of the call.
  686. DUALSTRINGARRAY *psaNew;
  687. HRESULT hr;
  688. if (m_fCsInitialized == FALSE)
  689. {
  690. ASSERT(FALSE);
  691. return E_OUTOFMEMORY;
  692. }
  693. psaNew = (DUALSTRINGARRAY *) PrivMemAlloc(sizeof(DUALSTRINGARRAY) + (pOxidInfo->psa->wNumEntries * sizeof(WCHAR)));
  694. if (psaNew == NULL)
  695. {
  696. return E_OUTOFMEMORY;
  697. }
  698. memcpy(psaNew, pOxidInfo->psa, sizeof(DUALSTRINGARRAY) + (pOxidInfo->psa->wNumEntries * sizeof(WCHAR)));
  699. CLock2 lck(s_mxs);
  700. // find a free slot in the table
  701. DWORD_PTR dwpIndex = s_iNextFree;
  702. if (dwpIndex == (DWORD_PTR)-1)
  703. {
  704. // grow the table
  705. dwpIndex = Grow();
  706. }
  707. if (dwpIndex != (DWORD_PTR)-1)
  708. {
  709. // get the pointer to the entry,
  710. WIPEntry *pEntry = s_pTbl + dwpIndex;
  711. // update the next free index.
  712. s_iNextFree = pEntry->hWnd;
  713. // copy in the data
  714. memcpy(&pEntry->std, pStd, sizeof(STDOBJREF));
  715. memcpy(&pEntry->oxidInfo, pOxidInfo, sizeof(OXID_INFO));
  716. pEntry->oxidInfo.psa = psaNew;
  717. pEntry->hWnd = hWnd;
  718. pEntry->dwFlags = WIPF_OCCUPIED;
  719. pEntry->sessId = sessId;
  720. pEntry->creator = creator;
  721. // set the cookie to return
  722. *pdwCookie = dwpIndex+5000;
  723. // return success
  724. hr = S_OK;
  725. }
  726. else
  727. {
  728. // free the allocated string array
  729. PrivMemFree(psaNew);
  730. hr = E_OUTOFMEMORY;
  731. }
  732. return hr;
  733. }
  734. //+-------------------------------------------------------------------------
  735. //
  736. // Member: CWIPTable::GetEntry, public
  737. //
  738. // Synopsis: Retrieves and optionally delets a WIPEntry from the table.
  739. //
  740. // Arguments: [hWnd] - window handle
  741. // [dwCookie] - cookie from the window
  742. // [pStd] - place to return STDOBJREF data
  743. // [pOxidInfo] - place to return info needed to resolve the OXID
  744. //
  745. // History: 22-Jan-96 Rickhi Created
  746. //
  747. //--------------------------------------------------------------------------
  748. HRESULT CWIPTable::GetEntry(
  749. DWORD_PTR hWnd,
  750. DWORD_PTR dwCookie,
  751. BOOL fRevoke,
  752. ULONG sessId,
  753. void* caller,
  754. STDOBJREF *pStd,
  755. OXID_INFO *pOxidInfo)
  756. {
  757. HRESULT hr = E_INVALIDARG;
  758. // validate the cookie
  759. DWORD_PTR dwpIndex = dwCookie - 5000;
  760. if (dwpIndex >= s_cEntries)
  761. {
  762. return hr;
  763. }
  764. if (m_fCsInitialized == FALSE)
  765. {
  766. ASSERT(FALSE);
  767. return E_OUTOFMEMORY;
  768. }
  769. CLock2 lck(s_mxs);
  770. // get the pointer to the entry,
  771. WIPEntry *pEntry = s_pTbl + dwpIndex;
  772. // make sure the entry is occupied
  773. if (pEntry->dwFlags & WIPF_OCCUPIED)
  774. {
  775. if (sessId != pEntry->sessId) // trying to access the droptarget of a different session???
  776. return E_ACCESSDENIED;
  777. if (fRevoke && (caller != pEntry->creator)) // trying to delete someone else's droptarget??
  778. return E_ACCESSDENIED;
  779. if (hWnd != pEntry->hWnd) // additional verification.. authorized clients should know what the hwnd is.
  780. return E_ACCESSDENIED;
  781. DUALSTRINGARRAY *psaNew;
  782. psaNew = (DUALSTRINGARRAY *) PrivMemAlloc(sizeof(DUALSTRINGARRAY) + (pEntry->oxidInfo.psa->wNumEntries * sizeof(WCHAR)));
  783. if (psaNew == NULL)
  784. {
  785. return E_OUTOFMEMORY;
  786. }
  787. memcpy(psaNew, pEntry->oxidInfo.psa, sizeof(DUALSTRINGARRAY) + (pEntry->oxidInfo.psa->wNumEntries * sizeof(WCHAR)));
  788. // copy out the data to return
  789. memcpy(pStd, &pEntry->std, sizeof(STDOBJREF));
  790. memcpy(pOxidInfo, &pEntry->oxidInfo, sizeof(OXID_INFO));
  791. pOxidInfo->psa = psaNew;
  792. if (fRevoke)
  793. {
  794. // free the entry by updating the flags and the next free index
  795. PrivMemFree(pEntry->oxidInfo.psa);
  796. pEntry->dwFlags = WIPF_VACANT;
  797. pEntry->hWnd = s_iNextFree;
  798. pEntry->sessId = 0;
  799. pEntry->creator = NULL;
  800. s_iNextFree = dwpIndex;
  801. }
  802. // return success
  803. hr = S_OK;
  804. }
  805. return hr;
  806. }
  807. //+-------------------------------------------------------------------------
  808. //
  809. // Member: CWIPTable::Grow, private
  810. //
  811. // Synopsis: grows the WIPTable size.
  812. //
  813. // History: 22-Jan-96 Rickhi Created
  814. //
  815. //--------------------------------------------------------------------------
  816. DWORD_PTR CWIPTable::Grow()
  817. {
  818. // compute the size and allocate a new table
  819. DWORD_PTR dwSize = (s_cEntries + WIPTBL_GROW_SIZE) * sizeof(WIPEntry);
  820. WIPEntry *pNewTbl = (WIPEntry *) PrivMemAlloc((size_t)dwSize);
  821. if (pNewTbl != NULL)
  822. {
  823. // copy the old table in
  824. memcpy(pNewTbl, s_pTbl, (size_t)(s_cEntries * sizeof(WIPEntry)));
  825. // free the old table
  826. if (s_pTbl)
  827. {
  828. PrivMemFree(s_pTbl);
  829. }
  830. // replace the old table ptr
  831. s_pTbl = pNewTbl;
  832. // update the free list and mark the new entries as vacant
  833. s_iNextFree = s_cEntries;
  834. WIPEntry *pNext = s_pTbl + s_cEntries;
  835. for (ULONG i=0; i< WIPTBL_GROW_SIZE; i++)
  836. {
  837. pNext->hWnd = ++s_cEntries;
  838. pNext->dwFlags = WIPF_VACANT;
  839. pNext->sessId = 0;
  840. pNext->creator = NULL;
  841. pNext++;
  842. }
  843. (pNext-1)->hWnd = (DWORD_PTR)-1; // last entry has END_OF_LIST marker
  844. }
  845. return s_iNextFree;
  846. }
  847. //+-------------------------------------------------------------------------
  848. //
  849. // Member: CWIPTable::RunDown, public
  850. //
  851. // Synopsis: Deletes all WIPEntry from the table that were created by creator.
  852. //
  853. // Arguments: [creator] - this is the CProcess object of the process being rundown
  854. //
  855. // History: 27-Mar-02 Hanyr Created
  856. //
  857. //--------------------------------------------------------------------------
  858. void CWIPTable::RunDown(
  859. void* creator)
  860. {
  861. if (m_fCsInitialized == FALSE)
  862. {
  863. ASSERT(FALSE);
  864. return;
  865. }
  866. CLock2 lck(s_mxs);
  867. // get the pointer to the entry,
  868. WIPEntry *pEntry = s_pTbl;
  869. for (ULONG i=0; i< s_cEntries; i++)
  870. {
  871. if ((pEntry->dwFlags == WIPF_OCCUPIED) && (pEntry->creator == creator)) // a match
  872. {
  873. PrivMemFree(pEntry->oxidInfo.psa);
  874. pEntry->dwFlags = WIPF_VACANT;
  875. pEntry->hWnd = s_iNextFree;
  876. pEntry->sessId = 0;
  877. pEntry->creator = NULL;
  878. s_iNextFree = i;
  879. }
  880. pEntry++;
  881. }
  882. }
  883. void DragDropRunDown(void *creator)
  884. {
  885. gpWIPTbl->RunDown(creator);
  886. }
  887. //+-------------------------------------------------------------------------
  888. //
  889. // Function: RegisterWindowPropInterface
  890. //
  891. // Synopsis: Associate a window property with a (standard) marshaled
  892. // interface.
  893. //
  894. // Arguments: [hRpc] - RPC handle
  895. // [hWnd] - window handle
  896. // [pStd] - standard marshaled interface STDOBJREF
  897. // [pOxidInfo] - info needed to resolve the OXID
  898. // [pdwCookie] - cookie to return (to be placed on the window)
  899. // [prpcstat] - communication status
  900. //
  901. // History: 22-Jan-96 Rickhi Created
  902. //
  903. //--------------------------------------------------------------------------
  904. extern "C" HRESULT RegisterWindowPropInterface(
  905. handle_t hRpc,
  906. PHPROCESS phProcess,
  907. DWORD_PTR hWnd,
  908. STDOBJREF *pStd,
  909. OXID_INFO *pOxidInfo,
  910. DWORD_PTR *pdwCookie,
  911. error_status_t *prpcstat)
  912. {
  913. // Parameter validation
  914. if (!pStd || !pOxidInfo || !pOxidInfo->psa || !pdwCookie || !prpcstat)
  915. return E_INVALIDARG;
  916. *prpcstat = 0; // we got here so we are OK
  917. CProcess *pProcess = CheckLocalSecurity(hRpc, phProcess);
  918. if (!pProcess)
  919. return E_ACCESSDENIED;
  920. ULONG sessId = pProcess->GetToken()->GetSessionId();
  921. CairoleDebugOut((DEB_SCM,
  922. "_IN RegisterWindowPropInterface hWnd:%x pStd:%x pOxidInfo:%x\n",
  923. hWnd, pStd, pOxidInfo));
  924. VDATEHEAP();
  925. HRESULT hr = gpWIPTbl->AddEntry(hWnd, pStd, pOxidInfo, sessId, pProcess, pdwCookie);
  926. if (SUCCEEDED(hr))
  927. pProcess->IncDropTargets();
  928. CairoleDebugOut((DEB_SCM, "_OUT RegisterWindowPropInterface dwCookie:%x\n",
  929. *pdwCookie));
  930. VDATEHEAP();
  931. return hr;
  932. }
  933. //+-------------------------------------------------------------------------
  934. //
  935. // Function: GetWindowPropInterface
  936. //
  937. // Synopsis: Get the marshaled interface associated with a window property.
  938. //
  939. // Arguments: [hRpc] - RPC handle
  940. // [hWnd] - window handle
  941. // [dwCookie] - cookie from the window
  942. // [fRevoke] - whether to revoke entry or not
  943. // [pStd] - standard marshaled interface STDOBJREF to return
  944. // [pOxidInfo] - info needed to resolve the OXID
  945. // [prpcstat] - communication status
  946. //
  947. // History: 22-Jan-96 Rickhi Created
  948. //
  949. //--------------------------------------------------------------------------
  950. extern "C" HRESULT GetWindowPropInterface(
  951. handle_t hRpc,
  952. PHPROCESS phProcess,
  953. DWORD_PTR hWnd,
  954. DWORD_PTR dwCookie,
  955. BOOL fRevoke,
  956. STDOBJREF *pStd,
  957. OXID_INFO *pOxidInfo,
  958. error_status_t *prpcstat)
  959. {
  960. // Parameter validation
  961. if (!pStd || !pOxidInfo || !prpcstat)
  962. return E_INVALIDARG;
  963. *prpcstat = 0;
  964. CProcess *pProcess = CheckLocalSecurity(hRpc, phProcess);
  965. if (!pProcess)
  966. return E_ACCESSDENIED;
  967. ULONG sessId = pProcess->GetToken()->GetSessionId();
  968. CairoleDebugOut((DEB_SCM,
  969. "_IN GetWindowPropInterface hWnd:%x dwCookie:%x fRevoke:%x\n",
  970. hWnd, dwCookie, fRevoke));
  971. VDATEHEAP();
  972. HRESULT hr = gpWIPTbl->GetEntry(hWnd, dwCookie, fRevoke, sessId, pProcess, pStd, pOxidInfo);
  973. if (fRevoke && SUCCEEDED(hr))
  974. pProcess->DecDropTargets();
  975. CairoleDebugOut((DEB_SCM,
  976. "_OUT GetWindowPropInterface pStd:%x pOxidInfo:%x\n", pStd, pOxidInfo));
  977. VDATEHEAP();
  978. return hr;
  979. }