Pelles C forum

C language => Work in progress => Topic started by: czerny on February 04, 2012, 12:32:37 AM

Title: spawn
Post by: czerny on February 04, 2012, 12:32:37 AM
I have to carry some different compilers with me on an usb stick. I use Geany as IDE.
In order to set a special environment for the compiler in question I wrote a spawn program.
This tool sets a environment variable DRIVE to the actual usb-drive, reads some other environment vars and the exe name from a configuration file (spawn.spn) and starts the exe. The spawn program can be renamed to some other name (some.exe), than it expects a configuration file 'some.spn'.

I would like to here some tipps to improve this or to remove some errors.

czerny

spawn.spn
Code: [Select]
[FILES]

EXECUTABLE=tst.exe

[ENVIRONMENT]

PATH=%PATH%;%DRIVE%:\C\spawn
BLA=ok
BLUB=something

spawn.c
Code: [Select]
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <string.h>
#include <tchar.h>
#include <stdio.h>


#define CHUNCK 500

int _tmain(int argc, TCHAR **argv)
{
DWORD flags, size, chars;
TCHAR *p, *buf = NULL, spn[MAX_PATH], exe[MAX_PATH], drive[] = TEXT("DRIVE=?");
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
BOOL ok;
 
GetFullPathName(argv[0], MAX_PATH, spn, NULL);

p = &spn[_tcslen(spn)-4];

if ('.' == *p)
{
p = &spn[_tcslen(spn)-3];
_tcscpy(p, TEXT("spn"));
} else
_tcscat(spn, TEXT(".spn"));

drive[6] = spn[0];

GetPrivateProfileString(TEXT("FILES"), TEXT("EXECUTABLE"), TEXT(""), exe, MAX_PATH, spn);

size = 8;
buf = (TCHAR *)malloc(size*sizeof(TCHAR));
_tcscpy(buf, drive);
p = buf + 8;

do {
size += CHUNCK;
buf = (TCHAR *)realloc(buf, size*sizeof(TCHAR));
chars = GetPrivateProfileSection(TEXT("ENVIRONMENT"), p, size - 8, spn);

  } while (chars + 2 == size - 8);

/*
p = buf;

while (*p)
{
_tprintf(TEXT("%ls\n"), p);
p += _tcslen(p) + 1;
}

*/
    si.cb = sizeof(STARTUPINFO);

#ifdef UNICODE
    flags = CREATE_UNICODE_ENVIRONMENT;
#endif

    ok = CreateProcess(exe, NULL, NULL, NULL, TRUE, flags,
        (LPVOID) buf,   // new environment block
        NULL, &si, &pi);
 
    if (! ok)
    {
        printf("CreateProcess failed (%d)\n", GetLastError());
        return 1;
    }

    //WaitForSingleObject(pi.hProcess, INFINITE);

return 0;
}

Title: Re: spawn
Post by: TimoVJL on February 04, 2012, 10:00:38 AM
Tip for configuration filename:
Code: [Select]
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
int __cdecl WinMainCRTStartup(void)
{
TCHAR szFile[MAX_PATH];
DWORD dwLen = GetModuleFileName(0,szFile,sizeof(szFile));
lstrcpy(&szFile[dwLen-3], TEXT("ini"));
MessageBox(0, szFile, 0, MB_OK);
ExitProcess(0);
}
EDIT: Or
Code: [Select]
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
int __cdecl WinMainCRTStartup(void)
{
TCHAR szFile[MAX_PATH];
DWORD dwLen = GetModuleFileName(0,szFile,sizeof(szFile));
#ifdef UNICODE
(*(DWORDLONG*)(&szFile[dwLen-3])) = 0x0069006E0069;
#else
(*(DWORD*)(&szFile[dwLen-3])) = 0x696E69;
#endif
MessageBox(0, szFile, 0, MB_OK);
ExitProcess(0);
}
Another tip:
Code: [Select]
size = CHUNCK;
buf = (TCHAR *)malloc(size * sizeof(TCHAR));
_tcscpy(buf, drive);
p = buf + 8;
buf[6] = spn[0];
do
{
chars = GetPrivateProfileSection(TEXT("ENVIRONMENT"), p, size - 8, spn);
if (chars != size - 8 - 2) break;
size += CHUNCK;
buf = (TCHAR *)realloc(buf, size * sizeof(TCHAR));
} while (1);
Title: Re: spawn
Post by: czerny on February 04, 2012, 01:19:49 PM
Yes, that's better. Path is complete and independant from the way spawn is called.
But how and why do you use WinMainCRTStartup.
The linker can not find _main.

czerny
Title: Re: spawn
Post by: TimoVJL on February 04, 2012, 01:32:56 PM
Quote
But how and why do you use WinMainCRTStartup.
The linker can not find _main.
Bad habit for small test programs without CRT.

BTW:
How you think to handle commandline in your program ?
Title: Re: spawn
Post by: czerny on February 04, 2012, 02:37:47 PM
Quote
BTW:
How you think to handle commandline in your program ?

I do not need this at the moment. But you are right, I should include this.


Ah, I have just seen your 3. tipp. Thank you for that.

czerny
Title: Re: spawn
Post by: czerny on February 04, 2012, 03:21:28 PM
This should do it, even with quoted path:

Code: [Select]
TCHAR *para = _tcsistr(GetCommandLine(), TEXT(".EXE"));
if (para) while (*para && *para++ != ' ') ;


    ok = CreateProcess(exe, para, NULL, NULL, TRUE, flags,
        (LPVOID) buf,   // new environment block
        NULL, &si, &pi);

czerny
Title: Re: spawn
Post by: CommonTater on February 04, 2012, 03:34:15 PM
You migh also want to look into the Path???() tools in shlwapi.h  In this case: 
PathUnquoteSpaces(), PathFindExtension(), PathRenameExtension(), PathRemoveExtension() and PathQuoteSpaces() might be usefull.

Title: Re: spawn
Post by: czerny on February 04, 2012, 03:42:28 PM
Thank you tater!