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.

570 lines
13 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. ipc.cpp
  5. Abstract:
  6. Implements code that communicates with shimeng to get the debug spew.
  7. On xpsp1 and beyong we get the debug info spewed by OutputDebugString.
  8. On the older platforms we use named pipes to communicate with shimeng.
  9. Notes:
  10. Unicode only.
  11. History:
  12. 04/22/2002 maonis Created
  13. --*/
  14. #include "precomp.h"
  15. extern APPINFO g_ai;
  16. // These are the only types of objects we created.
  17. typedef enum _SHIMVIEW_OBJECT_TYPE
  18. {
  19. SHIMVIEW_EVENT = 0,
  20. SHIMVIEW_FILE_MAPPING,
  21. SHIMVIEW_NAMED_PIPE
  22. } SHIMVIEW_OBJECT_TYPE;
  23. //
  24. // Stuff we need for the new version.
  25. //
  26. #define SHIMVIEW_SPEW_LEN 2048
  27. #define DEBUG_SPEW_DATA_PREFIX "SHIMVIEW:"
  28. #define DEBUG_SPEW_DATA_PREFIX_LEN (sizeof(DEBUG_SPEW_DATA_PREFIX)/sizeof(CHAR) - 1)
  29. LPSTR g_pDebugSpew;
  30. HANDLE g_hReadyEvent;
  31. HANDLE g_hAckEvent;
  32. /*++
  33. Routine Description:
  34. Creates a security descriptor that gives Everyone read and write access
  35. to the object itself, ie, we don't include permissions like WRITE_OWNER
  36. or WRITE_DAC.
  37. The resulting security descriptor should be freed by the caller using
  38. free.
  39. Arguments:
  40. eObjectType - the object type.
  41. Return Value:
  42. NULL on failure, a valid security descriptor on success.
  43. --*/
  44. PSECURITY_DESCRIPTOR
  45. CreateShimViewSd(
  46. SHIMVIEW_OBJECT_TYPE eObjectType
  47. )
  48. {
  49. BOOL bIsSuccess = FALSE;
  50. PSID pWorldSid = NULL;
  51. PSECURITY_DESCRIPTOR pWorldSd = NULL;
  52. DWORD dwAclSize = 0;
  53. PACL pAcl = NULL;
  54. DWORD dwAccessMask = 0;
  55. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  56. if (!AllocateAndInitializeSid(&WorldSidAuthority,
  57. 1,
  58. SECURITY_WORLD_RID,
  59. 0, 0, 0, 0, 0, 0, 0,
  60. &pWorldSid)) {
  61. MessageBox(NULL, L"Failed to allocate a SID", L"Error!", MB_ICONERROR);
  62. goto cleanup;
  63. }
  64. dwAclSize =
  65. sizeof (ACL) +
  66. sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) +
  67. GetLengthSid(pWorldSid);
  68. pWorldSd = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize);
  69. if (pWorldSd == NULL) {
  70. MessageBox(
  71. NULL,
  72. L"Failed to allocate memory for the security descriptor",
  73. L"Error",
  74. MB_ICONERROR);
  75. goto cleanup;
  76. }
  77. pAcl = (PACL)((BYTE *)pWorldSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  78. if (!InitializeAcl(pAcl,
  79. dwAclSize,
  80. ACL_REVISION)) {
  81. MessageBox(
  82. NULL,
  83. L"Failed to allocate memory for the security descriptor",
  84. L"Error",
  85. MB_ICONERROR);
  86. goto cleanup;
  87. }
  88. switch (eObjectType) {
  89. case SHIMVIEW_EVENT:
  90. dwAccessMask = READ_CONTROL | SYNCHRONIZE | EVENT_MODIFY_STATE;
  91. break;
  92. case SHIMVIEW_FILE_MAPPING:
  93. dwAccessMask = FILE_MAP_READ | FILE_MAP_WRITE;
  94. break;
  95. case SHIMVIEW_NAMED_PIPE:
  96. dwAccessMask = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
  97. break;
  98. default:
  99. MessageBox(
  100. NULL,
  101. L"You specified an unknown object type to create the security descriptor",
  102. L"Error",
  103. MB_ICONERROR);
  104. goto cleanup;
  105. }
  106. if (!AddAccessAllowedAce(pAcl,
  107. ACL_REVISION,
  108. dwAccessMask,
  109. pWorldSid)) {
  110. MessageBox(
  111. NULL,
  112. L"Failed to add the ACE to the security descriptor",
  113. L"Error",
  114. MB_ICONERROR);
  115. goto cleanup;
  116. }
  117. if (!InitializeSecurityDescriptor(pWorldSd, SECURITY_DESCRIPTOR_REVISION) ||
  118. !SetSecurityDescriptorDacl(pWorldSd, TRUE, pAcl, FALSE)) {
  119. MessageBox(
  120. NULL,
  121. L"Failed to set the DACL for the security descriptor",
  122. L"Error",
  123. MB_ICONERROR);
  124. goto cleanup;
  125. }
  126. bIsSuccess = TRUE;
  127. cleanup:
  128. if (pWorldSid) {
  129. FreeSid(pWorldSid);
  130. }
  131. if (!bIsSuccess) {
  132. if (pWorldSd) {
  133. free(pWorldSd);
  134. pWorldSd = NULL;
  135. }
  136. }
  137. return pWorldSd;
  138. }
  139. void
  140. AddSpewW(
  141. LPCWSTR pwszBuffer
  142. )
  143. {
  144. WCHAR* pTemp = NULL;
  145. //
  146. // See if this is a new process notification.
  147. //
  148. pTemp = wcsstr(pwszBuffer, L"process");
  149. if (pTemp) {
  150. //
  151. // We got a new process notification.
  152. // See if any items are already in the list
  153. //
  154. if (ListView_GetItemCount(g_ai.hWndList)) {
  155. AddListViewItem(L"");
  156. }
  157. }
  158. AddListViewItem((LPWSTR)pwszBuffer);
  159. }
  160. void
  161. AddSpewA(
  162. LPCSTR pszBuffer
  163. )
  164. {
  165. int iChars = 0;
  166. LPWSTR pwszBuffer = NULL;
  167. iChars = MultiByteToWideChar(CP_ACP, 0, pszBuffer, -1, NULL, 0);
  168. if (iChars) {
  169. pwszBuffer = (LPWSTR)malloc(iChars * sizeof(WCHAR));
  170. if (pwszBuffer) {
  171. if (MultiByteToWideChar(CP_ACP, 0, pszBuffer, -1, pwszBuffer, iChars)) {
  172. pwszBuffer[iChars - 1] = 0;
  173. AddSpewW(pwszBuffer);
  174. }
  175. free(pwszBuffer);
  176. }
  177. }
  178. }
  179. /*++
  180. Routine Description:
  181. Thread callback responsible for receiving data from the client.
  182. Arguments:
  183. *pVoid - A handle to the pipe.
  184. Return Value:
  185. -1 on failure, 1 on success.
  186. --*/
  187. UINT
  188. InstanceThread(
  189. IN void* pVoid
  190. )
  191. {
  192. HANDLE hPipe;
  193. BOOL fSuccess = TRUE;
  194. DWORD cbBytesRead = 0;
  195. WCHAR wszBuffer[SHIMVIEW_SPEW_LEN];
  196. //
  197. // The pipe handle was passed as an argument.
  198. //
  199. hPipe = (HANDLE)pVoid;
  200. while (TRUE) {
  201. fSuccess = ReadFile(hPipe,
  202. wszBuffer,
  203. SHIMVIEW_SPEW_LEN * sizeof(WCHAR),
  204. &cbBytesRead,
  205. NULL);
  206. if (!fSuccess || cbBytesRead == 0) {
  207. break;
  208. }
  209. wszBuffer[cbBytesRead / sizeof(WCHAR)] = 0;
  210. AddSpewW(wszBuffer);
  211. }
  212. //
  213. // Flush the pipe to allow the client to read the pipe's contents
  214. // before disconnecting. Then disconnect the pipe, and close the
  215. // handle to this pipe instance.
  216. //
  217. FlushFileBuffers(hPipe);
  218. DisconnectNamedPipe(hPipe);
  219. CloseHandle(hPipe);
  220. return 1;
  221. }
  222. /*++
  223. Routine Description:
  224. Creates a pipe and listens for messages from the client.
  225. This code is modified from the pipe.cpp that was sd deleted.
  226. Arguments:
  227. None.
  228. Return Value:
  229. -1 on failure, 0 on success.
  230. --*/
  231. UINT
  232. CreatePipeAndWait()
  233. {
  234. HANDLE hPipe, hThread;
  235. BOOL fConnected = FALSE;
  236. while (g_ai.fMonitor) {
  237. //
  238. // Create the named pipe.
  239. //
  240. SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
  241. PSECURITY_DESCRIPTOR pSd = CreateShimViewSd(SHIMVIEW_NAMED_PIPE);
  242. if (pSd == NULL) {
  243. return -1;
  244. }
  245. sa.lpSecurityDescriptor = pSd;
  246. hPipe = CreateNamedPipe(PIPE_NAME, // pipe name
  247. PIPE_ACCESS_INBOUND, // read access
  248. PIPE_TYPE_MESSAGE | // message type pipe
  249. PIPE_READMODE_MESSAGE | // message-read mode
  250. PIPE_WAIT, // blocking mode
  251. PIPE_UNLIMITED_INSTANCES, // max. instances
  252. 0, // output buffer size
  253. SHIMVIEW_SPEW_LEN, // input buffer size
  254. 0, // client time-out
  255. &sa); // no security attribute
  256. free(pSd);
  257. if (INVALID_HANDLE_VALUE == hPipe) {
  258. return -1;
  259. }
  260. //
  261. // Wait for clients to connect.
  262. //
  263. fConnected = ConnectNamedPipe(hPipe, NULL) ?
  264. TRUE :
  265. (GetLastError() == ERROR_PIPE_CONNECTED);
  266. if (fConnected && g_ai.fMonitor) {
  267. hThread = (HANDLE)_beginthreadex(NULL,
  268. 0,
  269. &InstanceThread,
  270. (LPVOID)hPipe,
  271. 0,
  272. &g_ai.uInstThreadId);
  273. if (INVALID_HANDLE_VALUE == hThread) {
  274. return -1;
  275. } else {
  276. CloseHandle(hThread);
  277. }
  278. } else {
  279. CloseHandle(hPipe);
  280. }
  281. }
  282. return 0;
  283. }
  284. /*++
  285. Routine Description:
  286. Waits for the spew from OutputDebugString and add it to the listview.
  287. Code is modified from the dbmon source.
  288. Arguments:
  289. None.
  290. Return Value:
  291. -1 on failure, 0 on success.
  292. --*/
  293. UINT
  294. GetOutputDebugStringSpew()
  295. {
  296. DWORD dwRet;
  297. while (TRUE) {
  298. dwRet = WaitForSingleObject(g_hReadyEvent, INFINITE);
  299. if (dwRet != WAIT_OBJECT_0) {
  300. return -1;
  301. } else {
  302. if (g_ai.fMonitor &&
  303. !strncmp(g_pDebugSpew,
  304. DEBUG_SPEW_DATA_PREFIX,
  305. DEBUG_SPEW_DATA_PREFIX_LEN)) {
  306. //
  307. // Only add when it came from shimeng.
  308. //
  309. AddSpewA(g_pDebugSpew + DEBUG_SPEW_DATA_PREFIX_LEN);
  310. }
  311. SetEvent(g_hAckEvent);
  312. }
  313. }
  314. return 0;
  315. }
  316. /*++
  317. Routine Description:
  318. Creates the necessary objects to get the spew from OutputDebugString.
  319. Code is modified from the dbmon source.
  320. Arguments:
  321. None.
  322. Return Value:
  323. FALSE on failure, TRUE on success.
  324. --*/
  325. BOOL
  326. CreateDebugObjects(
  327. void
  328. )
  329. {
  330. SECURITY_ATTRIBUTES saEvent = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
  331. SECURITY_ATTRIBUTES saFileMapping = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
  332. PSECURITY_DESCRIPTOR pSdEvent = NULL;
  333. PSECURITY_DESCRIPTOR pSdFileMapping = NULL;
  334. HANDLE hSharedFile;
  335. LPVOID pSharedMem;
  336. BOOL bReturn = FALSE;
  337. pSdEvent = CreateShimViewSd(SHIMVIEW_EVENT);
  338. if (pSdEvent == NULL) {
  339. goto cleanup;
  340. }
  341. pSdFileMapping = CreateShimViewSd(SHIMVIEW_FILE_MAPPING);
  342. if (pSdFileMapping == NULL) {
  343. goto cleanup;
  344. }
  345. saEvent.lpSecurityDescriptor = pSdEvent;
  346. saFileMapping.lpSecurityDescriptor = pSdFileMapping;
  347. g_hAckEvent = CreateEvent(&saEvent, FALSE, FALSE, L"DBWIN_BUFFER_READY");
  348. if (g_hAckEvent == NULL) {
  349. goto cleanup;
  350. }
  351. g_hReadyEvent = CreateEvent(&saEvent, FALSE, FALSE, L"DBWIN_DATA_READY");
  352. if (g_hReadyEvent == NULL) {
  353. goto cleanup;
  354. }
  355. hSharedFile = CreateFileMapping((HANDLE)-1,
  356. &saFileMapping,
  357. PAGE_READWRITE,
  358. 0,
  359. 4096,
  360. L"DBWIN_BUFFER");
  361. if (hSharedFile == NULL) {
  362. goto cleanup;
  363. }
  364. pSharedMem = MapViewOfFile(hSharedFile,
  365. FILE_MAP_READ,
  366. 0,
  367. 0,
  368. 512);
  369. if (pSharedMem == NULL) {
  370. goto cleanup;
  371. }
  372. g_pDebugSpew = (LPSTR)pSharedMem + sizeof(DWORD);
  373. SetEvent(g_hAckEvent);
  374. bReturn = TRUE;
  375. cleanup:
  376. if (pSdEvent) {
  377. free(pSdEvent);
  378. }
  379. if (pSdFileMapping) {
  380. free(pSdFileMapping);
  381. }
  382. return bReturn;
  383. }
  384. UINT
  385. GetSpewProc(
  386. IN void* pVoid
  387. )
  388. {
  389. if (g_ai.bUsingNewShimEng) {
  390. return GetOutputDebugStringSpew();
  391. } else {
  392. return CreatePipeAndWait();
  393. }
  394. }
  395. /*++
  396. Routine Description:
  397. Check the version of the OS - for 5.2 and beyong shimeng outputs debug spew via
  398. OutputDebugString. For OS version < 5.2 it writes to the named pipe.
  399. Arguments:
  400. None.
  401. Return Value:
  402. TRUE on success, FALSE otherwise.
  403. --*/
  404. BOOL
  405. CreateReceiveThread(
  406. void
  407. )
  408. {
  409. HANDLE hThread;
  410. hThread = (HANDLE)_beginthreadex(NULL,
  411. 0,
  412. &GetSpewProc,
  413. NULL,
  414. 0,
  415. &g_ai.uThreadId);
  416. CloseHandle(hThread);
  417. return TRUE;
  418. }