0

I am trying to call function CreateProcessAsUser. Passing constant string is fine. Trying to pick up an Environment variable using char* getenv(const char name) is causing me a problem.

If I use the following, notepad.exe will run.

CreateProcessAsUser(hTokenDup, _T("c:\\windows\\notepad.exe"), 
                    _T("c:\\windows\\notepad.exe"), NULL, NULL, FALSE,
                    dwCreationFlag, pEnvironment, NULL, &si, &pi);

However, if I use the following nothing runs.

CreateProcessAsUser(hTokenDup, _T("MyAppName"), 
                    (LPTSTR)getenv("MYENVVAR"), NULL, NULL, FALSE,
                    dwCreationFlag, pEnvironment, NULL, &si, &pi);

Have I specified the getenv and (LPTSTR) correctly?

I have tried using user and system environment vars containing c:\\windows\\notepad.exe and c:\windows\notepad.exe.

Thanks!

Lars Strojny
  • 667
  • 4
  • 11
fred
  • 18
  • 4
  • 4
    Get rid of the cast to `(LPTSTR)`—if the compiler is giving you an error message there without the cast, then inserting a cast to shut the compiler up is **the wrong thing to do**. The compiler is trying to tell you something. In that case, you're compiling a Unicode application, and you're trying to pass an ANSI string when a Unicode string is expected—use [`_tgetenv`](http://msdn.microsoft.com/en-us/library/tehxacec.aspx) instead of `getenv`. – Adam Rosenfield Jul 01 '11 at 21:59
  • Do you know if `getenv` succeeded? – Billy ONeal Jul 01 '11 at 21:59
  • 1
    @Adam Rosenfield: ["Since the compiler was unable to convert the parameter, let's give it some help and stick a cast in front. There, that shut up the compiler. Those compiler guys are so stupid."](http://blogs.msdn.com/b/oldnewthing/archive/2011/05/06/10161590.aspx) – Billy ONeal Jul 01 '11 at 22:23
  • Use _wgetenv() to solve your problem, underscore-t is archaic. The best thing to do is to set the 2nd argument to NULL and the 3rd argument to exepath + " " + arguments. That makes sure that some C programs that rely on argv[0] being the program path don't fall over. CreateProcess is rocket science. – Hans Passant Jul 01 '11 at 22:45

2 Answers2

2

The third parameter, lpCommandLine is LPTSTR which means it must be writeable memory. You need to copy the command line into a writeable string before calling CreateProcessAsUser.

The documentation for getenv states:

It is not safe to modify the value of the environment variable using the returned pointer.

You therefore cannot pass this as the lpCommandLine parameter of CreateProcessAsUser.

Your first call to CreateProcessAsUser appears to be wrong too since you also are not passing writeable memory for lpCommandLine.

Of course it's most likely that your immediate problem is that you are mixing ANSI and Unicode. If your app is Unicode then you need to call _wgetenv, or _tgetenv if you really do want to target both ANSI and Unicode from the same source. But make sure you copy it into a writeable buffer before passing it on.

Finally, as Adam commented, every time you write a cast, there is a strong possibility that you are making a mistake.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Ah, good call, I forgot that the `*getenv` functions return read-only but non-`const` pointers. As for why `CreateProcessAsUser` and `CreateProcess` require writable command lines, see [Why does the CreateProcess function modify its input command line?](http://blogs.msdn.com/b/oldnewthing/archive/2009/06/01/9673254.aspx). – Adam Rosenfield Jul 02 '11 at 00:53
0

getenv() will always return a char* no matter what character set your application is set to use. Try using _tgetenv() instead, as it adjusts between char* and wchar_t* as needed.

Darryl
  • 5,907
  • 1
  • 25
  • 36