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.

441 lines
15 KiB

  1. /*++
  2. Copyright (C) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. gdithnk.cxx
  6. Abstract:
  7. This file contains the startup code for the
  8. surrogate rpc server used to load 64 bit dlls
  9. in 32 bit apps
  10. Author:
  11. Khaled Sedky (khaleds) 19-Jun-2000
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "sddl.h"
  17. #ifndef __LDFUNCS_HPP__
  18. #include "ldfuncs.hpp"
  19. #endif
  20. #ifndef __LDMGR_HPP__
  21. #include "ldmgr.hpp"
  22. #endif
  23. #ifndef __GDITHNK_HPP__
  24. #include "gdithnk.hpp"
  25. #endif
  26. /*++
  27. Function Name:
  28. LPCConnMsgsServingThread
  29. Description:
  30. This funciton is the main loop for processing LPC requests
  31. by dispatching them to the LPC handler which takes the proper
  32. action according to the request.
  33. This function runs in a Thread of its own.
  34. Parameters:
  35. pThredData : The Thread specific data which encapsulates the
  36. pointer to the LPC handler.
  37. Return Value
  38. Always returns 1
  39. --*/
  40. EXTERN_C
  41. DWORD
  42. LPCConnMsgsServingThread(
  43. PVOID pThrdData
  44. )
  45. {
  46. //
  47. // Communication Port Handles are unique , i.e. one per
  48. // Client Server conversation
  49. //
  50. HANDLE ConnectionPortHandle;
  51. NTSTATUS Status = STATUS_SUCCESS;
  52. DWORD ErrorCode = ERROR_SUCCESS;
  53. PVOID pCommunicationPortContext = NULL;
  54. SPROXY_MSG RequestMsg;
  55. PSPROXY_MSG pReplyMsg;
  56. //
  57. // reconstruct the Data passed in for the Thread
  58. //
  59. TLPCMgr* pMgrInst = reinterpret_cast<TLPCMgr*>((reinterpret_cast<PSLPCMSGSTHRDDATA>(pThrdData))->pData);
  60. SPLASSERT(pMgrInst);
  61. ConnectionPortHandle = pMgrInst->GetUMPDLpcConnPortHandle();
  62. for(pReplyMsg=NULL,memset(&RequestMsg,0,sizeof(SPROXY_MSG));
  63. pMgrInst;)
  64. {
  65. //
  66. // Data sent back to client and then call blocked until another message
  67. // comes in
  68. //
  69. Status = NtReplyWaitReceivePort( ConnectionPortHandle,
  70. reinterpret_cast<PVOID*>(&pCommunicationPortContext),
  71. reinterpret_cast<PPORT_MESSAGE>(pReplyMsg),
  72. reinterpret_cast<PPORT_MESSAGE>(&RequestMsg)
  73. );
  74. DBGMSG(DBG_WARN,
  75. ("LPCConnMsgsServingThread Active \n"));
  76. ConnectionPortHandle = pMgrInst->GetUMPDLpcConnPortHandle();
  77. pReplyMsg = NULL;
  78. if(NT_SUCCESS(Status))
  79. {
  80. switch(RequestMsg.Msg.u2.s2.Type)
  81. {
  82. //
  83. // For a Connection Request coming from the Client
  84. //
  85. case LPC_CONNECTION_REQUEST:
  86. {
  87. pMgrInst->ProcessConnectionRequest((PPORT_MESSAGE)&RequestMsg);
  88. break;
  89. }
  90. //
  91. // For a Data Request coming in from the client
  92. //
  93. case LPC_REQUEST:
  94. {
  95. if((ErrorCode = pMgrInst->ProcessRequest(&RequestMsg)) == ERROR_SUCCESS)
  96. {
  97. pReplyMsg = &RequestMsg;
  98. }
  99. //
  100. // We retrieve the coomunication handle from LPC becauce this is how we send data
  101. // back to the client. We can't used a connection port
  102. //
  103. ConnectionPortHandle = (reinterpret_cast<TLPCMgr::TClientInfo*>(pCommunicationPortContext))->GetPort();
  104. break;
  105. }
  106. //
  107. // When the client close the port.
  108. //
  109. case LPC_PORT_CLOSED:
  110. {
  111. if(pCommunicationPortContext)
  112. {
  113. HANDLE hPortID =
  114. (reinterpret_cast<TLPCMgr::TClientInfo*>(pCommunicationPortContext))->GetPort();
  115. pMgrInst->ProcessPortClosure(&RequestMsg,hPortID);
  116. }
  117. break;
  118. }
  119. //
  120. // When the client terminates (Normally or Abnormally)
  121. //
  122. case LPC_CLIENT_DIED:
  123. {
  124. if(pCommunicationPortContext)
  125. {
  126. pMgrInst->ProcessClientDeath(&RequestMsg);
  127. }
  128. break;
  129. }
  130. default:
  131. {
  132. //
  133. // Basically here we do nothing, we just retrun.
  134. //
  135. break;
  136. }
  137. }
  138. }
  139. }
  140. //
  141. // Cleaning up the memory allocated before leaving the Thread
  142. //
  143. delete pThrdData;
  144. return 1;
  145. }
  146. EXTERN_C
  147. DWORD
  148. GDIThunkingVIALPCThread(
  149. PVOID pThrdData
  150. )
  151. {
  152. OBJECT_ATTRIBUTES ObjectAttrib;
  153. UNICODE_STRING UString;
  154. PFNGDIPRINTERTHUNKPROC pfnThnkFn;
  155. NTSTATUS Status = STATUS_SUCCESS;
  156. HINSTANCE hGDI = NULL;
  157. WCHAR pszPortName[MAX_PATH] = {0};
  158. WCHAR szFullSD[MAX_PATH] = {0};
  159. //
  160. // reconstruct the Data passed in for the Thread
  161. //
  162. DWORD *pErrorCode = &(reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->ErrorCode;
  163. HANDLE hSyncEvent = (reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->hEvent;
  164. TLPCMgr *pMgrInst = reinterpret_cast<TLPCMgr*>((reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->pData);
  165. if(hGDI = LoadLibrary(L"GDI32.DLL"))
  166. {
  167. if(pfnThnkFn = reinterpret_cast<PFNGDIPRINTERTHUNKPROC>(GetProcAddress(hGDI,
  168. "GdiPrinterThunk")))
  169. {
  170. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  171. LPWSTR pszUserSID = NULL;
  172. HRESULT hRes = E_FAIL;
  173. //
  174. // Give System SID a full access ACE
  175. // Give Creator Owner SID a full access ACE
  176. // Give the current user a full access ACE
  177. //
  178. WCHAR* szSD = L"D:"
  179. L"(A;OICI;GA;;;SY)"
  180. L"(A;OICI;GA;;;CO)"
  181. L"(A;;GA;;;";
  182. StringCchPrintfW(pszPortName,
  183. MAX_PATH,
  184. L"%s_%x",
  185. GDI_LPC_PORT_NAME,
  186. pMgrInst->GetCurrSessionId());
  187. RtlInitUnicodeString(&UString,
  188. pszPortName);
  189. if(SUCCEEDED (hRes = GetCurrentUserSID(&pszUserSID,
  190. pErrorCode)))
  191. {
  192. //
  193. // Concatenate everything representing
  194. // the required ACEs for the pipe DACL
  195. //
  196. StringCchPrintf(szFullSD,MAX_PATH,
  197. L"%ws%ws%ws",szSD,pszUserSID,L")");
  198. LocalFree(pszUserSID);
  199. if( ConvertStringSecurityDescriptorToSecurityDescriptor(szFullSD,
  200. SDDL_REVISION_1,
  201. &pSecurityDescriptor,
  202. NULL))
  203. {
  204. InitializeObjectAttributes(&ObjectAttrib,
  205. &UString,
  206. OBJ_CASE_INSENSITIVE,
  207. NULL,
  208. pSecurityDescriptor);
  209. Status = NtCreatePort(pMgrInst->GetUMPDLPCConnPortHandlePtr(),
  210. &ObjectAttrib,
  211. PORT_MAXIMUM_MESSAGE_LENGTH,
  212. PORT_MAXIMUM_MESSAGE_LENGTH,
  213. PORT_MAXIMUM_MESSAGE_LENGTH*32
  214. );
  215. if(NT_SUCCESS(Status))
  216. {
  217. //
  218. // Start processing the LPC messages either in one Thread
  219. // or multiple Threads
  220. //
  221. HANDLE hMsgThrd;
  222. DWORD MsgThrdId;
  223. if(PSLPCMSGSTHRDDATA pLPCMsgData = new SLPCMSGSTHRDDATA)
  224. {
  225. pLPCMsgData->pData = reinterpret_cast<void*>(pMgrInst);
  226. pMgrInst->SetPFN(pfnThnkFn);
  227. if(hMsgThrd = CreateThread(NULL,
  228. 0,
  229. LPCConnMsgsServingThread,
  230. (VOID *)pLPCMsgData,
  231. 0,
  232. &MsgThrdId))
  233. {
  234. CloseHandle(hMsgThrd);
  235. }
  236. else
  237. {
  238. delete pLPCMsgData;
  239. *pErrorCode = GetLastError();
  240. DBGMSG(DBG_WARN,
  241. ("GDIThunkVIALPCThread: Failed to create the messaging thread - %u\n",*pErrorCode));
  242. }
  243. }
  244. else
  245. {
  246. *pErrorCode = GetLastError();
  247. DBGMSG(DBG_WARN,
  248. ("GDIThunkVIALPCThread: Failed to allocate memory - %u\n",*pErrorCode));
  249. }
  250. }
  251. else
  252. {
  253. *pErrorCode = pMgrInst->MapNtStatusToWin32Error(Status);
  254. DBGMSG(DBG_WARN,
  255. ("GDIThunkVIALPCThread: Failed to create the LPC port - %u\n",Status));
  256. }
  257. LocalFree(pSecurityDescriptor);
  258. }
  259. else
  260. {
  261. *pErrorCode = GetLastError();
  262. DBGMSG(DBG_WARN,
  263. ("GDIThunkVIALPCThread: Failed to create the Security Descriptor - %u\n",*pErrorCode));
  264. }
  265. }
  266. }
  267. else
  268. {
  269. *pErrorCode = GetLastError();
  270. DBGMSG(DBG_WARN,
  271. ("GDIThunkVIALPCThread: Failed to get the entry point GdiPrinterThunk - %u\n",*pErrorCode));
  272. }
  273. }
  274. else
  275. {
  276. *pErrorCode = GetLastError();
  277. DBGMSG(DBG_WARN,
  278. ("GDIThunkVIALPCThread: Failed to load GDI32 - %u\n",*pErrorCode));
  279. }
  280. SetEvent(hSyncEvent);
  281. return 1;
  282. }
  283. /*++
  284. Function Name:
  285. GetCurrentUserSID
  286. Description:
  287. This funciton returns the SID of the current logged on user
  288. Parameters:
  289. ppszUserSID : This is the out string to be filled by
  290. the current user SID
  291. pErrorCode : Return the WIN32 error code to the caller
  292. Return Value
  293. HRSEUSLT : S_OK = success
  294. E_FAIL = failure
  295. --*/
  296. HRESULT
  297. GetCurrentUserSID(
  298. PWSTR* ppszUserSID,
  299. PDWORD pErrorCode
  300. )
  301. {
  302. HANDLE hToken = NULL;
  303. PTOKEN_USER pTokenUser = NULL;
  304. DWORD TokenUserLen = 0;
  305. HRESULT hRes = E_FAIL;
  306. if(OpenThreadToken(GetCurrentThread(),
  307. TOKEN_QUERY,
  308. TRUE,
  309. &hToken))
  310. {
  311. hRes = S_OK;
  312. }
  313. else if((*pErrorCode = GetLastError()) == ERROR_NO_TOKEN)
  314. {
  315. if(OpenProcessToken(GetCurrentProcess(),
  316. TOKEN_QUERY,
  317. &hToken))
  318. {
  319. hRes = S_OK;
  320. }
  321. else
  322. {
  323. *pErrorCode = GetLastError();
  324. DBGMSG(DBG_WARN,
  325. ("GetCurrentUserSID: Failed to open the Process Token - %u\n",*pErrorCode));
  326. }
  327. }
  328. else
  329. {
  330. DBGMSG(DBG_WARN,
  331. ("GetCurrentUserSID: Failed to open the Thread Token - %u\n",*pErrorCode));
  332. }
  333. if(SUCCEEDED(hRes))
  334. {
  335. *pErrorCode = ERROR_SUCCESS;
  336. if(!GetTokenInformation(hToken,
  337. TokenUser,
  338. NULL,
  339. 0,
  340. &TokenUserLen) &&
  341. ((*pErrorCode = GetLastError()) == ERROR_INSUFFICIENT_BUFFER))
  342. {
  343. if(pTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[TokenUserLen]))
  344. {
  345. if(GetTokenInformation(hToken,
  346. TokenUser,
  347. pTokenUser,
  348. TokenUserLen,
  349. &TokenUserLen))
  350. {
  351. *pErrorCode = ERROR_SUCCESS;
  352. //
  353. // The required SID is at pTokenUser->User.Sid
  354. //
  355. if(!ConvertSidToStringSid(pTokenUser->User.Sid,
  356. ppszUserSID))
  357. {
  358. *pErrorCode = GetLastError();
  359. }
  360. }
  361. delete [] reinterpret_cast<BYTE*>(pTokenUser);
  362. }
  363. else
  364. {
  365. *pErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  366. }
  367. }
  368. else
  369. {
  370. DBGMSG(DBG_WARN,
  371. ("GetCurrentUserSID: Failed to get Thread Information - %u\n",*pErrorCode));
  372. }
  373. hRes = *pErrorCode == ERROR_SUCCESS ? S_OK : E_FAIL;
  374. CloseHandle(hToken);
  375. }
  376. return hRes;
  377. }