From 15d1c1036eb6d2bc0465b2990361107aa89eb24d Mon Sep 17 00:00:00 2001 From: "rob_strong@exchangecode.com" Date: Tue, 19 Sep 2006 18:09:58 +0000 Subject: [PATCH] Bug 353089 - Fix / remove ddeexec hack. r=bsmedberg --- .../shell/src/nsWindowsShellService.cpp | 135 +++++------------- .../shell/src/nsWindowsShellService.h | 4 - toolkit/xre/nsNativeAppSupportWin.cpp | 102 +++++++++---- 3 files changed, 108 insertions(+), 133 deletions(-) diff --git a/browser/components/shell/src/nsWindowsShellService.cpp b/browser/components/shell/src/nsWindowsShellService.cpp index 0841362fd2f9..672014432e80 100644 --- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -145,11 +145,12 @@ OpenKeyForWriting(const char* aKeyName, HKEY* aKey, PRBool aForAllUsers, PRBool // are mapped like so: // // HKCU\SOFTWARE\Classes\\ -// DefaultIcon (default) REG_SZ ,1 +// DefaultIcon (default) REG_SZ ,0 // shell\open\command (default) REG_SZ -url "%1" -// shell\open\ddeexec (default) REG_SZ "%1",,-1,0,,,, +// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, // shell\open\ddeexec NoActivateHandler REG_SZ // \application (default) REG_SZ Firefox +// \ifexec (default) REG_SZ ,,0,0,,,, // \topic (default) REG_SZ WWW_OpenURL // // @@ -193,10 +194,12 @@ typedef struct { #define DDE "\\shell\\open\\ddeexec\\" #define DDE_NAME "Firefox" // This must be kept in sync with ID_DDE_APPLICATION_NAME as defined in splash.rc #define DDE_COMMAND "\"%1\",,0,0,,,," +#define DDE_IFEXEC ",,0,0,,,," #define EXE "firefox.exe" #define CLS_HTML "FirefoxHTML" -#define VAL_ICON "%APPPATH%,1" +#define VAL_URL_ICON "%APPPATH%,0" +#define VAL_FILE_ICON "%APPPATH%,1" #define VAL_OPEN "%APPPATH% -url \"%1\"" #define MAKE_KEY_NAME1(PREFIX, MID) \ @@ -223,21 +226,43 @@ static SETTING gSettings[] = { { MAKE_KEY_NAME1(CLS, ".xhtml"), "", CLS_HTML, NO_SUBSTITUTION | NON_ESSENTIAL }, // File Extension Class - { MAKE_KEY_NAME2(CLS, CLS_HTML, DI), "", VAL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME2(CLS, CLS_HTML, DI), "", VAL_FILE_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, { MAKE_KEY_NAME2(CLS, CLS_HTML, SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL }, // Protocol Handlers - { MAKE_KEY_NAME2(CLS, "HTTP", DI), "", VAL_ICON, PATH_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "HTTP", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION }, { MAKE_KEY_NAME2(CLS, "HTTP", SOP), "", VAL_OPEN, PATH_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "HTTPS", DI), "", VAL_ICON, PATH_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "HTTPS", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION }, { MAKE_KEY_NAME2(CLS, "HTTPS", SOP), "", VAL_OPEN, PATH_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "FTP", DI), "", VAL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME2(CLS, "FTP", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, { MAKE_KEY_NAME2(CLS, "FTP", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL }, - { MAKE_KEY_NAME2(CLS, "GOPHER", DI), "", VAL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME2(CLS, "GOPHER", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, { MAKE_KEY_NAME2(CLS, "GOPHER", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL }, - { MAKE_KEY_NAME2(CLS, "CHROME", DI), "", VAL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME2(CLS, "CHROME", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL }, { MAKE_KEY_NAME2(CLS, "CHROME", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL }, + // DDE settings + { MAKE_KEY_NAME2(CLS, "HTTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTP", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "HTTPS", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "FTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "FTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "FTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, + { MAKE_KEY_NAME3(CLS, "FTP", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "GOPHER", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, "CHROME", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL }, + { MAKE_KEY_NAME3(CLS, "CHROME", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION }, + // Windows XP Start Menu { MAKE_KEY_NAME2(SMI, "%APPEXE%", DI), "", @@ -261,29 +286,6 @@ static SETTING gSettings[] = { // firefox.exe\shell\safemode (default) REG_SZ Firefox &Safe Mode }; -static SETTING gDDESettings[] = { - { MAKE_KEY_NAME2(CLS, "HTTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "HTTP", DDE), "NoActivateHandler", "", NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "HTTPS", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "HTTPS", DDE), "NoActivateHandler", "", NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "FTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "FTP", DDE), "NoActivateHandler", "", NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "FTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "FTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "GOPHER", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "GOPHER", DDE), "NoActivateHandler", "", NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "CHROME", DDE), "", DDE_COMMAND, NO_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, "CHROME", DDE), "NoActivateHandler", "", NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION }, - { MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION } -}; - NS_IMETHODIMP nsWindowsShellService::Register(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *registryLocation, const char *componentType, const nsModuleComponentInfo *info) @@ -302,31 +304,6 @@ nsWindowsShellService::nsWindowsShellService() obsServ->AddObserver(this, "quit-application", PR_FALSE); } -nsresult -nsWindowsShellService::RegisterDDESupport() -{ - SETTING* end = gDDESettings + sizeof(gDDESettings)/sizeof(SETTING); - for (SETTING* settings = gDDESettings; settings < end; ++settings) { - nsCAutoString key(settings->keyName); - nsCAutoString data(settings->valueData); - - SetRegKey(key.get(), settings->valueName, data.get(), - PR_FALSE, 0, PR_TRUE, PR_TRUE); - } - return NS_OK; -} - -nsresult -nsWindowsShellService::UnregisterDDESupport() -{ - DeleteRegKey(HKEY_CLASSES_ROOT, "HTTP\\shell\\open\\ddeexec"); - DeleteRegKey(HKEY_CLASSES_ROOT, "HTTPS\\shell\\open\\ddeexec"); - DeleteRegKey(HKEY_CLASSES_ROOT, "FTP\\shell\\open\\ddeexec"); - DeleteRegKey(HKEY_CLASSES_ROOT, "CHROME\\shell\\open\\ddeexec"); - DeleteRegKey(HKEY_CLASSES_ROOT, "GOPHER\\shell\\open\\ddeexec"); - return NS_OK; -} - NS_IMETHODIMP nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefaultBrowser) { @@ -501,9 +478,6 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs // Close the key we opened. ::RegCloseKey(backupKey); - // We need to reregister DDE support - RegisterDDESupport(); - // Refresh the Shell ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)"SOFTWARE\\Clients\\StartMenuInternet", @@ -556,43 +530,6 @@ nsWindowsShellService::RestoreFileSettings(PRBool aForAllUsers) return NS_OK; } -// Utility function to delete a registry subkey. -DWORD -nsWindowsShellService::DeleteRegKey(HKEY baseKey, const char *keyName) -{ - // Make sure input subkey isn't null. - if (!keyName || !::strlen(keyName)) - return ERROR_BADKEY; - - DWORD rc; - // Open subkey. - HKEY key; - rc = ::RegOpenKeyEx(baseKey, keyName, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &key); - - // Continue till we get an error or are done. - while (rc == ERROR_SUCCESS) { - char subkeyName[_MAX_PATH]; - DWORD len = sizeof subkeyName; - // Get first subkey name. Note that we always get the - // first one, then delete it. So we need to get - // the first one next time, also. - rc = ::RegEnumKeyEx(key, 0, subkeyName, &len, 0, 0, 0, 0); - if (rc == ERROR_NO_MORE_ITEMS) { - // No more subkeys. Delete the main one. - rc = ::RegDeleteKey(baseKey, keyName); - break; - } - if (rc == ERROR_SUCCESS) { - // Another subkey, delete it, recursively. - rc = DeleteRegKey(key, subkeyName); - } - } - - // Close the key we opened. - ::RegCloseKey(key); - return rc; -} - void nsWindowsShellService::SetRegKey(const char* aKeyName, const char* aValueName, const char* aValue, PRBool aBackup, @@ -1062,8 +999,6 @@ nsWindowsShellService::Observe(nsISupports* aObject, const char* aTopic, const P IsDefaultBrowser(PR_FALSE, &isDefault); if (!isDefault) return NS_OK; - - return RegisterDDESupport(); } else if (!nsCRT::strcmp("quit-application", aTopic)) { PRBool isDefault; @@ -1073,8 +1008,6 @@ nsWindowsShellService::Observe(nsISupports* aObject, const char* aTopic, const P nsCOMPtr os(do_GetService("@mozilla.org/observer-service;1")); os->RemoveObserver(this, "quit-application"); - - return UnregisterDDESupport(); } return NS_OK; diff --git a/browser/components/shell/src/nsWindowsShellService.h b/browser/components/shell/src/nsWindowsShellService.h index e8905d536130..5ca91e3ab5fc 100644 --- a/browser/components/shell/src/nsWindowsShellService.h +++ b/browser/components/shell/src/nsWindowsShellService.h @@ -66,10 +66,6 @@ protected: void SetRegKey(const char* aKeyName, const char* aValueName, const char* aValue, PRBool aBackup, HKEY aBackupKey, PRBool aReplaceExisting, PRBool aForAllUsers); - DWORD DeleteRegKey(HKEY baseKey, const char *keyName); - - nsresult RegisterDDESupport(); - nsresult UnregisterDDESupport(); private: PRBool mCheckedThisSession; diff --git a/toolkit/xre/nsNativeAppSupportWin.cpp b/toolkit/xre/nsNativeAppSupportWin.cpp index e36e4a82eb5b..b83c40c54a2f 100644 --- a/toolkit/xre/nsNativeAppSupportWin.cpp +++ b/toolkit/xre/nsNativeAppSupportWin.cpp @@ -256,6 +256,47 @@ private: * whether Mozilla is already running. */ +/* Update 2006 September + * + * A change in behavior was implemented in July 2004 which made the + * application add on launch and remove on quit the ddexec registry key. + * See bug 246078. + * Windows Vista has changed the methods used to set an application as default + * and the new methods are incompatible with removing the ddeexec registry key. + * See bug 353089. + * + * OS DDE Sequence: + * 1. OS checks if the dde name is registered. + * 2. If it is registered the OS sends a DDE request with the WWW_OpenURL topic + * and the params as specified in the default value of the ddeexec registry + * key for the verb (e.g. open). + * 3. If it isn't registered the OS launches the executable defined in the + * verb's (e.g. open) command registry key. + * 4. If the ifexec registry key is not present the OS sends a DDE request with + * the WWW_OpenURL topic and the params as specified in the default value of + * the ddeexec registry key for the verb (e.g. open). + * 5. If the ifexec registry key is present the OS sends a DDE request with the + * WWW_OpenURL topic and the params as specified in the ifexec registry key + * for the verb (e.g. open). + * + * Application DDE Sequence: + * 1. If the application is running a DDE request is received DDE with the + * WWW_OpenURL topic and the params as specified in the default value of the + * ddeexec registry key (e.g. "%1",,0,0,,,, where '%1' is the url to open) + * for the verb (e.g. open). + * 2. If the application is not running it is launched with the -url argument. + * + * Note: Typically the application should use the DDE request to open the page + * instead of using a command line argument. The command line argument is + * used to work around when the DDE queue is hung by a different + * application. See bug 53952. + * + * 3. The application receives a DDE request with the WWW_OpenURL topic and the + * params from the ifexec key without the url (e.g. ,,0,0,,,,). The + * application treats this request as a noop internally and returns the + * correct values for the DDE request to the OS. + */ + class nsNativeAppSupportWin : public nsNativeAppSupportBase, public nsIObserver { @@ -976,23 +1017,26 @@ nsNativeAppSupportWin::HandleDDENotification( UINT uType, // transaction t nsCAutoString url; ParseDDEArg(hsz2, 0, url); - // Read the 3rd argument in the command to determine if a - // new window is to be used. - nsCAutoString windowID; - ParseDDEArg(hsz2, 2, windowID); - // "" means to open the URL in a new window. - if ( windowID.Equals( "" ) ) { - url.Insert("mozilla -new-window ", 0); - } - else { - url.Insert("mozilla -url ", 0); - } + if ( !url.Equals( "" ) ) { + // Read the 3rd argument in the command to determine if a + // new window is to be used. + nsCAutoString windowID; + ParseDDEArg(hsz2, 2, windowID); + // "" means to open the URL in a new window. + if ( windowID.Equals( "" ) ) { + url.Insert("mozilla -new-window ", 0); + } + else { + url.Insert("mozilla -url ", 0); + } #if MOZ_DEBUG_DDE - printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() ); + printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() ); #endif - // Now handle it. - HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT); + // Now handle it. + HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT); + } + // Return pseudo window ID. result = CreateDDEData( 1 ); break; @@ -1146,23 +1190,25 @@ nsNativeAppSupportWin::HandleDDENotification( UINT uType, // transaction t nsCAutoString url; ParseDDEArg((const char*) request, 0, url); - // Read the 3rd argument in the command to determine if a - // new window is to be used. - nsCAutoString windowID; - ParseDDEArg((const char*) request, 2, windowID); + if ( !url.Equals( "" ) ) { + // Read the 3rd argument in the command to determine if a + // new window is to be used. + nsCAutoString windowID; + ParseDDEArg((const char*) request, 2, windowID); - // "" means to open the URL in a new window. - if ( windowID.Equals( "" ) ) { - url.Insert("mozilla -new-window ", 0); - } - else { - url.Insert("mozilla -url ", 0); - } + // "" means to open the URL in a new window. + if ( windowID.Equals( "" ) ) { + url.Insert("mozilla -new-window ", 0); + } + else { + url.Insert("mozilla -url ", 0); + } #if MOZ_DEBUG_DDE - printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() ); + printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() ); #endif - // Now handle it. - HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT); + // Now handle it. + HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT); + } // Release the data. DdeUnaccessData( hdata );