mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 20:29:32 +02:00
* Windows: Do not use CommandLineToArgvW for parsing command line parameters, because it treats \" as an escape sequence for the double quote.
- Implemented parsing of the command line which is backward compatible. - Do not use GetCommandLineA. git-svn-id: trunk@45227 -
This commit is contained in:
parent
112b48a5e0
commit
187cc46b32
@ -253,10 +253,6 @@ type
|
||||
|
||||
function GetCommandLineW : pwidechar;
|
||||
stdcall;external KernelDLL name 'GetCommandLineW';
|
||||
function GetCommandLineA : pansichar;
|
||||
stdcall;external KernelDLL name 'GetCommandLineA';
|
||||
function CommandLineToArgvW(lpCmdLine: PWideChar; out pNumArgs: longint): PPWideChar;
|
||||
stdcall; external 'shell32.dll' name 'CommandLineToArgvW';
|
||||
|
||||
function GetCurrentProcessId:DWORD;
|
||||
stdcall; external KernelDLL name 'GetCurrentProcessId';
|
||||
@ -361,8 +357,6 @@ type
|
||||
stdcall; external 'oleaut32.dll' name 'SysFreeString';
|
||||
function SysReAllocStringLen(var bstr:pointer;psz: pointer;
|
||||
len:dword): Integer; stdcall;external 'oleaut32.dll' name 'SysReAllocStringLen';
|
||||
function GlobalFree(hMem: pointer): pointer;
|
||||
stdcall; external KernelDLL name 'GlobalFree';
|
||||
{$endif WINCE}
|
||||
|
||||
Procedure Errno2InOutRes(oserror: longword);
|
||||
|
@ -218,16 +218,91 @@ var
|
||||
|
||||
procedure setup_arguments;
|
||||
var
|
||||
CmdLineW, pw: PWideChar;
|
||||
c: WideChar;
|
||||
buf: array[0..MaxPathLen] of WideChar;
|
||||
i, len: longint;
|
||||
s: ansistring;
|
||||
i, len, argvw_size: longint;
|
||||
s: RawByteString;
|
||||
quote: boolean;
|
||||
begin
|
||||
// Get argvw
|
||||
argvw:=CommandLineToArgvW(GetCommandLineW, argc);
|
||||
// Get the full module name for argvw[0]
|
||||
len:=(GetModuleFileNameW(0, @buf, Length(buf)) + 1)*SizeOf(WideChar);
|
||||
argvw[0]:=SysGetMem(len);
|
||||
Move(buf, argvw[0]^, len);
|
||||
// Get the unicode command line
|
||||
CmdLineW:=GetCommandLineW;
|
||||
// Create the ansi command line
|
||||
s:=ansistring(CmdLineW);
|
||||
len:=Length(s) + 1;
|
||||
CmdLine:=SysGetMem(len);
|
||||
Move(PAnsiChar(s)^, CmdLine^, len);
|
||||
// Alloc initial space for argvw
|
||||
if CmdLineW^ = #0 then
|
||||
argvw_size:=2
|
||||
else
|
||||
argvw_size:=10;
|
||||
argvw:=SysGetMem(argvw_size*SizeOf(pointer));
|
||||
// Get the full module name to be used as the first argument
|
||||
len:=GetModuleFileNameW(0, @buf, Length(buf));
|
||||
// Alloc maximum possible space for all arguments
|
||||
pw:=SysGetMem((len + IndexWord(CmdLineW^, High(longint), 0) + 2)*SizeOf(WideChar));
|
||||
// Copy the module name as the first argument. It will be nil terminated later
|
||||
Move(buf, pw^, len*SizeOf(WideChar));
|
||||
argvw[0]:=pw;
|
||||
Inc(pw, len);
|
||||
// Parse the command line
|
||||
argc:=0;
|
||||
quote:=False;
|
||||
while True do
|
||||
begin
|
||||
c:=CmdLineW^;
|
||||
Inc(CmdLineW);
|
||||
case c of
|
||||
#0..#32:
|
||||
if not quote or (c = #0) then
|
||||
begin
|
||||
// Are there any chars of an argument?
|
||||
if argvw[argc] <> pw then
|
||||
begin
|
||||
// End of an argument found
|
||||
pw^:=#0;
|
||||
Inc(pw);
|
||||
Inc(argc);
|
||||
if argc = argvw_size then
|
||||
begin
|
||||
// Increase the argvw space
|
||||
Inc(argvw_size, argvw_size shr 1);
|
||||
SysReAllocMem(argvw, argvw_size*SizeOf(pointer));
|
||||
end;
|
||||
if c = #0 then
|
||||
break;
|
||||
argvw[argc]:=pw;
|
||||
continue;
|
||||
end
|
||||
else
|
||||
if c = #0 then
|
||||
break
|
||||
else
|
||||
continue; // Skip whitespace
|
||||
end;
|
||||
'"':
|
||||
begin
|
||||
quote:=not quote;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
// Ignore the first argument, it is already copied
|
||||
if argc <> 0 then
|
||||
begin
|
||||
// Copy the argument's char
|
||||
pw^:=c;
|
||||
Inc(pw);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Finalization
|
||||
// argvw is terminated by nil
|
||||
argvw[argc]:=nil;
|
||||
// Trim the memory
|
||||
SysReAllocMem(argvw, (argc + 1)*SizeOf(pointer));
|
||||
SysReAllocMem(argvw[0], ptruint(pw) - ptruint(argvw[0]));
|
||||
|
||||
// Construct the ansi argv
|
||||
argv:=SysGetMem((argc + 1)*SizeOf(pointer));
|
||||
for i:=0 to argc - 1 do
|
||||
@ -240,19 +315,17 @@ begin
|
||||
end;
|
||||
// argv is terminated by nil
|
||||
argv[argc]:=nil;
|
||||
// Get the ansi CmdLine
|
||||
CmdLine:=GetCommandLineA;
|
||||
end;
|
||||
|
||||
procedure finalize_arguments;
|
||||
var
|
||||
i: longint;
|
||||
begin
|
||||
// Free the module name
|
||||
SysFreeMem(CmdLine);
|
||||
// Free unicode arguments
|
||||
SysFreeMem(argvw[0]);
|
||||
// Use GlobalFree to free the buffer returned by CommandLineToArgvW
|
||||
GlobalFree(argvw);
|
||||
// Free argv
|
||||
SysFreeMem(argvw);
|
||||
// Free ansi arguments
|
||||
for i:=0 to argc - 1 do
|
||||
SysFreeMem(argv[i]);
|
||||
SysFreeMem(argv);
|
||||
|
Loading…
Reference in New Issue
Block a user