shell32 patch 23 c

Martin Fuchs martin-fuchs at gmx.net
Wed Mar 3 14:12:03 CST 2004


Changelog:
- enumerate all "shell\<verb>\command" entries in the registry instead of searching only for "shell\open\command" entries
  To make the code more readable, I moved that part of SHELL_FindExecutable(), which is now called in two different cases
  into a new subfunction SHELL_FindExecutableByOperation().

In effect this patch eliminates this TODO:
/* We set the default to open, and that should generally work.
   But that is not really the way the MS docs say to do it. */


Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.32
diff -u -p -d -w -b -r1.32 shlexec.c
--- shlexec.c	3 Mar 2004 05:26:30 -0000	1.32
+++ shlexec.c	3 Mar 2004 20:07:46 -0000
@@ -267,6 +267,54 @@ end:
     return found;
 }
 
+static UINT SHELL_FindExecutableByOperation(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen)
+{
+    static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
+
+    /* Looking for ...buffer\shell\<verb>\command */
+    strcatW(filetype, wszShell);
+    strcatW(filetype, lpOperation);
+    strcatW(filetype, wCommand);
+
+    if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command,
+                       &commandlen) == ERROR_SUCCESS)
+    {
+	commandlen /= sizeof(WCHAR);
+        if (key) strcpyW(key, filetype);
+#if 0
+        LPWSTR tmp;
+        WCHAR param[256];
+	LONG paramlen = sizeof(param);
+        static const WCHAR wSpace[] = {' ',0};
+
+        /* FIXME: it seems all Windows version don't behave the same here.
+         * the doc states that this ddeexec information can be found after
+         * the exec names.
+         * on Win98, it doesn't appear, but I think it does on Win2k
+         */
+	/* Get the parameters needed by the application
+	   from the associated ddeexec key */
+	tmp = strstrW(filetype, wCommand);
+	tmp[0] = '\0';
+	strcatW(filetype, wDdeexec);
+	if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param,
+				     &paramlen) == ERROR_SUCCESS)
+	{
+	    paramlen /= sizeof(WCHAR);
+            strcatW(command, wSpace);
+            strcatW(command, param);
+            commandlen += paramlen;
+	}
+#endif
+
+	command[commandlen] = '\0';
+
+	return 33; /* FIXME see SHELL_FindExecutable() */
+    }
+
+    return 31;	/* default - 'No association was found' */
+}
+
 /*************************************************************************
  *	SHELL_FindExecutable [Internal]
  *
@@ -294,7 +342,6 @@ static UINT SHELL_FindExecutable(LPCWSTR
     WCHAR filetype[256];     /* registry name for this filetype */
     LONG  filetypelen = sizeof(filetype); /* length of above */
     WCHAR command[256];      /* command from registry */
-    LONG  commandlen = sizeof(command);  /* This is the most DOS can handle :) */
     WCHAR wBuffer[256];      /* Used to GetProfileString */
     UINT  retval = 31;       /* default - 'No association was found' */
     WCHAR *tok;              /* token pointer */
@@ -392,46 +439,46 @@ static UINT SHELL_FindExecutable(LPCWSTR
 	filetypelen /= sizeof(WCHAR);
 	filetype[filetypelen] = '\0';
 	TRACE("File type: %s\n", debugstr_w(filetype));
+    }
 
-	/* Looking for ...buffer\shell\lpOperation\command */
-	strcatW(filetype, wShell);
-	strcatW(filetype, lpOperation);
-	strcatW(filetype, wCommand);
-
-	if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command,
-                           &commandlen) == ERROR_SUCCESS)
+    if (*filetype)
 	{
-	    commandlen /= sizeof(WCHAR);
-            if (key) strcpyW(key, filetype);
-#if 0
-            LPWSTR tmp;
-            WCHAR param[256];
-	    LONG paramlen = sizeof(param);
-            static const WCHAR wSpace[] = {' ',0};
+	if (lpOperation)
+	{
+	    /* pass the operation string to SHELL_FindExecutableByOperation() */
+	    filetype[filetypelen] = '\0';
+	    retval = SHELL_FindExecutableByOperation(lpPath, lpFile, lpOperation, key, filetype, command, sizeof(command));
+	}
+	else
+	{
+	    WCHAR operation[MAX_PATH];
+	    HKEY hkey;
 
-            /* FIXME: it seems all Windows version don't behave the same here.
-             * the doc states that this ddeexec information can be found after
-             * the exec names.
-             * on Win98, it doesn't appear, but I think it does on Win2k
-             */
-	    /* Get the parameters needed by the application
-	       from the associated ddeexec key */
-	    tmp = strstrW(filetype, wCommand);
-	    tmp[0] = '\0';
-	    strcatW(filetype, wDdeexec);
+	    /* Looking for ...buffer\shell\<operation>\command */
+	    strcatW(filetype, wszShell);
 
-	    if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param,
-					 &paramlen) == ERROR_SUCCESS)
+	    /* enumerate the operation subkeys in the registry and search for one with an associated command */
+	    if (RegOpenKeyW(HKEY_CLASSES_ROOT, filetype, &hkey) == ERROR_SUCCESS)
 	    {
-		paramlen /= sizeof(WCHAR);
-                strcatW(command, wSpace);
-                strcatW(command, param);
-                commandlen += paramlen;
+		int idx = 0;
+		for(;; ++idx)
+		{
+		    if (RegEnumKeyW(hkey, idx, operation, MAX_PATH) != ERROR_SUCCESS)
+			break;
+
+		    filetype[filetypelen] = '\0';
+		    retval = SHELL_FindExecutableByOperation(lpPath, lpFile, operation, key, filetype, command, sizeof(command));
+
+		    if (retval > 32)
+			break;
 	    }
-#endif
-            command[commandlen] = '\0';
+		RegCloseKey(hkey);
+	    }
+	}
+
+	if (retval > 32)
+        {
             SHELL_ArgifyW(lpResult, 1024 /*FIXME*/, command, xlpFile);
-            retval = 33; /* FIXME see above */
 	}
     }
     else /* Check win.ini */
@@ -680,7 +727,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
     void *env;
     int gap, len;
     WCHAR lpstrProtocol[256];
-    LPCWSTR lpFile,lpOperation;
+    LPCWSTR lpFile;
     UINT retval = 31;
     WCHAR wcmd[1024];
     BOOL done;
@@ -765,13 +812,6 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
             return FALSE;
     }
 
-    /* We set the default to open, and that should generally work.
-       But that is not really the way the MS docs say to do it. */
-    if (sei->lpVerb == NULL)
-        lpOperation = wszOpen;
-    else
-        lpOperation = sei->lpVerb;
-
     /* Else, try to execute the filename */
     TRACE("execute:'%s','%s'\n", debugstr_w(wszApplicationName), debugstr_w(wszCommandline));
 
@@ -788,7 +828,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
 
     /* Else, try to find the executable */
     wcmd[0] = '\0';
-    retval = SHELL_FindExecutable(sei->lpDirectory, lpFile, lpOperation, wcmd, lpstrProtocol, &env);
+    retval = SHELL_FindExecutable(sei->lpDirectory, lpFile, sei->lpVerb, wcmd, lpstrProtocol, &env);
     if (retval > 32)  /* Found */
     {
         WCHAR wszQuotedCmd[MAX_PATH+2];
@@ -827,7 +867,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         strncpyW(lpstrProtocol, lpFile, iSize);
         lpstrProtocol[iSize] = '\0';
         strcatW(lpstrProtocol, wShell);
-        strcatW(lpstrProtocol, lpOperation);
+        strcatW(lpstrProtocol, sei->lpVerb? sei->lpVerb: wszOpen);
         strcatW(lpstrProtocol, wCommand);
 
         /* Remove File Protocol from lpFile */
@@ -846,7 +886,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         WCHAR lpstrTmpFile[256];
         strcpyW(lpstrTmpFile, wHttp);
         strcatW(lpstrTmpFile, lpFile);
-        retval = (UINT)ShellExecuteW(sei->hwnd, lpOperation, lpstrTmpFile, NULL, NULL, 0);
+        retval = (UINT)ShellExecuteW(sei->hwnd, sei->lpVerb, lpstrTmpFile, NULL, NULL, 0);
     }
 
     TRACE("retval %u\n", retval);





More information about the wine-patches mailing list