|
|
// Upload.cpp : Implementation of CUpload
#include "stdafx.h"
#include "resource.h"
#include "CompatUI.h"
#include "shlobj.h"
extern "C" { #include "shimdb.h"
}
#include "Upload.h"
TCHAR szKeyDataFiles[] = TEXT("DataFiles");
//
// lives in util.cpp
//
BOOL GetExePathFromObject( LPCTSTR lpszPath, // path to an arbitrary object
CComBSTR& bstrExePath );
//
// lives in proglist.cpp
//
wstring LoadResourceString(UINT nID);
//
// lives in ntutil.c
//
extern "C" BOOL WINAPI CheckFileLocation( LPCWSTR pwszDosPath, BOOL* pbRoot, BOOL* pbLeaf );
//
// conversion
//
BOOL VariantToBOOL(CComVariant& v) { if (SUCCEEDED(v.ChangeType(VT_BOOL))) { return v.boolVal; }
return FALSE; }
wstring VariantToStr(CComVariant& v) { wstring str;
if (v.vt != VT_EMPTY && v.vt != VT_NULL) { if (SUCCEEDED(v.ChangeType(VT_BSTR))) { str = v.bstrVal; } }
return str; }
HRESULT StringToVariant(VARIANT* pv, const wstring& str) { HRESULT hr = E_FAIL;
pv->vt = VT_NULL; pv->bstrVal = ::SysAllocString(str.c_str()); if (pv->bstrVal == NULL) { hr = E_OUTOFMEMORY; } else { pv->vt = VT_BSTR; hr = S_OK; }
return hr; }
BOOL GetTempFile( LPCTSTR lpszPrefix, CComBSTR& bstrFile ) { DWORD dwLength; TCHAR szBuffer[MAX_PATH]; TCHAR szTempFile[MAX_PATH];
dwLength = GetTempPath(CHARCOUNT(szBuffer), szBuffer); if (!dwLength || dwLength > CHARCOUNT(szBuffer)) { return FALSE; }
//
// we got directory, generate the file now
//
dwLength = GetTempFileName(szBuffer, lpszPrefix, 0, szTempFile); if (!dwLength) { return FALSE; }
bstrFile = szTempFile; return TRUE;
}
wstring StrUpCase(wstring& wstr) { ctype<wchar_t> _ct; wstring::iterator iter;
for (iter = wstr.begin(); iter != wstr.end(); ++iter) { (*iter) = _ct.toupper(*iter); }
return wstr; }
/////////////////////////////////////////////////////////////////////////////
// CUpload
BOOL CUpload::GetDataFilesKey(CComBSTR& bstrVal) { // STRVEC::iterator iter;
MAPSTR2MFI::iterator iter;
bstrVal.Empty();
for (iter = m_DataFiles.begin(); iter != m_DataFiles.end(); ++iter) { if (bstrVal.Length()) { bstrVal.Append(TEXT("|")); } bstrVal.Append((*iter).second.strFileName.c_str()); } return bstrVal.Length() != 0;
}
STDMETHODIMP CUpload::SetKey(BSTR pszKey, VARIANT* pvValue) { wstring strKey = pszKey; VARIANT vStr; HRESULT hr; HRESULT hrRet = S_OK;
//
// dwwin is case-sensitive
//
// StrUpCase(strKey);
if (strKey == szKeyDataFiles) { // data files cannot be set directly
return E_INVALIDARG; }
VariantInit(&vStr);
hr = VariantChangeType(&vStr, pvValue, 0, VT_BSTR); if (SUCCEEDED(hr)) { wstring strVal = vStr.bstrVal;
m_mapManifest[strKey] = strVal; } else if (pvValue->vt == VT_NULL || pvValue->vt == VT_EMPTY) { m_mapManifest.erase(strKey); } else { hrRet = E_INVALIDARG; } VariantClear(&vStr);
return hrRet; }
STDMETHODIMP CUpload::GetKey(BSTR pszKey, VARIANT *pValue) { CComBSTR bstrVal; wstring strKey = pszKey;
// StrUpCase(strKey);
if (strKey == szKeyDataFiles) { //
// data files -- handled separately
//
if (GetDataFilesKey(bstrVal)) { pValue->vt = VT_BSTR; pValue->bstrVal = bstrVal.Copy(); } else { pValue->vt = VT_NULL; }
} else {
MAPSTR2STR::iterator iter = m_mapManifest.find(strKey); if (iter != m_mapManifest.end()) { bstrVal = (*iter).second.c_str(); pValue->vt = VT_BSTR; pValue->bstrVal = bstrVal.Copy(); } else { pValue->vt = VT_NULL; } } return S_OK; }
#define DWWIN_HEADLESS_MODE 0x00000080
BOOL CUpload::IsHeadlessMode(void) { CComVariant varFlags; HRESULT hr; BOOL bHeadless = FALSE;
GetKey(TEXT("Flags"), &varFlags);
hr = varFlags.ChangeType(VT_I4); if (SUCCEEDED(hr)) { bHeadless = !!(varFlags.lVal & DWWIN_HEADLESS_MODE); }
return bHeadless; }
/*
DWORD CUpload::CountFiles(DWORD nLevel, LPCWSTR pszPath) { WIN32_FIND_DATA wfd; wstring strPath = pszPath; wstring::size_type nPos; HANDLE hFind = INVALID_HANDLE_VALUE; DWORD dwCount = 0;
nPos = strPath.length(); if (strPath[nPos-1] != TEXT('\\')) { strPath += TEXT('\\'); ++nPos; }
FindFirstFileExW(
strPath += TEXT('*');
hFind = FindFirstFile(strPath.c_str(), &wfd); if (hFind != INVALID_HANDLE_VALUE) { do { if (nLevel < 3 && wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (wcscmp(wfd.cFileName, TEXT(".")) && wcscmp(wfd.cFileName, TEXT(".."))) { strPath.replace(nPos, wstring::nPos, wfd.cFileName); dwCount += CountFiles(nLevel + 1, strPath.c_str()); } } else { // file
++dwCount; } } while (FindNextFile(hFind, &wfd));
FindClose(hFind); }
return dwCount; } */
BOOL CALLBACK CUpload::_GrabmiCallback( LPVOID lpvCallbackParam, // application-defined parameter
LPCTSTR lpszRoot, // root directory path
LPCTSTR lpszRelative, // relative path
PATTRINFO pAttrInfo, // attributes
LPCWSTR pwszXML // resulting xml
) { GMEPARAMS* pParams = (GMEPARAMS*)lpvCallbackParam;
CUpload* pT = pParams->first; IProgressDialog* ppd = pParams->second;
if (ppd == NULL) { return TRUE; }
ppd->SetLine(2, lpszRoot, TRUE, NULL);
// ppd->SetLine(2, lpszRelative, TRUE, NULL);
return !ppd->HasUserCancelled(); }
STDMETHODIMP CUpload::AddMatchingInfo( BSTR pszCommand, VARIANT vFilter, VARIANT vKey, VARIANT vDescription, VARIANT vProgress, BOOL *pbSuccess) {
/* HANDLE hThread = NULL;
DWORD dwExitCode = 0; DWORD dwWait; */
CComVariant varFilter(vFilter); DWORD dwFilter = GRABMI_FILTER_NORMAL; wstring strKey; wstring strDescription;
if (SUCCEEDED(varFilter.ChangeType(VT_I4))) { dwFilter = (DWORD)varFilter.lVal; }
strKey = VariantToStr(CComVariant(vKey)); strDescription = VariantToStr(CComVariant(vDescription));
*pbSuccess = AddMatchingInfoInternal(::GetActiveWindow(), pszCommand, dwFilter, VariantToBOOL(CComVariant(vProgress)), strKey.empty() ? NULL : strKey.c_str(), strDescription.empty() ? NULL : strDescription.c_str());
/*
MITHREADPARAMBLK* pParam = new MITHREADPARAMBLK; CComVariant varFilter(vFilter);
if (!pParam) { goto cleanup; }
pParam->pThis = this; pParam->strCommand = pszCommand; pParam->hwndParent = ::GetActiveWindow(); pParam->dwFilter = GRABMI_FILTER_NORMAL;
if (SUCCEEDED(varFilter.ChangeType(VT_I4))) { pParam->dwFilter = (DWORD)varFilter.lVal; }
pParam->bNoProgress = VariantToBOOL(CComVariant(vProgress)); pParam->strKey = VariantToStr(CComVariant(vKey)); pParam->strDescription = VariantToStr(CComVariant(vDescription));
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_AddMatchingInfoThreadProc, (LPVOID)pParam, 0, NULL); if (!hThread) { goto cleanup; }
dwWait = WaitForSingleObject(hThread, INFINITE); if (dwWait != WAIT_OBJECT_0) { goto cleanup; }
GetExitCodeThread(hThread, &dwExitCode);
cleanup: if (hThread) { CloseHandle(hThread); }
*pbSuccess = !!dwExitCode; */
return S_OK; }
DWORD WINAPI CUpload::_AddMatchingInfoThreadProc(LPVOID lpvThis) { BOOL bSuccess; HRESULT hr;
MITHREADPARAMBLK* pParam = (MITHREADPARAMBLK*)lpvThis; if (!pParam->bNoProgress) { hr = CoInitialize(NULL); if (!SUCCEEDED(hr)) { pParam->bNoProgress = TRUE; } }
bSuccess = pParam->pThis->AddMatchingInfoInternal(::GetActiveWindow(), pParam->strCommand.c_str(), pParam->dwFilter, pParam->bNoProgress, pParam->strKey.empty() ? NULL : pParam->strKey.c_str(), pParam->strDescription.empty() ? NULL : pParam->strDescription.c_str()); if (!pParam->bNoProgress) { CoUninitialize(); } delete pParam; return bSuccess; }
BOOL CUpload::AddMatchingInfoInternal( HWND hwndParent, LPCWSTR pszCommand, DWORD dwFilter, BOOL bNoProgress, LPCTSTR pszKey, LPCTSTR pszDescription) { CComBSTR bstrPath; CComBSTR bstrGrabmiFile; BOOL bSuccess = FALSE;
IProgressDialog * ppd = NULL; HRESULT hr; GMEPARAMS GrabmiParams; MFI MatchingFileInfo; wstring strKey;
UINT DriveType; BOOL bLeaf = NULL; BOOL bRoot = NULL; DWORD dwFilters[3]; wstring Paths[3]; int nDrive; DWORD nPasses = 1; wstring DriveRoot(TEXT("X:\\"));
//
// this is kinda dangerous, the way it works. We collect the info while yielding to the
// creating process (due to the start dialog
// so the calling window needs to be disabled -- or we need to trap doing something else
// while we're collecting data
//
if (!::GetExePathFromObject(pszCommand, bstrPath)) { return FALSE; }
//
// bstrPath is exe path, create and grab matching info
//
if (!GetTempFile(TEXT("ACG"), bstrGrabmiFile)) { goto cleanup; }
//
// we are going to run grabmi!!!
//
//
// prepare callback
//
if (!bNoProgress) { hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void **)&ppd); if (!SUCCEEDED(hr)) { ppd = NULL; } }
//
// check to see what happened to hr
//
if (ppd) { wstring strCaption;
strCaption = LoadResourceString(IDS_COLLECTINGDATACAPTION); ppd->SetTitle(strCaption.c_str()); // Set the title of the dialog.
ppd->SetAnimation (_Module.GetModuleInstance(), IDA_FINDANIM); // Set the animation to play.
strCaption = LoadResourceString(IDS_WAITCLEANUP); ppd->SetCancelMsg (strCaption.c_str(), NULL); // Will only be displayed if Cancel
strCaption = LoadResourceString(IDS_GRABMISTATUS_COLLECTING); ppd->SetLine(1, strCaption.c_str(), FALSE, NULL);
ppd->StartProgressDialog(hwndParent, NULL, PROGDLG_NOPROGRESSBAR| PROGDLG_MODAL| PROGDLG_NOMINIMIZE| PROGDLG_NORMAL| PROGDLG_NOTIME, NULL); // Display and enable automatic estimated time remain
}
//
// this is where we have to determine whether grabmi is a going to be running wild
// Check the drive first to see whether it's removable media
// cases : leaf node / root node
// : system directory
// : cd-rom
// : temp directory
// there could be many combinations
//
if (ppd) { wstring strCaption = LoadResourceString(IDS_CHECKING_FILES); ppd->SetLine(2, strCaption.c_str(), FALSE, NULL); }
//
// this is the default filter we shall use
//
dwFilters[0] = GRABMI_FILTER_PRIVACY; Paths [0] = bstrPath; nPasses = 1;
//
// determine if it's root/leaf node (could be both)
//
if (!CheckFileLocation(bstrPath, &bRoot, &bLeaf)) { // we cannot check the file's location
goto GrabInformation; }
DriveType = GetDriveTypeW(bstrPath); // this will give us *some* clue
// rules:
// cdrom and not root -- three passes
// root - add current file
//
if (bRoot || DRIVE_REMOTE == DriveType) {
dwFilters[0] |= GRABMI_FILTER_LIMITFILES;
} else if (DRIVE_CDROM == DriveType) {
nDrive = PathGetDriveNumber(bstrPath); if (nDrive >= 0) { dwFilters[0] |= GRABMI_FILTER_NOCLOSE|GRABMI_FILTER_APPEND;
dwFilters[1] = GRABMI_FILTER_NORECURSE|GRABMI_FILTER_APPEND; Paths [1] = DriveRoot; Paths [1].at(0) = (WCHAR)(TEXT('A') + nDrive); nPasses = 2; }
}
if (bLeaf) { // we may want to do more here -- future dev
; }
GrabInformation:
//
// set callback context
//
GrabmiParams.first = this; GrabmiParams.second = ppd;
while (nPasses-- > 0) {
if (SdbGrabMatchingInfoEx(Paths[nPasses].c_str(), dwFilters[nPasses], bstrGrabmiFile, _GrabmiCallback, (LPVOID)&GrabmiParams) == GMI_FAILED) { goto cleanup; } }
//
// figure out the key/description
//
if (pszDescription) { MatchingFileInfo.strDescription = pszDescription; }
MatchingFileInfo.strFileName = bstrGrabmiFile; MatchingFileInfo.bOwn = TRUE; // we have generated this file
//
// key
//
if (pszKey == NULL) { strKey = MatchingFileInfo.strFileName; } else { strKey = pszKey; } StrUpCase(strKey);
m_DataFiles[strKey] = MatchingFileInfo;
// m_DataFiles.push_back(StrUpCase(wstring(bstrGrabmiFile)));
//
//
//
bSuccess = TRUE;
cleanup: if (ppd) { ppd->StopProgressDialog(); ppd->Release(); }
return bSuccess; }
STDMETHODIMP CUpload::AddDataFile( BSTR pszDataFile, VARIANT vKey, VARIANT vDescription, VARIANT vOwn) { MFI MatchingFileInfo; wstring strKey = VariantToStr(CComVariant(vKey)); BOOL bKeyFromName = FALSE;
if (strKey.empty()) { strKey = pszDataFile; bKeyFromName = TRUE; } StrUpCase(strKey);
if (m_DataFiles.find(strKey) != m_DataFiles.end() && !bKeyFromName) { CComBSTR bstrKey = strKey.c_str(); RemoveDataFile(bstrKey); }
MatchingFileInfo.strDescription = VariantToStr(CComVariant(vDescription)); MatchingFileInfo.strFileName = pszDataFile; MatchingFileInfo.bOwn = VariantToBOOL(CComVariant(vOwn));
m_DataFiles[strKey] = MatchingFileInfo;
// m_DataFiles.push_back(StrUpCase(wstring(pszDataFile)));
return S_OK; }
STDMETHODIMP CUpload::RemoveDataFile(BSTR pszDataFile) { // STRVEC::iterator iter;
MAPSTR2MFI::iterator iter; wstring strFileName;
wstring strDataFile = pszDataFile;
StrUpCase(strDataFile);
iter = m_DataFiles.find(strDataFile); if (iter != m_DataFiles.end()) { if ((*iter).second.bOwn) { ::DeleteFile((*iter).second.strFileName.c_str()); }
m_DataFiles.erase(iter); }
/*
for (iter = m_DataFiles.begin(); iter != m_DataFiles.end(); ++iter) { if (*iter == strDataFile) { //
// found it
//
m_DataFiles.erase(iter); break; } } */ return S_OK; }
STDMETHODIMP CUpload::CreateManifestFile(BOOL *pbSuccess) { //
// manifest file creation code
//
HANDLE hFile = INVALID_HANDLE_VALUE; WCHAR UNICODE_MARKER[] = { (WCHAR)0xFEFF, L'\r', L'\n' }; MAPSTR2STR::iterator iter; DWORD dwWritten; wstring strLine; CComBSTR bstrDataFiles; BOOL bResult; BOOL bSuccess = FALSE;
if (!GetTempFile(TEXT("ACM"), m_bstrManifest)) { goto cleanup; }
//
// m_bstrManifest is our file
//
hFile = CreateFileW(m_bstrManifest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { goto cleanup; }
bResult = WriteFile(hFile, UNICODE_MARKER, sizeof(UNICODE_MARKER), &dwWritten, NULL); if (!bResult) { goto cleanup; }
//
// done with the marker, now do the manifest strings
//
//
for (iter = m_mapManifest.begin(); iter != m_mapManifest.end(); ++iter) { strLine = (*iter).first + TEXT('=') + (*iter).second + TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; } }
//
// done with the general stuff, do the data files
//
if (GetDataFilesKey(bstrDataFiles)) { strLine = wstring(szKeyDataFiles) + TEXT('=') + wstring(bstrDataFiles) + TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; } } bSuccess = TRUE;
cleanup:
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
if (!bSuccess && m_bstrManifest.Length()) { DeleteFile(m_bstrManifest); m_bstrManifest.Empty(); } *pbSuccess = bSuccess;
return S_OK; }
STDMETHODIMP CUpload::SendReport(BOOL *pbSuccess) { UINT uSize; TCHAR szSystemWindowsDirectory[MAX_PATH]; wstring strDWCmd; wstring strDWPath; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; DWORD dwWait; BOOL bSuccess = FALSE; BOOL bResult; DWORD dwExitCode; BOOL bTerminated = FALSE; DWORD dwTimeout = 10; // 10ms per ping
//
// Create Progress dialog
//
IProgressDialog * ppd = NULL; HRESULT hr;
if (IsHeadlessMode()) {
hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void **)&ppd); if (!SUCCEEDED(hr)) { ppd = NULL; } }
//
// check to see what happened to hr
//
if (ppd) { wstring strCaption;
strCaption = LoadResourceString(IDS_SENDINGCAPTION); ppd->SetTitle(strCaption.c_str()); // Set the title of the dialog.
ppd->SetAnimation (_Module.GetModuleInstance(), IDA_WATSONANIM); // Set the animation to play.
strCaption = LoadResourceString(IDS_WAITCLEANUP); ppd->SetCancelMsg (strCaption.c_str(), NULL); // Will only be displayed if Cancel
strCaption = LoadResourceString(IDS_LAUNCHINGDR); ppd->SetLine (1, strCaption.c_str(), FALSE, NULL);
ppd->StartProgressDialog(::GetActiveWindow(), NULL, PROGDLG_NOPROGRESSBAR| PROGDLG_MODAL| PROGDLG_NOMINIMIZE| PROGDLG_NORMAL| PROGDLG_NOTIME, NULL); // Display and enable automatic estimated time remain
}
uSize = ::GetSystemWindowsDirectory(szSystemWindowsDirectory, CHARCOUNT(szSystemWindowsDirectory)); if (uSize == 0 || uSize > CHARCOUNT(szSystemWindowsDirectory)) { goto cleanup; }
strDWPath = szSystemWindowsDirectory; if (strDWPath.at(strDWPath.length() - 1) != TCHAR('\\')) { strDWPath.append(TEXT("\\")); }
strDWPath += TEXT("system32\\dwwin.exe"); strDWCmd = strDWPath + TEXT(" -d ") + (LPCWSTR)m_bstrManifest;
ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
bResult = CreateProcess(strDWPath.c_str(), (LPWSTR)strDWCmd.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo); if (bResult) { //
// recover an exit code please
//
if (ppd) { wstring strSending = LoadResourceString(IDS_SENDINGINFO); ppd->SetLine(1, strSending.c_str(), FALSE, NULL); } while(TRUE) { dwWait = WaitForSingleObject(ProcessInfo.hProcess, dwTimeout); if (dwWait == WAIT_OBJECT_0) { if (GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode)) { bSuccess = (dwExitCode == 0); } else { bSuccess = FALSE; } break;
} else if (dwWait == WAIT_TIMEOUT) {
//
// check the cancel button
//
if (ppd && !bTerminated && ppd->HasUserCancelled()) { TerminateProcess(ProcessInfo.hProcess, (UINT)-1); bTerminated = TRUE; bSuccess = FALSE; dwTimeout = 1000; // wait a bit longer
}
} else { // object somehow became abandoned
bSuccess = FALSE; break; } }
}
if (ppd) { wstring strCleaningUp = LoadResourceString(IDS_CLEANINGUP); ppd->SetLine(1, strCleaningUp.c_str(), FALSE, NULL); }
cleanup:
if (ProcessInfo.hThread) { CloseHandle(ProcessInfo.hThread); } if (ProcessInfo.hProcess) { CloseHandle(ProcessInfo.hProcess); }
if (ppd) { ppd->StopProgressDialog(); ppd->Release(); }
*pbSuccess = bSuccess;
return S_OK; }
wstring MakeXMLAttr(LPCTSTR lpszName, LPCTSTR lpszValue) { wstring str; wstring strVal; LPCTSTR pch; wstring::size_type nPos = 0; int nlen;
if (NULL != lpszValue) { strVal = lpszValue; }
// find and replace: all the instances of " & < >
//
while (nPos != wstring::npos && nPos < strVal.length()) {
nPos = strVal.find_first_of(TEXT("&\"<>"), nPos); if (nPos == wstring::npos) { break; }
switch(strVal.at(nPos)) { case TEXT('&'): pch = TEXT("&"); break;
case TEXT('>'): pch = TEXT(">"); break;
case TEXT('<'): pch = TEXT("<"); break;
case TEXT('\"'): pch = TEXT("""); break; default: // lunacy, we saw it -- and now it's gone
pch = NULL; break; }
if (pch) { strVal.replace(nPos, 1, pch); // one character
nPos += _tcslen(pch); } }
// once we got the string, assign
str = lpszName; str += TEXT("=\""); str += strVal; str += TEXT("\"");
return str; }
wstring MakeXMLAttr(LPCTSTR lpszName, LONG lValue) { WCHAR szBuf[32]; wstring str;
swprintf(szBuf, TEXT("\"0x%lx\""), lValue);
str = lpszName; str += TEXT("="); str += szBuf; return str; }
wstring MakeXMLLayers(LPCTSTR lpszLayers) { wstring str; wstring strLayer; LPCTSTR pch, pbrk;
//
// partition the string
//
pch = lpszLayers;
while (pch && *pch != TEXT('\0')) {
pch += _tcsspn(pch, TEXT(" \t"));
// check if we're not at the end
if (*pch == TEXT('\0')) { break; }
pbrk = _tcspbrk(pch, TEXT(" \t")); if (pbrk == NULL) { // from pch to the end of the string
strLayer.assign(pch); } else { strLayer.assign(pch, (int)(pbrk-pch)); }
if (!str.empty()) { str += TEXT("\r\n"); } str += TEXT(" "); // lead-in
str += TEXT("<LAYER NAME=\""); str += strLayer; str += TEXT("\"/>");
pch = pbrk; }
return str; }
STDMETHODIMP CUpload::AddDescriptionFile( BSTR pszApplicationName, BSTR pszApplicationPath, LONG lMediaType, BOOL bCompatSuccess, VARIANT* pvFixesApplied, VARIANT vKey, BOOL *pbSuccess ) {
//
// manifest file creation code
//
HANDLE hFile = INVALID_HANDLE_VALUE; WCHAR UNICODE_MARKER[] = { (WCHAR)0xFEFF, L'\r', L'\n' }; DWORD dwWritten; wstring strLine; CComBSTR bstrDescriptionFile; BOOL bResult; BOOL bSuccess = FALSE; WCHAR szBuf[32]; VARIANT vFixes; MFI MatchingFileInfo; wstring strKey = VariantToStr(CComVariant(vKey)); wstring strLayers; static TCHAR szTab[] = TEXT(" "); static TCHAR szCRTab[] = TEXT("\r\n "); VariantInit(&vFixes);
if (!GetTempFile(TEXT("ACI"), bstrDescriptionFile)) { goto cleanup; }
//
// m_bstrManifest is our file
//
hFile = CreateFileW(bstrDescriptionFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { goto cleanup; }
bResult = WriteFile(hFile, UNICODE_MARKER, sizeof(UNICODE_MARKER), &dwWritten, NULL); if (!bResult) { goto cleanup; }
// xml marker
strLine = TEXT("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
// compose compat wizard...
strLine = TEXT("<CompatWizardResults"); strLine += TEXT(' '); strLine += MakeXMLAttr(TEXT("ApplicationName"), pszApplicationName); strLine += szCRTab; strLine += MakeXMLAttr(TEXT("ApplicationPath"), pszApplicationPath); strLine += szCRTab; strLine += MakeXMLAttr(TEXT("MediaType"), lMediaType); strLine += szCRTab; strLine += MakeXMLAttr(TEXT("CompatibilityResult"), bCompatSuccess ? TEXT("Success") : TEXT("Failure")); strLine += TEXT(">\r\n");
if (SUCCEEDED(VariantChangeType(&vFixes, pvFixesApplied, 0, VT_BSTR))) { strLayers = vFixes.bstrVal; }
if (!strLayers.empty()) { //
// parse the layers string and get all of them listed
//
strLine += MakeXMLLayers(strLayers.c_str()); strLine += TEXT("\r\n"); }
strLine += TEXT("</CompatWizardResults>\r\n");
// we are done generating data, write it all out
bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
/*
//
// after we get through the descriptions
// write out data
strLine = TEXT("[CompatWizardResults]\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
//
// write out all the info
//
strLine = TEXT("ApplicationName="); strLine += pszApplicationName; strLine += TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
strLine = TEXT("ApplicationPath="); strLine += pszApplicationPath; strLine += TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
strLine = TEXT("MediaType="); _sntprintf(szBuf, CHARCOUNT(szBuf), TEXT("0x%lx"), lMediaType); strLine += szBuf; strLine += TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
//
// success
//
strLine = TEXT("CompatibilityResult="); strLine += bCompatSuccess ? TEXT("Success") : TEXT("Failure"); strLine += TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; }
//
// fixes applied
//
strLine = TEXT("Layers="); if (!SUCCEEDED(VariantChangeType(&vFixes, pvFixesApplied, 0, VT_BSTR))) { strLine += TEXT("none"); } else { strLine += vFixes.bstrVal; } strLine += TEXT("\r\n"); bResult = WriteFile(hFile, strLine.c_str(), strLine.length() * sizeof(WCHAR), &dwWritten, NULL); if (!bResult) { goto cleanup; } */
// standard file -- manifesto
MatchingFileInfo.strDescription = TEXT("Application Compatibility Description File"); MatchingFileInfo.strFileName = bstrDescriptionFile; MatchingFileInfo.bOwn = TRUE;
//
// key is the filename prefixed by ACI_c:\foo\bar.exe
//
if (strKey.empty()) { strKey = TEXT("ACI_"); strKey += pszApplicationPath; } StrUpCase(strKey);
m_DataFiles[strKey] = MatchingFileInfo;
// m_DataFiles.push_back(StrUpCase(wstring(bstrDescriptionFile)));
bSuccess = TRUE;
cleanup:
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
if (!bSuccess && bstrDescriptionFile.Length()) { DeleteFile(bstrDescriptionFile); } *pbSuccess = bSuccess;
VariantClear(&vFixes);
return S_OK; }
STDMETHODIMP CUpload::DeleteTempFiles() { // kill all the supplemental files
// STRVEC::iterator iter;
MAPSTR2MFI::iterator iter;
for (iter = m_DataFiles.begin(); iter != m_DataFiles.end(); ++iter) { if ((*iter).second.bOwn) { ::DeleteFile((*iter).second.strFileName.c_str()); } }
m_DataFiles.clear();
//
// kill the manifest
//
if (m_bstrManifest.Length() > 0) { ::DeleteFile((LPCTSTR)m_bstrManifest); } m_bstrManifest.Empty();
return S_OK; }
VOID CUpload::ListTempFiles(wstring& str) { // STRVEC::iterator iter;
MAPSTR2MFI::iterator iter;
str = TEXT("");
for (iter = m_DataFiles.begin(); iter != m_DataFiles.end(); ++iter) { if (!str.empty()) { str += TEXT(";"); } str += (*iter).second.strFileName.c_str(); }
/* // this will show the manifest file as well -- but I don't think we need to
// do this as the manifest is irrelevant
if (!str.empty()) { str += TEXT("\r\n"); } str += (LPCTSTR)m_bstrManifest; */ }
STDMETHODIMP CUpload::ShowTempFiles() { TCHAR szMshtml[] = TEXT("mshtml.dll"); TCHAR szModuleFileName[MAX_PATH]; LPMONIKER pmk = NULL; HRESULT hr; CComVariant vargIn; CComVariant vargOut; DWORD dwLength; TCHAR szUrl2[MAX_PATH]; wstring strURL = TEXT("res://"); wstring strArg; SHOWHTMLDIALOGFN* pfnShowDlg = NULL;
HMODULE hMshtml = ::GetModuleHandle(szMshtml); if (NULL == hMshtml) { hMshtml = ::LoadLibrary(szMshtml); if (NULL == hMshtml) { goto cleanup; } }
pfnShowDlg = (SHOWHTMLDIALOGFN*)GetProcAddress(hMshtml, "ShowHTMLDialog");
if (NULL == pfnShowDlg) { goto cleanup; }
dwLength = ::GetModuleFileName(_Module.GetModuleInstance(), szModuleFileName, CHARCOUNT(szModuleFileName));
if (dwLength == 0 || dwLength >= CHARCOUNT(szModuleFileName)) { goto cleanup; }
_sntprintf(szUrl2, CHARCOUNT(szUrl2), TEXT("/#%d/%s"), (int)PtrToInt(RT_HTML), IDR_SHOWTEMPFILESDLG);
strURL += szModuleFileName; strURL += szUrl2;
hr = CreateURLMoniker(NULL, strURL.c_str(), &pmk);
if (!SUCCEEDED(hr)) { goto cleanup; }
ListTempFiles(strArg); // create argument In
vargIn = strArg.c_str();
pfnShowDlg(::GetActiveWindow(), pmk, &vargIn, TEXT("center:yes"), &vargOut);
cleanup:
if (NULL != pmk) { pmk->Release(); }
return S_OK; }
STDMETHODIMP CUpload::GetDataFile(VARIANT vKey, LONG InformationClass, VARIANT* pVal) { CComVariant varKey(vKey); LONG lIndex; MAPSTR2MFI::iterator iter; wstring str; HRESULT hr = S_OK;
pVal->vt = VT_NULL;
switch(InformationClass) { case InfoClassCount: // requested: counter
pVal->vt = VT_I4; pVal->lVal = m_DataFiles.size(); break;
case InfoClassKey:
if (!SUCCEEDED(varKey.ChangeType(VT_I4))) { break; } lIndex = varKey.lVal; iter = m_DataFiles.begin(); while (iter != m_DataFiles.end() && lIndex > 0) { ++iter; --lIndex; }
if (iter != m_DataFiles.end()) { hr = StringToVariant(pVal, (*iter).first); } break;
case InfoClassFileName: case InfoClassDescription:
if (SUCCEEDED(varKey.ChangeType(VT_I4))) { lIndex = varKey.lVal; iter = m_DataFiles.begin(); while (iter != m_DataFiles.end() && lIndex > 0) { ++iter; --lIndex; }
} else if (SUCCEEDED(varKey.ChangeType(VT_BSTR))) { str = varKey.bstrVal; iter = m_DataFiles.find(str); }
if (iter != m_DataFiles.end()) { switch(InformationClass) { case InfoClassFileName: str = (*iter).second.strFileName; break;
case InfoClassDescription: str = (*iter).second.strDescription; break; }
hr = StringToVariant(pVal, str);
} break; default: break; }
return hr; }
|