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

/*******************************************************************
*
* DESCRIPTION: Upload.cpp : Generates and sends out AppCompat report
*
* DATE:6/13/2002
*
*******************************************************************/
#include <wtypes.h>
#include <malloc.h>
#include <strsafe.h>
#include <commdlg.h>
#include <shimdb.h>
#include <faultrep.h>
#include "upload.h"
#include <wchar.h>
// These values are directly fron the web page and it must be in
// sync with it in order for report to work properly
LPCWSTR g_ProblemTypeDescs[] = {
L"Uninitialized",
L"Install_Fail",
L"System_Slow",
L"App_Faulting",
L"App_ErrorOSVer",
L"App_HWDevice",
L"App_OSUpgrade",
L"Uninstall_Fail",
L"App_CDError",
L"App_UserError",
L"App_Internet",
L"App_Print",
L"App_PartlyWork",
NULL
};
ULONG
GetProblemTypeId(
LPWSTR wszProblemType
)
{
ULONG len;
len = wcslen(wszProblemType);
while (len && isdigit(wszProblemType[len-1]))
{
--len;
}
if (wszProblemType[len])
{
return _wtoi(wszProblemType+len);
}
return 0;
}
// ***************************************************************************
DWORD GetAppCompatFlag(LPCWSTR wszPath)
{
LPWSTR pwszFile, wszSysDirLocal = NULL, pwszDir = NULL;
DWORD dwOpt = 0;
DWORD cchPath, cch;
UINT uiDrive;
WCHAR wszSysDir[MAX_PATH+2];
LPWSTR wszBuffer = NULL;
DWORD BufferChCount;
if (wszPath == NULL)
{
goto exitGetACF;
}
// can't be a valid path if it's less than 3 characters long
cchPath = wcslen(wszPath);
if (cchPath < 3)
{
goto exitGetACF;
}
if (!GetSystemDirectoryW(wszSysDir, MAX_PATH+1))
{
goto exitGetACF;
}
// do we have a UNC path?
if (wszPath[0] == L'\\' && wszPath[1] == L'\\')
{
dwOpt = GRABMI_FILTER_THISFILEONLY;
goto exitGetACF;
}
BufferChCount = cchPath+1;
wszBuffer = (LPWSTR) malloc(BufferChCount * sizeof(WCHAR));
if (!wszBuffer)
{
goto exitGetACF;
}
// ok, maybe a remote mapped path or system32?
StringCchCopyW(wszBuffer, BufferChCount, wszPath);
for(pwszFile = wszBuffer + cchPath;
*pwszFile != L'\\' && pwszFile > wszBuffer;
pwszFile--);
if (*pwszFile == L'\\')
*pwszFile = L'\0';
else
goto exitGetACF;
cch = wcslen(wszSysDir) + 1;
// see if it's in system32 or in any parent folder of it.
pwszDir = wszSysDir + cch;
do
{
if (_wcsicmp(wszBuffer, wszSysDir) == 0)
{
dwOpt = GRABMI_FILTER_SYSTEM;
goto exitGetACF;
}
for(;
*pwszDir != L'\\' && pwszDir > wszSysDir;
pwszDir--);
if (*pwszDir == L'\\')
*pwszDir = L'\0';
}
while (pwszDir > wszSysDir);
// is the file sitting in the root of a drive?
if (pwszFile <= &wszBuffer[3])
{
dwOpt = GRABMI_FILTER_THISFILEONLY;
goto exitGetACF;
}
// well, if we've gotten this far, then the path is in the form of
// X:\<something>, so cut off the <something> and find out if we're on
// a mapped drive or not
*pwszFile = L'\\';
wszBuffer[3] = L'\0';
switch(GetDriveTypeW(wszBuffer))
{
case DRIVE_UNKNOWN:
case DRIVE_NO_ROOT_DIR:
goto exitGetACF;
case DRIVE_REMOTE:
dwOpt = GRABMI_FILTER_THISFILEONLY;
goto exitGetACF;
}
dwOpt = GRABMI_FILTER_PRIVACY;
exitGetACF:
if (wszBuffer)
{
free (wszBuffer);
}
return dwOpt;
}
//
// Check if the registry settings allow for user to send the error report
//
BOOL
RegSettingsAllowSend()
{
HKEY hkey, hkeyDoRpt;
BOOL fDoReport = FALSE;
DWORD dw, cb;
cb = sizeof(fDoReport);
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRegErrRpt, 0,
KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hkey, L"DoReport", NULL, NULL, (PBYTE)&fDoReport,
&cb) != ERROR_SUCCESS)
{
fDoReport = TRUE;
}
RegCloseKey(hkey);
if (!fDoReport)
{
return FALSE;
}
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRegDWPolicy, 0,
KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS)
{
ULONG TreeRpt=0, NeverUpload=0;
if (RegQueryValueEx(hkey, L"DWFileTreeReport", NULL, NULL, (PBYTE)&TreeRpt,
&cb) != ERROR_SUCCESS)
{
TreeRpt = TRUE;
}
if (RegQueryValueEx(hkey, L"NeverUpload", NULL, NULL, (PBYTE)&NeverUpload,
&cb) != ERROR_SUCCESS)
{
NeverUpload = FALSE;
}
RegCloseKey(hkey);
if (NeverUpload || !TreeRpt)
{
return FALSE;
}
}
// If registry key did not exist we still want to report
return TRUE;
}
//
// Retrive filevesion
//
HRESULT
GetAppFileVersion(
LPWSTR wszAppName,
PULONG pVersion // Should be ULONG[4]
)
{
PVOID pVerBuf;
ULONG dwSize;
HRESULT Hr = S_OK;
dwSize = GetFileVersionInfoSizeW(wszAppName, 0);
pVerBuf = malloc(dwSize);
if (!pVerBuf)
{
return E_OUTOFMEMORY;
}
if (GetFileVersionInfoW(wszAppName, 0, dwSize, pVerBuf))
{
VS_FIXEDFILEINFO *verinfo;
UINT dwVerLen;
if (VerQueryValueW(pVerBuf, L"\\", (LPVOID *)&verinfo, &dwVerLen))
{
pVersion[0] = verinfo->dwFileVersionMS >> 16;
pVersion[1] = verinfo->dwFileVersionMS & 0xFFFF;
pVersion[2] = verinfo->dwFileVersionLS >> 16;
pVersion[3] = verinfo->dwFileVersionLS & 0xFFFF;
} else
{
Hr = E_FAIL;
}
} else
{
// Hr = E_FAIL;
}
free ( pVerBuf );
return Hr;
}
//
// Create a temp dir and return full path name of file
//
HRESULT
GetTempFileFullPath(
LPWSTR wszFileName,
LPWSTR *pwszFullPath
)
{
ULONG cch, cchFile, cchDir;
ULONG Suffix;
LPWSTR wszTempFile;
if (pwszFullPath == NULL || wszFileName == NULL)
{
return E_INVALIDARG;
}
cchFile = wcslen(wszFileName);
if (cchFile == 0)
{
return E_INVALIDARG;
}
cch = GetTempPathW(0, NULL);
if (cch == 0)
{
return E_FAIL;
}
cch += cchFile+2+10;
wszTempFile = (LPWSTR) malloc(cch * sizeof(WCHAR));
if (wszTempFile == NULL)
{
return E_OUTOFMEMORY;
}
if (GetTempPathW(cch, wszTempFile) == 0 ||
StringCchCatW(wszTempFile, cch, L"ACW.00") != S_OK)
{
free (wszTempFile);
return E_FAIL;
}
cchDir = wcslen(wszTempFile);
Suffix = 0;
// Create temp dir for our files
do
{
BOOL fRet;
fRet = CreateDirectoryW(wszTempFile, NULL);
if (fRet)
break;
wszTempFile[cchDir-2] = L'0' + (WCHAR)(Suffix / 10);
wszTempFile[cchDir-1] = L'0' + (WCHAR)(Suffix % 10);
Suffix++;
}
while (Suffix <= 100);
if (Suffix > 100 ||
StringCchCatW(wszTempFile, cch, L"\\") != S_OK ||
StringCchCatW(wszTempFile, cch, wszFileName) != S_OK)
{
free (wszTempFile);
return E_FAIL;
}
*pwszFullPath = wszTempFile;
return S_OK;
}
typedef BOOL (APIENTRY *pfn_SDBGRABMATCHINGINFOW)(LPCWSTR, DWORD, LPCWSTR);
//////////////////////////////////////////////////////////////////////////
// GenerateAppCompatText
// Generates application compatibility report in a temporary file
// File is created un user temp directory
//////////////////////////////////////////////////////////////////////////
HRESULT
GenerateAppCompatText(
LPWSTR wszAppName,
LPWSTR *pwszAppCompatReport
)
{
HRESULT Hr;
LPWSTR wszFile = NULL;
HMODULE hMod = NULL;
pfn_SDBGRABMATCHINGINFOW pSdbGrabMatchingInfo;
if (pwszAppCompatReport == NULL)
{
return E_INVALIDARG;
}
hMod = LoadLibraryW(L"apphelp.dll");
if (hMod == NULL)
{
return E_FAIL;
} else
{
pSdbGrabMatchingInfo = (pfn_SDBGRABMATCHINGINFOW) GetProcAddress(hMod, "SdbGrabMatchingInfo");
if (pSdbGrabMatchingInfo != NULL)
{
Hr = GetTempFileFullPath(L"appcompat.txt", &wszFile);
if (SUCCEEDED(Hr))
{
if ((*pSdbGrabMatchingInfo)(wszAppName,
GetAppCompatFlag(wszAppName),
wszFile))
{
*pwszAppCompatReport = wszFile;
FreeLibrary(hMod);
return S_OK;
} else
{
Hr = E_FAIL;
}
free (wszFile);
}
} else
{
Hr = E_FAIL;
}
FreeLibrary(hMod);
}
return E_FAIL;
}
//
// This allocates returns full file-path for wszFileName in same directory as wszDirFile
//
LPWSTR
GenerateFilePath(
LPCWSTR wszDirFile,
LPCWSTR wszFileName
)
{
ULONG cch;
LPWSTR wszFile;
if (!wszFileName || !wszDirFile)
{
return NULL;
}
// Build the filename
cch = wcslen(wszDirFile) + 1;
cch+= wcslen(wszFileName);
wszFile = (LPWSTR) malloc(cch * sizeof(WCHAR));
if (!wszFile)
{
return NULL;
}
StringCchCopyW(wszFile, cch, wszDirFile);
LPWSTR wszTemp = wcsrchr(wszFile, L'\\');
if (!wszTemp)
{
free (wszFile);
return NULL;
}
wszTemp++; *wszTemp = L'\0';
StringCchCatW(wszFile, cch, wszFileName);
return wszFile;
}
//
// Creates usrrpt.txt file and puts this data in it
//
HRESULT
BuildUserReport(
LPWSTR wszProblemType,
LPWSTR wszComment,
LPWSTR wszAppComWiz,
LPWSTR wszAppCompatFile,
LPWSTR *pwszUserReport
)
{
#define BYTE_ORDER_MARK 0xFEFF
enum REPORT_TYPE {
LT_ANSI,
LT_UNICODE
};
LPWSTR wszFile, wszTemp;
DWORD dwRptType = LT_UNICODE;
static WCHAR wchBOM = BYTE_ORDER_MARK;
ULONG cch;
if (wszProblemType == NULL || wszComment == NULL || wszAppComWiz == NULL ||
wszAppCompatFile == NULL || pwszUserReport == NULL)
{
return E_INVALIDARG;
}
// Build the filename
wszFile = GenerateFilePath(wszAppCompatFile, L"usrrpt.txt");
if (wszFile == NULL)
{
return E_OUTOFMEMORY;
}
//
// Now write data to the file
//
HANDLE hFile;
hFile = CreateFileW(wszFile, GENERIC_READ | GENERIC_WRITE,
0, NULL,
CREATE_ALWAYS, 0, NULL);
if (hFile == NULL ||
hFile == INVALID_HANDLE_VALUE)
{
free (wszFile);
return E_FAIL;
}
#define ByteCount(wsz) wcslen(wsz)*sizeof(WCHAR)
ULONG bw;
if (!WriteFile(hFile, &wchBOM, sizeof(WCHAR), &bw, NULL ) ||
!WriteFile(hFile, c_wszLblType, sizeof(c_wszLblType), &bw, NULL) ||
!WriteFile(hFile, wszProblemType, ByteCount(wszProblemType), &bw, NULL) ||
!WriteFile(hFile, c_wszLblACW, sizeof(c_wszLblACW), &bw, NULL) ||
!WriteFile(hFile, wszAppComWiz, ByteCount(wszAppComWiz), &bw, NULL) ||
!WriteFile(hFile, c_wszLblComment, sizeof(c_wszLblComment), &bw, NULL) ||
!WriteFile(hFile, wszComment, min(ByteCount(wszComment), 2000*sizeof(WCHAR)), &bw, NULL))
{
CloseHandle(hFile);
free (wszFile);
return E_FAIL;
}
CloseHandle(hFile);
*pwszUserReport = wszFile;
return S_OK;
}
HRESULT
MyReportEREventDW(
EEventType eet,
LPCWSTR wszDump,
SEventInfoW *pei
)
{
HMODULE hMod = NULL;
pfn_REPORTEREVENTDW pReportEREventDW;
HRESULT Hr = E_FAIL;
hMod = LoadLibraryW(L"faultrep.dll"); //"H:\\binaries.x86chk\\"
if (hMod == NULL)
{
return E_FAIL;
} else
{
pReportEREventDW = (pfn_REPORTEREVENTDW) GetProcAddress(hMod, "ReportEREventDW");
if (pReportEREventDW != NULL)
{
Hr = (HRESULT) (*pReportEREventDW)(eet, wszDump, pei);
}
FreeLibrary(hMod);
}
return Hr;
}
LPWSTR
GetDefaultServer( void )
{
return (LPWSTR) c_wszServer;
}
HRESULT
ReportDwManifest(
LPWSTR wszAppCompatFile,
SEventInfoW *pei
)
{
LPWSTR wszManifest;
WCHAR wszBuffer[500], wszBufferApp[MAX_PATH], wszDir[100];
HANDLE hManifest;
HRESULT Hr;
DWORD dw, dwFlags, cbToWrite;
LPWSTR pwszServer, pwszBrand, pwszUiLcid;
STARTUPINFOW si;
PROCESS_INFORMATION pi;
wszManifest = GenerateFilePath(wszAppCompatFile, L"manifest.txt");
if (!wszManifest)
{
return E_OUTOFMEMORY;
}
hManifest = CreateFileW(wszManifest, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hManifest == INVALID_HANDLE_VALUE)
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
// write the leading 0xFFFE out to the file
wszBuffer[0] = 0xFEFF;
if (!WriteFile(hManifest, wszBuffer, sizeof(wszBuffer[0]), &dw,
NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
// write out the server, LCID, Brand, Flags, & title
// Server=<server>
// UI LCID=GetSystemDefaultLCID()
// Flags=fDWWhister + fDWUserHKLM + headless if necessary
// Brand=<Brand> ("WINDOWS" by default)
// TitleName=<title>
pwszBrand = (LPWSTR) c_wszBrand;
// determine what server we're going to send the data to.
pwszServer = GetDefaultServer();
dwFlags = fDwWhistler | fDwUseHKLM | fDwAllowSuspend | fDwMiniDumpWithUnloadedModules;
dwFlags |= fDwUseLitePlea ;
Hr = StringCbPrintfW(wszBuffer, sizeof(wszBuffer), c_wszManHdr,
pwszServer, GetUserDefaultUILanguage(), dwFlags, c_wszBrand);
if (FAILED(Hr))
goto exitReportDwManifest;
cbToWrite = wcslen(wszBuffer);
cbToWrite *= sizeof(WCHAR);
Hr = WriteFile(hManifest, wszBuffer, cbToWrite, &dw, NULL) ? S_OK : E_FAIL;
if (FAILED(Hr))
goto exitReportDwManifest;
// write out the title text
if (pei->wszTitle != NULL)
{
LPCWSTR wszOut;
wszOut = pei->wszTitle;
cbToWrite = wcslen(wszOut);
cbToWrite *= sizeof(WCHAR);
Hr = WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL) ? S_OK : E_FAIL;
if (FAILED(Hr))
goto exitReportDwManifest;
}
// write out dig PID path
// DigPidRegPath=HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\DigitalProductId
if (!WriteFile(hManifest, c_wszManPID,
sizeof(c_wszManPID) - sizeof(WCHAR), &dw,
NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
// write out the registry subpath for policy info
// RegSubPath==Microsoft\\PCHealth\\ErrorReporting\\DW
if (!WriteFile(hManifest, c_wszManSubPath,
sizeof(c_wszManSubPath) - sizeof(WCHAR), &dw,
NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
// write out the error message if we have one
// ErrorText=<error text read from resource>
if (pei->wszErrMsg != NULL)
{
LPCWSTR wszOut;
if (!WriteFile(hManifest, c_wszManErrText,
sizeof(c_wszManErrText) - sizeof(WCHAR), &dw,
NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
wszOut = pei->wszErrMsg;
cbToWrite = wcslen(wszOut);
cbToWrite *= sizeof(WCHAR);
if (!WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the header text if we have one
// HeaderText=<header text read from resource>
if (pei->wszHdr != NULL)
{
LPCWSTR wszOut;
wszOut = pei->wszHdr;
cbToWrite = wcslen(wszOut);
cbToWrite *= sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManHdrText,
sizeof(c_wszManHdrText) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, wszOut, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the plea text if we have one
// Plea=<plea text>
if (pei->wszPlea != NULL)
{
cbToWrite = wcslen(pei->wszPlea) * sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManPleaText,
sizeof(c_wszManPleaText) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, pei->wszPlea, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the ReportButton text if we have one
// ReportButton=<button text>
if (pei->wszSendBtn != NULL)
{
cbToWrite = wcslen(pei->wszSendBtn) * sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManSendText,
sizeof(c_wszManSendText) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, pei->wszSendBtn, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the NoReportButton text if we have one
// NoReportButton=<button text>
if (pei->wszNoSendBtn != NULL)
{
cbToWrite = wcslen(pei->wszNoSendBtn) * sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManNSendText,
sizeof(c_wszManNSendText) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, pei->wszNoSendBtn, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the EventLog text if we have one
// EventLogSource=<button text>
if (pei->wszEventSrc != NULL)
{
cbToWrite = wcslen(pei->wszEventSrc) * sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManEventSrc,
sizeof(c_wszManEventSrc) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, pei->wszEventSrc, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the stage 1 URL if there is one
// Stage1URL=<stage 1 URL>
if (pei->wszStage1 != NULL)
{
cbToWrite = wcslen(pei->wszStage1) * sizeof(WCHAR);
if (!WriteFile(hManifest, pei->wszStage1, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the stage 2 URL
// Stage2URL=<stage 2 URL>
if (pei->wszStage2 != NULL)
{
cbToWrite = wcslen(pei->wszStage2) * sizeof(WCHAR);
if (!WriteFile(hManifest, pei->wszStage2, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out files to collect if we have any
// DataFiles=<list of files to include in cab>
if (pei->wszFileList != NULL)
{
cbToWrite = wcslen(pei->wszFileList) * sizeof(WCHAR);
if (!WriteFile(hManifest, c_wszManFiles,
sizeof(c_wszManFiles) - sizeof(WCHAR), &dw,
NULL) ||
!WriteFile(hManifest, pei->wszFileList, cbToWrite, &dw, NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
}
// write out the final "\r\n"
wszBuffer[0] = L'\r';
wszBuffer[1] = L'\n';
if (!WriteFile(hManifest, wszBuffer, 2 * sizeof(wszBuffer[0]), &dw,
NULL))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
CloseHandle(hManifest);
hManifest = INVALID_HANDLE_VALUE;
// create the process
GetSystemDirectoryW(wszDir, sizeof(wszDir)/sizeof(WCHAR));
StringCbPrintfW(wszBufferApp, sizeof(wszBufferApp), c_wszDWExe, wszDir);
StringCbPrintfW(wszBuffer, sizeof(wszBuffer), c_wszDWCmdLine, wszManifest);
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
// check and see if the system is shutting down. If so, CreateProcess is
// gonna pop up some annoying UI that we can't get rid of, so we don't
// want to call it if we know it's gonna happen.
if (GetSystemMetrics(SM_SHUTTINGDOWN))
{
Hr = E_FAIL;
goto exitReportDwManifest;
}
// we're creating the process in the same user context that we're in
si.lpDesktop = L"Winsta0\\Default";
if (!CreateProcessW(wszBufferApp, wszBuffer, NULL, NULL, TRUE,
CREATE_DEFAULT_ERROR_MODE |
NORMAL_PRIORITY_CLASS,
NULL, wszDir, &si, &pi))
{
Hr = ERROR_APPRPT_DW_LAUNCH;
goto exitReportDwManifest;
}
// don't need the thread handle & we gotta close it, so close it now
CloseHandle(pi.hThread);
pi.hThread = NULL;
// wait 5 minutes for DW to close. If it doesn't close by then, just
// return.
dw = WaitForSingleObject(pi.hProcess, 5*60*1000);
if (dw == WAIT_TIMEOUT)
{
CloseHandle(pi.hProcess);
Hr = ERROR_APPRPT_DW_TIMEOUT;
goto exitReportDwManifest;
}
else if (dw == WAIT_FAILED)
{
CloseHandle(pi.hProcess);
goto exitReportDwManifest;
}
CloseHandle(pi.hProcess);
GetExitCodeProcess(pi.hProcess, &dw);
if (dw == STILL_ACTIVE)
{
// "DW process still active!"
// Kill dw and let user know dw timed out
TerminateProcess(pi.hProcess, 1);
Hr = ERROR_APPRPT_DW_TIMEOUT;
} else if (dw == 0)
{
Hr = S_OK;
}
else
{
Hr = E_FAIL;
}
pi.hProcess = NULL;
exitReportDwManifest:
// Note again that we assume there was no previous impersonation token
// on the the thread before we did the impersonation above.
if (hManifest != INVALID_HANDLE_VALUE)
CloseHandle(hManifest);
if (FAILED(Hr) || wszManifest != NULL)
{
DeleteFileW(wszManifest);
free (wszManifest);
}
return Hr;
}
//
// Calls up faultrep.dll to launch DwWin for uploading the error report
//
HRESULT
UploadAppProblem(
LPWSTR wszAppName,
LPWSTR wszProblemType,
LPWSTR wszUserComment,
LPWSTR wszMiscData,
LPWSTR wszAppCompatText
)
{
EEventType eet;
SEventInfoW ei = {0};
LPWSTR wszUerRpt = NULL;
HRESULT Hr;
LPWSTR wszFileList = NULL;
LPWSTR wszStage1URL = NULL;
LPWSTR wszStage2URL = NULL;
LPWSTR wszBaseName;
ULONG cch;
ULONG VerInfo[4];
ULONG OffsetFromProbType;
if ((wszAppName == NULL) || (wszProblemType == NULL) ||
(wszMiscData == NULL) || (wszAppCompatText == NULL))
{
goto exitUpload;
}
if (wszUserComment == NULL)
{
wszUserComment = L"";
}
if (!RegSettingsAllowSend())
{
Hr = E_FAIL;
goto exitUpload;
}
if ((Hr = GetAppFileVersion(wszAppName, &VerInfo[0])) != S_OK)
{
goto exitUpload;
}
if ((Hr = BuildUserReport(wszProblemType, wszUserComment, wszMiscData,
wszAppCompatText, &wszUerRpt)) != S_OK)
{
goto exitUpload;
}
OffsetFromProbType = GetProblemTypeId(wszProblemType);
wszFileList = (LPWSTR) malloc((cch = (wcslen(wszAppCompatText) + wcslen(wszUerRpt) + 2)) * sizeof(WCHAR));
if (!wszFileList)
{
Hr = E_OUTOFMEMORY;
goto exitUpload;
}
StringCchPrintfW(wszFileList, cch, L"%ws|%ws", wszAppCompatText, wszUerRpt);
wszBaseName = wcsrchr(wszAppName, L'\\');
if (wszBaseName == NULL)
{
Hr = E_INVALIDARG;
goto exitUpload;
}
wszBaseName++;
cch = wcslen(wszBaseName) + sizeof(c_wszStage1)/sizeof(WCHAR) + 4*5 + 2;
wszStage1URL = (LPWSTR) malloc( cch * sizeof (WCHAR));
if (!wszStage1URL)
{
Hr = E_OUTOFMEMORY;
goto exitUpload;
}
Hr = StringCchPrintfW(wszStage1URL, cch, c_wszStage1, wszBaseName,
VerInfo[0], VerInfo[1], VerInfo[2], VerInfo[3],
OffsetFromProbType);
if (FAILED(Hr))
{
goto exitUpload;
}
cch = wcslen(wszBaseName) + sizeof(c_wszStage2)/sizeof(WCHAR) + 4*5 + 2;
wszStage2URL = (LPWSTR) malloc( cch * sizeof (WCHAR));
if (!wszStage2URL)
{
Hr = E_OUTOFMEMORY;
goto exitUpload;
}
Hr = StringCchPrintfW(wszStage2URL, cch, c_wszStage2, wszBaseName,
VerInfo[0], VerInfo[1], VerInfo[2], VerInfo[3],
OffsetFromProbType);
if (FAILED(Hr))
{
goto exitUpload;
}
eet = eetUseEventInfo;
ei.cbSEI = sizeof(ei);
ei.wszTitle = L"Microsoft Windows";
ei.wszErrMsg = L"Thank-you for creating an application compatibility report.";
ei.wszHdr = L"Report an Application Compatibility Issue";
ei.wszPlea = L"We have created an error report that you can send to help us improve "
L"Microsoft Windows. We will treat this report as confidential and anonymous.";
ei.wszEventName = L"User initiated report";
ei.fUseLitePlea = FALSE;
ei.wszStage1 = wszStage1URL;
ei.wszStage2 = wszStage2URL;
ei.wszCorpPath = NULL;
ei.wszSendBtn = L"&Send Error Report";
ei.wszNoSendBtn = L"&Don't Send";
ei.wszFileList = wszFileList;
if ((Hr = ReportDwManifest(wszAppCompatText, &ei)) != S_OK)
// if ((Hr = MyReportEREventDW(eet, NULL, &ei)) != S_OK)
{
// we failed
}
exitUpload:
if (wszFileList != NULL) free( wszFileList );
if (wszStage1URL != NULL) free( wszStage1URL );
if (wszStage2URL != NULL) free( wszStage2URL );
// Delete all temporary files
if (wszUerRpt != NULL)
{
DeleteFileW(wszUerRpt);
free (wszUerRpt );
}
if (wszAppCompatText != NULL)
{
DeleteFileW(wszAppCompatText);
wszBaseName = wcsrchr(wszAppCompatText, L'\\');
if (wszBaseName)
{
*wszBaseName = L'\0';
RemoveDirectoryW(wszAppCompatText);
*wszBaseName = L'\\';
}
}
return Hr;
}