From: Vincent T. <vt...@un...> - 2007-05-24 17:52:56
|
Hey, I've tried to use CommandLineToArgvW in a simple program : int argc = 0; LPWSTR *argv; argv = CommandLineToArgvW ((LPCWSTR )lpCmdLine, &argc); printf ("%d **%s**\n", argc, (char *)argv[0]); With the following command: ./ddraw.exe --toto tata i get that result: 1 **--toto tata ** I think that it is not the behavior described here: http://msdn2.microsoft.com/en-us/library/ms647232.aspx Vincent Torri |
From: Tor L. <tm...@ik...> - 2007-05-24 23:13:42
|
Vincent Torri writes: > I've tried to use CommandLineToArgvW in a simple program : > int argc = 0; > LPWSTR *argv; > > argv = CommandLineToArgvW ((LPCWSTR )lpCmdLine, &argc); > printf ("%d **%s**\n", argc, (char *)argv[0]); That is not a complete program. If you want us to ponder what might be your problem, please provide a *complete* sample program, including the command line you use to compile it. But anyway, I don't understand what you think you will achieve by casting argv[0], which is a pointer to wide characters (wchar_t *), to a plain character pointer (char *)? --tml |
From: Vincent T. <vt...@un...> - 2007-05-25 06:06:07
|
On Fri, 25 May 2007, Tor Lillqvist wrote: > Vincent Torri writes: > > I've tried to use CommandLineToArgvW in a simple program : > > > int argc = 0; > > LPWSTR *argv; > > > > argv = CommandLineToArgvW ((LPCWSTR )lpCmdLine, &argc); > > printf ("%d **%s**\n", argc, (char *)argv[0]); > > That is not a complete program. If you want us to ponder what might be > your problem, please provide a *complete* sample program, Here it is: #include <stdio.h> #include <windows.h> int APIENTRY WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int argc = 0; LPWSTR *argv; argv = CommandLineToArgvW ((LPCWSTR )lpCmdLine, &argc); printf ("%d **%s**\n", argc, (char *)argv[0]); return 0; } > including > the command line you use to compile it. gcc -g -Wall -o test3 test3.c -lshell32 Is the problem being the fact that I use the lpCmdLine parameter which is not a LPCWSTR ? The fact that argc is not 2 (it seems that in that case, the name of the prog is not included in argv, see: http://msdn2.microsoft.com/en-us/library/ms683156.aspx) Actually, I would use the standard C main function, which would solve all my problems, but I create a window and I would need an HINSTANCE for it. I don't know how to create such variable. Vincent Torri |
From: Julien L. <ju...@fa...> - 2007-05-25 14:24:11
|
Vincent Torri wrote: > Here it is: > > #include <stdio.h> > #include <windows.h> > > int APIENTRY > WinMain (HINSTANCE hinstance, > HINSTANCE hPrevInstance, > LPSTR lpCmdLine, > int nCmdShow) > { > int argc = 0; > LPWSTR *argv; > > argv = CommandLineToArgvW ((LPCWSTR )lpCmdLine, &argc); > printf ("%d **%s**\n", argc, (char *)argv[0]); > > return 0; > } > >> including >> the command line you use to compile it. > > gcc -g -Wall -o test3 test3.c -lshell32 Using -Wall to have warnings enabled, and then hushing them up by using casts is a source of errors and undefined behavior. Without the casts : gcc -g -Wall -o test3 test3.c -lshell32 test3.c: In function `WinMain': test3.c:14: warning: passing arg 1 of `CommandLineToArgvW' from incompatible pointer type test3.c:15: warning: char format, different type arg (arg 3) > Is the problem being the fact that I use the lpCmdLine parameter which is > not a LPCWSTR ? Yes. A wide string and a c string are not the same, and nor are pointers to them. Why not use GetCommandLineW() as MSDN recommends ? ==BOF test1.c== #include <stdio.h> #include <windows.h> int APIENTRY WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int argc, i; LPWSTR *argv; // NB: Use 'W' versions and %ls in printf if ((argv = CommandLineToArgvW(GetCommandLineW(), &argc))) { // success... for (i = 0; i < argc; i++) printf("%d=%ls\n", i, argv[i]); // MSDN says to LocalFree the memory LocalFree(argv); } return 0; } ==EOF test1.c== $ gcc -o test1.exe test1.c && ./test1.exe --toto --tata > Actually, I would use the standard C main function, which would solve all > my problems, but I create a window and I would need an HINSTANCE for it. I > don't know how to create such variable. Actually HINSTANCE is the same as HMODULE so you can use GetModuleHandle(0) to get HINSTANCE of your process. Julien |
From: Vincent T. <vt...@un...> - 2007-05-25 15:53:26
|
On Fri, 25 May 2007, Julien Lecomte wrote: > Vincent Torri wrote: > > Using -Wall to have warnings enabled, and then hushing them up by using casts > is a source of errors and undefined behavior. I am completely aware of the warnings and such things. But the API of windows is crappy and you sometimes have to cast to remove warnings. Like the directdraw 7 interface, for instance. >> Is the problem being the fact that I use the lpCmdLine parameter which is >> not a LPCWSTR ? > > Yes. A wide string and a c string are not the same, and nor are pointers to > them. > Why not use GetCommandLineW() as MSDN recommends ? >From the web page i mentioned in my previous mail : "ANSI GUI applications can use the lpCmdLine parameter of the WinMain function to access the command-line string, excluding the program name." ==BOF test1.c== > #include <stdio.h> > #include <windows.h> > > int APIENTRY > WinMain (HINSTANCE hinstance, > HINSTANCE hPrevInstance, > LPSTR lpCmdLine, > int nCmdShow) > { > int argc, i; > LPWSTR *argv; > // NB: Use 'W' versions and %ls in printf > if ((argv = CommandLineToArgvW(GetCommandLineW(), &argc))) > { > // success... > for (i = 0; i < argc; i++) > printf("%d=%ls\n", i, argv[i]); > // MSDN says to LocalFree the memory > LocalFree(argv); > } > return 0; > } > ==EOF test1.c== > $ gcc -o test1.exe test1.c && ./test1.exe --toto --tata > >> Actually, I would use the standard C main function, which would solve all >> my problems, but I create a window and I would need an HINSTANCE for it. I >> don't know how to create such variable. > > Actually HINSTANCE is the same as HMODULE so you can use GetModuleHandle(0) > to get HINSTANCE of your process. I'll try that. Thank you Vincent Torri |
From: Luke D. <cod...@ho...> - 2007-05-25 16:04:21
|
----- Original Message ----- From: "Vincent Torri" <vt...@un...> To: "Julien Lecomte" <ju...@fa...> Cc: "MinGW Users List" <min...@li...> Sent: Friday, May 25, 2007 11:53 PM Subject: Re: [Mingw-users] CommandLineToArgvW is not working > > > On Fri, 25 May 2007, Julien Lecomte wrote: > >> Vincent Torri wrote: >> >> Using -Wall to have warnings enabled, and then hushing them up by using >> casts >> is a source of errors and undefined behavior. > > I am completely aware of the warnings and such things. But the API of > windows is crappy and you sometimes have to cast to remove warnings. Like > the directdraw 7 interface, for instance. > >>> Is the problem being the fact that I use the lpCmdLine parameter which >>> is >>> not a LPCWSTR ? >> >> Yes. A wide string and a c string are not the same, and nor are pointers >> to >> them. >> Why not use GetCommandLineW() as MSDN recommends ? > >>From the web page i mentioned in my previous mail : > > "ANSI GUI applications can use the lpCmdLine parameter of the WinMain > function to access the command-line string, excluding the program name." Yes, and if you only want the ANSI string then you should be calling CommandLineToArgvA() instead. Luke > > ==BOF test1.c== > #include <stdio.h> >> #include <windows.h> >> >> int APIENTRY >> WinMain (HINSTANCE hinstance, >> HINSTANCE hPrevInstance, >> LPSTR lpCmdLine, >> int nCmdShow) >> { >> int argc, i; >> LPWSTR *argv; >> // NB: Use 'W' versions and %ls in printf >> if ((argv = CommandLineToArgvW(GetCommandLineW(), &argc))) >> { >> // success... >> for (i = 0; i < argc; i++) >> printf("%d=%ls\n", i, argv[i]); >> // MSDN says to LocalFree the memory >> LocalFree(argv); >> } >> return 0; >> } >> ==EOF test1.c== >> $ gcc -o test1.exe test1.c && ./test1.exe --toto --tata >> >>> Actually, I would use the standard C main function, which would solve >>> all >>> my problems, but I create a window and I would need an HINSTANCE for it. >>> I >>> don't know how to create such variable. >> >> Actually HINSTANCE is the same as HMODULE so you can use >> GetModuleHandle(0) >> to get HINSTANCE of your process. > > I'll try that. Thank you > > Vincent Torri |
From: Vincent T. <vt...@un...> - 2007-05-25 16:09:00
|
On Sat, 26 May 2007, Luke Dunstan wrote: > > Yes, and if you only want the ANSI string then you should be calling > CommandLineToArgvA() instead. already tried that wihtout success. More precisely: grep -r CommandLineToArgvA /mingw/include returns nothing. Only the wide char version exists (mingw 5.1.3 installer, candidate version). Vincent Torri |
From: Julien L. <ju...@fa...> - 2007-05-29 09:16:33
|
(NB: I'm replying to a post in another thread, because for some reason, even if I did receive a post ack, when I create a new thread my post mysteriously never gets through. I'm sorry.) Vincent Torri's mail on WinMain, CommandLineToArgvW and GetCommandLineA/W made me notice the following "bug" which can be tested with the following code: == BOF test1.c == #include <stdio.h> #include <windows.h> int APIENTRY WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { printf("lpCmdLine (%d) = **%s**\n", strlen(lpCmdLine), lpCmdLine); // strip right trailing spaces CHAR* cstrip = lpCmdLine + strlen(lpCmdLine) - 1; while (*cstrip == ' ') *cstrip-- = 0; printf("stripped (%d) = **%s**\n\n", strlen(lpCmdLine), lpCmdLine); return 0; } == EOF test1.c == I've noticed that the mingw-runtime will: - often add at least a trailing space when using several commands in a row. - convert/remove quotes in some cases. With the folowing commands (please note that spaces can be important) $ gcc test1.c -o test1.exe $ ./test1.exe "toto1" $ ./test1.exe 'toto2' $ ./test1.exe toto3&& ./test1.exe toto4 $ ./test1.exe toto5 && ./test1.exe toto6 I get the selected following results: With console MSYS shell (TERM=cygwin; MSYSTEM=MINGW32) julienlecomte@PUMILIO ~/procrast $ ./test1.exe "toto1" lpCmdLine (6) = **toto1 ** stripped (5) = **toto1** $ ./test1.exe 'toto2' lpCmdLine (6) = **toto2 ** stripped (5) = **toto2** $ ./test1.exe toto3&& ./test1.exe toto4 lpCmdLine (6) = **toto3 ** stripped (5) = **toto3** lpCmdLine (6) = **toto4 ** stripped (5) = **toto4** $ ./test1.exe toto5 && ./test1.exe toto6 lpCmdLine (6) = **toto5 ** stripped (5) = **toto5** lpCmdLine (6) = **toto6 ** stripped (5) = **toto6** With console cmd.exe: M:\home>test1.exe "toto1" lpCmdLine (7) = **"toto1"** stripped (7) = **"toto1"** M:\home>test1.exe 'toto2' lpCmdLine (7) = **'toto2'** stripped (7) = **'toto2'** M:\home>test1.exe toto3&& test1.exe toto4 lpCmdLine (5) = **toto3** stripped (5) = **toto3** lpCmdLine (5) = **toto4** stripped (5) = **toto4** M:\home>test1.exe toto5 && test1.exe toto6 lpCmdLine (12) = **toto5 ** stripped (5) = **toto5** lpCmdLine (5) = **toto6** stripped (5) = **toto6** I might be able to understand why quotes are converted (toto1 and toto2 for example) depending on console box as this might be an effect of the shell before creating the process. On the other hand, I can't understand why behavior isn't the same in toto5 test case since I tend to believe that any command line will (should?) always be right space trimmed. I believe that mingw-runtime should trim the spaces on the right before calling WinMain and that results should be more consistent under cmd.exe. Should we or not modify mingw-runtime to trim those spaces? |
From: Keith M. <kei...@to...> - 2007-05-29 11:18:26
|
Julien Lecomte wrote: > I believe that mingw-runtime should trim the spaces on the right > before calling WinMain and that results should be more consistent > under cmd.exe. Should we or not modify mingw-runtime to trim > those spaces? I believe this is more likely to be an issue with the way in which MSYS' sh.exe reconstructs the command line it passes to the child process, rather than a problem in mingw-runtime. Any native Woe32 process receives its arguments as a single string of characters. Whatever you type on the cmd.exe command line just gets passed verbatim to the child; this includes any leading or trailing spaces which happen to be present, after the command name has been carved off, and up to any following command separator. The only exception to this is that redirection operators are actioned, and filtered out. MSYS' sh.exe, OTOH, behaves like any UNIX shell. It parses each command line, expanding one level of quoting, and constructs an argument vector; this is then passed to the child through an `exec' function call, (after forking a process in which to run the child). To make this work in the Woe32 world, MSYS' `exec' function has to reconstruct a single command line argument string, from the passed argument vector; it is this reconstructed string which is then passed to the child, via the system's own `CreateProcess' function. I don't think it would be practical to make sh.exe reproduce the behaviour of cmd.exe, wrt redundant white space; here are just a few of the reasons which spring to mind: 1) While constructing the argument vector for `exec', one level of quoting is expanded; the quoting characters are discarded. 2) In this process, all unquoted white space is discarded. 3) Attempting to modify this behaviour would, in all likelihood, destroy sh.exe's variable expansion and command substitution features. 4) sh.exe supports a much richer set of quoting capabilities; it is not practical to simply pass all quoting directly to a Woe32 process, which is unlikely to understand the syntax. One thing which does seem odd, is the single trailing space left on the *unquoted* argument in your example; I would not have expected the MSYS `exec' function to add that, so it could be considered a bug, which we may wish to investigate. Please raise a ticket on the bug tracker: https://sourceforge.net/tracker/?func=add&group_id=2435&atid=102435 FWIW, you should also note that Woe32's own `exec' function, as provided by MSVCRT, is critically broken wrt the quoting of grouped arguments with included white space, which are present in the passed argument vector. The disfunctional `spawn' functions, which MSVCRT provides instead of the `fork()...exec()' API is identically broken. For an explanation, and GPLed workaround, see: https://sourceforge.net/project/showfiles.php?group_id=2435&package_id=82725&release_id=366538 Regards, Keith. |