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.

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