CommandLineToArgvW fix

Francois Gouget fgouget at free.fr
Mon Oct 8 17:54:45 CDT 2001


On 8 Oct 2001, Alexandre Julliard wrote:

> Francois Gouget <fgouget at free.fr> writes:
> 
> > On Mon, 8 Oct 2001, Malte Starostik wrote:
> > 
> > > Don't free cmdline as the return values point into that string. It's the 
> > > caller's responsibility to GlobalFree() this according to msdn.
> > 
> >    Ok, I tested my patch and it works. So I propose it here.
> 
> If the caller is supposed to call GlobalFree on the returned value, it
> would be much cleaner to allocate it with GlobalAlloc.

   Seems compatible, but it would indeed be cleaner.
   Here's the patch.

   Grrr, HGLOBAL is not a void* pointer... yet => casts :-(

   People, bug #90 needs your help!


--
Francois Gouget         fgouget at free.fr        http://fgouget.free.fr/
  Any sufficiently advanced Operating System is indistinguishable from Linux

-------------- next part --------------
Index: dlls/shell32/shell32_main.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.c,v
retrieving revision 1.85
diff -u -r1.85 shell32_main.c
--- dlls/shell32/shell32_main.c	2001/10/03 18:42:16	1.85
+++ dlls/shell32/shell32_main.c	2001/10/08 21:33:09
@@ -65,6 +65,7 @@
 {
     DWORD argc;
     LPWSTR  *argv;
+    LPCWSTR cs;
     LPWSTR arg,s,d;
     LPWSTR cmdline;
     int in_quotes,bcount;
@@ -74,14 +75,13 @@
         /* Return the path to the executable */
         DWORD size;
 
-        argv=HeapAlloc(GetProcessHeap(), 0, 2*sizeof(LPWSTR));
-        argv[0]=NULL;
+        argv=NULL;
         size=16;
         do {
             size*=2;
-            argv[0]=HeapReAlloc(GetProcessHeap(), 0, argv[0], size);
-        } while (GetModuleFileNameW((HMODULE)0, argv[0], size) == 0);
-        argv[1]=NULL;
+            argv=(LPWSTR*)GlobalReAlloc((HGLOBAL)argv, size, 0);
+        } while (GetModuleFileNameW((HMODULE)0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)) == 0);
+        argv[0]=(LPWSTR)(argv+1);
         if (numargs)
             *numargs=2;
 
@@ -89,30 +89,26 @@
     }
 
     /* to get a writeable copy */
-    cmdline = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpCmdline)+1) * sizeof(WCHAR));
-    if (!cmdline)
-        return NULL;
-    strcpyW(cmdline, lpCmdline);
     argc=0;
     bcount=0;
     in_quotes=0;
-    s=cmdline;
+    cs=lpCmdline;
     while (1) {
-        if (*s==0 || ((*s==0x0009 || *s==0x0020) && !in_quotes)) {
+        if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) {
             /* space */
             argc++;
             /* skip the remaining spaces */
-            while (*s==0x0009 || *s==0x0020) {
-                s++;
+            while (*cs==0x0009 || *cs==0x0020) {
+                cs++;
             }
-            if (*s==0)
+            if (*cs==0)
                 break;
             bcount=0;
             continue;
-        } else if (*s==0x005c) {
+        } else if (*cs==0x005c) {
             /* '\', count them */
             bcount++;
-        } else if ((*s==0x0022) && ((bcount & 1)==0)) {
+        } else if ((*cs==0x0022) && ((bcount & 1)==0)) {
             /* unescaped '"' */
             in_quotes=!in_quotes;
             bcount=0;
@@ -120,9 +116,16 @@
             /* a regular character */
             bcount=0;
         }
-        s++;
+        cs++;
     }
-    argv=HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
+    /* Allocate in a single lump, the string array, and the strings that go with it.
+     * This way the caller can make a single GlobalFree call to free both, as per MSDN.
+     */
+    argv=(LPWSTR*)GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
+    if (!argv)
+        return NULL;
+    cmdline=(LPWSTR)(argv+argc);
+    strcpyW(cmdline, lpCmdline);
 
     argc=0;
     bcount=0;
@@ -172,13 +175,11 @@
     }
     if (*arg) {
         *d='\0';
-        argv[argc++]=arg;
+        argv[argc]=arg;
     }
-    argv[argc]=NULL;
     if (numargs)
         *numargs=argc;
 
-    HeapFree(GetProcessHeap(), 0, cmdline);
     return argv;
 }
 


More information about the wine-patches mailing list