Allocate the array and strings in one lump (bug found by Malte

Starostik).
Same thing for the lpCmdline="" case.
There is no NULL pointer at the end of the argv list.
This commit is contained in:
Francois Gouget 2001-10-10 20:25:59 +00:00 committed by Alexandre Julliard
parent fef698c892
commit 0136b813ad
1 changed files with 25 additions and 22 deletions

View File

@ -64,24 +64,25 @@ DEFAULT_DEBUG_CHANNEL(shell);
LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
{ {
DWORD argc; DWORD argc;
HGLOBAL hargv;
LPWSTR *argv; LPWSTR *argv;
LPCWSTR cs;
LPWSTR arg,s,d; LPWSTR arg,s,d;
LPWSTR cmdline; LPWSTR cmdline;
int in_quotes,bcount; int in_quotes,bcount;
/* FIXME: same thing if we only have spaces */
if (*lpCmdline==0) { if (*lpCmdline==0) {
/* Return the path to the executable */ /* Return the path to the executable */
DWORD size; DWORD size;
argv=HeapAlloc(GetProcessHeap(), 0, 2*sizeof(LPWSTR)); hargv=0;
argv[0]=NULL;
size=16; size=16;
do { do {
size*=2; size*=2;
argv[0]=HeapReAlloc(GetProcessHeap(), 0, argv[0], size); hargv=GlobalReAlloc(hargv, size, 0);
} while (GetModuleFileNameW((HMODULE)0, argv[0], size) == 0); argv=GlobalLock(hargv);
argv[1]=NULL; } while (GetModuleFileNameW((HMODULE)0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)) == 0);
argv[0]=(LPWSTR)(argv+1);
if (numargs) if (numargs)
*numargs=2; *numargs=2;
@ -89,30 +90,26 @@ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
} }
/* to get a writeable copy */ /* to get a writeable copy */
cmdline = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpCmdline)+1) * sizeof(WCHAR));
if (!cmdline)
return NULL;
strcpyW(cmdline, lpCmdline);
argc=0; argc=0;
bcount=0; bcount=0;
in_quotes=0; in_quotes=0;
s=cmdline; cs=lpCmdline;
while (1) { while (1) {
if (*s==0 || ((*s==0x0009 || *s==0x0020) && !in_quotes)) { if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) {
/* space */ /* space */
argc++; argc++;
/* skip the remaining spaces */ /* skip the remaining spaces */
while (*s==0x0009 || *s==0x0020) { while (*cs==0x0009 || *cs==0x0020) {
s++; cs++;
} }
if (*s==0) if (*cs==0)
break; break;
bcount=0; bcount=0;
continue; continue;
} else if (*s==0x005c) { } else if (*cs==0x005c) {
/* '\', count them */ /* '\', count them */
bcount++; bcount++;
} else if ((*s==0x0022) && ((bcount & 1)==0)) { } else if ((*cs==0x0022) && ((bcount & 1)==0)) {
/* unescaped '"' */ /* unescaped '"' */
in_quotes=!in_quotes; in_quotes=!in_quotes;
bcount=0; bcount=0;
@ -120,9 +117,17 @@ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
/* a regular character */ /* a regular character */
bcount=0; 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.
*/
hargv=GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
argv=GlobalLock(hargv);
if (!argv)
return NULL;
cmdline=(LPWSTR)(argv+argc);
strcpyW(cmdline, lpCmdline);
argc=0; argc=0;
bcount=0; bcount=0;
@ -172,13 +177,11 @@ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
} }
if (*arg) { if (*arg) {
*d='\0'; *d='\0';
argv[argc++]=arg; argv[argc]=arg;
} }
argv[argc]=NULL;
if (numargs) if (numargs)
*numargs=argc; *numargs=argc;
HeapFree(GetProcessHeap(), 0, cmdline);
return argv; return argv;
} }