Getting errors with CreateProcess in C using putenv and getpid

Viewed 118

I am getting these errors, but I have looked for answers everywhere and I have not found a solution:

launcher.c:107:12: warning: implicit declaration of function 'putenv'
launcher.c:116:10: warning: passing argument 2 of 'CreateProcessA' makes pointer from integer without a cast
c:\cs30200\mingw32\bin\../lib/gcc/mingw32/4.5.1/../../../../include/winbase.h:1250:24: 
note: expected 'LPSTR' but argument is of type 'int'

My errors are on putenv() with CreateProcess(). I do know putenv() returns an int, but I cannot get the new command prompt to display a new line title. However, I am also having issues with getpid() giving me the same number starting every program. I had it working before and now I cannot find where it went wrong.

#include <windows.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

void printError(char* functionName);
#define INFO_BUFFER_SIZE 32767
    
int main(void)
{
   int numInput;
   int x=1,y=1;
   static char *promptCmd = "PROMPT=Speak$sUp:$G";
   DWORD dwExitCode = 0;
       
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
       
   pid_t pid;
   pid = getpid();
    
   STARTUPINFO suNW;
   PROCESS_INFORMATION piNW;
   suNW.cb = sizeof(suNW);
   suNW.lpReserved = NULL;
   suNW.dwFlags = 0;
   suNW.cbReserved2 = 0;
   suNW.lpReserved2 = NULL; 
   suNW.lpDesktop = NULL;
   suNW.lpTitle = "What is your command?";
   suNW.dwX = x;
   suNW.dwY = y;
   suNW.dwXSize = CW_USEDEFAULT;
   suNW.dwYSize = CW_USEDEFAULT;
   suNW.dwFillAttribute = FOREGROUND_INTENSITY| FOREGROUND_GREEN|FOREGROUND_RED|BACKGROUND_RED;
   suNW.dwFlags = STARTF_USEPOSITION|STARTF_USEFILLATTRIBUTE;
   suNW.wShowWindow = TRUE;
   suNW.hStdInput = NULL;
   suNW.hStdOutput = NULL;
   suNW.hStdError = NULL;
    
   HANDLE hProc;
   hProc = pi.hProcess;
   GetStartupInfo(&si);
    
   const size_t full_size=256;
   TCHAR  sysLoc[INFO_BUFFER_SIZE],lpCommandLine[5][INFO_BUFFER_SIZE];
   char * progLoc;
    
   GetSystemDirectory(sysLoc, INFO_BUFFER_SIZE);                  //Get location of System32 folder
   progLoc = getenv("ProgramFiles(x86)");                         //Get location of Program Files folder x64
   if (progLoc==NULL) progLoc = getenv("ProgramFiles");           //If running x86 get location of Program Files folder
     
   snprintf(lpCommandLine[1],full_size,"%s\\notepad.exe",sysLoc);
   snprintf(lpCommandLine[2],full_size,"%s\\cmd.exe",sysLoc);
   snprintf(lpCommandLine[3],full_size,"%s\\nslookup.exe",sysLoc);
   snprintf(lpCommandLine[4],full_size,"%s\\charmap.exe",sysLoc);
   snprintf(lpCommandLine[5],full_size,"%s\\Windows NT\\Accessories\\wordpad.exe",progLoc);
    
runProgram:
   printf("Which program would you like to run:\n");
   printf("0: Quit\n");
   printf("1: Run Notepad\n");
   printf("*2: Run cmd shell\n");
   printf("#3: Run NS LooKUp\n");
   printf("4: Run Character Map\n");
   printf("5: Run WordPad\n");
   printf("Enter your choice now: ");
   scanf("%d", &numInput);
       
   switch(numInput)
   {
       case 0:
          
           exit(0);
             
       case 1:
            
           if(TRUE==CreateProcessA(NULL,lpCommandLine[1], NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
           {
               printf("Started program 1 with pid = %i",getpid());//pid);
           }  
           else printError(lpCommandLine[1]);
             
           printf("\n\n");
           goto runProgram;
           break;
             
       case 2:
             
           if (CreateProcess(
               lpCommandLine[2],         // LPCTSTR lpApplicationName
               promptCmd,//putenv(promptCmd),               // LPTSTR lpCommandLine
               NULL,                // LPSECURITY_ATTRIBUTES lpProcessAttributes
               NULL,                // LPSECURITY_ATTRIBUTES lpThreadAttributes
               FALSE,//TRUE,               // BOOL bInheritHandles
               CREATE_NEW_CONSOLE,    // DWORD dwCreationFlags
               NULL,                // LPVOID lpEnvironment
               NULL,                // LPCTSTR lpCurrentDirectory
               &suNW,       // LPSTARTUPINFO lpStartupInfo
               &piNW        // LPPROCESS_INFORMATION lpProcessInformation
           ))
           {
               printf("Started program 2 with pid = %i \n",getpid());//pid);
               printf("  waiting for program 2 to terminate...\n");

               WaitForSingleObject(piNW.hProcess,INFINITE);
               CloseHandle(piNW.hThread);

               GetExitCodeProcess(piNW.hProcess,&dwExitCode);                  

               CloseHandle(piNW.hProcess);   
           }  
           else printError(lpCommandLine[2]);
             
           printf("  program 2 exited with a return value %i\n", dwExitCode);
           printf("\n\n");
           goto runProgram;
           break;     
          
       case 3:
           if(CreateProcessA(NULL, lpCommandLine[3], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ 
               printf("Started program 3 with pid = %i \n",getpid());//pid);
               WaitForSingleObject(pi.hProcess,INFINITE);
               CloseHandle(pi.hThread);
               CloseHandle(pi.hProcess);    
               goto runProgram;
           }  
           else printError(lpCommandLine[3]);
             
           printf("\n");
           goto runProgram;
           break;     
          
       case 4:
           if(CreateProcessA(NULL,lpCommandLine[4], NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
           { 
               printf("Started program 4 with pid = %i \n",getpid());//pid);
               CloseHandle(pi.hThread);
               CloseHandle(pi.hProcess); 
           }
           else printError(lpCommandLine[4]);
                
           printf("\n\n"); 
           goto runProgram;
           break;     
          
       case 5:
           if(CreateProcessA(NULL,lpCommandLine[5], NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
           { 
               printf("Started program 5 with pid = %i \n",getpid());//pid);
               CloseHandle(pi.hThread);
               CloseHandle(pi.hProcess); 
           }
           else printError(lpCommandLine[5]);
                
           printf("\n\n");
           goto runProgram;
           break;
   }
       
   return 0;
}
    
/****************************************************************
 The following function can be used to print out "meaningful"
 error messages. If you call a Win32 function and it returns
 with an error condition, then call this function right away and
 pass it a string containing the name of the Win32 function that
 failed. This function will print out a reasonable text message
 explaining the error and then (if chosen) terminate the program.
*/
void printError(char* functionName)
{
   LPVOID lpMsgBuf;
   int error_no;
   error_no = GetLastError();
   FormatMessage(
       FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       NULL,
       error_no,
       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
       (LPTSTR) &lpMsgBuf,
       0,
       NULL
   );
   // Display the string.
   fprintf(stderr, "\n%s failed on error %d: ", functionName, error_no);
   fprintf(stderr, (char*)lpMsgBuf);
   // Free the buffer.
   LocalFree( lpMsgBuf );
   //ExitProcess(1);  // terminate the program
}//printError
1 Answers

getpid returns the process ID of the calling process. The process ID of the newly created process is returned through the lpProcessInformation parameter, in the dwProcessId field. So instead of calling getpid change your code as follows:

printf("Started program 1 with pid = %i", pi.dwProcessId);

As for putenv, it also modifies the environment of the calling process. On Windows, it also changes only the CRT's copy of the environment, not the true process environment. To change the process environment you shall use SetEnvironmentVariable. The child will inherit the process environment of the parent as long as lpEnvironment of CreateProcess is set to NULL.

Putting it all together, the simplest way to achieve what you want is to simply set the PROMPT=... environment on your process at the beginning of your program:

SetEnvironmentVariableA("PROMPT", "Speak$sUp:$G");

and then let the children inherit it by doing nothing special in CreateProcess.

Related