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.

1467 lines
47 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. faultrep.cpp
  5. Abstract:
  6. Implements kernel fault reporting
  7. Revision History:
  8. created derekm 07/07/00
  9. ******************************************************************************/
  10. #include "stdafx.h"
  11. #include "ntiodump.h"
  12. #include "userenv.h"
  13. #include <setupapi.h>
  14. ///////////////////////////////////////////////////////////////////////////////
  15. // utilities
  16. #define ARRAYSIZE(sz) (sizeof(sz)/sizeof(sz[0]))
  17. #define WRITE_CWSZ(hr, hFile, wsz, cb) \
  18. TESTBOOL(hr, WriteFile(hFile, wsz, sizeof(wsz) - sizeof(WCHAR), \
  19. &(cb), NULL)); \
  20. if (FAILED(hr)) goto done; else 0
  21. // **************************************************************************
  22. #ifndef _WIN64
  23. HRESULT ExtractBCInfo(LPCWSTR wszMiniDump, ULONG *pulBCCode, ULONG *pulBCP1,
  24. ULONG *pulBCP2, ULONG *pulBCP3, ULONG *pulBCP4)
  25. #else
  26. HRESULT ExtractBCInfo(LPCWSTR wszMiniDump, ULONG *pulBCCode, ULONG64 *pulBCP1,
  27. ULONG64 *pulBCP2, ULONG64 *pulBCP3, ULONG64 *pulBCP4)
  28. #endif
  29. {
  30. USE_TRACING("ExtractBCInfo");
  31. #ifndef _WIN64
  32. DUMP_HEADER32 *pdmp = NULL;
  33. #else
  34. DUMP_HEADER64 *pdmp = NULL;
  35. #endif
  36. HRESULT hr = NOERROR;
  37. DWORD dw;
  38. VALIDATEPARM(hr, (wszMiniDump == NULL || pulBCCode == NULL ||
  39. pulBCP1 == NULL || pulBCP2 == NULL || pulBCP3 == NULL ||
  40. pulBCP4 == NULL));
  41. if (FAILED(hr))
  42. {
  43. SetLastError(ERROR_INVALID_PARAMETER);
  44. goto done;
  45. }
  46. TESTHR(hr, OpenFileMapped((LPWSTR)wszMiniDump, (LPVOID *)&pdmp, &dw));
  47. if (FAILED(hr))
  48. goto done;
  49. // make sure the file is at least the appropriate # of bytes for a dump
  50. // header.
  51. // Then make sure it's the appropriate type of minidump cuz the code below
  52. // will only handle dumps for the platform it's compiled for (ia64 vs x86)
  53. #ifndef _WIN64
  54. if (dw < sizeof(DUMP_HEADER32) ||
  55. pdmp->Signature != DUMP_SIGNATURE32 ||
  56. pdmp->ValidDump != DUMP_VALID_DUMP32 ||
  57. #else
  58. if (dw < sizeof(DUMP_HEADER64) ||
  59. pdmp->Signature != DUMP_SIGNATURE64 ||
  60. pdmp->ValidDump != DUMP_VALID_DUMP64 ||
  61. #endif
  62. pdmp->DumpType != DUMP_TYPE_TRIAGE)
  63. {
  64. SetLastError(ERROR_INVALID_PARAMETER);
  65. hr = Err2HR(ERROR_INVALID_PARAMETER);
  66. goto done;
  67. }
  68. *pulBCCode = pdmp->BugCheckCode;
  69. *pulBCP1 = pdmp->BugCheckParameter1;
  70. *pulBCP2 = pdmp->BugCheckParameter2;
  71. *pulBCP3 = pdmp->BugCheckParameter3;
  72. *pulBCP4 = pdmp->BugCheckParameter4;
  73. done:
  74. dw = GetLastError();
  75. if (pdmp != NULL)
  76. UnmapViewOfFile(pdmp);
  77. SetLastError(dw);
  78. return hr;
  79. }
  80. // **************************************************************************
  81. DWORD XMLEncodeString(LPCWSTR wszSrc, LPWSTR wszDest, DWORD cchDest)
  82. {
  83. WCHAR *pwch = (WCHAR *)wszSrc;
  84. WCHAR *pwchDest = wszDest;
  85. DWORD cch = 0, cchNeed = 0;
  86. // determine how much space we need & if the buffer supports it
  87. for(; *pwch != L'\0'; pwch++)
  88. {
  89. switch(*pwch)
  90. {
  91. case L'&': cchNeed += 5; break;
  92. case L'>': // fall thru
  93. case L'<': cchNeed += 4; break;
  94. case L'\'': // fall thru
  95. case L'\"': cchNeed += 6; break;
  96. default: cchNeed += 1;
  97. }
  98. }
  99. if (cchNeed >= cchDest || cchNeed == 0)
  100. return 0;
  101. // do the conversion
  102. for(pwch = (WCHAR *)wszSrc; *pwch != L'\0'; pwch++)
  103. {
  104. switch(*pwch)
  105. {
  106. case L'&': wcscpy(pwchDest, L"&amp;"); pwchDest += 5; break;
  107. case L'>': wcscpy(pwchDest, L"&gt;"); pwchDest += 4; break;
  108. case L'<': wcscpy(pwchDest, L"&lt;"); pwchDest += 4; break;
  109. case L'\'': wcscpy(pwchDest, L"&apos;"); pwchDest += 6; break;
  110. case L'\"': wcscpy(pwchDest, L"&quot;"); pwchDest += 6; break;
  111. default: *pwchDest = *pwch; pwchDest += 1; break;
  112. }
  113. }
  114. *pwchDest = L'\0';
  115. return cchNeed;
  116. }
  117. // **************************************************************************
  118. HRESULT GetDevicePropertyW(HDEVINFO hDevInfo,
  119. PSP_DEVINFO_DATA pDevInfoData,
  120. ULONG ulProperty,
  121. ULONG ulRequiredType,
  122. PBYTE pData,
  123. ULONG ulDataSize)
  124. {
  125. ULONG ulPropType;
  126. USE_TRACING("GetDeviceProperty");
  127. // The data returned is often string data so leave some
  128. // extra room for forced termination.
  129. if (SetupDiGetDeviceRegistryPropertyW(hDevInfo,
  130. pDevInfoData,
  131. ulProperty,
  132. &ulPropType,
  133. pData,
  134. ulDataSize - 2 * sizeof(WCHAR),
  135. &ulDataSize))
  136. {
  137. // Got the data, verify the type.
  138. if (ulPropType != ulRequiredType)
  139. {
  140. return E_INVALIDARG;
  141. }
  142. // Force a double terminator at the end to make sure
  143. // that all strings and multistrings are terminated.
  144. ZeroMemory(pData + ulDataSize, 2 * sizeof(WCHAR));
  145. return S_OK;
  146. }
  147. else
  148. {
  149. return HRESULT_FROM_WIN32(GetLastError());
  150. }
  151. }
  152. // **************************************************************************
  153. struct DEVICE_DATA_STRINGS
  154. {
  155. //
  156. // The device description and service names have fixed
  157. // maximum lengths. The hardware ID data can be arbitrarily
  158. // large, however in practice it is rarely more than
  159. // a few hundred characters. We just make
  160. // a single allocation with nice roomy buffers and
  161. // use that for every device rather than doing allocations
  162. // per device.
  163. //
  164. WCHAR wszDeviceDesc[LINE_LEN];
  165. WCHAR wszHardwareId[8192];
  166. WCHAR wszService[MAX_SERVICE_NAME_LEN];
  167. WCHAR wszServiceImage[MAX_PATH];
  168. // We only need the first string of the hardware ID multi-sz
  169. // so this translation temporary buffer doesn't need
  170. // to be as large as the whole multi-sz.
  171. WCHAR wszXml[1024];
  172. };
  173. HRESULT GetDeviceData(HANDLE hFile)
  174. {
  175. HRESULT hr;
  176. HDEVINFO hDevInfo;
  177. DEVICE_DATA_STRINGS* pStrings = NULL;
  178. SC_HANDLE hSCManager = NULL;
  179. USE_TRACING("GetDeviceData");
  180. hDevInfo = SetupDiGetClassDevsW(NULL, NULL, NULL, DIGCF_ALLCLASSES);
  181. if (hDevInfo == INVALID_HANDLE_VALUE)
  182. {
  183. return HRESULT_FROM_WIN32(GetLastError());
  184. }
  185. pStrings = (DEVICE_DATA_STRINGS*)MyAlloc(sizeof(*pStrings));
  186. if (!pStrings)
  187. {
  188. hr = E_OUTOFMEMORY;
  189. goto done;
  190. }
  191. SP_DEVINFO_DATA DevInfoData;
  192. ULONG ulDevIndex;
  193. ulDevIndex = 0;
  194. DevInfoData.cbSize = sizeof(DevInfoData);
  195. while (SetupDiEnumDeviceInfo(hDevInfo, ulDevIndex, &DevInfoData))
  196. {
  197. ULONG cb;
  198. //
  199. // If we can't get a required property for this device
  200. // we skip the device and continue on and try to
  201. // get as much device data as possible.
  202. //
  203. if (GetDevicePropertyW(hDevInfo, &DevInfoData,
  204. SPDRP_DEVICEDESC, REG_SZ,
  205. (PBYTE)pStrings->wszDeviceDesc,
  206. sizeof(pStrings->wszDeviceDesc)) == S_OK &&
  207. GetDevicePropertyW(hDevInfo, &DevInfoData,
  208. SPDRP_HARDWAREID, REG_MULTI_SZ,
  209. (PBYTE)pStrings->wszHardwareId,
  210. sizeof(pStrings->wszHardwareId)) == S_OK)
  211. {
  212. PWSTR pwszStr;
  213. ULONG cbOut;
  214. // Default to no service image name.
  215. pStrings->wszServiceImage[0] = 0;
  216. // The Service property is optional.
  217. if (GetDevicePropertyW(hDevInfo, &DevInfoData,
  218. SPDRP_SERVICE, REG_SZ,
  219. (PBYTE)pStrings->wszService,
  220. sizeof(pStrings->wszService)) != S_OK)
  221. {
  222. pStrings->wszService[0] = 0;
  223. }
  224. else
  225. {
  226. SC_HANDLE hService;
  227. LPQUERY_SERVICE_CONFIGW lpqscBuf;
  228. DWORD dwBytes;
  229. //
  230. // If we found the service, open it, and retrieve the image
  231. // name so we can map to the drivers list in the XML.
  232. //
  233. if (hSCManager == NULL)
  234. {
  235. hSCManager = OpenSCManagerW(NULL, NULL,
  236. SC_MANAGER_ENUMERATE_SERVICE);
  237. }
  238. if (hSCManager != NULL)
  239. {
  240. hService = OpenServiceW(hSCManager, pStrings->wszService,
  241. SERVICE_QUERY_CONFIG);
  242. if (hService != NULL)
  243. {
  244. #define SERVICE_CONFIG_QUERY_SIZE 8192
  245. lpqscBuf = (LPQUERY_SERVICE_CONFIGW)
  246. MyAlloc(SERVICE_CONFIG_QUERY_SIZE);
  247. if (lpqscBuf != NULL)
  248. {
  249. if (QueryServiceConfigW(hService, lpqscBuf,
  250. SERVICE_CONFIG_QUERY_SIZE,
  251. &dwBytes))
  252. {
  253. WCHAR *wcpBuf;
  254. //
  255. // Remove the path information and just store
  256. // the image name.
  257. //
  258. wcpBuf =
  259. wcsrchr(lpqscBuf->lpBinaryPathName, '\\');
  260. if (wcpBuf)
  261. {
  262. wcscpy(pStrings->wszServiceImage,
  263. wcpBuf + 1);
  264. }
  265. else
  266. {
  267. wcscpy(pStrings->wszServiceImage,
  268. lpqscBuf->lpBinaryPathName);
  269. }
  270. }
  271. MyFree(lpqscBuf);
  272. }
  273. CloseServiceHandle(hService);
  274. }
  275. }
  276. }
  277. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevice, cb);
  278. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevDesc, cb);
  279. cbOut = XMLEncodeString(pStrings->wszDeviceDesc,
  280. pStrings->wszXml,
  281. sizeofSTRW(pStrings->wszXml));
  282. cbOut *= sizeof(WCHAR);
  283. TESTBOOL(hr, WriteFile(hFile, pStrings->wszXml, cbOut, &cb, NULL));
  284. if (FAILED(hr))
  285. {
  286. goto done;
  287. }
  288. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevDesc, cb);
  289. //
  290. // The hardware ID is a multistring but we
  291. // only need the first string.
  292. //
  293. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevHwId, cb);
  294. cbOut = XMLEncodeString(pStrings->wszHardwareId,
  295. pStrings->wszXml,
  296. sizeofSTRW(pStrings->wszXml));
  297. cbOut *= sizeof(WCHAR);
  298. TESTBOOL(hr, WriteFile(hFile, pStrings->wszXml, cbOut, &cb, NULL));
  299. if (FAILED(hr))
  300. {
  301. goto done;
  302. }
  303. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevHwId, cb);
  304. if (pStrings->wszService[0])
  305. {
  306. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevService, cb);
  307. cbOut = XMLEncodeString(pStrings->wszService,
  308. pStrings->wszXml,
  309. sizeofSTRW(pStrings->wszXml));
  310. cbOut *= sizeof(WCHAR);
  311. TESTBOOL(hr, WriteFile(hFile, pStrings->wszXml, cbOut,
  312. &cb, NULL));
  313. if (FAILED(hr))
  314. {
  315. goto done;
  316. }
  317. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevService, cb);
  318. }
  319. if (pStrings->wszServiceImage[0])
  320. {
  321. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevImage, cb);
  322. cbOut = XMLEncodeString(pStrings->wszServiceImage,
  323. pStrings->wszXml,
  324. sizeofSTRW(pStrings->wszXml));
  325. cbOut *= sizeof(WCHAR);
  326. TESTBOOL(hr, WriteFile(hFile, pStrings->wszXml, cbOut,
  327. &cb, NULL));
  328. if (FAILED(hr))
  329. {
  330. goto done;
  331. }
  332. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevImage, cb);
  333. }
  334. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevice, cb);
  335. }
  336. ulDevIndex++;
  337. }
  338. hr = S_OK;
  339. done:
  340. SetupDiDestroyDeviceInfoList(hDevInfo);
  341. if (pStrings)
  342. {
  343. MyFree(pStrings);
  344. }
  345. if (hSCManager)
  346. {
  347. CloseServiceHandle(hSCManager);
  348. }
  349. return hr;
  350. }
  351. // **************************************************************************
  352. HRESULT WriteDriverRecord(HANDLE hFile, LPWSTR wszFile)
  353. {
  354. WIN32_FILE_ATTRIBUTE_DATA w32fad;
  355. SYSTEMTIME st;
  356. HRESULT hr = NOERROR;
  357. LPWSTR pwszFileName;
  358. DWORD cb, cbOut;
  359. WCHAR wsz[1025], wszVer[MAX_PATH], wszCompany[MAX_PATH];
  360. WCHAR wszName[MAX_PATH];
  361. USE_TRACING("WriteDriverRecord");
  362. TESTBOOL(hr, GetFileAttributesExW(wszFile, GetFileExInfoStandard,
  363. (LPVOID *)&w32fad));
  364. if (FAILED(hr))
  365. goto done;
  366. // <DRIVER>
  367. // <FILENAME>...
  368. TESTBOOL(hr, WriteFile(hFile, c_wszXMLDriver1,
  369. sizeof(c_wszXMLDriver1) - sizeof(WCHAR), &cb, NULL));
  370. if (FAILED(hr))
  371. goto done;
  372. // ...[filename data]...
  373. for(pwszFileName = wszFile + wcslen(wszFile);
  374. *pwszFileName != L'\\' && pwszFileName > wszFile;
  375. pwszFileName--);
  376. if (*pwszFileName == L'\\')
  377. pwszFileName++;
  378. wsz[0] = L'\0';
  379. cbOut = XMLEncodeString(pwszFileName, wsz, sizeofSTRW(wsz));
  380. cbOut *= sizeof(WCHAR);
  381. TESTBOOL(hr, WriteFile(hFile, wsz, cbOut, &cb, NULL));
  382. if (FAILED(hr))
  383. goto done;
  384. // ...</FILENAME>
  385. // <FILESIZE>[file size data]</FILESIZE>
  386. // <CREATIONDATE>MM-DD-YYYY HH:MM:SS</CREATIONDATE>
  387. // <VERSION>...
  388. FileTimeToSystemTime(&w32fad.ftCreationTime, &st);
  389. cbOut = swprintf(wsz, c_wszXMLDriver2, w32fad.nFileSizeLow, st.wMonth,
  390. st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);
  391. cbOut *= sizeof(WCHAR);
  392. TESTBOOL(hr, WriteFile(hFile, wsz, cbOut, &cb, NULL));
  393. if (FAILED(hr))
  394. goto done;
  395. wsz[0] = L'\0';
  396. TESTHR(hr, GetVerName(wszFile, wszName, sizeofSTRW(wszName),
  397. wszVer, sizeofSTRW(wszVer),
  398. wszCompany, sizeofSTRW(wszCompany), TRUE, TRUE));
  399. if (FAILED(hr))
  400. goto done;
  401. wszCompany[sizeofSTRW(wszCompany) - 1] = L'\0';
  402. wszName[sizeofSTRW(wszName) - 1] = L'\0';
  403. wszVer[sizeofSTRW(wszVer) - 1] = L'\0';
  404. // ...[version data]...
  405. wsz[0] = L'\0';
  406. cbOut = XMLEncodeString(wszVer, wsz, sizeofSTRW(wsz));
  407. cbOut *= sizeof(WCHAR);
  408. TESTBOOL(hr, WriteFile(hFile, wsz, cbOut, &cb, NULL));
  409. if (FAILED(hr))
  410. goto done;
  411. // ...</VERSION>
  412. // <MANUFACTURER>...
  413. TESTBOOL(hr, WriteFile(hFile, c_wszXMLDriver3,
  414. sizeof(c_wszXMLDriver3) - sizeof(WCHAR), &cb, NULL));
  415. if (FAILED(hr))
  416. goto done;
  417. // ...[manufacturer data]...
  418. wsz[0] = L'\0';
  419. cbOut = XMLEncodeString(wszCompany, wsz, sizeofSTRW(wsz));
  420. cbOut *= sizeof(WCHAR);
  421. TESTBOOL(hr, WriteFile(hFile, wsz, cbOut, &cb, NULL));
  422. if (FAILED(hr))
  423. goto done;
  424. // ...</MANUFACTURER>
  425. // <PRODUCTNAME>...
  426. TESTBOOL(hr, WriteFile(hFile, c_wszXMLDriver4,
  427. sizeof(c_wszXMLDriver4) - sizeof(WCHAR), &cb, NULL));
  428. if (FAILED(hr))
  429. goto done;
  430. // ...[product name data]...
  431. wsz[0] = L'\0';
  432. cbOut = XMLEncodeString(wszName, wsz, sizeofSTRW(wsz));
  433. cbOut *= sizeof(WCHAR);
  434. TESTBOOL(hr, WriteFile(hFile, wsz, cbOut, &cb, NULL));
  435. if (FAILED(hr))
  436. goto done;
  437. // ...</PRODUCTNAME>
  438. // <DRIVER>
  439. TESTBOOL(hr, WriteFile(hFile, c_wszXMLDriver5,
  440. sizeof(c_wszXMLDriver5) - sizeof(WCHAR), &cb, NULL));
  441. if (FAILED(hr))
  442. goto done;
  443. done:
  444. return hr;
  445. }
  446. // **************************************************************************
  447. void GrovelDriverDir(HANDLE hFile, LPWSTR wszDrivers)
  448. {
  449. WIN32_FIND_DATAW wfd;
  450. HRESULT hr = NOERROR;
  451. HANDLE hFind = INVALID_HANDLE_VALUE;
  452. WCHAR *wszFind, *pwszFind;
  453. DWORD cchNeed;
  454. USE_TRACING("GrovelDriverDir");
  455. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE || wszDrivers == NULL)
  456. return;
  457. cchNeed = wcslen(wszDrivers) + MAX_PATH + 2;
  458. __try { wszFind = (LPWSTR)_alloca(cchNeed * sizeof(WCHAR)); }
  459. __except(EXCEPTION_STACK_OVERFLOW) { wszFind = NULL; }
  460. if (wszFind == NULL)
  461. goto done;
  462. wcscpy(wszFind, wszDrivers);
  463. wcscat(wszFind, L"\\*");
  464. pwszFind = wszFind + wcslen(wszFind) - 1;
  465. // add the driver info to the file
  466. ZeroMemory(&wfd, sizeof(wfd));
  467. hFind = FindFirstFileW(wszFind, &wfd);
  468. if (hFind != NULL)
  469. {
  470. do
  471. {
  472. if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 &&
  473. wcslen(wfd.cFileName) < MAX_PATH)
  474. {
  475. wcscpy(pwszFind, wfd.cFileName);
  476. TESTHR(hr, WriteDriverRecord(hFile, wszFind));
  477. if (FAILED(hr))
  478. goto done;
  479. }
  480. }
  481. while(FindNextFileW(hFind, &wfd));
  482. }
  483. done:
  484. if (hFind != INVALID_HANDLE_VALUE)
  485. FindClose(hFind);
  486. }
  487. // **************************************************************************
  488. HRESULT GetDriverData(HANDLE hFile)
  489. {
  490. FILETIME ft;
  491. HRESULT hr = NOERROR;
  492. LPWSTR wszKey = NULL;
  493. DWORD iKey, dw, cchKeyMax, dwSvcType, cb, cchNeed, cchSysDir, cch;
  494. WCHAR wszSvcPath[1024], *pwszSysDir, *pwszFile;
  495. HKEY hkeySvc = NULL, hkey = NULL;
  496. USE_TRACING("GetDriverData");
  497. VALIDATEPARM(hr, (hFile == NULL));
  498. if (FAILED(hr))
  499. goto done;
  500. cchNeed = GetSystemDirectoryW(NULL, 0);
  501. if (cchNeed == 0)
  502. goto done;
  503. // according to MSDN, a service name can not be longer than 256 chars
  504. cchNeed += 32;
  505. __try { pwszSysDir = (LPWSTR)_alloca(cchNeed * sizeof(WCHAR)); }
  506. __except(EXCEPTION_STACK_OVERFLOW) { pwszSysDir = NULL; }
  507. if (pwszSysDir == NULL)
  508. {
  509. SetLastError(ERROR_OUTOFMEMORY);
  510. goto done;
  511. }
  512. cchSysDir = GetSystemDirectoryW(pwszSysDir, cchNeed);
  513. if (cchSysDir == 0)
  514. goto done;
  515. if (pwszSysDir[cchSysDir - 1] != L'\\')
  516. {
  517. pwszSysDir[cchSysDir++] = L'\\';
  518. pwszSysDir[cchSysDir] = L'\0';
  519. }
  520. wcscpy(&pwszSysDir[cchSysDir], L"drivers");
  521. cchSysDir += sizeofSTRW(L"drivers");
  522. // get all the drivers that live in the default drivers directory
  523. GrovelDriverDir(hFile, pwszSysDir);
  524. // start grovelling the registry
  525. TESTERR(hr, RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRPSvc, 0, KEY_READ,
  526. &hkeySvc));
  527. if (FAILED(hr))
  528. goto done;
  529. TESTERR(hr, RegQueryInfoKey(hkeySvc, NULL, NULL, NULL, NULL, &cchKeyMax,
  530. NULL, NULL, NULL, NULL, NULL, NULL));
  531. if (FAILED(hr) || cchKeyMax == 0)
  532. goto done;
  533. cchKeyMax += 8;
  534. __try { wszKey = (LPWSTR)_alloca(cchKeyMax * sizeof(WCHAR)); }
  535. __except(EXCEPTION_STACK_OVERFLOW) { wszKey = NULL; }
  536. if (wszKey == NULL)
  537. {
  538. SetLastError(ERROR_OUTOFMEMORY);
  539. hr = E_OUTOFMEMORY;
  540. goto done;
  541. }
  542. // loop thru the services reg key & extract out all the driver entries
  543. for(iKey = 0; ; iKey++)
  544. {
  545. cch = cchKeyMax;
  546. TESTERR(hr, RegEnumKeyExW(hkeySvc, iKey, wszKey, &cch, NULL, NULL,
  547. NULL, &ft));
  548. if (FAILED(hr))
  549. {
  550. if (hr == Err2HR(ERROR_NO_MORE_ITEMS))
  551. break;
  552. else if (hr == Err2HR(ERROR_MORE_DATA))
  553. continue;
  554. else
  555. goto done;
  556. }
  557. TESTERR(hr, RegOpenKeyExW(hkeySvc, wszKey, 0, KEY_READ, &hkey));
  558. if (FAILED(hr))
  559. continue;
  560. cb = sizeof(dwSvcType);
  561. TESTERR(hr, RegQueryValueExW(hkey, c_wszRVSvcType, NULL, NULL,
  562. (LPBYTE)&dwSvcType, &cb));
  563. if (FAILED(hr))
  564. goto doneLoop;
  565. // only care about drivers
  566. if ((dwSvcType & SERVICE_DRIVER) == 0)
  567. goto doneLoop;
  568. // get the ImagePath to the driver. If none is present, then create
  569. // the following path: "%windir%\system32\drivers\<name>.sys" because
  570. // that's what the OS does if no ImagePath field is present.
  571. cb = sizeof(wszSvcPath);
  572. dw = RegQueryValueExW(hkey, c_wszRVSvcPath, NULL, NULL,
  573. (LPBYTE)wszSvcPath, &cb);
  574. if (dw != ERROR_SUCCESS)
  575. {
  576. hr = Err2HR(dw);
  577. goto doneLoop;
  578. }
  579. // don't want to gather the info if we already did above, so check if
  580. // the file lives in the drivers directory
  581. for(pwszFile = wszSvcPath + wcslen(wszSvcPath);
  582. *pwszFile != L'\\' && pwszFile > wszSvcPath;
  583. pwszFile--);
  584. if (*pwszFile != L'\\')
  585. goto doneLoop;
  586. *pwszFile = L'\0';
  587. if (_wcsicmp(pwszSysDir, wszSvcPath) == 0)
  588. goto doneLoop;
  589. // make sure we have a full path
  590. if ((wszSvcPath[0] != L'\\' || wszSvcPath[1] != L'\\') &&
  591. (wszSvcPath[1] != L':' || wszSvcPath[2] != L'\\'))
  592. goto doneLoop;
  593. *pwszFile = L'\\';
  594. // do the actual writing of the info.
  595. TESTHR(hr, WriteDriverRecord(hFile, wszSvcPath));
  596. if (FAILED(hr))
  597. goto done;
  598. doneLoop:
  599. if (hkey != NULL)
  600. {
  601. RegCloseKey(hkey);
  602. hkey = NULL;
  603. }
  604. }
  605. hr = NOERROR;
  606. done:
  607. if (hkeySvc != NULL)
  608. RegCloseKey(hkeySvc);
  609. if (hkey != NULL)
  610. RegCloseKey(hkey);
  611. return hr;
  612. }
  613. // **************************************************************************
  614. HRESULT GetExtraReportInfo(LPCWSTR wszFile, OSVERSIONINFOEXW &osvi)
  615. {
  616. WIN32_FIND_DATAW wfd;
  617. HRESULT hr = NOERROR;
  618. HANDLE hFile = INVALID_HANDLE_VALUE;
  619. WCHAR wszFind[MAX_PATH], *pwszFind, *pwsz;
  620. WCHAR wszBuf[1025], *pwszProd;
  621. WCHAR wszSku[200];
  622. WCHAR cchEmpty = L'\0';
  623. DWORD cb, cbOut, cch, cchNeed;
  624. HKEY hkey = NULL;
  625. USE_TRACING("GetExtraReportInfo");
  626. VALIDATEPARM(hr, (wszFile == NULL));
  627. if (FAILED(hr))
  628. {
  629. SetLastError(ERROR_INVALID_PARAMETER);
  630. goto done;
  631. }
  632. // create the file
  633. hFile = CreateFileW(wszFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0,
  634. NULL);
  635. TESTBOOL(hr, (hFile != INVALID_HANDLE_VALUE));
  636. if (FAILED(hr))
  637. goto done;
  638. // determine the SKU
  639. wszSku[0]=0;
  640. // we could have an embedded srv or wks installation here...
  641. if ((osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) != 0)
  642. wcscat(wszSku, L"Embedded ");
  643. if (osvi.wProductType == VER_NT_WORKSTATION)
  644. {
  645. if ((osvi.wSuiteMask & VER_SUITE_PERSONAL) != 0)
  646. wcscat(wszSku, L"Home Edition");
  647. else
  648. wcscat(wszSku, L"Professional");
  649. }
  650. else
  651. {
  652. if ((osvi.wSuiteMask & VER_SUITE_DATACENTER) != 0)
  653. wcscat(wszSku, L"DataCenter Server");
  654. else if ((osvi.wSuiteMask & VER_SUITE_ENTERPRISE) != 0)
  655. wcscat(wszSku, L"Advanced Server");
  656. else if ((osvi.wSuiteMask & VER_SUITE_BLADE) != 0)
  657. wcscat(wszSku, L"Web Server");
  658. else if ((osvi.wSuiteMask & VER_SUITE_BACKOFFICE) != 0)
  659. wcscat(wszSku, L"Back Office Server");
  660. else if ((osvi.wSuiteMask & VER_SUITE_SMALLBUSINESS) != 0)
  661. wcscat(wszSku, L"Small Business Server");
  662. else if ((osvi.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED) != 0)
  663. wcscat(wszSku, L"Small Business Server (restricted)");
  664. else if ((osvi.wSuiteMask & VER_SUITE_COMMUNICATIONS) != 0)
  665. wcscat(wszSku, L"Communications Server");
  666. else
  667. wcscat(wszSku, L"Server");
  668. }
  669. // fetch the product ID from the registry
  670. pwszProd = &cchEmpty;
  671. TESTHR(hr, OpenRegKey(HKEY_LOCAL_MACHINE, c_wszRKWNTCurVer, FALSE, &hkey));
  672. if (SUCCEEDED(hr))
  673. {
  674. cb = sizeofSTRW(wszBuf);
  675. TESTHR(hr, ReadRegEntry(hkey, c_wszRVProdName, NULL, (LPBYTE)wszBuf,
  676. &cb, NULL, 0));
  677. if (SUCCEEDED(hr))
  678. {
  679. cb = wcslen(wszBuf) * sizeof(WCHAR) * 6 + sizeof(WCHAR);
  680. __try { pwszProd = (WCHAR *)_alloca(cb); }
  681. __except(EXCEPTION_STACK_OVERFLOW) { pwszProd = NULL; }
  682. if (pwszProd == NULL)
  683. goto done;
  684. XMLEncodeString(wszBuf, pwszProd, cb / sizeof(WCHAR));
  685. }
  686. else
  687. {
  688. pwszProd = &cchEmpty;
  689. }
  690. RegCloseKey(hkey);
  691. hkey = NULL;
  692. }
  693. // <SYSTEMINFO>
  694. // <SYSTEM>
  695. // <OSNAME>[os product name] [os sku name]</OSNAME>
  696. // <OSVER>[major.minor.build SPmajor.SPminor]</OSVER>
  697. // <OSLANGUAGE>[system LCID]</OSLANGUAGE>
  698. wszBuf[0] = 0xfeff;
  699. cbOut = swprintf(wszBuf + 1, c_wszXMLHeader, pwszProd, wszSku,
  700. osvi.dwMajorVersion, osvi.dwMinorVersion,
  701. osvi.dwBuildNumber, osvi.wServicePackMajor,
  702. osvi.wServicePackMinor, GetSystemDefaultLangID());
  703. cbOut *= sizeof(WCHAR);
  704. TESTBOOL(hr, WriteFile(hFile, wszBuf, cbOut, &cb, NULL));
  705. if (FAILED(hr))
  706. goto done;
  707. WRITE_CWSZ(hr, hFile, c_wszXMLCloseSystem, cb);
  708. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDevices, cb);
  709. TESTHR(hr, GetDeviceData(hFile));
  710. WRITE_CWSZ(hr, hFile, c_wszXMLCloseDevices, cb);
  711. WRITE_CWSZ(hr, hFile, c_wszXMLOpenDrivers, cb);
  712. TESTHR(hr, GetDriverData(hFile));
  713. // </DRIVERS>
  714. // </SYSTEMINFO>
  715. WRITE_CWSZ(hr, hFile, c_wszXMLFooter, cb);
  716. done:
  717. if (hFile != INVALID_HANDLE_VALUE)
  718. CloseHandle(hFile);
  719. if (hkey != NULL)
  720. RegCloseKey(hkey);
  721. return hr;
  722. }
  723. // **************************************************************************
  724. BOOL DoImmediateEventReport(HANDLE hToken, EEventType eet)
  725. {
  726. USE_TRACING("DoImmediateEventReport");
  727. PROCESS_INFORMATION pi = { NULL, NULL, 0, 0 };
  728. STARTUPINFOW si;
  729. LPWSTR pwszSysDir, pwszCmdLine;
  730. LPVOID pvEnv = NULL;
  731. DWORD cch, cchNeed;
  732. BOOL fRet = FALSE;
  733. if (hToken == NULL ||
  734. (eet != eetKernelFault && eet != eetShutdown))
  735. {
  736. SetLastError(ERROR_INVALID_PARAMETER);
  737. goto done;
  738. }
  739. // get the system directory
  740. cch = GetSystemDirectoryW(NULL, 0);
  741. if (cch == 0)
  742. goto done;
  743. cch++;
  744. __try { pwszSysDir = (LPWSTR)_alloca(cch * sizeof(WCHAR)); }
  745. __except(EXCEPTION_STACK_OVERFLOW) { pwszSysDir = NULL; }
  746. if (pwszSysDir == NULL)
  747. {
  748. SetLastError(ERROR_OUTOFMEMORY);
  749. goto done;
  750. }
  751. cch = GetSystemDirectoryW(pwszSysDir, cch);
  752. if (cch == 0)
  753. goto done;
  754. if (*(pwszSysDir + cch - 1) == L'\\')
  755. *(pwszSysDir + cch - 1) = L'\0';
  756. // create the full command line
  757. cchNeed = cch + sizeofSTRW(c_wszKrnlCmdLine) + 1;
  758. __try { pwszCmdLine = (LPWSTR)_alloca(cchNeed * sizeof(WCHAR)); }
  759. __except(EXCEPTION_STACK_OVERFLOW) { pwszCmdLine = NULL; }
  760. if (pwszCmdLine == NULL)
  761. {
  762. SetLastError(ERROR_OUTOFMEMORY);
  763. goto done;
  764. }
  765. wcscpy(pwszCmdLine, pwszSysDir);
  766. if (eet == eetKernelFault)
  767. wcscat(pwszCmdLine, c_wszKrnlCmdLine);
  768. else
  769. wcscat(pwszCmdLine, c_wszShutCmdLine);
  770. // get the environment block for the user
  771. fRet = CreateEnvironmentBlock(&pvEnv, hToken, FALSE);
  772. if (fRet == FALSE)
  773. pvEnv = NULL;
  774. ZeroMemory(&si, sizeof(si));
  775. si.cb = sizeof(si);
  776. fRet = CreateProcessAsUserW(hToken, NULL, pwszCmdLine, NULL, NULL, FALSE,
  777. CREATE_UNICODE_ENVIRONMENT, pvEnv, pwszSysDir,
  778. &si, &pi);
  779. if (fRet)
  780. {
  781. if (pi.hProcess != NULL)
  782. CloseHandle(pi.hProcess);
  783. if (pi.hThread != NULL)
  784. CloseHandle(pi.hThread);
  785. }
  786. done:
  787. if (pvEnv != NULL)
  788. DestroyEnvironmentBlock(pvEnv);
  789. return fRet;
  790. }
  791. ///////////////////////////////////////////////////////////////////////////////
  792. // exported functions
  793. // **************************************************************************
  794. EFaultRepRetVal APIENTRY ReportEREvent(EEventType eet, LPCWSTR wszDump,
  795. SEventInfoW *pei)
  796. {
  797. USE_TRACING("ReportEREvent");
  798. CPFFaultClientCfg oCfg;
  799. EFaultRepRetVal frrvRet = frrvErrNoDW;
  800. HANDLE hFaultLog = INVALID_HANDLE_VALUE;
  801. DWORD dw;
  802. WCHAR wszDir[MAX_PATH];
  803. HKEY hkey = NULL;
  804. if ((eet != eetKernelFault && eet != eetShutdown && eet != eetUseEventInfo) ||
  805. (eet == eetUseEventInfo &&
  806. (pei == NULL || pei->wszTitle == NULL || pei->wszStage2 == NULL ||
  807. pei->wszEventName == NULL)) ||
  808. ((eet == eetKernelFault || eet == eetShutdown) && wszDump == NULL))
  809. {
  810. SetLastError(ERROR_INVALID_PARAMETER);
  811. goto done;
  812. }
  813. if (FAILED(oCfg.Read(eroPolicyRO)))
  814. goto done;
  815. if (oCfg.get_TextLog() == eedEnabled)
  816. {
  817. // assume system is on a local drive with a base path of "X:\"
  818. GetSystemDirectoryW(wszDir, sizeofSTRW(wszDir));
  819. wszDir[3] = L'\0';
  820. wcscat(wszDir, c_wszLogFileName);
  821. hFaultLog = CreateFileW(wszDir, GENERIC_WRITE,
  822. FILE_SHARE_WRITE | FILE_SHARE_READ,
  823. NULL, OPEN_ALWAYS, 0, NULL);
  824. if (hFaultLog != INVALID_HANDLE_VALUE)
  825. {
  826. SYSTEMTIME st;
  827. LPCWSTR wszEvent = NULL;
  828. DWORD cb, cbWritten;
  829. char szMsg[512];
  830. if (eet == eetUseEventInfo)
  831. wszEvent = pei->wszEventName;
  832. if (wszEvent == NULL)
  833. wszEvent = c_rgwszEvents[eet];
  834. if (wcslen(wszEvent) > MAX_PATH)
  835. wszEvent = c_wszUnknown;
  836. GetSystemTime(&st);
  837. cb = wsprintf(szMsg, "%02d-%02d-%04d %02d:%02d:%02d (notifying) %ls\r\n",
  838. st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute,
  839. st.wSecond, wszEvent);
  840. SetFilePointer(hFaultLog, 0, NULL, FILE_END);
  841. WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
  842. CloseHandle(hFaultLog);
  843. }
  844. wszDir[0] = L'\0';
  845. }
  846. // if we are in silent mode or are not reporting one of the two special
  847. // case items (kernel fault & unplanned shutdown), then just go ahead and
  848. // report directly
  849. if ((oCfg.get_ShowUI() == eedDisabled &&
  850. oCfg.get_DoReport() == eedEnabled) ||
  851. (eet != eetKernelFault && eet != eetShutdown))
  852. {
  853. frrvRet = ReportEREventDW(eet, wszDump, pei);
  854. }
  855. else
  856. {
  857. LPCWSTR wszRK = ((eet == eetShutdown) ? c_wszRKShut : c_wszRKKrnl);
  858. HANDLE hToken = NULL;
  859. DWORD dwSession;
  860. BOOL fFoundAdmin = FALSE;
  861. // create the fault key (if it isn't there) and add this one to the list
  862. dw = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wszRK, 0, NULL, 0,
  863. KEY_WRITE, NULL, &hkey, NULL);
  864. if (dw == ERROR_SUCCESS)
  865. {
  866. DWORD cbData;
  867. DWORD dwData;
  868. cbData = sizeof(dwData);
  869. dwData = 0;
  870. RegSetValueExW(hkey, wszDump, 0, REG_DWORD, (LPBYTE)&dwData,
  871. cbData);
  872. RegCloseKey(hkey);
  873. hkey = NULL;
  874. // no point in going on if we aren't priviledged cuz we won't be
  875. // able to launch processes or fetch the user token...
  876. if (AmIPrivileged(TRUE))
  877. fFoundAdmin = FindAdminSession(&dwSession, &hToken);
  878. if (fFoundAdmin)
  879. fFoundAdmin = DoImmediateEventReport(hToken, eet);
  880. // there is no admin logged on, so add the value to the run key
  881. if (fFoundAdmin == FALSE)
  882. {
  883. // create our value in the RunOnce key so that we can report the
  884. // next time someone logs in.
  885. dw = RegCreateKeyExW(HKEY_LOCAL_MACHINE, c_wszRKRun, 0, NULL, 0,
  886. KEY_WRITE, NULL, &hkey, NULL);
  887. if (dw == ERROR_SUCCESS)
  888. {
  889. LPCWSTR wszRV = NULL;
  890. LPCWSTR wszRVD = NULL;
  891. DWORD cbRVD = NULL;
  892. if (eet == eetShutdown)
  893. {
  894. wszRV = c_wszRVSEC;
  895. wszRVD = c_wszRVVSEC;
  896. cbRVD = sizeof(c_wszRVVSEC) - sizeof(WCHAR);
  897. }
  898. else
  899. {
  900. wszRV = c_wszRVKFC;
  901. wszRVD = c_wszRVVKFC;
  902. cbRVD = sizeof(c_wszRVVKFC) - sizeof(WCHAR);
  903. }
  904. RegSetValueExW(hkey, wszRV, 0, REG_EXPAND_SZ,
  905. (LPBYTE)wszRVD, cbRVD);
  906. RegCloseKey(hkey);
  907. }
  908. }
  909. }
  910. frrvRet = frrvOk;
  911. }
  912. done:
  913. return frrvRet;
  914. }
  915. // **************************************************************************
  916. EFaultRepRetVal APIENTRY ReportEREventDW(EEventType eet, LPCWSTR wszDump,
  917. SEventInfoW *pei)
  918. {
  919. USE_TRACING("ReportEREventDW");
  920. CPFFaultClientCfg oCfg;
  921. OSVERSIONINFOEXW ovi;
  922. EFaultRepRetVal frrvRet = frrvErrNoDW;
  923. SDWManifestBlob dwmb;
  924. HRESULT hr = NOERROR;
  925. LPWSTR wszFiles = NULL, pwszExtra = NULL, wszDir = NULL;
  926. LPWSTR wszManifest = NULL;
  927. DWORD dw, cch, cchDir, cchSep;
  928. WCHAR wszBuffer[1025];
  929. ULONG ulBCCode;
  930. BOOL fAllowSend = TRUE;
  931. HKEY hkey = NULL;
  932. #ifndef _WIN64
  933. ULONG ulBCP1, ulBCP2, ulBCP3, ulBCP4;
  934. #else
  935. ULONG64 ulBCP1, ulBCP2, ulBCP3, ulBCP4;
  936. #endif
  937. VALIDATEPARM(hr, ((eet != eetKernelFault && eet != eetShutdown && eet != eetUseEventInfo) ||
  938. (eet == eetUseEventInfo &&
  939. (pei == NULL || pei->wszTitle == NULL || pei->wszStage2 == NULL || 0 == wcslen(pei->wszStage2) ||
  940. pei->wszEventName == NULL || pei->cbSEI != sizeof(SEventInfoW))) ||
  941. ((eet == eetKernelFault || eet == eetShutdown) && wszDump == NULL)));
  942. if (FAILED(hr))
  943. {
  944. SetLastError(ERROR_INVALID_PARAMETER);
  945. goto done;
  946. }
  947. TESTHR(hr, oCfg.Read(eroPolicyRO));
  948. if (FAILED(hr))
  949. goto done;
  950. if (oCfg.get_TextLog() == eedEnabled)
  951. {
  952. HANDLE hFaultLog = INVALID_HANDLE_VALUE;
  953. // assume system is on a local drive with a base path of "X:\"
  954. GetSystemDirectoryW(wszBuffer, sizeofSTRW(wszBuffer));
  955. wszBuffer[3] = L'\0';
  956. wcscat(wszBuffer, c_wszLogFileName);
  957. hFaultLog = CreateFileW(wszBuffer, GENERIC_WRITE,
  958. FILE_SHARE_WRITE | FILE_SHARE_READ,
  959. NULL, OPEN_ALWAYS, 0, NULL);
  960. if (hFaultLog != INVALID_HANDLE_VALUE)
  961. {
  962. SYSTEMTIME st;
  963. LPCWSTR wszEvent = NULL;
  964. DWORD cb, cbWritten;
  965. char szMsg[512];
  966. if (eet == eetUseEventInfo)
  967. wszEvent = pei->wszEventName;
  968. if (wszEvent == NULL)
  969. wszEvent = c_rgwszEvents[eet];
  970. if (wcslen(wszEvent) > MAX_PATH)
  971. wszEvent = c_wszUnknown;
  972. GetSystemTime(&st);
  973. cb = wsprintf(szMsg, "%02d-%02d-%04d %02d:%02d:%02d (reporting) %ls\r\n",
  974. st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute,
  975. st.wSecond, wszEvent);
  976. SetFilePointer(hFaultLog, 0, NULL, FILE_END);
  977. WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
  978. CloseHandle(hFaultLog);
  979. }
  980. wszBuffer[0] = L'\0';
  981. }
  982. // if setup is in progress, we want to just bail cuz we don't want to hang
  983. // setup. Also, the network isn't setup so we can't really report anyway.
  984. // At some point, might want to cache this info & report on first launch.
  985. dw = RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRKSetup, 0, KEY_READ, &hkey);
  986. if (dw == ERROR_SUCCESS)
  987. {
  988. DWORD cbData;
  989. DWORD dwData;
  990. cbData = sizeof(dwData);
  991. dwData = 0;
  992. dw = RegQueryValueExW(hkey, c_wszRVSetupNow, NULL, NULL,
  993. (LPBYTE)&dwData, &cbData);
  994. RegCloseKey(hkey);
  995. if (dw == ERROR_SUCCESS && dwData != 0)
  996. {
  997. DBG_MSG("Setup in progress");
  998. goto done;
  999. }
  1000. }
  1001. if (oCfg.get_ShowUI() == eedDisabled)
  1002. {
  1003. LPCWSTR wszULPath = oCfg.get_DumpPath(NULL, 0);
  1004. DBG_MSG("ShowUI disabled");
  1005. // if we're disabled, then don't do anything at all. Still return the
  1006. // frrvErrNoDW so that the calling app can perform whatever default
  1007. // actions it wants to...
  1008. if (oCfg.get_DoReport() == eedDisabled)
  1009. {
  1010. DBG_MSG("DoReport disabled");
  1011. goto done;
  1012. }
  1013. // check and make sure that we have a corporate path specified. If we
  1014. // don't, bail
  1015. if (wszULPath == NULL || *wszULPath == L'\0')
  1016. {
  1017. DBG_MSG("no CER path found");
  1018. goto done;
  1019. }
  1020. #ifdef REAL_CER_FOR_CLIENT
  1021. //
  1022. // When kernel faults are reported by savedump at machine
  1023. // boot time it is possible that the full net infrastructure
  1024. // hasn't quite started by the time savedump calls to report.
  1025. // UNC path references can fail, causing spurious failures
  1026. // when in CER mode. Do a quick retry loop to check for
  1027. // such failures and allow time for the net code to start.
  1028. //
  1029. if (wszULPath[0] == L'\\' && wszULPath[1] == L'\\')
  1030. {
  1031. ULONG ulUncRetry = 30;
  1032. while (ulUncRetry-- > 0)
  1033. {
  1034. // Try to limit the errors for which we'll wait
  1035. // to the minimum set so that a plain bad path
  1036. // won't cause a delay.
  1037. if (GetFileAttributesW(wszULPath) != -1 ||
  1038. (GetLastError() != ERROR_NETWORK_UNREACHABLE &&
  1039. GetLastError() != ERROR_BAD_NETPATH))
  1040. {
  1041. break;
  1042. }
  1043. Sleep(1000);
  1044. }
  1045. // We do not panic and fail here if the path
  1046. // was inaccessible. Instead we let the normal
  1047. // failure path take care of things.
  1048. }
  1049. #endif REAL_CER_FOR_CLIENT
  1050. }
  1051. // if kernel reporting or general reporting is disabled, don't show the
  1052. // send button
  1053. if (oCfg.get_DoReport() == eedDisabled ||
  1054. (eet == eetKernelFault && oCfg.get_IncKernel() == eedDisabled) ||
  1055. (eet == eetShutdown && oCfg.get_IncShutdown() == eedDisabled))
  1056. fAllowSend = FALSE;
  1057. if (CreateTempDirAndFile(NULL, NULL, &wszDir) == 0)
  1058. goto done;
  1059. cchDir = wcslen(wszDir);
  1060. cch = cchDir + sizeofSTRW(c_wszManFileName) + 4;
  1061. __try { wszManifest = (LPWSTR)_alloca(cch * sizeof(WCHAR)); }
  1062. __except(EXCEPTION_STACK_OVERFLOW) { wszManifest = NULL; }
  1063. if (wszManifest == NULL)
  1064. {
  1065. DBG_MSG("Out of stack");
  1066. SetLastError(ERROR_OUTOFMEMORY);
  1067. goto done;
  1068. }
  1069. wcscpy(wszManifest, wszDir);
  1070. wszManifest[cchDir] = L'\\';
  1071. wszManifest[cchDir + 1] = L'\0';
  1072. wcscat(wszManifest, c_wszManFileName);
  1073. ZeroMemory(&dwmb, sizeof(dwmb));
  1074. if (eet != eetUseEventInfo)
  1075. {
  1076. ZeroMemory(&ovi, sizeof(ovi));
  1077. ovi.dwOSVersionInfoSize = sizeof(ovi);
  1078. GetVersionExW((LPOSVERSIONINFOW)&ovi);
  1079. cch = 2 * cchDir + wcslen(wszDump) + sizeofSTRW(c_wszEventData) + 4;
  1080. __try { wszFiles = (LPWSTR)_alloca(cch * sizeof(WCHAR)); }
  1081. __except(EXCEPTION_STACK_OVERFLOW) { wszFiles = NULL; }
  1082. if (wszFiles == NULL)
  1083. {
  1084. SetLastError(ERROR_OUTOFMEMORY);
  1085. goto done;
  1086. }
  1087. wcscpy(wszFiles, wszDump);
  1088. cchSep = wcslen(wszFiles);
  1089. pwszExtra = wszFiles + cchSep + 1;
  1090. wcscpy(pwszExtra, wszDir);
  1091. pwszExtra[cchDir] = L'\\';
  1092. pwszExtra[cchDir + 1] = L'\0';
  1093. wcscat(pwszExtra, c_wszEventData);
  1094. TESTHR(hr, GetExtraReportInfo(pwszExtra, ovi));
  1095. if (SUCCEEDED(hr))
  1096. wszFiles[cchSep] = L'|';
  1097. // since AndreVa has promised us that savedump will ALWAYS hand us a
  1098. // minidump, we don't have to do any conversions. But this fn will make
  1099. // sure it's a kernel minidump anyway and fail if it isn't
  1100. if (eet == eetKernelFault)
  1101. {
  1102. TESTHR(hr, ExtractBCInfo(wszDump, &ulBCCode, &ulBCP1, &ulBCP2,
  1103. &ulBCP3, &ulBCP4));
  1104. if (FAILED(hr))
  1105. goto done;
  1106. // log an event- don't care if it fails or not.
  1107. TESTHR(hr, LogKrnl(ulBCCode, ulBCP1, ulBCP2, ulBCP3, ulBCP4));
  1108. swprintf(wszBuffer, c_wszManKS2, ulBCCode, ulBCP1, ulBCP2, ulBCP3,
  1109. ulBCP4, ovi.dwMajorVersion, ovi.dwMinorVersion,
  1110. ovi.dwBuildNumber, ovi.wServicePackMajor,
  1111. ovi.wServicePackMinor, ovi.wSuiteMask, ovi.wProductType);
  1112. dwmb.nidTitle = IDS_KTITLE;
  1113. dwmb.nidErrMsg = IDS_KERRMSG;
  1114. dwmb.nidHdr = IDS_KHDRTXT;
  1115. dwmb.wszStage2 = wszBuffer;
  1116. dwmb.wszBrand = c_wszDWBrand;
  1117. dwmb.wszFileList = wszFiles;
  1118. dwmb.wszCorpPath = c_wszManKCorpPath;
  1119. dwmb.fIsMSApp = TRUE;
  1120. dwmb.dwOptions = emoSupressBucketLogs | emoNoDefCabLimit;
  1121. }
  1122. else if (eet == eetShutdown)
  1123. {
  1124. swprintf(wszBuffer, c_wszManSS2, ovi.dwMajorVersion,
  1125. ovi.dwMinorVersion, ovi.dwBuildNumber,
  1126. ovi.wServicePackMajor, ovi.wServicePackMinor,
  1127. ovi.wSuiteMask, ovi.wProductType);
  1128. dwmb.nidTitle = IDS_STITLE;
  1129. dwmb.nidErrMsg = IDS_SERRMSG;
  1130. dwmb.nidHdr = IDS_SHDRTXT;
  1131. dwmb.wszStage2 = wszBuffer;
  1132. dwmb.wszBrand = c_wszDWBrand;
  1133. dwmb.wszFileList = wszFiles;
  1134. dwmb.wszCorpPath = c_wszManSCorpPath;
  1135. dwmb.fIsMSApp = TRUE;
  1136. dwmb.dwOptions = emoSupressBucketLogs | emoNoDefCabLimit;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. dwmb.wszTitle = pei->wszTitle;
  1142. dwmb.wszErrMsg = pei->wszErrMsg;
  1143. dwmb.wszHdr = pei->wszHdr;
  1144. dwmb.wszPlea = pei->wszPlea;
  1145. dwmb.fIsMSApp = (pei->fUseLitePlea == FALSE);
  1146. dwmb.wszStage1 = pei->wszStage1;
  1147. dwmb.wszStage2 = pei->wszStage2;
  1148. dwmb.wszCorpPath = pei->wszCorpPath;
  1149. dwmb.wszEventSrc = pei->wszEventSrc;
  1150. dwmb.wszSendBtn = pei->wszSendBtn;
  1151. dwmb.wszNoSendBtn = pei->wszNoSendBtn;
  1152. dwmb.wszFileList = pei->wszFileList;
  1153. dwmb.dwOptions = 0;
  1154. if (pei->fUseIEForURLs)
  1155. dwmb.dwOptions |= emoUseIEforURLs;
  1156. if (pei->fNoBucketLogs)
  1157. dwmb.dwOptions |= emoSupressBucketLogs;
  1158. if (pei->fNoDefCabLimit)
  1159. dwmb.dwOptions |= emoNoDefCabLimit;
  1160. }
  1161. // check and see if the system is shutting down. If so, CreateProcess is
  1162. // gonna pop up some annoying UI that we can't get rid of, so we don't
  1163. // want to call it if we know it's gonna happen.
  1164. if (GetSystemMetrics(SM_SHUTTINGDOWN))
  1165. goto done;
  1166. frrvRet = StartDWManifest(oCfg, dwmb, wszManifest, fAllowSend);
  1167. done:
  1168. dw = GetLastError();
  1169. if (frrvRet != frrvErrTimeout)
  1170. {
  1171. if (wszManifest != NULL)
  1172. DeleteFileW(wszManifest);
  1173. if (wszFiles != NULL)
  1174. {
  1175. if (pwszExtra != NULL)
  1176. {
  1177. wszFiles[cchSep] = L'\0';
  1178. DeleteFileW(pwszExtra);
  1179. }
  1180. }
  1181. if (wszDir != NULL)
  1182. {
  1183. DeleteTempDirAndFile(wszDir, FALSE);
  1184. MyFree(wszDir);
  1185. }
  1186. }
  1187. SetLastError(dw);
  1188. return frrvRet;
  1189. }
  1190. // **************************************************************************
  1191. EFaultRepRetVal APIENTRY ReportKernelFaultA(LPCSTR szDump)
  1192. {
  1193. #if 0
  1194. USE_TRACING("ReportEventA");
  1195. EFaultRepRetVal frrv = frrvErrNoDW;
  1196. LPWSTR wszDump = NULL;
  1197. DWORD cch;
  1198. if (szDump == NULL)
  1199. {
  1200. SetLastError(ERROR_INVALID_PARAMETER);
  1201. goto done;
  1202. }
  1203. cch = strlen(szDump) + 1;
  1204. __try
  1205. {
  1206. wszDump = (LPWSTR)_alloca(cch * sizeof(WCHAR));
  1207. }
  1208. __except(EXCEPTION_STACK_OVERFLOW)
  1209. {
  1210. wszDump = NULL;
  1211. }
  1212. if (wszDump == NULL)
  1213. {
  1214. SetLastError(ERROR_OUTOFMEMORY);
  1215. goto done;
  1216. }
  1217. if (MultiByteToWideChar(CP_ACP, 0, szDump, -1, wszDump, cch) == 0)
  1218. goto done;
  1219. frrv = ReportEREvent(eetKernelFault, wszDump, NULL);
  1220. done:
  1221. return frrv;
  1222. #else
  1223. return frrvErrNoDW;
  1224. #endif
  1225. }
  1226. // **************************************************************************
  1227. EFaultRepRetVal APIENTRY ReportKernelFaultW(LPCWSTR wszDump)
  1228. {
  1229. // return ReportEREvent(eetKernelFault, wszDump, NULL);
  1230. return frrvErrNoDW;
  1231. }
  1232. // **************************************************************************
  1233. EFaultRepRetVal APIENTRY ReportKernelFaultDWW(LPCWSTR wszDump)
  1234. {
  1235. return ReportEREventDW(eetKernelFault, wszDump, NULL);
  1236. }