I am trying to launch a process using CreateProcess() I have to modify the Path environment variable as well as add some environment variables of my own. What I am doing is I get the parent's environment block using GetEnvironmentStrings(). I basically copy the parent env block and only modify the Path variable. I then use my new environment block in CreateProcess.
NOTE: I have tried Unicode and ANSI version of env block and it works when I pass it with Path unmodified or if I only add new environment variables to the environment block (e.g. ALEX=TRUE). However any attempts to modify Path results in error 87. Below is my code. Is there any restrictions in modifying Path environment variable during process creation? I can't seem to find any documentation that says so. At first I thought it was the env block or env var size but it they are within the limit. Maximum size for my env block is only 4000. Coding for Windows2003.
Below is ANSI version.
int main(int argc, char* argv[])
{
int retval=0;
LPTSTR lpszEnvEntryBuff = NULL; /* Buffer for reading the parent environment block */
LPTSTR lpszPrevEnvEntry = NULL; /* Pointer to the previous read entry of parent env block */
LPTSTR lpszNextEnvEntry = NULL; /* Pointer to next environment entry to be added */
LPTCH lpvEnv = NULL; /* Parent environment block */
LPTCH lpvNewEnv = NULL; /* New environment block with altshell entries added */
LPTCH lpvTmpEnv = NULL; /* Placeholder for reallocating the new environment block */
int iEnvEntryBuffLen = 0; /* Length of current environment entry being parsed */
int iCurrNewEnvSize = 0; /* Current size of the new environment block */
int iPrevNewEnvSize = 0; /* Previous size of the new environment block */
char szNewPathBuff[BUFFSIZE];
LPTSTR lpszNewPathBuff = NULL;
int iNewPathSize = 0;
char szShellPath[BUFFSIZE];
char szTMP[BUFFSIZE];
/* Load Config File entries */
GetShellEnvVars(szShellPath, szTMP);
/* Get a pointer to the environment block. */
lpvEnv = GetEnvironmentStrings();
/* If the returned pointer is NULL, exit. */
if (lpvEnv != NULL)
{
/* Variable strings are separated by NULL byte, and the block is
terminated by a NULL byte. Copy parent environment as the environment
returned by GetEnvironmentStrings()is readonly */
lpszEnvEntryBuff = (LPTSTR) lpvEnv;
while (*lpszEnvEntryBuff)
{
/* Check for PATH, TEMP, TMP. Modify according to New Shell Environment Vars */
if (Similar("PATH=", lpszEnvEntryBuff, 5))
{
lpszPrevEnvEntry = lpszEnvEntryBuff; /* Store current pos of buffer in parent env block */
NullFld(szNewPathBuff, BUFFSIZE); /* Clean the buffer */
iNewPathSize = strlen(lpszEnvEntryBuff) + strlen(szShellPath);
sprintf(szNewPathBuff, "PATH=%s;%s", szShellPath, lpszEnvEntryBuff + 5);
lpszEnvEntryBuff = szNewPathBuff;
}
iEnvEntryBuffLen = strlen(lpszEnvEntryBuff);
iCurrNewEnvSize = iCurrNewEnvSize + iEnvEntryBuffLen + 1;
/* Reallocate space for lpvNewEnv per additional environment entry */
lpvTmpEnv = (LPTCH)realloc(lpvNewEnv, iCurrNewEnvSize);
if (!lpvTmpEnv)
{
return -1;
}
lpvNewEnv = lpvTmpEnv;
/* Copy current Enviroment Entry to new Environment Block then */
/* go to end of new Environment Block and add a NULL byte */
lpszNextEnvEntry = lpvNewEnv + iPrevNewEnvSize;
MemCopy(lpszEnvEntryBuff, lpszNextEnvEntry, iEnvEntryBuffLen);
lpszNextEnvEntry = lpszNextEnvEntry + iEnvEntryBuffLen;
*lpszNextEnvEntry = '\0';
iPrevNewEnvSize = iCurrNewEnvSize;
if (lpszPrevEnvEntry)
{
lpszEnvEntryBuff = lpszPrevEnvEntry; /* restore to saved position before incrementing*/
lpszPrevEnvEntry = NULL;
}
lpszEnvEntryBuff = lpszEnvEntryBuff + iEnvEntryBuffLen + 1;
}
FreeEnvironmentStrings(lpvEnv);
/* Add terminating NULL character */
lpvTmpEnv = (LPTCH)realloc(lpvNewEnv, iCurrNewEnvSize + 1);
if (!lpvTmpEnv)
{
return -1;
}
lpvNewEnv = lpvTmpEnv;
lpszNextEnvEntry = lpvNewEnv + iCurrNewEnvSize;
*lpszNextEnvEntry = '\0';
lpszEnvEntryBuff = (LPTSTR) lpvNewEnv;
while (*lpszEnvEntryBuff)
{
iEnvEntryBuffLen = strlen(lpszEnvEntryBuff);
lpszEnvEntryBuff += iEnvEntryBuffLen + 1;
}
}
/*Create Child*/
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
GetStartupInfo(&StartupInfo);
StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
StartupInfo.dwFlags = STARTF_USESTDHANDLES;
StartupInfo.lpDesktop = NULL;
ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
if( !CreateProcess( NULL, // No module name (use command line)
"run.exe D:\\dev\\obj\\FORM.gnt APPS", // Command line
NULL, // Process handle
NULL, // Thread handle
TRUE, // handle inheritance
NULL, // creation flags
lpvNewEnv, // environment block
NULL, // Use parent's starting directory
&StartupInfo, // Pointer to STARTUPINFO structure
&ProcessInfo ) // Pointer to PROCESS_INFORMATION structure
)
{
return -1;
}
// Wait until child process exits.
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
free(lpvNewEnv);
return retval;
}