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.

798 lines
18 KiB

  1. /*++
  2. Copyright (C) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. TLPCMgr.cxx
  6. Abstract:
  7. This file inlcuded the implementation of the class
  8. that processes both Connection and Communication Requests
  9. for the LPC port managing the Thunking between 32-bit and
  10. 64-bit processes.
  11. Author:
  12. Khaled Sedky (khaleds) 19-Jun-2000
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #ifndef __LDFUNCS_HPP__
  18. #include "ldfuncs.hpp"
  19. #endif
  20. #ifndef __LDMGR_HPP__
  21. #include "ldmgr.hpp"
  22. #endif
  23. /* ------------------------------------ */
  24. /* Implemetation of class TLPCMgr */
  25. /* ------------------------------------ */
  26. /*++
  27. Function Name:
  28. TLPCMgr :: TLPCMgr
  29. Description:
  30. Constructor of the LPC Thunking management object
  31. Parameters:
  32. TLoad64BitDllsMgr* : Pointer to the main loader object
  33. which manage the process
  34. Return Value:
  35. None
  36. --*/
  37. TLPCMgr ::
  38. TLPCMgr(
  39. IN TLoad64BitDllsMgr* pIpLdrObj
  40. ) :
  41. m_pLdrObj(pIpLdrObj),
  42. m_UMPDLPCConnPortHandle(NULL),
  43. TClassID("TLPCMgr")
  44. {
  45. //
  46. // If we cann't create the list here. It would be a better idea
  47. // if we just continue for this session with leaks other than
  48. // failing the wow64 printing for this session
  49. //
  50. m_pCnctdClients = NULL;
  51. if(!(m_pCnctdClients =
  52. new TLstMgr<TConnectedClientsInfo,ULONG_PTR>(TLstMgr<TConnectedClientsInfo,ULONG_PTR>::KUniqueEntries)))
  53. {
  54. DBGMSG(DBG_WARN, ("TLPCMgr ctor failer to create the list of connected Clients\n",GetLastError()));
  55. }
  56. m_pLdrObj->AddRef();
  57. }
  58. /*++
  59. Function Name:
  60. TLPCMgr :: ~TLPCMgr
  61. Description:
  62. Destructor of the Printer(Driver) Event object
  63. Parameters:
  64. None
  65. Return Value:
  66. None
  67. --*/
  68. TLPCMgr ::
  69. ~TLPCMgr(
  70. VOID
  71. )
  72. {
  73. if(m_pCnctdClients)
  74. {
  75. delete m_pCnctdClients;
  76. }
  77. m_pLdrObj->Release();
  78. }
  79. DWORD
  80. TLPCMgr ::
  81. GetCurrSessionId(
  82. VOID
  83. ) const
  84. {
  85. return m_CurrSessionId;
  86. }
  87. VOID
  88. TLPCMgr ::
  89. SetCurrSessionId(
  90. DWORD InID
  91. )
  92. {
  93. m_CurrSessionId = InID;
  94. }
  95. VOID
  96. TLPCMgr ::
  97. SetPFN(
  98. PFNGDIPRINTERTHUNKPROC InPFN
  99. )
  100. {
  101. m_pfn = InPFN;
  102. }
  103. PFNGDIPRINTERTHUNKPROC
  104. TLPCMgr ::
  105. GetPFN(
  106. VOID
  107. )const
  108. {
  109. return m_pfn;
  110. }
  111. /*++
  112. Function Name:
  113. TLPCMgr :: GetUMPDLPCConnPortHandlePtr
  114. Description:
  115. returns the address of the LPC port
  116. Parameters:
  117. None
  118. Return Value:
  119. Handle* : LPC Port Handle
  120. --*/
  121. HANDLE*
  122. TLPCMgr ::
  123. GetUMPDLPCConnPortHandlePtr()
  124. {
  125. return reinterpret_cast<HANDLE*>(&m_UMPDLPCConnPortHandle);
  126. }
  127. TLoad64BitDllsMgr*
  128. TLPCMgr ::
  129. GetLdrObj(
  130. VOID
  131. ) const
  132. {
  133. return m_pLdrObj;
  134. }
  135. HANDLE
  136. TLPCMgr ::
  137. GetUMPDLpcConnPortHandle(
  138. VOID
  139. )const
  140. {
  141. return m_UMPDLPCConnPortHandle;
  142. }
  143. /*++
  144. Function Name:
  145. TLPCMgr :: InitUMPDLPCServer
  146. Description:
  147. Creates the Thread handling LPC operations for
  148. GDI thunking
  149. Parameters:
  150. None
  151. Return Value:
  152. DWORD ErrorCode : ERROR_SUCCESS in case of success
  153. LastError in case of failure
  154. --*/
  155. DWORD
  156. TLPCMgr ::
  157. InitUMPDLPCServer(
  158. VOID
  159. )
  160. {
  161. DWORD ThnkThreadId = 0;
  162. HANDLE hThnkThrd = NULL;
  163. SGDIThnkThrdData SThrdData = {0};
  164. HANDLE hThnkSyncEvent = NULL;
  165. DWORD ErrorCode = ERROR_SUCCESS;
  166. if(hThnkSyncEvent = CreateEvent(NULL,FALSE,FALSE,NULL))
  167. {
  168. SThrdData.hEvent = hThnkSyncEvent;
  169. SThrdData.pData = reinterpret_cast<ULONG_PTR*>(this);
  170. SThrdData.ErrorCode = ERROR_SUCCESS;
  171. //
  172. // At this stage we spin a new Thread which creates the LPC
  173. // port and starts waiting on both connection and communication
  174. // requests
  175. //
  176. if(hThnkThrd = CreateThread(NULL,0,
  177. GDIThunkingVIALPCThread,
  178. &SThrdData,
  179. 0,
  180. &ThnkThreadId))
  181. {
  182. CloseHandle(hThnkThrd);
  183. WaitForSingleObject(hThnkSyncEvent,INFINITE);
  184. if(!*(GetUMPDLPCConnPortHandlePtr()))
  185. {
  186. //
  187. // If here then we failed to create the LPC port
  188. //
  189. ErrorCode = SThrdData.ErrorCode;
  190. DBGMSG(DBG_WARN, ("Failed to create the LPC port with error %u\n",ErrorCode));
  191. }
  192. }
  193. else
  194. {
  195. ErrorCode = GetLastError();
  196. DBGMSG(DBG_WARN, ("Failed to spin the GDI Thunking thread with Error %u\n",ErrorCode));
  197. }
  198. CloseHandle(hThnkSyncEvent);
  199. }
  200. else
  201. {
  202. ErrorCode = GetLastError();
  203. DBGMSG(DBG_WARN, ("Failed to create the synchronization event with Error %u\n",ErrorCode));
  204. }
  205. return ErrorCode;
  206. }
  207. DWORD
  208. TLPCMgr ::
  209. ProcessConnectionRequest(
  210. IN PPORT_MESSAGE pMsg
  211. )
  212. {
  213. NTSTATUS Status;
  214. HANDLE CommunicationPortHandle = NULL;
  215. DBGMSG(DBG_WARN,
  216. ("Processing Connection Request\n"));
  217. //
  218. // Since this is a new connection then we carry out 2 work items
  219. // 1. Add the Client to the list of connected clients
  220. // 2. Allocate a Port Context to be used by LPC for consecutive
  221. // operations on this port.
  222. //
  223. if(TClientInfo *pClientInfoInstant = new TClientInfo(pMsg->ClientId.UniqueThread))
  224. {
  225. //
  226. // While Accepting the connection we also set in the communication Port
  227. // context used for communication with this particular client, the refrence
  228. // to the clients info which saves the communication port handle and other
  229. // data
  230. //
  231. Status = NtAcceptConnectPort(&CommunicationPortHandle,
  232. (PVOID)pClientInfoInstant,
  233. pMsg,
  234. 1,
  235. NULL,
  236. NULL);
  237. if(NT_SUCCESS(Status))
  238. {
  239. pClientInfoInstant->SetPort(CommunicationPortHandle);
  240. Status = NtCompleteConnectPort(CommunicationPortHandle);
  241. if(!NT_SUCCESS(Status))
  242. {
  243. DBGMSG(DBG_WARN,
  244. ("TLPCMgr::ProcessConnectionRequest failed to complete port connection - %u \n",Status));
  245. }
  246. else
  247. {
  248. if(m_pCnctdClients)
  249. {
  250. //
  251. // We maintain an internal list of all connected clients based on their Thread and
  252. // Process ID . So things look like
  253. //
  254. //
  255. // ----- ----- -----
  256. // List of Processes (Apps)----> | | ----------| | ----------| |
  257. // | | | | | |
  258. // ----- ----- -----
  259. // |
  260. // |
  261. // |
  262. // ---------
  263. // | |
  264. // ---------
  265. // |
  266. // |
  267. // |
  268. // ---------
  269. // Thread/App -----> | |
  270. // ---------
  271. //
  272. TLstNd<TConnectedClientsInfo,ULONG_PTR> *pNode = NULL;
  273. if((pNode = m_pCnctdClients->ElementInList((ULONG_PTR)pMsg->ClientId.UniqueProcess)) ||
  274. (pNode = m_pCnctdClients->AppendListByElem((ULONG_PTR)pMsg->ClientId.UniqueProcess)))
  275. {
  276. ((*(*pNode)).GetPerClientPorts())->AppendListByElem(pClientInfoInstant);
  277. }
  278. else
  279. {
  280. Status = STATUS_NO_MEMORY;
  281. }
  282. }
  283. m_pLdrObj->IncUIRefCnt();
  284. }
  285. }
  286. else
  287. {
  288. DBGMSG(DBG_WARN,
  289. ("TLPCMgr :: ProcessConnectionRequest failed to accept port connection - %u \n",Status));
  290. delete pClientInfoInstant;
  291. }
  292. }
  293. else
  294. {
  295. Status = STATUS_NO_MEMORY;
  296. DBGMSG(DBG_WARN,
  297. ("TLPCMgr :: ProcessConnectionRequest failed to create the CleintInfo for Port Context - %u \n",Status));
  298. }
  299. return !!Status;
  300. }
  301. DWORD
  302. TLPCMgr ::
  303. ProcessRequest(
  304. IN PSPROXY_MSG pMsg
  305. ) const
  306. {
  307. ULONG DataSize;
  308. DWORD ErrorCode = ERROR_SUCCESS;
  309. DBGMSG(DBG_WARN,
  310. ("Processing Request\n"));
  311. if (((DataSize = pMsg->Msg.u1.s1.DataLength) == (sizeof(*pMsg) - sizeof(pMsg->Msg))) &&
  312. m_pfn)
  313. {
  314. UMTHDR* pUmHdr = reinterpret_cast<UMTHDR*>(reinterpret_cast<PSPROXYMSGEXTENSION>(pMsg->MsgData)->pvIn);
  315. PVOID pvOut = reinterpret_cast<PSPROXYMSGEXTENSION>(pMsg->MsgData)->pvOut;
  316. ULONG cjOut = reinterpret_cast<PSPROXYMSGEXTENSION>(pMsg->MsgData)->cjOut;
  317. DBGMSG(DBG_WARN,("ProcessRequest handling thunk %d \n",pUmHdr->ulType));
  318. m_pfn(pUmHdr,
  319. pvOut,
  320. cjOut);
  321. }
  322. else
  323. {
  324. ErrorCode = ERROR_INVALID_PARAMETER;
  325. DBGMSG(DBG_WARN,
  326. ("Failed to process the client request %u\n",ErrorCode));
  327. }
  328. return ErrorCode;
  329. }
  330. DWORD
  331. TLPCMgr ::
  332. ProcessClientDeath(
  333. IN PSPROXY_MSG pMsg
  334. )
  335. {
  336. DWORD ErrorCode = ERROR_SUCCESS;
  337. TLstNd<TConnectedClientsInfo,ULONG_PTR> *pNode = NULL;
  338. DBGMSG(DBG_WARN,
  339. ("Processing Client Death \n"));
  340. if(pNode =
  341. (GetConnectedClients())->ElementInList((ULONG_PTR)pMsg->Msg.ClientId.UniqueProcess))
  342. {
  343. if(((*(*pNode)).GetCurrentState()) == TConnectedClientsInfo::KClientAlive)
  344. {
  345. ((*(*pNode)).SetCurrentState(TConnectedClientsInfo::KClientDead));
  346. }
  347. }
  348. else
  349. {
  350. ErrorCode = ERROR_INVALID_PARAMETER;
  351. DBGMSG(DBG_WARN,
  352. ("Failed to Process Client Death \n",ErrorCode));
  353. }
  354. return(ErrorCode);
  355. }
  356. DWORD
  357. TLPCMgr ::
  358. ProcessPortClosure(
  359. IN PSPROXY_MSG pMsg,
  360. IN HANDLE hPort
  361. )
  362. {
  363. DWORD ErrorCode = ERROR_SUCCESS;
  364. TLstNd<TConnectedClientsInfo,ULONG_PTR> *pNode = NULL;
  365. DBGMSG(DBG_WARN,
  366. ("Processing Port Closure \n"));
  367. if(pNode =
  368. (GetConnectedClients())->ElementInList((ULONG_PTR)pMsg->Msg.ClientId.UniqueProcess))
  369. {
  370. ((*(*pNode)).GetPerClientPorts())->RmvElemFromList((HANDLE)hPort);
  371. if(!((*(*pNode)).GetPerClientPorts())->GetNumOfListNodes() &&
  372. (((*(*pNode)).GetCurrentState()) == TConnectedClientsInfo::KClientDead))
  373. {
  374. m_pCnctdClients->RmvElemFromList((ULONG_PTR)pMsg->Msg.ClientId.UniqueProcess);
  375. }
  376. m_pLdrObj->DecUIRefCnt();
  377. }
  378. else
  379. {
  380. ErrorCode = ERROR_INVALID_PARAMETER;
  381. {
  382. DBGMSG(DBG_WARN,
  383. ("Failed to Process Port Closure \n",ErrorCode));
  384. }
  385. }
  386. return(ErrorCode);
  387. }
  388. TLstMgr<TLPCMgr::TConnectedClientsInfo,ULONG_PTR>*
  389. TLPCMgr::
  390. GetConnectedClients(
  391. VOID
  392. ) const
  393. {
  394. return m_pCnctdClients;
  395. }
  396. TLPCMgr::
  397. TClientInfo::
  398. TClientInfo() :
  399. m_UniqueThreadID(NULL),
  400. m_hPort(NULL),
  401. m_SanityChkMagic(UMPD_SIGNATURE)
  402. {
  403. }
  404. TLPCMgr::
  405. TClientInfo::
  406. TClientInfo(
  407. IN const HANDLE& InPort
  408. ) :
  409. m_UniqueThreadID(NULL),
  410. m_hPort(InPort),
  411. m_SanityChkMagic(UMPD_SIGNATURE)
  412. {
  413. }
  414. TLPCMgr::
  415. TClientInfo::
  416. TClientInfo(
  417. IN const ULONG_PTR& InThreadID
  418. ) :
  419. m_UniqueThreadID(InThreadID),
  420. m_hPort(NULL),
  421. m_SanityChkMagic(UMPD_SIGNATURE)
  422. {
  423. }
  424. TLPCMgr::
  425. TClientInfo::
  426. TClientInfo(
  427. IN const TClientInfo& InInfo
  428. ) :
  429. m_UniqueThreadID(InInfo.m_UniqueThreadID),
  430. m_hPort(InInfo.m_hPort),
  431. m_SanityChkMagic(InInfo.m_SanityChkMagic)
  432. {
  433. }
  434. TLPCMgr::
  435. TClientInfo::
  436. ~TClientInfo(
  437. VOID
  438. )
  439. {
  440. }
  441. const TLPCMgr::TClientInfo&
  442. TLPCMgr::
  443. TClientInfo::
  444. operator=(
  445. IN const TClientInfo& InInfo
  446. )
  447. {
  448. if(&InInfo != this)
  449. {
  450. m_UniqueThreadID = InInfo.m_UniqueThreadID;
  451. m_hPort = InInfo.m_hPort;
  452. m_SanityChkMagic = InInfo.m_SanityChkMagic;
  453. }
  454. return *this;
  455. }
  456. BOOL
  457. TLPCMgr::
  458. TClientInfo::
  459. operator==(
  460. IN const TClientInfo& InInfo
  461. ) const
  462. {
  463. return m_hPort == InInfo.m_hPort;
  464. }
  465. BOOL
  466. TLPCMgr::
  467. TClientInfo::
  468. operator==(
  469. IN const HANDLE& InPort
  470. ) const
  471. {
  472. return m_hPort == InPort;
  473. }
  474. BOOL
  475. TLPCMgr::
  476. TClientInfo::
  477. operator!(
  478. VOID
  479. ) const
  480. {
  481. return (m_hPort && m_SanityChkMagic == UMPD_SIGNATURE);
  482. }
  483. VOID
  484. TLPCMgr::
  485. TClientInfo::
  486. SetValidity(
  487. DWORD
  488. )
  489. {
  490. }
  491. BOOL
  492. TLPCMgr::
  493. TClientInfo::
  494. Validate(
  495. VOID
  496. ) const
  497. {
  498. return (m_hPort && m_SanityChkMagic == UMPD_SIGNATURE);
  499. }
  500. VOID
  501. TLPCMgr::
  502. TClientInfo::
  503. SetPort(
  504. IN HANDLE InPort
  505. )
  506. {
  507. m_hPort = InPort;
  508. }
  509. HANDLE
  510. TLPCMgr::
  511. TClientInfo::
  512. GetPort(
  513. VOID
  514. ) const
  515. {
  516. return m_hPort;
  517. }
  518. TLPCMgr::
  519. TConnectedClientsInfo::
  520. TConnectedClientsInfo() :
  521. m_UniqueProcessID(NULL),
  522. m_CurrentState(KClientAlive)
  523. {
  524. m_pPerClientPorts = new TLstMgr<TClientInfo,HANDLE>(TLstMgr<TClientInfo,HANDLE>::KUniqueEntries);
  525. }
  526. TLPCMgr::
  527. TConnectedClientsInfo::
  528. TConnectedClientsInfo(
  529. IN const ULONG_PTR& InProcess
  530. ) :
  531. m_UniqueProcessID(InProcess),
  532. m_CurrentState(KClientAlive)
  533. {
  534. m_pPerClientPorts = new TLstMgr<TClientInfo,HANDLE>(TLstMgr<TClientInfo,HANDLE>::KUniqueEntries);
  535. }
  536. TLPCMgr::
  537. TConnectedClientsInfo::
  538. TConnectedClientsInfo(
  539. IN const TClientInfo& InInfo
  540. )
  541. {
  542. //
  543. // I am not sure if I want this at this stage or not
  544. // especially with the required deep copy for the list
  545. // of ports.
  546. //
  547. }
  548. TLPCMgr::
  549. TConnectedClientsInfo::
  550. ~TConnectedClientsInfo()
  551. {
  552. if(m_pPerClientPorts)
  553. {
  554. delete m_pPerClientPorts;
  555. }
  556. }
  557. const TLPCMgr::TConnectedClientsInfo&
  558. TLPCMgr::
  559. TConnectedClientsInfo::
  560. operator=(
  561. IN const TConnectedClientsInfo& InInfo
  562. )
  563. {
  564. if(&InInfo != this)
  565. {
  566. //
  567. // Also here I am not sure whether I want to implement a deep copy for the
  568. // list or not
  569. // (TO BE IMPLEMENTED LATER)
  570. //
  571. }
  572. return *this;
  573. }
  574. BOOL
  575. TLPCMgr::
  576. TConnectedClientsInfo::
  577. operator==(
  578. IN const TConnectedClientsInfo& InInfo
  579. ) const
  580. {
  581. return (m_UniqueProcessID == InInfo.m_UniqueProcessID);
  582. }
  583. BOOL
  584. TLPCMgr::
  585. TConnectedClientsInfo::
  586. operator==(
  587. IN const ULONG_PTR& InProcess
  588. ) const
  589. {
  590. return m_UniqueProcessID == InProcess;
  591. }
  592. BOOL
  593. TLPCMgr::
  594. TConnectedClientsInfo::
  595. operator!(
  596. VOID
  597. ) const
  598. {
  599. return !!m_UniqueProcessID;
  600. }
  601. VOID
  602. TLPCMgr::
  603. TConnectedClientsInfo::
  604. SetValidity(
  605. DWORD
  606. )
  607. {
  608. }
  609. BOOL
  610. TLPCMgr::
  611. TConnectedClientsInfo::
  612. Validate(
  613. VOID
  614. ) const
  615. {
  616. //
  617. // Still (TO BE IMPLEMENTED)
  618. // never being called
  619. //
  620. return FALSE;
  621. }
  622. TLstMgr<TLPCMgr::TClientInfo,HANDLE>*
  623. TLPCMgr::
  624. TConnectedClientsInfo::
  625. GetPerClientPorts(
  626. VOID
  627. ) const
  628. {
  629. return m_pPerClientPorts;
  630. }
  631. ULONG_PTR
  632. TLPCMgr::
  633. TConnectedClientsInfo::
  634. GetUniqueProcessID(
  635. VOID
  636. ) const
  637. {
  638. return m_UniqueProcessID;
  639. }
  640. VOID
  641. TLPCMgr::
  642. TConnectedClientsInfo::
  643. SetCurrentState(
  644. TLPCMgr::TConnectedClientsInfo::EClientState InState
  645. )
  646. {
  647. m_CurrentState = InState;
  648. }
  649. TLPCMgr::
  650. TConnectedClientsInfo::
  651. EClientState
  652. TLPCMgr::
  653. TConnectedClientsInfo::
  654. GetCurrentState(
  655. VOID
  656. ) const
  657. {
  658. return m_CurrentState;
  659. }