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.

179 lines
5.5 KiB

  1. #define NOTRACE 1
  2. #include "windows.h"
  3. #include "util.h"
  4. #include "faultrep.h"
  5. #include "pchrexec.h"
  6. #include "stdio.h"
  7. #include "stdlib.h"
  8. // ***************************************************************************
  9. LPWSTR MarshallString(LPCWSTR wszSrc, PBYTE pBase, ULONG cbMaxBuf,
  10. PBYTE *ppToWrite, DWORD *pcbWritten)
  11. {
  12. DWORD cb;
  13. PBYTE pwszNormalized;
  14. cb = (wcslen(wszSrc) + 1) * sizeof(WCHAR);
  15. if ((*pcbWritten + cb) > cbMaxBuf)
  16. return NULL;
  17. RtlMoveMemory(*ppToWrite, wszSrc, cb);
  18. // the normalized ptr is the current count
  19. pwszNormalized = (PBYTE)(*ppToWrite - pBase);
  20. // cb is always a mutliple of sizeof(WHCAR) so the pointer addition below
  21. // always produces a result that is 2byte aligned (assuming the input was
  22. // 2byte aligned of course)
  23. *ppToWrite += cb;
  24. *pcbWritten += cb;
  25. return (LPWSTR)pwszNormalized;
  26. }
  27. // **************************************************************************
  28. EFaultRepRetVal PrepareUserManifest(LPWSTR wszExe, DWORD dwSession,
  29. DWORD dwProc, DWORD dwThread)
  30. {
  31. SPCHExecServDWRequest *pesdwreq = NULL;
  32. SPCHExecServDWReply *pesrep = NULL;
  33. EFaultRepRetVal frrvRet = frrvErrNoDW;
  34. HRESULT hr = NOERROR;
  35. DWORD cbReq, cbRead;
  36. WCHAR wszName[MAX_PATH];
  37. BYTE Buf[HANGREP_EXECSVC_BUF_SIZE], *pBuf;
  38. BYTE BufRep[HANGREP_EXECSVC_BUF_SIZE];
  39. VALIDATEPARM(hr, (wszExe == NULL));
  40. if (FAILED(hr))
  41. goto done;
  42. ZeroMemory(&Buf, sizeof(Buf));
  43. pesdwreq = (SPCHExecServDWRequest *)Buf;
  44. cbReq = ((sizeof(SPCHExecServDWRequest) * sizeof(WCHAR)) + sizeof(WCHAR) - 1) / sizeof(WCHAR);
  45. pBuf = Buf + cbReq;
  46. pesdwreq->cbESR = sizeof(SPCHExecServDWRequest);
  47. pesdwreq->pidReqProcess = dwProc;
  48. pesdwreq->thidFault = dwThread;
  49. pesdwreq->ulSessionId = dwSession;
  50. pesdwreq->pvFaultAddr = (UINT64)UnhandledExceptionFilter;
  51. #ifdef _WIN64
  52. pesdwreq->fIs64bit = TRUE;
  53. #else
  54. pesdwreq->fIs64bit = FALSE;
  55. #endif
  56. // marshal in the strings
  57. pesdwreq->wszExe = (UINT64)MarshallString(wszExe, Buf, sizeof(Buf), &pBuf,
  58. &cbReq);
  59. if (pesdwreq->wszExe == 0)
  60. goto done;
  61. pesdwreq->cbTotal = cbReq;
  62. // check and see if the system is shutting down. If so, CreateProcess is
  63. // gonna pop up some annoying UI that we can't get rid of, so we don't
  64. // want to call it if we know it's gonna happen.
  65. if (GetSystemMetrics(SM_SHUTTINGDOWN))
  66. goto done;
  67. // Send the buffer out to the server- wait at most 2m for this to
  68. // succeed. If it times out, bail.
  69. wcscpy(wszName, HANGREP_EXECSVC_DWPIPE);
  70. TESTBOOL(hr, CallNamedPipeW(wszName, Buf, cbReq, &BufRep, sizeof(BufRep),
  71. &cbRead, 120000));
  72. if (FAILED(hr))
  73. {
  74. // determine the error code that indicates whether we've timed out so
  75. // we can set the return code appropriately.
  76. goto done;
  77. }
  78. pesrep = (SPCHExecServDWReply *)BufRep;
  79. // did the call succeed?
  80. VALIDATEEXPR(hr, (pesrep->fRet == FALSE), Err2HR(pesrep->dwErr));
  81. if (FAILED(hr))
  82. {
  83. fprintf(stdout, "Named pipe call failed: 0x%08x\n", pesrep->dwErr);
  84. SetLastError(pesrep->dwErr);
  85. goto done;
  86. }
  87. else
  88. {
  89. fprintf(stdout, "Named pipe call success\n");
  90. }
  91. // gotta wait for DW to be done before we nuke the manifest file, but if
  92. // it hasn't parsed it in 5 minutes, something's wrong with it.
  93. if (WaitForSingleObject(pesrep->pi.hProcess, 300000) == WAIT_TIMEOUT)
  94. {
  95. frrvRet = frrvErrTimeout;
  96. }
  97. // we're only going to delete the files if DW has finished with them. Yes
  98. // this means we can leave stray files in the temp dir, but this is better
  99. // than having DW randomly fail while sending...
  100. else
  101. {
  102. if (pesrep->wszDump != 0)
  103. {
  104. if (pesrep->wszDump < cbRead &&
  105. pesrep->wszDump >= sizeof(SPCHExecServDWReply))
  106. pesrep->wszDump += (UINT64)pesrep;
  107. else
  108. pesrep->wszDump = 0;
  109. }
  110. if (pesrep->wszDump != 0)
  111. fprintf(stdout, "Dump file: %ls\n", pesrep->wszDump);
  112. if (pesrep->wszManifest != 0)
  113. {
  114. if (pesrep->wszManifest < cbRead &&
  115. pesrep->wszManifest >= sizeof(SPCHExecServDWReply))
  116. pesrep->wszManifest += (UINT64)pesrep;
  117. else
  118. pesrep->wszManifest = 0;
  119. }
  120. if (pesrep->wszManifest != 0)
  121. fprintf(stdout, "Manifest file: %ls\n", pesrep->wszDump);
  122. }
  123. CloseHandle(pesrep->pi.hProcess);
  124. CloseHandle(pesrep->pi.hThread);
  125. frrvRet = frrvOkManifest;
  126. SetLastError(0);
  127. done:
  128. return frrvRet;
  129. }
  130. // **************************************************************************
  131. void __cdecl wmain(int argc, WCHAR **argv)
  132. {
  133. DWORD dwPID;
  134. DWORD dwThID;
  135. DWORD dwSession;
  136. WCHAR *wszExe;
  137. if (argc < 4 || argc > 5)
  138. {
  139. fprintf(stdout, "Usage:\nmdpipe <exe name> <PID> <Thread ID> [<Session ID>]\n");
  140. return;
  141. }
  142. wszExe = argv[1];
  143. dwPID = _wtol(argv[2]);
  144. dwThID = _wtol(argv[3]);
  145. if (argc == 5)
  146. dwSession = _wtol(argv[4]);
  147. else
  148. ProcessIdToSessionId(GetCurrentProcessId(), &dwSession);
  149. PrepareUserManifest(wszExe, dwSession, dwPID, dwThID);
  150. }