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.

373 lines
12 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: PortMessage.cpp
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // A class to wrap a PORT_MESSAGE struct within an object. It contains space
  7. // for PORT_MAXIMUM_MESSAGE_LENGTH - sizeof(PORT_MESSAGE) bytes of data. Subclass
  8. // this class to write typed functions that access this data. Otherwise use
  9. // CPortMessage::GetData and type case the pointer returned.
  10. //
  11. // History: 1999-11-07 vtan created
  12. // 2000-08-25 vtan moved from Neptune to Whistler
  13. // --------------------------------------------------------------------------
  14. #include "StandardHeader.h"
  15. #include "PortMessage.h"
  16. #include "LPCGeneric.h"
  17. // --------------------------------------------------------------------------
  18. // CPortMessage::CPortMessage
  19. //
  20. // Arguments: <none>
  21. //
  22. // Returns: <none>
  23. //
  24. // Purpose: Constructor for CPortMessage. Zero the memory.
  25. //
  26. // History: 1999-11-07 vtan created
  27. // 2000-08-25 vtan moved from Neptune to Whistler
  28. // --------------------------------------------------------------------------
  29. CPortMessage::CPortMessage (void)
  30. {
  31. ZeroMemory(&_portMessage, sizeof(_portMessage));
  32. ZeroMemory(_data, sizeof(_data));
  33. }
  34. // --------------------------------------------------------------------------
  35. // CPortMessage::CPortMessage
  36. //
  37. // Arguments: <none>
  38. //
  39. // Returns: <none>
  40. //
  41. // Purpose: Copy constructor for CPortMessage. Copies the given
  42. // CPortMessage and all the data in it to the member variable.
  43. //
  44. // History: 1999-11-07 vtan created
  45. // 2000-08-25 vtan moved from Neptune to Whistler
  46. // --------------------------------------------------------------------------
  47. CPortMessage::CPortMessage (const CPortMessage& portMessage) :
  48. _portMessage(*portMessage.GetPortMessage())
  49. {
  50. CSHORT sDataSize = portMessage.GetDataLength();
  51. ASSERTMSG(sDataSize <= sizeof(_data), "Impending heap corruption (illegal PORT_MESSAGE) in CPortMessage::CPortMessage");
  52. if (sDataSize <= sizeof(_data))
  53. {
  54. CopyMemory(_data, portMessage.GetPortMessage() + 1, sDataSize);
  55. }
  56. else
  57. {
  58. // If the source object is corrupted, ignore its data
  59. _portMessage.u1.s1.DataLength = 0;
  60. _portMessage.u1.s1.TotalLength = sizeof(PORT_MESSAGE);
  61. }
  62. }
  63. // --------------------------------------------------------------------------
  64. // CPortMessage::~CPortMessage
  65. //
  66. // Arguments: <none>
  67. //
  68. // Returns: <none>
  69. //
  70. // Purpose: Destructor for CPortMessage.
  71. //
  72. // History: 1999-11-07 vtan created
  73. // 2000-08-25 vtan moved from Neptune to Whistler
  74. // --------------------------------------------------------------------------
  75. CPortMessage::~CPortMessage (void)
  76. {
  77. }
  78. // --------------------------------------------------------------------------
  79. // CPortMessage::GetPortMessage
  80. //
  81. // Arguments: <none>
  82. //
  83. // Returns: const PORT_MESSAGE*
  84. //
  85. // Purpose: Returns a pointer to the PORT_MESSAGE struct for const
  86. // objects.
  87. //
  88. // History: 1999-11-07 vtan created
  89. // 2000-08-25 vtan moved from Neptune to Whistler
  90. // --------------------------------------------------------------------------
  91. const PORT_MESSAGE* CPortMessage::GetPortMessage (void) const
  92. {
  93. return(&_portMessage);
  94. }
  95. // --------------------------------------------------------------------------
  96. // CPortMessage::GetPortMessage
  97. //
  98. // Arguments: <none>
  99. //
  100. // Returns: const PORT_MESSAGE*
  101. //
  102. // Purpose: Returns a pointer to the PORT_MESSAGE struct for non-const
  103. // objects.
  104. //
  105. // History: 1999-11-07 vtan created
  106. // 2000-08-25 vtan moved from Neptune to Whistler
  107. // --------------------------------------------------------------------------
  108. PORT_MESSAGE* CPortMessage::GetPortMessage (void)
  109. {
  110. return(&_portMessage);
  111. }
  112. // --------------------------------------------------------------------------
  113. // CPortMessage::GetData
  114. //
  115. // Arguments: <none>
  116. //
  117. // Returns: const char*
  118. //
  119. // Purpose: Returns a pointer to the data area for const objects.
  120. //
  121. // History: 1999-11-07 vtan created
  122. // 2000-08-25 vtan moved from Neptune to Whistler
  123. // --------------------------------------------------------------------------
  124. const char* CPortMessage::GetData (void) const
  125. {
  126. return(_data);
  127. }
  128. // --------------------------------------------------------------------------
  129. // CPortMessage::GetData
  130. //
  131. // Arguments: <none>
  132. //
  133. // Returns: char*
  134. //
  135. // Purpose: Returns a pointer to the data area for non-const objects.
  136. //
  137. // History: 1999-11-07 vtan created
  138. // 2000-08-25 vtan moved from Neptune to Whistler
  139. // --------------------------------------------------------------------------
  140. char* CPortMessage::GetData (void)
  141. {
  142. return(_data);
  143. }
  144. // --------------------------------------------------------------------------
  145. // CPortMessage::GetDataLength
  146. //
  147. // Arguments: <none>
  148. //
  149. // Returns: CSHORT
  150. //
  151. // Purpose: Returns the length of the data sent in the PORT_MESSAGE.
  152. //
  153. // History: 1999-11-07 vtan created
  154. // 2000-08-25 vtan moved from Neptune to Whistler
  155. // --------------------------------------------------------------------------
  156. CSHORT CPortMessage::GetDataLength (void) const
  157. {
  158. return(_portMessage.u1.s1.DataLength);
  159. }
  160. // --------------------------------------------------------------------------
  161. // CPortMessage::GetType
  162. //
  163. // Arguments: <none>
  164. //
  165. // Returns: CSHORT
  166. //
  167. // Purpose: Returns the type of message sent in the PORT_MESSAGE.
  168. //
  169. // History: 1999-11-07 vtan created
  170. // 2000-08-25 vtan moved from Neptune to Whistler
  171. // --------------------------------------------------------------------------
  172. CSHORT CPortMessage::GetType (void) const
  173. {
  174. #pragma warning (disable:4310)
  175. return(static_cast<CSHORT>(_portMessage.u2.s2.Type & ~LPC_KERNELMODE_MESSAGE));
  176. #pragma warning (default:4310)
  177. }
  178. // --------------------------------------------------------------------------
  179. // CPortMessage::GetUniqueProcess
  180. //
  181. // Arguments: <none>
  182. //
  183. // Returns: HANDLE
  184. //
  185. // Purpose: Returns the process ID of the client process sent in the
  186. // PORT_MESSAGE.
  187. //
  188. // History: 1999-11-07 vtan created
  189. // 2000-08-25 vtan moved from Neptune to Whistler
  190. // --------------------------------------------------------------------------
  191. HANDLE CPortMessage::GetUniqueProcess (void) const
  192. {
  193. return(_portMessage.ClientId.UniqueProcess);
  194. }
  195. // --------------------------------------------------------------------------
  196. // CPortMessage::GetUniqueThread
  197. //
  198. // Arguments: <none>
  199. //
  200. // Returns: HANDLE
  201. //
  202. // Purpose: Returns the thread ID of the client process sent in the
  203. // PORT_MESSAGE.
  204. //
  205. // History: 1999-11-07 vtan created
  206. // 2000-08-25 vtan moved from Neptune to Whistler
  207. // --------------------------------------------------------------------------
  208. HANDLE CPortMessage::GetUniqueThread (void) const
  209. {
  210. return(_portMessage.ClientId.UniqueThread);
  211. }
  212. // --------------------------------------------------------------------------
  213. // CPortMessage::SetReturnCode
  214. //
  215. // Arguments: status = NTSTATUS to send back to client.
  216. //
  217. // Returns: <none>
  218. //
  219. // Purpose: Sets the return NTSTATUS code in the PORT_MESSAGE to send
  220. // back to the client.
  221. //
  222. // History: 1999-11-12 vtan created
  223. // 2000-08-25 vtan moved from Neptune to Whistler
  224. // --------------------------------------------------------------------------
  225. void CPortMessage::SetReturnCode (NTSTATUS status)
  226. {
  227. reinterpret_cast<API_GENERIC*>(&_data)->status = status;
  228. }
  229. // --------------------------------------------------------------------------
  230. // CPortMessage::SetData
  231. //
  232. // Arguments: pData = Pointer to data passed in.
  233. // ulDataSize = Size of data passed in.
  234. //
  235. // Returns: <none>
  236. //
  237. // Purpose: Copies the given data to the port message buffer that follows
  238. // the PORT_MESSAGE struct and set the PORT_MESSAGE sizes to
  239. // match the data size.
  240. //
  241. // History: 1999-11-07 vtan created
  242. // 2000-08-25 vtan moved from Neptune to Whistler
  243. // --------------------------------------------------------------------------
  244. void CPortMessage::SetData (const void *pData, CSHORT sDataSize)
  245. {
  246. ASSERTMSG(sDataSize <= sizeof(_data), "Too much data passed to CPortMessage::SetData");
  247. if (sDataSize <= sizeof(_data))
  248. {
  249. CopyMemory(_data, pData, sDataSize);
  250. _portMessage.u1.s1.DataLength = sDataSize;
  251. _portMessage.u1.s1.TotalLength = static_cast<CSHORT>(sizeof(PORT_MESSAGE) + sDataSize);
  252. }
  253. }
  254. // --------------------------------------------------------------------------
  255. // CPortMessage::SetDataLength
  256. //
  257. // Arguments: ulDataSize = Size of data.
  258. //
  259. // Returns: <none>
  260. //
  261. // Purpose: Set the PORT_MESSAGE sizes to match the data size.
  262. //
  263. // History: 1999-11-07 vtan created
  264. // 2000-08-25 vtan moved from Neptune to Whistler
  265. // --------------------------------------------------------------------------
  266. void CPortMessage::SetDataLength (CSHORT sDataSize)
  267. {
  268. ASSERTMSG(sDataSize <= sizeof(_data), "Length too large in CPortMessage::SetDataLength");
  269. if (sDataSize <= sizeof(_data))
  270. {
  271. _portMessage.u1.s1.DataLength = sDataSize;
  272. _portMessage.u1.s1.TotalLength = static_cast<CSHORT>(sizeof(PORT_MESSAGE) + sDataSize);
  273. }
  274. }
  275. // --------------------------------------------------------------------------
  276. // CPortMessage::OpenClientToken
  277. //
  278. // Arguments: hToken = HANDLE to the token of the client.
  279. //
  280. // Returns: NTSTATUS
  281. //
  282. // Purpose: Gets the token of the client. This can be the thread
  283. // impersonation token, the process primary token or failure.
  284. //
  285. // History: 1999-11-07 vtan created
  286. // 2000-08-25 vtan moved from Neptune to Whistler
  287. // --------------------------------------------------------------------------
  288. NTSTATUS CPortMessage::OpenClientToken (HANDLE& hToken) const
  289. {
  290. NTSTATUS status;
  291. HANDLE hThread;
  292. OBJECT_ATTRIBUTES objectAttributes;
  293. CLIENT_ID clientID;
  294. hToken = NULL;
  295. InitializeObjectAttributes(&objectAttributes,
  296. NULL,
  297. 0,
  298. NULL,
  299. NULL);
  300. clientID.UniqueProcess = NULL;
  301. clientID.UniqueThread = GetUniqueThread();
  302. status = NtOpenThread(&hThread, THREAD_QUERY_INFORMATION, &objectAttributes, &clientID);
  303. if (NT_SUCCESS(status))
  304. {
  305. (NTSTATUS)NtOpenThreadToken(hThread, TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, FALSE, &hToken);
  306. TSTATUS(NtClose(hThread));
  307. }
  308. if (hToken == NULL)
  309. {
  310. HANDLE hProcess;
  311. clientID.UniqueProcess = GetUniqueProcess();
  312. clientID.UniqueThread = NULL;
  313. status = NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION, &objectAttributes, &clientID);
  314. if (NT_SUCCESS(status))
  315. {
  316. (NTSTATUS)NtOpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, &hToken);
  317. }
  318. TSTATUS(NtClose(hProcess));
  319. }
  320. return(status);
  321. }