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:
parent
fef698c892
commit
0136b813ad
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue