#include #include #include #include "dbglog.h" // debug msg stuff void Msg(LPCWSTR pwz) { MessageBox(NULL, pwz, L"ClickOnce", 0); } // ---------------------------------------------------------------------------- void ShowError(LPCWSTR pwz) { MessageBox(NULL, pwz, L"ClickOnce Error", MB_ICONERROR); } // ---------------------------------------------------------------------------- void ShowError(HRESULT hr, LPCWSTR pwz=NULL) { DWORD dwErrorCode = HRESULT_CODE(hr); LPWSTR MessageBuffer = NULL; DWORD dwBufferLength; // ISSUE-2002/03/27-felixybc note: check for E_OUTOFMEMORY? // Call FormatMessage() to allow for message // text to be acquired from the system if(dwBufferLength = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, // module to get message from (NULL == system) dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPWSTR) &MessageBuffer, 0, NULL)) { // BUGBUG: Process any inserts in MessageBuffer LPWSTR pwzMsg = MessageBuffer; CString sMsg; if (pwz != NULL) { if (SUCCEEDED(sMsg.Assign((LPWSTR)pwz))) if (SUCCEEDED(sMsg.Append(L"\n\n"))) if (SUCCEEDED(sMsg.Append(MessageBuffer))) pwzMsg = sMsg._pwz; } // Display the string ShowError(pwzMsg); // Free the buffer allocated by the system LocalFree(MessageBuffer); } else { // ISSUE-2002/03/27-felixybc Error in this error handling code. Should print error code from format msg and orginal hr // should at least print error code? if (pwz != NULL) ShowError((LPWSTR)pwz); else ShowError(L"Error occurred. Unable to retrieve associated error message from the system."); } } /*void _stdcall EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); hwnd - window handle that should be used as the owner window for any windows your DLL creates hinst - your DLL's instance handle lpszCmdLine - ASCIIZ command line your DLL should parse nCmdShow - describes how your DLL's windows should be displayed */ // --------------------------------------------------------------------------- // DisableCurrentVersionW // The rundll32 entry point for rollback to previous version // The function should be named as 'DisableCurrentVersion' on rundll32's command line // --------------------------------------------------------------------------- void CALLBACK DisableCurrentVersionW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { HRESULT hr = S_OK; MAKE_ERROR_MACROS_STATIC(hr); LPVERSION_MANAGEMENT pVerMan = NULL; LPWSTR pwzDisplayNameMask = NULL; IF_FAILED_EXIT(CoInitialize(NULL)); // parse commandline // accepted formats: "displayNameMask" if (*lpszCmdLine == L'\"') { LPWSTR pwz = NULL; pwz = wcschr(lpszCmdLine+1, L'\"'); if (pwz != NULL) { *pwz = L'\0'; pwzDisplayNameMask = lpszCmdLine+1; } } // exit if invalid arguments IF_NULL_EXIT(pwzDisplayNameMask, E_INVALIDARG); IF_FAILED_EXIT(CreateVersionManagement(&pVerMan, 0)); IF_FAILED_EXIT(pVerMan->Rollback(pwzDisplayNameMask)); if (hr == S_FALSE) Msg(L"Application files cannot be found. Operation is aborted."); exit: SAFERELEASE(pVerMan); if (FAILED(hr)) { if (hr != E_ABORT) ShowError(hr); } CoUninitialize(); return; } // --------------------------------------------------------------------------- // UninstallW // The rundll32 entry point for Control Panel's Add/Remove Program // The function should be named as 'Uninstall' on rundll32's command line // --------------------------------------------------------------------------- void CALLBACK UninstallW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { HRESULT hr = S_OK; MAKE_ERROR_MACROS_STATIC(hr); LPVERSION_MANAGEMENT pVerMan = NULL; LPWSTR pwzDisplayNameMask = NULL; LPWSTR pwzDesktopManifestPath = NULL; HKEY hkey = NULL; LONG lReturn = 0; IF_FAILED_EXIT(CoInitialize(NULL)); // parse commandline // accepted formats: "displayNameMask" "pathToDesktopManifest" if (*lpszCmdLine == L'\"') { LPWSTR pwz = NULL; pwz = wcschr(lpszCmdLine+1, L'\"'); if (pwz != NULL) { *pwz = L'\0'; pwzDisplayNameMask = lpszCmdLine+1; pwz = wcschr(pwz+1, L'\"'); if (pwz != NULL) { pwzDesktopManifestPath = pwz+1; pwz = wcschr(pwzDesktopManifestPath, L'\"'); if (pwz != NULL) *pwz = L'\0'; else pwzDesktopManifestPath = NULL; } } } // exit if invalid arguments IF_FALSE_EXIT(pwzDisplayNameMask != NULL && pwzDesktopManifestPath != NULL, E_INVALIDARG); IF_TRUE_EXIT(MessageBox(NULL, L"Do you want to remove this application and unregister its subscription?", L"ClickOnce", MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) != IDYES, E_ABORT); IF_FAILED_EXIT(CreateVersionManagement(&pVerMan, 0)); IF_FAILED_EXIT(pVerMan->Uninstall(pwzDisplayNameMask, pwzDesktopManifestPath)); if (hr == S_FALSE) { IF_TRUE_EXIT(MessageBox(NULL, L"The application can no longer be located on the system. Do you want to remove this entry?", L"ClickOnce", MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDNO, E_ABORT); // delete registry uninstall info extern const WCHAR* pwzUninstallSubKey; // defined in versionmanagement.cpp // open uninstall key lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pwzUninstallSubKey, 0, DELETE, &hkey); IF_WIN32_FAILED_EXIT(lReturn); lReturn = RegDeleteKey(hkey, pwzDisplayNameMask); IF_WIN32_FAILED_EXIT(lReturn); } exit: SAFERELEASE(pVerMan); if (hkey) { lReturn = RegCloseKey(hkey); if (SUCCEEDED(hr)) hr = (HRESULT_FROM_WIN32(lReturn)); } if (FAILED(hr)) { if (hr != E_ABORT) ShowError(hr); } CoUninitialize(); return; } // --------------------------------------------------------------------------- // StartW // The single rundll32 entry point for both shell (file type host) and mimehandler/url // The function should be named as 'Start' on rundll32's command line // --------------------------------------------------------------------------- void CALLBACK StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { HRESULT hr = S_OK; MAKE_ERROR_MACROS_STATIC(hr); LPACTIVATOR pActivator = NULL; LPWSTR pwzShortcutPath = NULL; LPWSTR pwzShortcutUrl = NULL; BOOL bIsFromWeb = FALSE; CDebugLog * pDbgLog = NULL; if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { // ISSUE-2002/03/27-felixybc work around on longhorn builds, avalon bug 1493 if(hr == RPC_E_CHANGED_MODE) hr = S_OK; // allow RPC_E_CHANGED_MODE error for now. else goto exit; } // parse commandline // accepted formats: "Path" "Path" "URL" if (*lpszCmdLine == L'\"') { LPWSTR pwz = NULL; pwz = wcschr(lpszCmdLine+1, L'\"'); if (pwz != NULL) { *pwz = L'\0'; // case 1 desktop/local, path to shortcut only pwzShortcutPath = lpszCmdLine+1; pwz = wcschr(pwz+1, L'\"'); if (pwz != NULL) { pwzShortcutUrl = pwz+1; pwz = wcschr(pwzShortcutUrl, L'\"'); if (pwz != NULL) { *pwz = L'\0'; // case 2 url/mimehandler, path to temp shortcut and source URL bIsFromWeb = TRUE; } } } } // exit if invalid arguments. ShortcutUrl is incomplete if bIsFromWeb is FALSE IF_FALSE_EXIT(!(pwzShortcutPath == NULL || (pwzShortcutUrl != NULL && !bIsFromWeb)), E_INVALIDARG); IF_FAILED_EXIT(CreateLogObject(&pDbgLog, NULL)); IF_FAILED_EXIT(CreateActivator(&pActivator, pDbgLog, 0)); IF_FAILED_EXIT(pActivator->Initialize(pwzShortcutPath, pwzShortcutUrl)); IF_FAILED_EXIT(pActivator->Process()); IF_FAILED_EXIT(pActivator->Execute()); exit: if(pDbgLog) { DUMPDEBUGLOG(pDbgLog, -1, hr); } SAFERELEASE(pActivator); if (FAILED(hr)) { if (hr != E_ABORT) ShowError(hr); } if (bIsFromWeb) { // delete the temp file from the mimehandler // ignore return value DeleteFile(pwzShortcutPath); } CoUninitialize(); SAFERELEASE(pDbgLog); return; }