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.

1038 lines
27 KiB

  1. /*******************************************************************
  2. *
  3. * DESCRIPTION: Upload.cpp : Generates and sends out AppCompat report
  4. *
  5. * DATE:6/13/2002
  6. *
  7. *******************************************************************/
  8. #include <wtypes.h>
  9. #include <malloc.h>
  10. #include <strsafe.h>
  11. #include <commdlg.h>
  12. #include <shimdb.h>
  13. #include <faultrep.h>
  14. #include "upload.h"
  15. #include <wchar.h>
  16. // These values are directly fron the web page and it must be in
  17. // sync with it in order for report to work properly
  18. LPCWSTR g_ProblemTypeDescs[] = {
  19. L"Uninitialized",
  20. L"Install_Fail",
  21. L"System_Slow",
  22. L"App_Faulting",
  23. L"App_ErrorOSVer",
  24. L"App_HWDevice",
  25. L"App_OSUpgrade",
  26. L"Uninstall_Fail",
  27. L"App_CDError",
  28. L"App_UserError",
  29. L"App_Internet",
  30. L"App_Print",
  31. L"App_PartlyWork",
  32. NULL
  33. };
  34. ULONG
  35. GetProblemTypeId(
  36. LPWSTR wszProblemType
  37. )
  38. {
  39. ULONG len;
  40. len = wcslen(wszProblemType);
  41. while (len && isdigit(wszProblemType[len-1]))
  42. {
  43. --len;
  44. }
  45. if (wszProblemType[len])
  46. {
  47. return _wtoi(wszProblemType+len);
  48. }
  49. return 0;
  50. }
  51. // ***************************************************************************
  52. DWORD GetAppCompatFlag(LPCWSTR wszPath)
  53. {
  54. LPWSTR pwszFile, wszSysDirLocal = NULL, pwszDir = NULL;
  55. DWORD dwOpt = 0;
  56. DWORD cchPath, cch;
  57. UINT uiDrive;
  58. WCHAR wszSysDir[MAX_PATH+2];
  59. LPWSTR wszBuffer = NULL;
  60. DWORD BufferChCount;
  61. if (wszPath == NULL)
  62. {
  63. goto exitGetACF;
  64. }
  65. // can't be a valid path if it's less than 3 characters long
  66. cchPath = wcslen(wszPath);
  67. if (cchPath < 3)
  68. {
  69. goto exitGetACF;
  70. }
  71. if (!GetSystemDirectoryW(wszSysDir, MAX_PATH+1))
  72. {
  73. goto exitGetACF;
  74. }
  75. // do we have a UNC path?
  76. if (wszPath[0] == L'\\' && wszPath[1] == L'\\')
  77. {
  78. dwOpt = GRABMI_FILTER_THISFILEONLY;
  79. goto exitGetACF;
  80. }
  81. BufferChCount = cchPath+1;
  82. wszBuffer = (LPWSTR) malloc(BufferChCount * sizeof(WCHAR));
  83. if (!wszBuffer)
  84. {
  85. goto exitGetACF;
  86. }
  87. // ok, maybe a remote mapped path or system32?
  88. StringCchCopyW(wszBuffer, BufferChCount, wszPath);
  89. for(pwszFile = wszBuffer + cchPath;
  90. *pwszFile != L'\\' && pwszFile > wszBuffer;
  91. pwszFile--);
  92. if (*pwszFile == L'\\')
  93. *pwszFile = L'\0';
  94. else
  95. goto exitGetACF;
  96. cch = wcslen(wszSysDir) + 1;
  97. // see if it's in system32 or in any parent folder of it.
  98. pwszDir = wszSysDir + cch;
  99. do
  100. {
  101. if (_wcsicmp(wszBuffer, wszSysDir) == 0)
  102. {
  103. dwOpt = GRABMI_FILTER_SYSTEM;
  104. goto exitGetACF;
  105. }
  106. for(;
  107. *pwszDir != L'\\' && pwszDir > wszSysDir;
  108. pwszDir--);
  109. if (*pwszDir == L'\\')
  110. *pwszDir = L'\0';
  111. }
  112. while (pwszDir > wszSysDir);
  113. // is the file sitting in the root of a drive?
  114. if (pwszFile <= &wszBuffer[3])
  115. {
  116. dwOpt = GRABMI_FILTER_THISFILEONLY;
  117. goto exitGetACF;
  118. }
  119. // well, if we've gotten this far, then the path is in the form of
  120. // X:\<something>, so cut off the <something> and find out if we're on
  121. // a mapped drive or not
  122. *pwszFile = L'\\';
  123. wszBuffer[3] = L'\0';
  124. switch(GetDriveTypeW(wszBuffer))
  125. {
  126. case DRIVE_UNKNOWN:
  127. case DRIVE_NO_ROOT_DIR:
  128. goto exitGetACF;
  129. case DRIVE_REMOTE:
  130. dwOpt = GRABMI_FILTER_THISFILEONLY;
  131. goto exitGetACF;
  132. }
  133. dwOpt = GRABMI_FILTER_PRIVACY;
  134. exitGetACF:
  135. if (wszBuffer)
  136. {
  137. free (wszBuffer);
  138. }
  139. return dwOpt;
  140. }
  141. //
  142. // Check if the registry settings allow for user to send the error report
  143. //
  144. BOOL
  145. RegSettingsAllowSend()
  146. {
  147. HKEY hkey, hkeyDoRpt;
  148. BOOL fDoReport = FALSE;
  149. DWORD dw, cb;
  150. cb = sizeof(fDoReport);
  151. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRegErrRpt, 0,
  152. KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS)
  153. {
  154. if (RegQueryValueEx(hkey, L"DoReport", NULL, NULL, (PBYTE)&fDoReport,
  155. &cb) != ERROR_SUCCESS)
  156. {
  157. fDoReport = TRUE;
  158. }
  159. RegCloseKey(hkey);
  160. if (!fDoReport)
  161. {
  162. return FALSE;
  163. }
  164. }
  165. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRegDWPolicy, 0,
  166. KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS)
  167. {
  168. ULONG TreeRpt=0, NeverUpload=0;
  169. if (RegQueryValueEx(hkey, L"DWFileTreeReport", NULL, NULL, (PBYTE)&TreeRpt,
  170. &cb) != ERROR_SUCCESS)
  171. {
  172. TreeRpt = TRUE;
  173. }
  174. if (RegQueryValueEx(hkey, L"NeverUpload", NULL, NULL, (PBYTE)&NeverUpload,
  175. &cb) != ERROR_SUCCESS)
  176. {
  177. NeverUpload = FALSE;
  178. }
  179. RegCloseKey(hkey);
  180. if (NeverUpload || !TreeRpt)
  181. {
  182. return FALSE;
  183. }
  184. }
  185. // If registry key did not exist we still want to report
  186. return TRUE;
  187. }
  188. //
  189. // Retrive filevesion
  190. //
  191. HRESULT
  192. GetAppFileVersion(
  193. LPWSTR wszAppName,
  194. PULONG pVersion // Should be ULONG[4]
  195. )
  196. {
  197. PVOID pVerBuf;
  198. ULONG dwSize;
  199. HRESULT Hr = S_OK;
  200. dwSize = GetFileVersionInfoSizeW(wszAppName, 0);
  201. pVerBuf = malloc(dwSize);
  202. if (!pVerBuf)
  203. {
  204. return E_OUTOFMEMORY;
  205. }
  206. if (GetFileVersionInfoW(wszAppName, 0, dwSize, pVerBuf))
  207. {
  208. VS_FIXEDFILEINFO *verinfo;
  209. UINT dwVerLen;
  210. if (VerQueryValueW(pVerBuf, L"\\", (LPVOID *)&verinfo, &dwVerLen))
  211. {
  212. pVersion[0] = verinfo->dwFileVersionMS >> 16;
  213. pVersion[1] = verinfo->dwFileVersionMS & 0xFFFF;
  214. pVersion[2] = verinfo->dwFileVersionLS >> 16;
  215. pVersion[3] = verinfo->dwFileVersionLS & 0xFFFF;
  216. } else
  217. {
  218. Hr = E_FAIL;
  219. }
  220. } else
  221. {
  222. // Hr = E_FAIL;
  223. }
  224. free ( pVerBuf );
  225. return Hr;
  226. }
  227. //
  228. // Create a temp dir and return full path name of file
  229. //
  230. HRESULT
  231. GetTempFileFullPath(
  232. LPWSTR wszFileName,
  233. LPWSTR *pwszFullPath
  234. )
  235. {
  236. ULONG cch, cchFile, cchDir;
  237. ULONG Suffix;
  238. LPWSTR wszTempFile;
  239. if (pwszFullPath == NULL || wszFileName == NULL)
  240. {
  241. return E_INVALIDARG;
  242. }
  243. cchFile = wcslen(wszFileName);
  244. if (cchFile == 0)
  245. {
  246. return E_INVALIDARG;
  247. }
  248. cch = GetTempPathW(0, NULL);
  249. if (cch == 0)
  250. {
  251. return E_FAIL;
  252. }
  253. cch += cchFile+2+10;
  254. wszTempFile = (LPWSTR) malloc(cch * sizeof(WCHAR));
  255. if (wszTempFile == NULL)
  256. {
  257. return E_OUTOFMEMORY;
  258. }
  259. if (GetTempPathW(cch, wszTempFile) == 0 ||
  260. StringCchCatW(wszTempFile, cch, L"ACW.00") != S_OK)
  261. {
  262. free (wszTempFile);
  263. return E_FAIL;
  264. }
  265. cchDir = wcslen(wszTempFile);
  266. Suffix = 0;
  267. // Create temp dir for our files
  268. do
  269. {
  270. BOOL fRet;
  271. fRet = CreateDirectoryW(wszTempFile, NULL);
  272. if (fRet)
  273. break;
  274. wszTempFile[cchDir-2] = L'0' + (WCHAR)(Suffix / 10);
  275. wszTempFile[cchDir-1] = L'0' + (WCHAR)(Suffix % 10);
  276. Suffix++;
  277. }
  278. while (Suffix <= 100);
  279. if (Suffix > 100 ||
  280. StringCchCatW(wszTempFile, cch, L"\\") != S_OK ||
  281. StringCchCatW(wszTempFile, cch, wszFileName) != S_OK)
  282. {
  283. free (wszTempFile);
  284. return E_FAIL;
  285. }
  286. *pwszFullPath = wszTempFile;
  287. return S_OK;
  288. }
  289. typedef BOOL (APIENTRY *pfn_SDBGRABMATCHINGINFOW)(LPCWSTR, DWORD, LPCWSTR);
  290. //////////////////////////////////////////////////////////////////////////
  291. // GenerateAppCompatText
  292. // Generates application compatibility report in a temporary file
  293. // File is created un user temp directory
  294. //////////////////////////////////////////////////////////////////////////
  295. HRESULT
  296. GenerateAppCompatText(
  297. LPWSTR wszAppName,
  298. LPWSTR *pwszAppCompatReport
  299. )
  300. {
  301. HRESULT Hr;
  302. LPWSTR wszFile = NULL;
  303. HMODULE hMod = NULL;
  304. pfn_SDBGRABMATCHINGINFOW pSdbGrabMatchingInfo;
  305. if (pwszAppCompatReport == NULL)
  306. {
  307. return E_INVALIDARG;
  308. }
  309. hMod = LoadLibraryW(L"apphelp.dll");
  310. if (hMod == NULL)
  311. {
  312. return E_FAIL;
  313. } else
  314. {
  315. pSdbGrabMatchingInfo = (pfn_SDBGRABMATCHINGINFOW) GetProcAddress(hMod, "SdbGrabMatchingInfo");
  316. if (pSdbGrabMatchingInfo != NULL)
  317. {
  318. Hr = GetTempFileFullPath(L"appcompat.txt", &wszFile);
  319. if (SUCCEEDED(Hr))
  320. {
  321. if ((*pSdbGrabMatchingInfo)(wszAppName,
  322. GetAppCompatFlag(wszAppName),
  323. wszFile))
  324. {
  325. *pwszAppCompatReport = wszFile;
  326. FreeLibrary(hMod);
  327. return S_OK;
  328. } else
  329. {
  330. Hr = E_FAIL;
  331. }
  332. free (wszFile);
  333. }
  334. } else
  335. {
  336. Hr = E_FAIL;
  337. }
  338. FreeLibrary(hMod);
  339. }
  340. return E_FAIL;
  341. }
  342. //
  343. // This allocates returns full file-path for wszFileName in same directory as wszDirFile
  344. //
  345. LPWSTR
  346. GenerateFilePath(
  347. LPCWSTR wszDirFile,
  348. LPCWSTR wszFileName
  349. )
  350. {
  351. ULONG cch;
  352. LPWSTR wszFile;
  353. if (!wszFileName || !wszDirFile)
  354. {
  355. return NULL;
  356. }
  357. // Build the filename
  358. cch = wcslen(wszDirFile) + 1;
  359. cch+= wcslen(wszFileName);
  360. wszFile = (LPWSTR) malloc(cch * sizeof(WCHAR));
  361. if (!wszFile)
  362. {
  363. return NULL;
  364. }
  365. StringCchCopyW(wszFile, cch, wszDirFile);
  366. LPWSTR wszTemp = wcsrchr(wszFile, L'\\');
  367. if (!wszTemp)
  368. {
  369. free (wszFile);
  370. return NULL;
  371. }
  372. wszTemp++; *wszTemp = L'\0';
  373. StringCchCatW(wszFile, cch, wszFileName);
  374. return wszFile;
  375. }
  376. //
  377. // Creates usrrpt.txt file and puts this data in it
  378. //
  379. HRESULT
  380. BuildUserReport(
  381. LPWSTR wszProblemType,
  382. LPWSTR wszComment,
  383. LPWSTR wszAppComWiz,
  384. LPWSTR wszAppCompatFile,
  385. LPWSTR *pwszUserReport
  386. )
  387. {
  388. #define BYTE_ORDER_MARK 0xFEFF
  389. enum REPORT_TYPE {
  390. LT_ANSI,
  391. LT_UNICODE
  392. };
  393. LPWSTR wszFile, wszTemp;
  394. DWORD dwRptType = LT_UNICODE;
  395. static WCHAR wchBOM = BYTE_ORDER_MARK;
  396. ULONG cch;
  397. if (wszProblemType == NULL || wszComment == NULL || wszAppComWiz == NULL ||
  398. wszAppCompatFile == NULL || pwszUserReport == NULL)
  399. {
  400. return E_INVALIDARG;
  401. }
  402. // Build the filename
  403. wszFile = GenerateFilePath(wszAppCompatFile, L"usrrpt.txt");
  404. if (wszFile == NULL)
  405. {
  406. return E_OUTOFMEMORY;
  407. }
  408. //
  409. // Now write data to the file
  410. //
  411. HANDLE hFile;
  412. hFile = CreateFileW(wszFile, GENERIC_READ | GENERIC_WRITE,
  413. 0, NULL,
  414. CREATE_ALWAYS, 0, NULL);
  415. if (hFile == NULL ||
  416. hFile == INVALID_HANDLE_VALUE)
  417. {
  418. free (wszFile);
  419. return E_FAIL;
  420. }
  421. #define ByteCount(wsz) wcslen(wsz)*sizeof(WCHAR)
  422. ULONG bw;
  423. if (!WriteFile(hFile, &wchBOM, sizeof(WCHAR), &bw, NULL ) ||
  424. !WriteFile(hFile, c_wszLblType, sizeof(c_wszLblType), &bw, NULL) ||
  425. !WriteFile(hFile, wszProblemType, ByteCount(wszProblemType), &bw, NULL) ||
  426. !WriteFile(hFile, c_wszLblACW, sizeof(c_wszLblACW), &bw, NULL) ||
  427. !WriteFile(hFile, wszAppComWiz, ByteCount(wszAppComWiz), &bw, NULL) ||
  428. !WriteFile(hFile, c_wszLblComment, sizeof(c_wszLblComment), &bw, NULL) ||
  429. !WriteFile(hFile, wszComment, min(ByteCount(wszComment), 2000*sizeof(WCHAR)), &bw, NULL))
  430. {
  431. CloseHandle(hFile);
  432. free (wszFile);
  433. return E_FAIL;
  434. }
  435. CloseHandle(hFile);
  436. *pwszUserReport = wszFile;
  437. return S_OK;
  438. }
  439. HRESULT
  440. MyReportEREventDW(
  441. EEventType eet,
  442. LPCWSTR wszDump,
  443. SEventInfoW *pei
  444. )
  445. {
  446. HMODULE hMod = NULL;
  447. pfn_REPORTEREVENTDW pReportEREventDW;
  448. HRESULT Hr = E_FAIL;
  449. hMod = LoadLibraryW(L"faultrep.dll"); //"H:\\binaries.x86chk\\"
  450. if (hMod == NULL)
  451. {
  452. return E_FAIL;
  453. } else
  454. {
  455. pReportEREventDW = (pfn_REPORTEREVENTDW) GetProcAddress(hMod, "ReportEREventDW");
  456. if (pReportEREventDW != NULL)
  457. {
  458. Hr = (HRESULT) (*pReportEREventDW)(eet, wszDump, pei);
  459. }
  460. FreeLibrary(hMod);
  461. }
  462. return Hr;
  463. }
  464. LPWSTR
  465. GetDefaultServer( void )
  466. {
  467. return (LPWSTR) c_wszServer;
  468. }
  469. HRESULT
  470. ReportDwManifest(
  471. LPWSTR wszAppCompatFile,
  472. SEventInfoW *pei
  473. )
  474. {
  475. LPWSTR wszManifest;
  476. WCHAR wszBuffer[500], wszBufferApp[MAX_PATH], wszDir[100];
  477. HANDLE hManifest;
  478. HRESULT Hr;
  479. DWORD dw, dwFlags, cbToWrite;
  480. LPWSTR pwszServer, pwszBrand, pwszUiLcid;
  481. STARTUPINFOW si;
  482. PROCESS_INFORMATION pi;
  483. wszManifest = GenerateFilePath(wszAppCompatFile, L"manifest.txt");
  484. if (!wszManifest)
  485. {
  486. return E_OUTOFMEMORY;
  487. }
  488. hManifest = CreateFileW(wszManifest, GENERIC_WRITE, FILE_SHARE_READ,
  489. NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN,
  490. NULL);
  491. if (hManifest == INVALID_HANDLE_VALUE)
  492. {
  493. Hr = E_FAIL;
  494. goto exitReportDwManifest;
  495. }
  496. // write the leading 0xFFFE out to the file
  497. wszBuffer[0] = 0xFEFF;
  498. if (!WriteFile(hManifest, wszBuffer, sizeof(wszBuffer[0]), &dw,
  499. NULL))
  500. {
  501. Hr = E_FAIL;
  502. goto exitReportDwManifest;
  503. }
  504. // write out the server, LCID, Brand, Flags, & title
  505. // Server=<server>
  506. // UI LCID=GetSystemDefaultLCID()
  507. // Flags=fDWWhister + fDWUserHKLM + headless if necessary
  508. // Brand=<Brand> ("WINDOWS" by default)
  509. // TitleName=<title>
  510. pwszBrand = (LPWSTR) c_wszBrand;
  511. // determine what server we're going to send the data to.
  512. pwszServer = GetDefaultServer();
  513. dwFlags = fDwWhistler | fDwUseHKLM | fDwAllowSuspend | fDwMiniDumpWithUnloadedModules;
  514. dwFlags |= fDwUseLitePlea ;
  515. Hr = StringCbPrintfW(wszBuffer, sizeof(wszBuffer), c_wszManHdr,
  516. pwszServer, GetUserDefaultUILanguage(), dwFlags, c_wszBrand);
  517. if (FAILED(Hr))
  518. goto exitReportDwManifest;
  519. cbToWrite = wcslen(wszBuffer);
  520. cbToWrite *= sizeof(WCHAR);
  521. Hr = WriteFile(hManifest, wszBuffer, cbToWrite, &dw, NULL) ? S_OK : E_FAIL;
  522. if (FAILED(Hr))
  523. goto exitReportDwManifest;
  524. // write out the title text
  525. if (pei->wszTitle != NULL)
  526. {
  527. LPCWSTR wszOut;
  528. wszOut = pei->wszTitle;
  529. cbToWrite = wcslen(wszOut);
  530. cbToWrite *= sizeof(WCHAR);
  531. Hr = WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL) ? S_OK : E_FAIL;
  532. if (FAILED(Hr))
  533. goto exitReportDwManifest;
  534. }
  535. // write out dig PID path
  536. // DigPidRegPath=HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\DigitalProductId
  537. if (!WriteFile(hManifest, c_wszManPID,
  538. sizeof(c_wszManPID) - sizeof(WCHAR), &dw,
  539. NULL))
  540. {
  541. Hr = E_FAIL;
  542. goto exitReportDwManifest;
  543. }
  544. // write out the registry subpath for policy info
  545. // RegSubPath==Microsoft\\PCHealth\\ErrorReporting\\DW
  546. if (!WriteFile(hManifest, c_wszManSubPath,
  547. sizeof(c_wszManSubPath) - sizeof(WCHAR), &dw,
  548. NULL))
  549. {
  550. Hr = E_FAIL;
  551. goto exitReportDwManifest;
  552. }
  553. // write out the error message if we have one
  554. // ErrorText=<error text read from resource>
  555. if (pei->wszErrMsg != NULL)
  556. {
  557. LPCWSTR wszOut;
  558. if (!WriteFile(hManifest, c_wszManErrText,
  559. sizeof(c_wszManErrText) - sizeof(WCHAR), &dw,
  560. NULL))
  561. {
  562. Hr = E_FAIL;
  563. goto exitReportDwManifest;
  564. }
  565. wszOut = pei->wszErrMsg;
  566. cbToWrite = wcslen(wszOut);
  567. cbToWrite *= sizeof(WCHAR);
  568. if (!WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL))
  569. {
  570. Hr = E_FAIL;
  571. goto exitReportDwManifest;
  572. }
  573. }
  574. // write out the header text if we have one
  575. // HeaderText=<header text read from resource>
  576. if (pei->wszHdr != NULL)
  577. {
  578. LPCWSTR wszOut;
  579. wszOut = pei->wszHdr;
  580. cbToWrite = wcslen(wszOut);
  581. cbToWrite *= sizeof(WCHAR);
  582. if (!WriteFile(hManifest, c_wszManHdrText,
  583. sizeof(c_wszManHdrText) - sizeof(WCHAR), &dw,
  584. NULL) ||
  585. !WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL))
  586. {
  587. Hr = E_FAIL;
  588. goto exitReportDwManifest;
  589. }
  590. }
  591. // write out the plea text if we have one
  592. // Plea=<plea text>
  593. if (pei->wszPlea != NULL)
  594. {
  595. cbToWrite = wcslen(pei->wszPlea) * sizeof(WCHAR);
  596. if (!WriteFile(hManifest, c_wszManPleaText,
  597. sizeof(c_wszManPleaText) - sizeof(WCHAR), &dw,
  598. NULL) ||
  599. !WriteFile(hManifest, pei->wszPlea, cbToWrite, &dw, NULL))
  600. {
  601. Hr = E_FAIL;
  602. goto exitReportDwManifest;
  603. }
  604. }
  605. // write out the ReportButton text if we have one
  606. // ReportButton=<button text>
  607. if (pei->wszSendBtn != NULL)
  608. {
  609. cbToWrite = wcslen(pei->wszSendBtn) * sizeof(WCHAR);
  610. if (!WriteFile(hManifest, c_wszManSendText,
  611. sizeof(c_wszManSendText) - sizeof(WCHAR), &dw,
  612. NULL) ||
  613. !WriteFile(hManifest, pei->wszSendBtn, cbToWrite, &dw, NULL))
  614. {
  615. Hr = E_FAIL;
  616. goto exitReportDwManifest;
  617. }
  618. }
  619. // write out the NoReportButton text if we have one
  620. // NoReportButton=<button text>
  621. if (pei->wszNoSendBtn != NULL)
  622. {
  623. cbToWrite = wcslen(pei->wszNoSendBtn) * sizeof(WCHAR);
  624. if (!WriteFile(hManifest, c_wszManNSendText,
  625. sizeof(c_wszManNSendText) - sizeof(WCHAR), &dw,
  626. NULL) ||
  627. !WriteFile(hManifest, pei->wszNoSendBtn, cbToWrite, &dw, NULL))
  628. {
  629. Hr = E_FAIL;
  630. goto exitReportDwManifest;
  631. }
  632. }
  633. // write out the EventLog text if we have one
  634. // EventLogSource=<button text>
  635. if (pei->wszEventSrc != NULL)
  636. {
  637. cbToWrite = wcslen(pei->wszEventSrc) * sizeof(WCHAR);
  638. if (!WriteFile(hManifest, c_wszManEventSrc,
  639. sizeof(c_wszManEventSrc) - sizeof(WCHAR), &dw,
  640. NULL) ||
  641. !WriteFile(hManifest, pei->wszEventSrc, cbToWrite, &dw, NULL))
  642. {
  643. Hr = E_FAIL;
  644. goto exitReportDwManifest;
  645. }
  646. }
  647. // write out the stage 1 URL if there is one
  648. // Stage1URL=<stage 1 URL>
  649. if (pei->wszStage1 != NULL)
  650. {
  651. cbToWrite = wcslen(pei->wszStage1) * sizeof(WCHAR);
  652. if (!WriteFile(hManifest, pei->wszStage1, cbToWrite, &dw, NULL))
  653. {
  654. Hr = E_FAIL;
  655. goto exitReportDwManifest;
  656. }
  657. }
  658. // write out the stage 2 URL
  659. // Stage2URL=<stage 2 URL>
  660. if (pei->wszStage2 != NULL)
  661. {
  662. cbToWrite = wcslen(pei->wszStage2) * sizeof(WCHAR);
  663. if (!WriteFile(hManifest, pei->wszStage2, cbToWrite, &dw, NULL))
  664. {
  665. Hr = E_FAIL;
  666. goto exitReportDwManifest;
  667. }
  668. }
  669. // write out files to collect if we have any
  670. // DataFiles=<list of files to include in cab>
  671. if (pei->wszFileList != NULL)
  672. {
  673. cbToWrite = wcslen(pei->wszFileList) * sizeof(WCHAR);
  674. if (!WriteFile(hManifest, c_wszManFiles,
  675. sizeof(c_wszManFiles) - sizeof(WCHAR), &dw,
  676. NULL) ||
  677. !WriteFile(hManifest, pei->wszFileList, cbToWrite, &dw, NULL))
  678. {
  679. Hr = E_FAIL;
  680. goto exitReportDwManifest;
  681. }
  682. }
  683. // write out the final "\r\n"
  684. wszBuffer[0] = L'\r';
  685. wszBuffer[1] = L'\n';
  686. if (!WriteFile(hManifest, wszBuffer, 2 * sizeof(wszBuffer[0]), &dw,
  687. NULL))
  688. {
  689. Hr = E_FAIL;
  690. goto exitReportDwManifest;
  691. }
  692. CloseHandle(hManifest);
  693. hManifest = INVALID_HANDLE_VALUE;
  694. // create the process
  695. GetSystemDirectoryW(wszDir, sizeof(wszDir)/sizeof(WCHAR));
  696. StringCbPrintfW(wszBufferApp, sizeof(wszBufferApp), c_wszDWExe, wszDir);
  697. StringCbPrintfW(wszBuffer, sizeof(wszBuffer), c_wszDWCmdLine, wszManifest);
  698. ZeroMemory(&si, sizeof(si));
  699. ZeroMemory(&pi, sizeof(pi));
  700. si.cb = sizeof(si);
  701. // check and see if the system is shutting down. If so, CreateProcess is
  702. // gonna pop up some annoying UI that we can't get rid of, so we don't
  703. // want to call it if we know it's gonna happen.
  704. if (GetSystemMetrics(SM_SHUTTINGDOWN))
  705. {
  706. Hr = E_FAIL;
  707. goto exitReportDwManifest;
  708. }
  709. // we're creating the process in the same user context that we're in
  710. si.lpDesktop = L"Winsta0\\Default";
  711. if (!CreateProcessW(wszBufferApp, wszBuffer, NULL, NULL, TRUE,
  712. CREATE_DEFAULT_ERROR_MODE |
  713. NORMAL_PRIORITY_CLASS,
  714. NULL, wszDir, &si, &pi))
  715. {
  716. Hr = ERROR_APPRPT_DW_LAUNCH;
  717. goto exitReportDwManifest;
  718. }
  719. // don't need the thread handle & we gotta close it, so close it now
  720. CloseHandle(pi.hThread);
  721. pi.hThread = NULL;
  722. // wait 5 minutes for DW to close. If it doesn't close by then, just
  723. // return.
  724. dw = WaitForSingleObject(pi.hProcess, 5*60*1000);
  725. if (dw == WAIT_TIMEOUT)
  726. {
  727. CloseHandle(pi.hProcess);
  728. Hr = ERROR_APPRPT_DW_TIMEOUT;
  729. goto exitReportDwManifest;
  730. }
  731. else if (dw == WAIT_FAILED)
  732. {
  733. CloseHandle(pi.hProcess);
  734. goto exitReportDwManifest;
  735. }
  736. CloseHandle(pi.hProcess);
  737. GetExitCodeProcess(pi.hProcess, &dw);
  738. if (dw == STILL_ACTIVE)
  739. {
  740. // "DW process still active!"
  741. // Kill dw and let user know dw timed out
  742. TerminateProcess(pi.hProcess, 1);
  743. Hr = ERROR_APPRPT_DW_TIMEOUT;
  744. } else if (dw == 0)
  745. {
  746. Hr = S_OK;
  747. }
  748. else
  749. {
  750. Hr = E_FAIL;
  751. }
  752. pi.hProcess = NULL;
  753. exitReportDwManifest:
  754. // Note again that we assume there was no previous impersonation token
  755. // on the the thread before we did the impersonation above.
  756. if (hManifest != INVALID_HANDLE_VALUE)
  757. CloseHandle(hManifest);
  758. if (FAILED(Hr) || wszManifest != NULL)
  759. {
  760. DeleteFileW(wszManifest);
  761. free (wszManifest);
  762. }
  763. return Hr;
  764. }
  765. //
  766. // Calls up faultrep.dll to launch DwWin for uploading the error report
  767. //
  768. HRESULT
  769. UploadAppProblem(
  770. LPWSTR wszAppName,
  771. LPWSTR wszProblemType,
  772. LPWSTR wszUserComment,
  773. LPWSTR wszMiscData,
  774. LPWSTR wszAppCompatText
  775. )
  776. {
  777. EEventType eet;
  778. SEventInfoW ei = {0};
  779. LPWSTR wszUerRpt = NULL;
  780. HRESULT Hr;
  781. LPWSTR wszFileList = NULL;
  782. LPWSTR wszStage1URL = NULL;
  783. LPWSTR wszStage2URL = NULL;
  784. LPWSTR wszBaseName;
  785. ULONG cch;
  786. ULONG VerInfo[4];
  787. ULONG OffsetFromProbType;
  788. if ((wszAppName == NULL) || (wszProblemType == NULL) ||
  789. (wszMiscData == NULL) || (wszAppCompatText == NULL))
  790. {
  791. goto exitUpload;
  792. }
  793. if (wszUserComment == NULL)
  794. {
  795. wszUserComment = L"";
  796. }
  797. if (!RegSettingsAllowSend())
  798. {
  799. Hr = E_FAIL;
  800. goto exitUpload;
  801. }
  802. if ((Hr = GetAppFileVersion(wszAppName, &VerInfo[0])) != S_OK)
  803. {
  804. goto exitUpload;
  805. }
  806. if ((Hr = BuildUserReport(wszProblemType, wszUserComment, wszMiscData,
  807. wszAppCompatText, &wszUerRpt)) != S_OK)
  808. {
  809. goto exitUpload;
  810. }
  811. OffsetFromProbType = GetProblemTypeId(wszProblemType);
  812. wszFileList = (LPWSTR) malloc((cch = (wcslen(wszAppCompatText) + wcslen(wszUerRpt) + 2)) * sizeof(WCHAR));
  813. if (!wszFileList)
  814. {
  815. Hr = E_OUTOFMEMORY;
  816. goto exitUpload;
  817. }
  818. StringCchPrintfW(wszFileList, cch, L"%ws|%ws", wszAppCompatText, wszUerRpt);
  819. wszBaseName = wcsrchr(wszAppName, L'\\');
  820. if (wszBaseName == NULL)
  821. {
  822. Hr = E_INVALIDARG;
  823. goto exitUpload;
  824. }
  825. wszBaseName++;
  826. cch = wcslen(wszBaseName) + sizeof(c_wszStage1)/sizeof(WCHAR) + 4*5 + 2;
  827. wszStage1URL = (LPWSTR) malloc( cch * sizeof (WCHAR));
  828. if (!wszStage1URL)
  829. {
  830. Hr = E_OUTOFMEMORY;
  831. goto exitUpload;
  832. }
  833. Hr = StringCchPrintfW(wszStage1URL, cch, c_wszStage1, wszBaseName,
  834. VerInfo[0], VerInfo[1], VerInfo[2], VerInfo[3],
  835. OffsetFromProbType);
  836. if (FAILED(Hr))
  837. {
  838. goto exitUpload;
  839. }
  840. cch = wcslen(wszBaseName) + sizeof(c_wszStage2)/sizeof(WCHAR) + 4*5 + 2;
  841. wszStage2URL = (LPWSTR) malloc( cch * sizeof (WCHAR));
  842. if (!wszStage2URL)
  843. {
  844. Hr = E_OUTOFMEMORY;
  845. goto exitUpload;
  846. }
  847. Hr = StringCchPrintfW(wszStage2URL, cch, c_wszStage2, wszBaseName,
  848. VerInfo[0], VerInfo[1], VerInfo[2], VerInfo[3],
  849. OffsetFromProbType);
  850. if (FAILED(Hr))
  851. {
  852. goto exitUpload;
  853. }
  854. eet = eetUseEventInfo;
  855. ei.cbSEI = sizeof(ei);
  856. ei.wszTitle = L"Microsoft Windows";
  857. ei.wszErrMsg = L"Thank-you for creating an application compatibility report.";
  858. ei.wszHdr = L"Report an Application Compatibility Issue";
  859. ei.wszPlea = L"We have created an error report that you can send to help us improve "
  860. L"Microsoft Windows. We will treat this report as confidential and anonymous.";
  861. ei.wszEventName = L"User initiated report";
  862. ei.fUseLitePlea = FALSE;
  863. ei.wszStage1 = wszStage1URL;
  864. ei.wszStage2 = wszStage2URL;
  865. ei.wszCorpPath = NULL;
  866. ei.wszSendBtn = L"&Send Error Report";
  867. ei.wszNoSendBtn = L"&Don't Send";
  868. ei.wszFileList = wszFileList;
  869. if ((Hr = ReportDwManifest(wszAppCompatText, &ei)) != S_OK)
  870. // if ((Hr = MyReportEREventDW(eet, NULL, &ei)) != S_OK)
  871. {
  872. // we failed
  873. }
  874. exitUpload:
  875. if (wszFileList != NULL) free( wszFileList );
  876. if (wszStage1URL != NULL) free( wszStage1URL );
  877. if (wszStage2URL != NULL) free( wszStage2URL );
  878. // Delete all temporary files
  879. if (wszUerRpt != NULL)
  880. {
  881. DeleteFileW(wszUerRpt);
  882. free (wszUerRpt );
  883. }
  884. if (wszAppCompatText != NULL)
  885. {
  886. DeleteFileW(wszAppCompatText);
  887. wszBaseName = wcsrchr(wszAppCompatText, L'\\');
  888. if (wszBaseName)
  889. {
  890. *wszBaseName = L'\0';
  891. RemoveDirectoryW(wszAppCompatText);
  892. *wszBaseName = L'\\';
  893. }
  894. }
  895. return Hr;
  896. }