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.

1058 lines
35 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // activate.cxx
  7. //
  8. // Main dcom activation service routines.
  9. //
  10. // History: VinayKr Created
  11. // 06-Nov-98 TarunA Changed remote/local activation logic
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "act.hxx"
  15. HRESULT GetProcessInfoFromActProps(IActivationPropertiesIn* pActPropsIn, DWORD* ppid, DWORD* pdwProcessReqType);
  16. LPWSTR GetOrigSrvrName( PACTIVATION_PARAMS pActParams );
  17. // Global counter
  18. LONG gThreadToken = 0;
  19. //-------------------------------------------------------------------------
  20. //
  21. // CalculateActParamsClassInfo
  22. //
  23. // Re-calculate the classinfo in the ACTIVATION_PARAMS structure.
  24. //
  25. //-------------------------------------------------------------------------
  26. HRESULT
  27. CalculateActParamsClassInfo(
  28. IN OUT PACTIVATION_PARAMS pActParams
  29. )
  30. {
  31. IComClassInfo *pComClassInfo = NULL;
  32. HRESULT hr = S_OK;
  33. if (pActParams->pToken)
  34. {
  35. //
  36. // I'm a little worried about this. Why do we do this?
  37. //
  38. if (!(pActParams->ClsContext & CLSCTX_INPROC_SERVER))
  39. {
  40. hr = gpCatalogSCM->GetClassInfo ( pActParams->ClsContext,
  41. pActParams->pToken,
  42. pActParams->Clsid,
  43. IID_IComClassInfo,
  44. (void**) &pComClassInfo );
  45. }
  46. }
  47. else
  48. hr = gpCatalog->GetClassInfo ( pActParams->Clsid,
  49. IID_IComClassInfo,
  50. (void**) &pComClassInfo );
  51. if (SUCCEEDED(hr) && (pComClassInfo))
  52. {
  53. if (pActParams->pComClassInfo)
  54. pActParams->pComClassInfo->Release();
  55. // Copy the reference, do not release.
  56. pActParams->pComClassInfo = pComClassInfo;
  57. if (pActParams->pActPropsIn)
  58. hr = pActParams->pActPropsIn->SetClassInfo(pComClassInfo);
  59. }
  60. if (hr == REGDB_E_CLASSNOTREG)
  61. {
  62. // It's OK for us to have no registration information.
  63. hr = S_OK;
  64. }
  65. return hr;
  66. }
  67. LONG ActivationExceptionFilter(LPEXCEPTION_POINTERS lpep)
  68. {
  69. ASSERT(NULL && "Unexpected exception thrown");
  70. return EXCEPTION_EXECUTE_HANDLER;
  71. }
  72. //-------------------------------------------------------------------------
  73. //
  74. // Activation
  75. //
  76. // Main entry point for both local and remote activations.
  77. //
  78. //-------------------------------------------------------------------------
  79. HRESULT
  80. Activation(
  81. IN OUT PACTIVATION_PARAMS pActParams
  82. )
  83. {
  84. CServerTableEntry* pServerTableEntry = NULL;
  85. CClsidData* pClsidData = NULL;
  86. CServerListEntry* pServerListEntry;
  87. CNamedObject* pLaunchMutex = NULL;
  88. HRESULT hr;
  89. RPC_STATUS Status;
  90. BOOL bStatus;
  91. BOOL bFirstTime = TRUE;
  92. CToken* pTkn;
  93. // NT #294385
  94. // If REMOTE_SERVER is set, and LOCAL_SERVER is not,
  95. // and we have a server name, and the server name is us,
  96. // then we need to turn the LOCAL_SERVER flag on
  97. if ( (CLSCTX_REMOTE_SERVER == (pActParams->ClsContext & ( CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER ))) &&
  98. pActParams->pwszServer != NULL &&
  99. gpMachineName->Compare (pActParams->pwszServer) )
  100. {
  101. pActParams->ClsContext |= CLSCTX_LOCAL_SERVER;
  102. #ifdef _WIN64
  103. // On Win64, this might change the classinfo.
  104. hr = CalculateActParamsClassInfo(pActParams);
  105. if (FAILED(hr))
  106. goto ActivationDone;
  107. #endif
  108. }
  109. #ifdef SECURITY_DBG
  110. {
  111. WCHAR dbgwszUser[MAX_PATH];
  112. if ( pActParams->pToken != NULL )
  113. {
  114. pActParams->pToken->Impersonate();
  115. ULONG cchSize = MAX_PATH;
  116. GetUserName( dbgwszUser, &cchSize );
  117. pActParams->pToken->Revert();
  118. }
  119. else
  120. {
  121. lstrcpyW( dbgwszUser, L"Anonymous" );
  122. }
  123. }
  124. #endif
  125. if ( pActParams->pwszServer )
  126. {
  127. //
  128. // Some apps may unnecessarily put slashes before their
  129. // server names. We'll allow this and strip them off.
  130. //
  131. if ( pActParams->pwszServer[0] == L'\\' &&
  132. pActParams->pwszServer[1] == L'\\' )
  133. pActParams->pwszServer += 2;
  134. if ( 0 == *pActParams->pwszServer )
  135. {
  136. hr = CO_E_BAD_SERVER_NAME;
  137. goto ActivationDone;
  138. }
  139. if ( ! gpMachineName->Compare( pActParams->pwszServer ) )
  140. {
  141. //
  142. // When a client specifies a remote server name we go straight to the
  143. // source, there is no need to check local configuration information.
  144. //
  145. // The CLSCTX_REMOTE_SERVER bit does not need to be specified by the
  146. // client, it is implied.
  147. //
  148. //
  149. // the remote activation call will null out the pointer in the ActivationPropertiesIn
  150. // object which caused the memory that pActParams->pwszServer is pointing to to be
  151. // freed. We need this name later on to pass to the oxid resoluton phase, so
  152. // we copy it to some memory on the stack
  153. //
  154. WCHAR *pszTemp = (WCHAR *)_alloca( ( lstrlenW(pActParams->pwszServer) + 1 ) * sizeof(WCHAR) );
  155. lstrcpyW(pszTemp, pActParams->pwszServer);
  156. hr = RemoteActivationCall( pActParams, pActParams->pwszServer );
  157. pActParams->pwszServer = pszTemp;
  158. goto ActivationDone;
  159. }
  160. }
  161. //
  162. // First search for a running object.
  163. //
  164. if ( pActParams->pwszPath )
  165. {
  166. //
  167. // This call returns TRUE if we found a ROT object and are now done.
  168. // When handling a remote activation it's possible we'll find a ROT
  169. // object, but we still need to continue in this case to get a remote
  170. // marshalled interface.
  171. //
  172. if ( LookupObjectInROT( pActParams, &hr ) )
  173. goto ActivationDone;
  174. }
  175. //
  176. // Try to get a CClsidData using the supplied pComClassInfo
  177. //
  178. pTkn = pActParams->RemoteActivation ? NULL : pActParams->pToken;
  179. hr = LookupClsidData( pActParams->Clsid,
  180. pActParams->pComClassInfo,
  181. pTkn,
  182. LOAD_NORMAL,
  183. &pClsidData );
  184. if (hr == REGDB_E_CLASSNOTREG)
  185. {
  186. ASSERT(!pClsidData);
  187. // No registration info for this clsid. If the client is interested
  188. // in a local server activation, we still need to check the class
  189. // table in case of unsolicited registrations. For COM+ components
  190. // we should never get here.
  191. if(pActParams->ClsContext & CLSCTX_LOCAL_SERVER)
  192. {
  193. pServerTableEntry = gpClassTable->Lookup(pActParams->Clsid);
  194. if (pServerTableEntry)
  195. {
  196. // Somebody on the machine registered a classfac for this
  197. // clsid; give it a shot:
  198. bStatus = pServerTableEntry->CallRunningServer( pActParams,
  199. 0,
  200. 0,
  201. NULL,
  202. &hr);
  203. if (bStatus)
  204. goto ActivationDone;
  205. }
  206. }
  207. //
  208. // As a last resort we always try an atstorage activation.
  209. //
  210. ActivateAtStorage( pActParams, NULL, &hr );
  211. goto ActivationDone;
  212. }
  213. else if (FAILED(hr))
  214. goto ActivationDone;
  215. ASSERT(pClsidData && "Registration lookup succeeded but returned nothing");
  216. //
  217. // If this is a remote activation, make sure that the ClassInfo we got
  218. // can be activated.
  219. //
  220. if (pActParams->RemoteActivation)
  221. {
  222. hr = pClsidData->IsEnabledRemote();
  223. if (FAILED(hr))
  224. {
  225. // Log it to the event log.
  226. if (hr == CO_E_CLASS_DISABLED)
  227. LogComPlusRemoteDisabled(pActParams->ClsContext, pActParams->Clsid);
  228. goto ActivationDone;
  229. }
  230. }
  231. // Look up an appropriate table entry if the client is interested in a
  232. // local activation
  233. if(pActParams->ClsContext & CLSCTX_LOCAL_SERVER)
  234. {
  235. if (pClsidData->DllHostOrComPlusProcess())
  236. {
  237. GUID* pAppidGuid = pClsidData->AppidGuid();
  238. ASSERT(pAppidGuid);
  239. pServerTableEntry = gpProcessTable->Lookup(*pAppidGuid);
  240. }
  241. else
  242. pServerTableEntry = gpClassTable->Lookup( pActParams->Clsid );
  243. }
  244. if ( !pServerTableEntry )
  245. {
  246. // At this point we have the class data but no running servers. If the
  247. // client wants remote activation only then go straight to do a remote activation
  248. // NOTE We '&' with flags CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER to
  249. // filter out any other bits like CLSCTX_INPROC etc
  250. if( (pActParams->ClsContext & (CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER)) == CLSCTX_REMOTE_SERVER)
  251. {
  252. // This call returns TRUE if a remote ActivateAtStorage call was
  253. // made, whether successful or not.
  254. if ( ActivateAtStorage( pActParams, pClsidData, &hr ) )
  255. goto ActivationDone;
  256. else
  257. goto ActivationDoneLocal;
  258. }
  259. // Figure out which table to create the table entry in
  260. if (pClsidData->DllHostOrComPlusProcess())
  261. {
  262. GUID* pAppidGuid = pClsidData->AppidGuid();
  263. ASSERT(pAppidGuid);
  264. pServerTableEntry = gpProcessTable->Create(*pAppidGuid);
  265. }
  266. else
  267. pServerTableEntry = gpClassTable->Create(pActParams->Clsid);
  268. if (!pServerTableEntry)
  269. {
  270. hr = E_OUTOFMEMORY;
  271. goto ActivationDone;
  272. }
  273. }
  274. ASSERT(pServerTableEntry);
  275. hr = GetProcessInfoFromActProps(pActParams->pActPropsIn, &(pActParams->dwPID), &(pActParams->dwProcessReqType));
  276. if (FAILED(hr))
  277. goto ActivationDone;
  278. for (;;)
  279. {
  280. //
  281. // Now check for a running server for the CLSID
  282. // NOTE: The fact that we reached here implies that the client wants at least a
  283. // local activation
  284. //
  285. CairoleDebugOut((DEB_SCM, "Calling ServerTableEntry at 0x%p\n", pServerTableEntry));
  286. // We reach here only when we are interested in at least a local activation
  287. ASSERT(pActParams->ClsContext & CLSCTX_LOCAL_SERVER);
  288. // We always try to use an existing running server, unless a custom
  289. // activator has told us specifically to create a new server.
  290. if (pActParams->dwProcessReqType != PRT_CREATE_NEW)
  291. {
  292. bStatus = pServerTableEntry->CallRunningServer( pActParams,
  293. 0,
  294. 0,
  295. pClsidData,
  296. &hr);
  297. if ( bStatus )
  298. goto ActivationDone;
  299. else
  300. {
  301. if (pActParams->dwProcessReqType == PRT_USE_THIS_ONLY)
  302. {
  303. // A custom activator specified a specific server which was not
  304. // found. No need to continue further.
  305. hr = E_UNEXPECTED; // REVIEW for better error code!
  306. goto ActivationDone;
  307. }
  308. else if(pActParams->dwProcessReqType == PRT_USE_THIS)
  309. {
  310. // A custom activator hinted at a specific process, which was not
  311. // found. Eg, the process in question was killed, died, etc. Although
  312. // this should not happen much in the normal case, it would be nice if
  313. // we could somehow save the client from getting an error. So what we
  314. // do is re-try the activation using any compatible server. If it works
  315. // great, if not then we're done (we won't start a new server).
  316. // note we're only resetting the pertinent flags in the actparams struct,
  317. // not the actprops object, but everybody downstream from here only looks
  318. // at the actparams so this is okay.
  319. pActParams->dwProcessReqType = PRT_IGNORE;
  320. pActParams->dwPID = 0;
  321. bStatus = pServerTableEntry->CallRunningServer( pActParams,
  322. 0,
  323. 0,
  324. pClsidData,
  325. &hr);
  326. goto ActivationDone;
  327. }
  328. // else { keep going }
  329. }
  330. }
  331. if (bFirstTime)
  332. {
  333. bFirstTime = FALSE;
  334. //
  335. // Try to do at-storage first
  336. //
  337. if (ActivateAtStorage(pActParams, pClsidData, &hr))
  338. goto ActivationDone;
  339. // Try a remote activation if
  340. // (1a) Class is configured to be activated remotely
  341. // AND
  342. // (1b) Client will accept a remote activation
  343. // OR
  344. // (2)SERVERTYPE_NONE
  345. if( (((pClsidData->GetAcceptableContext() & (CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER)) == CLSCTX_REMOTE_SERVER)
  346. &&
  347. (pActParams->ClsContext & CLSCTX_REMOTE_SERVER))
  348. ||
  349. (pClsidData->ServerType() == SERVERTYPE_NONE) )
  350. goto ActivationDoneLocal;
  351. }
  352. if ( ! pLaunchMutex )
  353. {
  354. pLaunchMutex = pClsidData->ServerLaunchMutex();
  355. if (!pLaunchMutex)
  356. {
  357. hr = E_OUTOFMEMORY;
  358. goto ActivationDone;
  359. }
  360. }
  361. else
  362. WaitForSingleObject( pLaunchMutex->Handle(), INFINITE );
  363. // At this point we now hold the launch mutex
  364. // If we've been told explicitly to launch a new server process, then
  365. // there's no reason to check for one already running.
  366. if (pActParams->dwProcessReqType != PRT_CREATE_NEW)
  367. {
  368. // If server exists, release launch mutex and try
  369. // to call server
  370. BOOL fExists;
  371. hr = pServerTableEntry->ServerExists(pActParams, &fExists);
  372. if (hr != S_OK)
  373. {
  374. ReleaseMutex( pLaunchMutex->Handle() );
  375. goto ActivationDone;
  376. }
  377. if (fExists)
  378. {
  379. ReleaseMutex( pLaunchMutex->Handle() );
  380. continue;
  381. }
  382. }
  383. ASSERT(pActParams->dwProcessReqType == PRT_IGNORE ||
  384. pActParams->dwProcessReqType == PRT_CREATE_NEW);
  385. RpcTryExcept
  386. {
  387. LONG lLaunchThreadToken;
  388. //
  389. // This returns when the server has registered the requested CLSID or
  390. // we give up.
  391. //
  392. CairoleDebugOut((DEB_SCM, "Starting ServerTableEntry at 0x%p\n", pServerTableEntry));
  393. // Grab a non-zero token for the launch that we will
  394. // use to associate the server with on the call
  395. do {
  396. lLaunchThreadToken = InterlockedIncrement(&gThreadToken);
  397. }
  398. while (lLaunchThreadToken == 0);
  399. // Use the token to launch
  400. // Note that StartServerAndWait could reset the token
  401. // to zero in some cases.
  402. hr = pServerTableEntry->StartServerAndWait( pActParams,
  403. pClsidData,
  404. lLaunchThreadToken);
  405. // Now call the server with the LaunchMutex held but
  406. // with the threadtoken to guarantee first access to
  407. // the class in the server we launched. This takes
  408. // care of SINGLEUSE as well as transient error cases.
  409. if (SUCCEEDED(hr))
  410. {
  411. // NOTE: if the server we just launched was an "extra" one (ie, on
  412. // behalf of some custom activator), it's not guaranteed that this
  413. // activation will use the just-launched server. It may get an old one.
  414. bStatus = pServerTableEntry->CallRunningServer(pActParams,
  415. 0,
  416. lLaunchThreadToken,
  417. pClsidData,
  418. &hr);
  419. if (!bStatus)
  420. hr = CO_E_SERVER_EXEC_FAILURE;
  421. }
  422. }
  423. RpcExcept(ActivationExceptionFilter(GetExceptionInformation()))
  424. {
  425. Status = RpcExceptionCode();
  426. hr = HRESULT_FROM_WIN32(Status);
  427. }
  428. RpcEndExcept
  429. ReleaseMutex( pLaunchMutex->Handle() );
  430. break;
  431. }// end for(;;)
  432. goto ActivationDone;
  433. ActivationDoneLocal:
  434. hr = REGDB_E_CLASSNOTREG;
  435. //
  436. // Server name will only be non-null if its our machine name.
  437. //
  438. if ( !pActParams->pwszServer &&
  439. pClsidData->RemoteServerNames() )
  440. {
  441. //
  442. // the remote activation call will null out the pointer in the ActivationPropertiesIn
  443. // object which caused the memory that pActParams->pwszServer is pointing to to be
  444. // freed. We need this name later on to pass to the oxid resoluton phase, so
  445. // we copy it to some memory on the stack
  446. //
  447. // We don't care here since pActParams->pwszServer==NULL if we are here.
  448. if (!ActivateRemote( pActParams, pClsidData, &hr ))
  449. {
  450. hr = (CLSCTX_REMOTE_SERVER == pActParams->ClsContext) ?
  451. CO_E_CANT_REMOTE : REGDB_E_CLASSNOTREG;
  452. }
  453. }
  454. ActivationDone:
  455. if (pLaunchMutex)
  456. pLaunchMutex->Release();
  457. // Registry data is not cached in any way.
  458. if ( pClsidData )
  459. delete pClsidData;
  460. if ( pServerTableEntry )
  461. pServerTableEntry->Release();
  462. // Don't need to resolve if we're return an inproc server.
  463. if ( (S_OK == hr) && ! *pActParams->ppwszDllServer )
  464. hr = ResolveORInfo( pActParams);
  465. if (pActParams->ulMarshaledTargetInfoLength)
  466. {
  467. MIDL_user_free(pActParams->pMarshaledTargetInfo);
  468. }
  469. return hr;
  470. }
  471. //-------------------------------------------------------------------------
  472. //
  473. // ResolveORInfo
  474. //
  475. // On the server side of a remote activation, gets the OXID in the
  476. // marshalled interface pointer.
  477. //
  478. // For a client side activation (local or remote), calls revolve OXID.
  479. //
  480. //-------------------------------------------------------------------------
  481. HRESULT
  482. ResolveORInfo(
  483. IN OUT PACTIVATION_PARAMS pActParams
  484. )
  485. {
  486. MInterfacePointer * pIFD;
  487. OBJREF * pObjRef;
  488. STDOBJREF * pStdObjRef;
  489. DUALSTRINGARRAY * pORBindings;
  490. DWORD DataSize;
  491. RPC_STATUS sc;
  492. DWORD n;
  493. BOOL ActivatedRemote = pActParams->activatedRemote;
  494. // Don't resolve if we are servicing a remote activation and
  495. // we also did a remote activation(i.e LB router)
  496. if (pActParams->RemoteActivation && ActivatedRemote)
  497. return S_OK;
  498. //
  499. // This routine probes the interface data returned from the server's
  500. // OLE during a successfull activation, but we're still going to
  501. // protect ourself from bogus data.
  502. //
  503. if (pActParams->pActPropsOut)
  504. {
  505. HRESULT hr;
  506. pActParams->pIIDs = 0;
  507. pActParams->pResults = 0;
  508. pActParams->ppIFD = 0;
  509. hr = pActParams->pActPropsOut->GetMarshalledResults(&pActParams->Interfaces,
  510. &pActParams->pIIDs,
  511. &pActParams->pResults,
  512. &pActParams->ppIFD);
  513. if (hr != S_OK)
  514. return hr;
  515. }
  516. pIFD = 0;
  517. for ( n = 0; n < pActParams->Interfaces; n++ )
  518. {
  519. pIFD = pActParams->ppIFD[n];
  520. if ( pIFD )
  521. break;
  522. }
  523. ASSERT( pIFD );
  524. if ( pIFD->ulCntData < 2*sizeof(ULONG) )
  525. {
  526. ASSERT( !"Bad interface data returned from server" );
  527. return S_OK;
  528. }
  529. pObjRef = (OBJREF *)pIFD->abData;
  530. if ( (pObjRef->signature != OBJREF_SIGNATURE) ||
  531. (pObjRef->flags & ~(OBJREF_STANDARD | OBJREF_HANDLER |
  532. OBJREF_CUSTOM | OBJREF_EXTENDED)) ||
  533. (pObjRef->flags == 0) )
  534. {
  535. ASSERT( !"Bad interface data returned from server" );
  536. return S_OK;
  537. }
  538. // No OR info sent back for custom marshalled interfaces.
  539. if ( pObjRef->flags == OBJREF_CUSTOM )
  540. return S_OK;
  541. DataSize = 2*sizeof(ULONG) + sizeof(GUID);
  542. pStdObjRef = (STDOBJREF *)(pIFD->abData + DataSize);
  543. DataSize += sizeof(STDOBJREF);
  544. if ( pObjRef->flags == OBJREF_HANDLER )
  545. DataSize += sizeof(CLSID);
  546. else if( pObjRef->flags == OBJREF_EXTENDED)
  547. DataSize += sizeof(DWORD);
  548. pORBindings = (DUALSTRINGARRAY *)(pIFD->abData + DataSize);
  549. DataSize += 2 * sizeof(USHORT);
  550. if ( pIFD->ulCntData < DataSize )
  551. {
  552. ASSERT( !"Bad interface data returned from server" );
  553. return S_OK;
  554. }
  555. // If we activated the server on this machine, we need the OXID of the server.
  556. if ( ! ActivatedRemote )
  557. *pActParams->pOxidServer = *((OXID UNALIGNED *)&pStdObjRef->oxid);
  558. //
  559. // If we're servicing a remote activation, all we need is the server's OXID.
  560. // The client will call ResolveClientOXID from its ResolveORInfo.
  561. //
  562. if ( pActParams->RemoteActivation )
  563. return S_OK;
  564. DataSize += pORBindings->wNumEntries * sizeof(USHORT);
  565. if ( (pIFD->ulCntData < DataSize) ||
  566. (pORBindings->wNumEntries != 0 &&
  567. (pORBindings->wSecurityOffset >= pORBindings->wNumEntries)) )
  568. {
  569. ASSERT( !"Bad interface data returned from server" );
  570. // Bug 658576 - don't send back a non-zero oxid if
  571. // server bindings are empty or corrupt.
  572. *pActParams->pOxidServer = 0;
  573. return S_OK;
  574. }
  575. //
  576. // If empty OR bindings were supplied then the server and client are
  577. // both local to this machine, so use the local OR bindings.
  578. //
  579. if (pORBindings->wNumEntries == 0)
  580. {
  581. sc = CopyMyOrBindings(pActParams->ppServerORBindings, NULL);
  582. if (sc != RPC_S_OK)
  583. return HRESULT_FROM_WIN32(sc);
  584. }
  585. else
  586. {
  587. //
  588. // This was a local activation so use our string bindings for the OR
  589. // binding string.
  590. //
  591. *pActParams->ppServerORBindings = (DUALSTRINGARRAY *)
  592. MIDL_user_allocate( sizeof(DUALSTRINGARRAY) +
  593. pORBindings->wNumEntries*sizeof(USHORT) );
  594. if ( ! *pActParams->ppServerORBindings )
  595. return E_OUTOFMEMORY;
  596. dsaCopy( *pActParams->ppServerORBindings, pORBindings );
  597. }
  598. //
  599. // If we did a remote activation then we already have the server's OXID and
  600. // OR string bindings from the RemoteActivation call and pieces of the OXID
  601. // info have been filled in.
  602. //
  603. // Could we optimize this at all for the local case?
  604. USHORT usAuthnSvc;
  605. sc = ResolveClientOXID( pActParams->hRpc,
  606. pActParams->pOxidServer,
  607. *pActParams->ppServerORBindings,
  608. pActParams->Apartment,
  609. pActParams->ProtseqId,
  610. pActParams->pwszServer,
  611. pActParams->pOxidInfo,
  612. pActParams->pLocalMidOfRemote,
  613. pActParams->UnsecureActivation,
  614. pActParams->AuthnSvc,
  615. pActParams->ulMarshaledTargetInfoLength,
  616. pActParams->pMarshaledTargetInfo,
  617. &pActParams->IsLocalOxid,
  618. NULL,
  619. NULL,
  620. &usAuthnSvc);
  621. return HRESULT_FROM_WIN32(sc);
  622. }
  623. //-------------------------------------------------------------------------
  624. //
  625. // ActivateAtStorage
  626. //
  627. // If the given CLSID is marked with ActivateAtStorage, do a remote
  628. // activation to the machine where the path points.
  629. //
  630. // Returns TRUE if a remote activation was tried or a wierd error was
  631. // encoutered. Returns FALSE if the CLSID is not marked with
  632. // ActivateAtStorage or the file path is determined to be local.
  633. //
  634. //-------------------------------------------------------------------------
  635. BOOL
  636. ActivateAtStorage(
  637. IN OUT ACTIVATION_PARAMS * pActParams,
  638. IN CClsidData * pClsidData,
  639. OUT HRESULT * phr
  640. )
  641. {
  642. //
  643. // See if we need to do a remote ActivateAtStorage activation. If
  644. // a server name is given, then we either made a remote activation
  645. // already or the server name is for the local machine in which case
  646. // ActivateAtStorage is ignored.
  647. LPWSTR pwszOrigSrvrName=NULL;
  648. pwszOrigSrvrName = GetOrigSrvrName(pActParams);
  649. if ( pActParams->RemoteActivation ||
  650. pActParams->pwszServer ||
  651. pwszOrigSrvrName ||
  652. !pActParams->pwszPath )
  653. return FALSE;
  654. // Note that if we have no information at all for a CLSID, we try a
  655. // atstorage activation. Part of initial dcom spec.
  656. //
  657. if ( pClsidData && ! pClsidData->ActivateAtStorage() )
  658. return FALSE;
  659. HRESULT hr;
  660. WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
  661. //
  662. #ifdef DFSACTIVATION
  663. //
  664. // This is for DFS support. If the file hasn't been opened yet, we must
  665. // open it before trying to resolve the DFS pathname in GetMachineName.
  666. // This is just how DFS works. FindFirstFile results in the fewest number
  667. // of network packets.
  668. //
  669. if ( ! pActParams->FileWasOpened )
  670. {
  671. HANDLE hFile;
  672. WIN32_FIND_DATA Data;
  673. if (pActParams->pToken != NULL)
  674. pActParams->pToken->Impersonate();
  675. hFile = FindFirstFile( pActParams->pwszPath, &Data );
  676. if ( hFile != INVALID_HANDLE_VALUE )
  677. (void) FindClose( hFile );
  678. if (pActParams->pToken != NULL)
  679. pActParams->pToken->Revert();
  680. if ( INVALID_HANDLE_VALUE == hFile )
  681. {
  682. *phr = CO_E_BAD_PATH;
  683. return TRUE;
  684. }
  685. }
  686. #endif
  687. hr = GetMachineName(
  688. pActParams->pwszPath,
  689. wszMachineName
  690. #ifdef DFSACTIVATION
  691. ,TRUE
  692. #endif
  693. );
  694. if ( hr == S_FALSE )
  695. {
  696. // We couldn't get the machine name, path must be local.
  697. return FALSE;
  698. }
  699. else if ( hr != S_OK )
  700. {
  701. // We got an error while trying to find the UNC machine name.
  702. *phr = hr;
  703. return TRUE;
  704. }
  705. if ( gpMachineName->Compare( wszMachineName ) )
  706. return FALSE;
  707. *phr = RemoteActivationCall( pActParams, wszMachineName );
  708. return TRUE;
  709. }
  710. //-------------------------------------------------------------------------
  711. //
  712. // ActivateRemote
  713. //
  714. // Does a remote activation based off of the RemoteServerName registry key
  715. // for the given CLSID.
  716. //
  717. // Returns TRUE if a remote activation was tried, FALSE if not.
  718. //
  719. //-------------------------------------------------------------------------
  720. BOOL
  721. ActivateRemote(
  722. IN OUT ACTIVATION_PARAMS * pActParams,
  723. IN CClsidData * pClsidData,
  724. OUT HRESULT * phr
  725. )
  726. {
  727. WCHAR * pwszServerName;
  728. BOOL bBadServerName;
  729. BOOL bMyServerName;
  730. *phr = S_OK;
  731. //
  732. // The CClsidData class puts the remote server name(s) into a REG_MULTI_SZ
  733. // format.
  734. //
  735. pwszServerName = pClsidData->RemoteServerNames();
  736. // jsimmons 3/11/00 prefix bug fix. We would crash below if RemoteServerNames
  737. // returned NULL (which is possible). The only caller of this function checks
  738. // that before calling us, though. However, it doesn't hurt to make sure.
  739. if (!pwszServerName)
  740. {
  741. ASSERT(0);
  742. *phr = E_UNEXPECTED;
  743. return FALSE;
  744. }
  745. bBadServerName = TRUE;
  746. bMyServerName = TRUE;
  747. for ( ; *pwszServerName; pwszServerName += lstrlenW(pwszServerName) + 1 )
  748. {
  749. if ( pwszServerName[0] == L'\\' && pwszServerName[1] == L'\\' )
  750. pwszServerName += 2;
  751. while ( *pwszServerName &&
  752. (*pwszServerName == L' ' || *pwszServerName == L'\t') )
  753. pwszServerName++;
  754. if ( pwszServerName[0] == L'\0' )
  755. continue;
  756. bBadServerName = FALSE;
  757. if ( gpMachineName->Compare( pwszServerName ) )
  758. continue;
  759. bMyServerName = FALSE;
  760. *phr = RemoteActivationCall( pActParams, pwszServerName );
  761. if ( S_OK == *phr )
  762. break;
  763. }
  764. if ( bBadServerName || bMyServerName )
  765. return FALSE;
  766. return TRUE;
  767. }
  768. //-------------------------------------------------------------------------
  769. //
  770. // LookupObjectInROT
  771. //
  772. // Looks for an object (file path in this activation) in the Running Object
  773. // Table.
  774. //
  775. // Returns TRUE if we found the object in the ROT and can pass its
  776. // marshalled interface pointer directly back to the client.
  777. //
  778. //-------------------------------------------------------------------------
  779. BOOL
  780. LookupObjectInROT(
  781. IN PACTIVATION_PARAMS pActParams,
  782. OUT HRESULT * phr )
  783. {
  784. SCMREGKEY Key;
  785. MNKEQBUF * pMnkEqBuf;
  786. BYTE Buffer[sizeof(DWORD)+ROT_COMPARE_MAX];
  787. pMnkEqBuf = (MNKEQBUF *) Buffer;
  788. *phr = CreateFileMonikerComparisonBuffer(
  789. pActParams->pwszPath,
  790. &pMnkEqBuf->abEqData[0],
  791. ROT_COMPARE_MAX,
  792. &pMnkEqBuf->cdwSize );
  793. if ( *phr != S_OK )
  794. return FALSE;
  795. *phr = gpscmrot->GetObject(
  796. pActParams->pToken,
  797. pActParams->pProcess ? pActParams->pProcess->WinstaDesktop() : NULL,
  798. 0,
  799. pMnkEqBuf,
  800. &Key,
  801. (InterfaceData **)&pActParams->pIFDROT );
  802. if ( *phr != S_OK )
  803. return FALSE;
  804. //
  805. // If our activation call is from a local client and for a single
  806. // interface then we can return success. Otherwise we return failure
  807. // because we must call the server either to get more interface
  808. // pointers or because we are servicing a remote activation and must get
  809. // a normal marshalled interface pointer rather than the table marshalled
  810. // interface pointer sitting in the ROT.
  811. //
  812. if ( ! pActParams->RemoteActivation && (1 == pActParams->Interfaces) )
  813. {
  814. // Return the marshaled interface from the ROT to the caller.
  815. pActParams->ppIFD = (MInterfacePointer **)
  816. MIDL_user_allocate(sizeof(MInterfacePointer *));
  817. pActParams->pResults = (HRESULT*) MIDL_user_allocate(sizeof(HRESULT));
  818. if ((pActParams->ppIFD==NULL) || (pActParams->pResults==NULL))
  819. {
  820. MIDL_user_free(pActParams->ppIFD);
  821. MIDL_user_free(pActParams->pResults);
  822. *phr = E_OUTOFMEMORY;
  823. return FALSE;
  824. }
  825. *pActParams->ppIFD = pActParams->pIFDROT;
  826. pActParams->pResults[0] = S_OK;
  827. // So we remember not to clean up the buffer
  828. pActParams->pIFDROT = NULL;
  829. // Let caller know that we got this from the ROT so
  830. // if it doesn't work they should try again.
  831. pActParams->FoundInROT = TRUE;
  832. *pActParams->pFoundInROT = TRUE;
  833. return TRUE;
  834. }
  835. //
  836. // REVIEW REVIEW. Can we return success if the ROT object was marshalled
  837. // strong? Do we really have to call the server if the object was
  838. // marshalled weak? Is the resulting race condition any worse then for a
  839. // normal activation?
  840. //
  841. //
  842. // We can't use a tabled marshalled interface pointer to send back to a
  843. // remote client, so we return failure here, but keep the ROT interface
  844. // data in pIFDROT.
  845. //
  846. return FALSE;
  847. }
  848. //+---------------------------------------------------------------------------
  849. //
  850. // Get the COSERVERINFO supplied by the client. We'll use this to decide
  851. // whether we want to do remote ActivateAtStorage.
  852. //
  853. //+---------------------------------------------------------------------------
  854. LPWSTR GetOrigSrvrName(
  855. PACTIVATION_PARAMS pActParams
  856. )
  857. {
  858. LPWSTR pwszOrigSrvrName = NULL;
  859. if (pActParams->pActPropsIn)
  860. {
  861. SecurityInfo* pLegacyInfo = pActParams->pActPropsIn->GetSecurityInfo();
  862. if (pLegacyInfo)
  863. {
  864. COSERVERINFO* pServerInfo = NULL;
  865. pLegacyInfo->GetCOSERVERINFO(&pServerInfo);
  866. if (pServerInfo)
  867. {
  868. pwszOrigSrvrName = pServerInfo->pwszName;
  869. }
  870. }
  871. }
  872. return pwszOrigSrvrName;
  873. }
  874. //
  875. // Helper function. ppid and pdwProcessReqType may be NULL if caller does not care about them.
  876. //
  877. HRESULT GetProcessInfoFromActProps(IActivationPropertiesIn* pActPropsIn, DWORD* ppid, DWORD* pdwProcessReqType)
  878. {
  879. HRESULT hr = E_INVALIDARG;
  880. ASSERT(pActPropsIn);
  881. if (pActPropsIn != NULL)
  882. {
  883. IServerLocationInfo *pSLInfo = NULL;
  884. hr = pActPropsIn->QueryInterface(IID_IServerLocationInfo, (void**) &pSLInfo);
  885. ASSERT(SUCCEEDED(hr) && pSLInfo);
  886. if (SUCCEEDED(hr) && pSLInfo != NULL)
  887. {
  888. DWORD dwPRT;
  889. DWORD dwPid;
  890. hr = pSLInfo->GetProcess(&dwPid, &dwPRT);
  891. ASSERT(SUCCEEDED(hr));
  892. ASSERT(dwPRT == PRT_IGNORE ||
  893. dwPRT == PRT_CREATE_NEW ||
  894. dwPRT == PRT_USE_THIS ||
  895. dwPRT == PRT_USE_THIS_ONLY);
  896. if (SUCCEEDED(hr))
  897. {
  898. if (ppid)
  899. *ppid = dwPid;
  900. if (pdwProcessReqType)
  901. *pdwProcessReqType = dwPRT;
  902. }
  903. pSLInfo->Release();
  904. pSLInfo = NULL;
  905. }
  906. }
  907. return hr;
  908. }