Fwd: Re: CommandLineToArgvW fix
Francois Gouget
fgouget at free.fr
Mon Oct 8 13:39:26 CDT 2001
On Mon, 8 Oct 2001, Malte Starostik wrote:
> Sorry, meant reply-to-all
>
> ---------- Weitergeleitete Nachricht ----------
>
> Subject: Re: CommandLineToArgvW fix
> Date: Mon, 8 Oct 2001 20:23:57 +0200
> From: Malte Starostik <malte at kde.org>
> To: eric pouech <eric.pouech at wanadoo.fr>
>
> Am Monday 08 October 2001 20:08 schrieben Sie:
> > 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.
> >
> > I don't understand what you've done.
> > cmdline is a copy of the passed lpCmdLine parameter used for getting the
> > different bits of the argv, so it should be freed
> > however, what's wrong with current implementation (hence your issues) is
> > that when freeing cmdline the argv array points to garbage
> > it means that the argv array and cmdline should be allocated in a single
> > memory block suh that argv[i] points to the part of the string
>
> You're definately right, I mixed up argv with argv[i] there.
Here's my take on this. I believe it's a slightly better patch.
I tested this in NT4 and there is indeed a single alloc done for the
array and the strings. Also, the array does not contain a terminating
NULL pointer like I thought. And the lpCmdLine="" case is handled the
same way so this patch changes that too.
I did not test the patch... yet (recompiling). If I find something
wrong I'll send an updated version.
--
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 17:12:35
@@ -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=HeapReAlloc(GetProcessHeap(), 0, argv, size);
+ } 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=HeapAlloc(GetProcessHeap(), 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-devel
mailing list