Drop 3 character extension restriction!!!

Francois Gouget fgouget at codeweavers.com
Thu Apr 8 18:49:05 CDT 2004


I can only invite janitors to closely review the shlexec.c code. It 
badly needs it as the couple of upcoming patches will show:

ShellExecuteEx needs to get the file extension in order to know what to 
do. Let's see how this works:


     WCHAR wtmpext[5];

This buffer is used to store a copy of the extension to be modified. Why 
5 character? Well, 1 for the '.', 1 for the '\0' -> 3 for the extension!
What about '.mpeg' or '.jpeg'? How well.


     extension = strrchrW(xlpFile, '.');
     if ((extension == NULL) || (extension == xlpFile[strlenW(xlpFile)]))

After this strrchrW call, either extension is NULL or it points to a 
'.'. xlpFile[strlenW(xlpFile)] always contains '\0' and thus can never 
be equal to extension. CQFD

I believe the intention was to check for filenames having no '.' at all, 
or having a trailing '.': if we have a trailing '.' then the extension 
is empty and it cannot match any file handler. Please let me know if I'm 
wrong.


    CharLowerW(wtmpext);
    ...
    if (strcmpW(tok, &wtmpext[1]) == 0)

    This is to match the contents of win.ini against the extension. 
However, are we sure that the extension is going to be in lower-case in 
win.ini? I believe it would be safer / more correct to do a case 
insensitive comparison here.


    if (RegQueryValueW(HKEY_CLASSES_ROOT, wtmpext, filetype,

    And this is the other reason for the wtmpext buffer. Except it's no 
reason at all since the registry is case insensitive. So the above call 
will work just as well with '.Pdf' as with '.pdf'.

So I removed the wtmpext buffer entirely and simplified the code 
accordingly. One less fixed-size buffer.

Unfortunately there are many more fixed-size buffers in shlexec.c. 
'WCHAR command[256]' for instance. Whoever said that 256 characters were 
enough for a command? Well, I felt lazy on that one so I just changed 
the size to 1024 characters but if someone feels motivated, please go 
ahead. There's plenty for everyone.


Changelog:

  * dlls/shell32/shlexec.c

    Cleanup the handling of the extension in SHELL_FindExecutable():
    - Eliminate the corresponding fixed-size buffer which removes the 
limitation to 3 character extensions.
    - Fix handling of the trailing '.' case.
    - Do a case-insensitive check for the extension in win.ini.
    Increase the size of the command buffer to 1024.


-- 
Francois Gouget
fgouget at codeweavers.com

-------------- next part --------------
Index: dlls/shell32/shlexec.c
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.40
diff -u -r1.40 shlexec.c
--- a/dlls/shell32/shlexec.c	7 Apr 2004 03:49:51 -0000	1.40
+++ b/dlls/shell32/shlexec.c	8 Apr 2004 23:12:53 -0000
@@ -516,10 +516,9 @@
     static const WCHAR wPrograms[] = {'p','r','o','g','r','a','m','s',0};
     static const WCHAR wExtensions[] = {'e','x','e',' ','p','i','f',' ','b','a','t',' ','c','m','d',' ','c','o','m',0};
     WCHAR *extension = NULL; /* pointer to file extension */
-    WCHAR wtmpext[5];        /* local copy to mung as we please */
     WCHAR filetype[256];     /* registry name for this filetype */
     LONG  filetypelen = sizeof(filetype); /* length of above */
-    WCHAR command[256];      /* command from registry */
+    WCHAR command[1024];     /* command from registry */
     WCHAR wBuffer[256];      /* Used to GetProfileString */
     UINT  retval = 31;       /* default - 'No association was found' */
     WCHAR *tok;              /* token pointer */
@@ -558,17 +557,12 @@
                                        /* .\FILE.EXE :( */
     TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension));
 
-    if ((extension == NULL) || (extension == &xlpFile[strlenW(xlpFile)]))
+    if (extension == NULL || extension[1]==0)
     {
         WARN("Returning 31 - No association\n");
         return 31; /* no association */
     }
 
-    /* Make local copy & lowercase it for reg & 'programs=' lookup */
-    lstrcpynW(wtmpext, extension, 5);
-    CharLowerW(wtmpext);
-    TRACE("%s file\n", debugstr_w(wtmpext));
-
     /* Three places to check: */
     /* 1. win.ini, [windows], programs (NB no leading '.') */
     /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
@@ -594,7 +588,7 @@
                 while (*p == ' ' || *p == '\t') p++;
             }
 
-            if (strcmpW(tok, &wtmpext[1]) == 0) /* have to skip the leading "." */
+            if (strcmpiW(tok, &extension[1]) == 0) /* have to skip the leading "." */
             {
                 strcpyW(lpResult, xlpFile);
                 /* Need to perhaps check that the file has a path
@@ -612,7 +606,7 @@
     }
 
     /* Check registry */
-    if (RegQueryValueW(HKEY_CLASSES_ROOT, wtmpext, filetype, 
+    if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, filetype, 
 			&filetypelen) == ERROR_SUCCESS)
     {
 	filetypelen /= sizeof(WCHAR);


More information about the wine-patches mailing list