コード例 #1
0
ファイル: task.c プロジェクト: Barrell/wine
/***********************************************************************
 *           GetDOSEnvironment     (KERNEL.131)
 *
 * Note: the environment is allocated once, it doesn't track changes
 * made using the Win32 API. This shouldn't matter.
 *
 * Format of a 16-bit environment block:
 * ASCIIZ   string 1 (xx=yy format)
 * ...
 * ASCIIZ   string n
 * BYTE     0
 * WORD     1
 * ASCIIZ   program name (e.g. C:\WINDOWS\SYSTEM\KRNL386.EXE)
 */
SEGPTR WINAPI GetDOSEnvironment16(void)
{
    static const char ENV_program_name[] = "C:\\WINDOWS\\SYSTEM\\KRNL386.EXE";
    static HGLOBAL16 handle;  /* handle to the 16 bit environment */

    if (!handle)
    {
        DWORD size;
        LPSTR p, env;

        p = env = GetEnvironmentStringsA();
        while (*p) p += strlen(p) + 1;
        p++;  /* skip last null */
        size = (p - env) + sizeof(WORD) + sizeof(ENV_program_name);
        handle = GlobalAlloc16( GMEM_FIXED, size );
        if (handle)
        {
            WORD one = 1;
            LPSTR env16 = GlobalLock16( handle );
            memcpy( env16, env, p - env );
            memcpy( env16 + (p - env), &one, sizeof(one));
            memcpy( env16 + (p - env) + sizeof(WORD), ENV_program_name, sizeof(ENV_program_name));
            GlobalUnlock16( handle );
        }
        FreeEnvironmentStringsA( env );
    }
    return WOWGlobalLock16( handle );
}
コード例 #2
0
ファイル: bp_cl.cpp プロジェクト: pkesist/buildpal
int main()
{
    //Timer t;
    Environment env( GetEnvironmentStringsA(), false );

    std::string compilerExecutable;
    PathList pathList;
    getPath( env, pathList );
    if ( !findOnPath( pathList, "cl.exe", compilerExecutable ) )
    {
        std::cerr << "Failed to locate executable 'cl.exe' on PATH.\n";
        return -1;
    }

    bool const disableFallback = !!env.get( "BP_DISABLE_FALLBACK" );
    llvm::Optional<std::string> const portNameVar( env.get( "BP_MANAGER_PORT" ) );

    return distributedCompile(
        "msvc",
        compilerExecutable.c_str(),
        env,
        GetCommandLineA(),
        NULL,
        portNameVar ? portNameVar->data() : "default",
        disableFallback ? NULL : runLocallyFallback,
        const_cast<char *>( compilerExecutable.c_str() )
    );
}
コード例 #3
0
ファイル: GetEnv.c プロジェクト: Wanderfalke/ghc
/* Windows does it differently, though arguably the most sanely.
 * GetEnvironmentStrings() returns a pointer to a block of
 * environment vars with a double null terminator:
 *   Var1=Value1\0
 *   Var2=Value2\0
 *   ...
 *   VarN=ValueN\0\0
 * But because everyone else (ie POSIX) uses a vector of strings, we convert
 * to that format. Fortunately this is just a matter of making an array of
 * offsets into the environment block.
 *
 * Note that we have to call FreeEnvironmentStrings() at the end.
 *
 */
void getProgEnvv(int *out_envc, char **out_envv[]) {
    int envc, i;
    char *env;
    char *envp;
    char **envv;

    /* For now, use the 'A'nsi not 'W'ide variant.
       Note: corresponding Free below must use the same 'A'/'W' variant. */
    env = GetEnvironmentStringsA();

    envc = 0;
    for (envp = env; *envp != 0; envp += strlen(envp) + 1) {
        envc++;
    }

    envv = stgMallocBytes(sizeof(char*) * (envc+1), "getProgEnvv");

    i = 0;
    for (envp = env; *envp != 0; envp += strlen(envp) + 1) {
        envv[i] = envp;
        i++;
    }
    /* stash whole env in last+1 entry */
    envv[envc] = env;

    *out_envc = envc;
    *out_envv = envv;
}
コード例 #4
0
static jstring
environmentBlock9x(JNIEnv *env)
{
    int i;
    jmethodID String_init_ID =
        (*env)->GetMethodID(env, JNU_ClassString(env), "<init>", "([B)V");
    jbyteArray bytes;
    jbyte *blockA = (jbyte *) GetEnvironmentStringsA();
    if (blockA == NULL) {
        /* Both GetEnvironmentStringsW and GetEnvironmentStringsA
         * failed.  Out of memory is our best guess.  */
        JNU_ThrowOutOfMemoryError(env, "GetEnvironmentStrings failed");
        return NULL;
    }

    /* Don't search for "\0\0", since an empty environment block may
       legitimately consist of a single "\0". */
    for (i = 0; blockA[i];)
        while (blockA[i++])
            ;

    if ((bytes = (*env)->NewByteArray(env, i)) == NULL) return NULL;
    (*env)->SetByteArrayRegion(env, bytes, 0, i, blockA);
    FreeEnvironmentStringsA(blockA);
    return (*env)->NewObject(env, JNU_ClassString(env),
                             String_init_ID, bytes);
}
コード例 #5
0
ファイル: emain.c プロジェクト: Antopower/PRB
int main (void)
{
	int argc;
	char **argv;
	char **envp;

		/* These variables are used by the WEL library */
	ghInstance = GetModuleHandle(NULL);
	eif_hInstance = GetModuleHandle(NULL);
	eif_hPrevInstance = NULL;
	eif_lpCmdLine = GetCommandLine();
	eif_nCmdShow = SW_SHOW;

		/* Initialization of the command line which is going to be passed to eiffel */
	get_argcargv (&argc, &argv);
		/* We get ANSI version of environment variables */
	envp = (char **) GetEnvironmentStringsA();

	eif_alloc_init();
#ifdef EIF_THREADS
	eif_thr_init_root();
#endif
	{
		GTCX
		struct ex_vect *exvect;
		jmp_buf exenv;
	
		egc_init_plug();
		initsig();
		initstk();
		exvect = exset((char *) 0, 0, (char *) 0);
		exvect->ex_jbuf = &exenv;
		if (setjmp(exenv))
			failure();
	
		eif_retrieve_root (&argc, argv);
		eif_rtinit(argc, argv, envp);
		eif_init_root();
		egc_rcdt_init();
		emain(argc, argv);
		free_argv (&argv);
		reclaim();
	}
	FreeEnvironmentStringsA ((LPSTR) envp);

	exit(0);
	return 0;
}
コード例 #6
0
ファイル: CrashHandler.c プロジェクト: DisAsmCompany/DisAsm
void InfoEnvironment()
{
	char * env = NULL;
	if (NULL != (env = GetEnvironmentStringsA()))
	{
		uint32_t length = 0;
		ConsoleIOPrint("Environment :\n");

		do
		{
			ConsoleIOPrintFormatted("%s\n", env);
			env += (length = xstrlen(env)) + 1;
		}
		while (length > 0);
	}
}
コード例 #7
0
ファイル: rust_builtin.cpp プロジェクト: gwillen/rust
extern "C" CDECL rust_str *
rust_getcwd() {
    rust_task *task = rust_get_current_task();
    LOG(task, task, "rust_getcwd()");

    char cbuf[BUF_BYTES];

#if defined(__WIN32__)
    if (!_getcwd(cbuf, sizeof(cbuf))) {
#else
        if (!getcwd(cbuf, sizeof(cbuf))) {
#endif
        task->fail();
        return NULL;
    }

    return make_str(task->kernel, cbuf, strlen(cbuf), "rust_str(getcwd)");
}

#if defined(__WIN32__)
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
    rust_task *task = rust_get_current_task();
    size_t envc = 0;
    LPTCH ch = GetEnvironmentStringsA();
    LPTCH c;
    for (c = ch; *c; c += strlen(c) + 1) {
        ++envc;
    }
    c = ch;
    rust_vec_box *v = (rust_vec_box *)
        task->kernel->malloc(vec_size<rust_vec_box*>(envc),
                       "str vec interior");
    v->body.fill = v->body.alloc = sizeof(rust_vec*) * envc;
    for (size_t i = 0; i < envc; ++i) {
        size_t n = strlen(c);
        rust_str *str = make_str(task->kernel, c, n, "str");
        ((rust_str**)&v->body.data)[i] = str;
        c += n + 1;
    }
    if (ch) {
        FreeEnvironmentStrings(ch);
    }
    return v;
}
#else
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
    rust_task *task = rust_get_current_task();
#ifdef __APPLE__
    char **environ = *_NSGetEnviron();
#endif
    char **e = environ;
    size_t envc = 0;
    while (*e) {
        ++envc; ++e;
    }
    return make_str_vec(task->kernel, envc, environ);
}
#endif

extern "C" CDECL void
unsupervise() {
    rust_task *task = rust_get_current_task();
    task->unsupervise();
}
コード例 #8
0
LPVOID __cdecl __crtGetEnvironmentStringsW(
        VOID
        )
{
        static int f_use = 0;
        void *penv = NULL;
        char *pch;
        wchar_t *pwch;
        wchar_t *wbuffer;
        int total_size = 0;
        int str_size;

        /*
         * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
         * Must actually call the function to ensure it's not a stub.
         */

        if ( 0 == f_use )
        {
            if ( NULL != (penv = GetEnvironmentStringsW()) )
                f_use = USE_W;

            else if ( NULL != (penv = GetEnvironmentStringsA()) )
                f_use = USE_A;
            else
                return NULL;
        }

        /* Use "W" version */

        if ( USE_W == f_use )
        {
            if ( NULL == penv )
                if ( NULL == (penv = GetEnvironmentStringsW()) )
                    return NULL;

            /* find out how big a buffer is needed */

            pwch = penv;
            while ( *pwch != L'\0' ) {
                if ( *++pwch == L'\0' )
                    pwch++;
            }

            total_size = (char *)pwch - (char *)penv + sizeof( wchar_t );

            /* allocate the buffer */

            if ( NULL == (wbuffer = _malloc_crt( total_size )) ) {
                FreeEnvironmentStringsW( penv );
                return NULL;
            }

            /* copy environment strings to buffer */

            memcpy( wbuffer, penv, total_size );

            FreeEnvironmentStringsW( penv );

            return (LPVOID)wbuffer;
        }

        /* Use "A" version */

        if ( USE_A == f_use )
        {
            /*
             * Convert strings and return the requested information.
             */
            if ( NULL == penv )
                if ( NULL == (penv = GetEnvironmentStringsA()) )
                    return NULL;

            pch = penv;

            /* find out how big a buffer we need */
            while ( *pch != '\0' )
            {
                if ( 0 == (str_size =
                      MultiByteToWideChar( __lc_codepage,
                                           MB_PRECOMPOSED,
                                           pch,
                                           -1,
                                           NULL,
                                           0 )) )
                    return 0;

                total_size += str_size;
                pch += strlen(pch) + 1;
            }

            /* room for final NULL */
            total_size++;

            /* allocate enough space for chars */
            if ( NULL == (wbuffer = (wchar_t *)
                 _malloc_crt( total_size * sizeof( wchar_t ) )) )
            {
                FreeEnvironmentStringsA( penv );
                return NULL;
            }

            /* do the conversion */
            pch = penv;
            pwch = wbuffer;
            while (*pch != '\0')
            {
                if ( 0 == MultiByteToWideChar( __lc_codepage,
                                               MB_PRECOMPOSED,
                                               pch,
                                               -1,
                                               pwch,
                                               total_size - (pwch -
                                                 wbuffer) ) )
                {
                    _free_crt( wbuffer );
                    FreeEnvironmentStringsA( penv );
                    return NULL;
                }

                pch += strlen(pch) + 1;
                pwch += wcslen(pwch) + 1;
            }
            *pwch = L'\0';

            FreeEnvironmentStringsA( penv );

            return (LPVOID)wbuffer;

        }
        else   /* f_use is neither USE_A nor USE_W */
            return NULL;
}
コード例 #9
0
ファイル: aw_env.c プロジェクト: chunhualiu/OpenNT
LPVOID __cdecl __crtGetEnvironmentStringsA(
	VOID
	)
{
        static int f_use = 0;
	wchar_t *wEnv;
	wchar_t *wTmp;
	char *aEnv;
	char *aTmp;
	int nSizeW;
	int nSizeA;

        /* 
         * Look for 'preferred' flavor. Otherwise use available flavor.
         * Must actually call the function to ensure it's not a stub.
         */

        if ( 0 == f_use )
        {
            if ( NULL != (wEnv = GetEnvironmentStringsW()) )
                f_use = USE_W;

            else if ( NULL != (aEnv = GetEnvironmentStringsA()) )
                f_use = USE_A;

            else
                return NULL;
        }

        /* Use "W" version */

        if (USE_W == f_use)
        {
            /* obtain wide environment block */
	    if ( NULL == wEnv )
		if ( NULL == (wEnv = GetEnvironmentStringsW()) )
		    return NULL;

            /* look for double null that indicates end of block */
            wTmp = wEnv;
	    while ( *wTmp != L'\0' ) {
                if ( *++wTmp == L'\0' )
                    wTmp++;
            }

            /* calculate total size of block, including all nulls */
            nSizeW = wTmp - wEnv + 1;

            /* find out how much space needed for multi-byte environment */
            nSizeA = WideCharToMultiByte(   CP_ACP,
                                            0,
                                            wEnv,
                                            nSizeW,
                                            NULL,
                                            0,
                                            NULL,
                                            NULL );

            /* allocate space for multi-byte string */
            if ( (nSizeA == 0) || 
		 ((aEnv = (char *)_malloc_crt(nSizeA)) == NULL) )
	    {
		FreeEnvironmentStringsW( wEnv );
                return NULL;
	    }

            /* do the conversion */
            if ( !WideCharToMultiByte(  CP_ACP,
                                        0,
                                        wEnv,
                                        nSizeW,
                                        aEnv,
                                        nSizeA,
                                        NULL,
                                        NULL ) )
	    {
		_free_crt( aEnv );
                aEnv = NULL; 
	    }

            FreeEnvironmentStringsW( wEnv );
            return aEnv;
        }

        /* Use "A" version */

        if ( USE_A == f_use )
        {
	    if ( NULL == aEnv )
		if ( NULL == (aEnv = GetEnvironmentStringsA()) )
		    return NULL;

	    /* determine how big a buffer is needed */

	    aTmp = aEnv;

	    while ( *aTmp != '\0' ) {
		if ( *++aTmp == '\0' )
		    aTmp++;
	    }
	
	    nSizeA = aTmp - aEnv + 1;

	    if ( NULL == (aTmp = _malloc_crt( nSizeA )) ) {
		FreeEnvironmentStringsA( aEnv );
		return NULL;
	    }

	    memcpy( aTmp, aEnv, nSizeA );

	    FreeEnvironmentStringsA( aEnv );

	    return aTmp;
        }

        return NULL;
}
コード例 #10
0
ファイル: except.c プロジェクト: amir9/longene
/******************************************************************
 *		start_debugger
 *
 * Does the effective debugger startup according to 'format'
 */
static BOOL	start_debugger(PEXCEPTION_POINTERS epointers, HANDLE hEvent)
{
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING nameW;
    char *cmdline, *env, *p;
    HANDLE		hDbgConf;
    DWORD		bAuto = TRUE;
    PROCESS_INFORMATION	info;
    STARTUPINFOA	startup;
    char*		format = NULL;
    BOOL		ret = FALSE;
    char buffer[256];

    static const WCHAR AeDebugW[] = {'M','a','c','h','i','n','e','\\',
                                     'S','o','f','t','w','a','r','e','\\',
                                     'M','i','c','r','o','s','o','f','t','\\',
                                     'W','i','n','d','o','w','s',' ','N','T','\\',
                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
                                     'A','e','D','e','b','u','g',0};
    static const WCHAR DebuggerW[] = {'D','e','b','u','g','g','e','r',0};
    static const WCHAR AutoW[] = {'A','u','t','o',0};

    format_exception_msg( epointers, buffer, sizeof(buffer) );
    MESSAGE("wine: %s (thread %04x), starting debugger...\n", buffer, GetCurrentThreadId());

    attr.Length = sizeof(attr);
    attr.RootDirectory = 0;
    attr.ObjectName = &nameW;
    attr.Attributes = 0;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;
    RtlInitUnicodeString( &nameW, AeDebugW );

    if (!NtOpenKey( &hDbgConf, KEY_ALL_ACCESS, &attr ))
    {
        char buffer[64];
        KEY_VALUE_PARTIAL_INFORMATION *info;
        DWORD format_size = 0;

        RtlInitUnicodeString( &nameW, DebuggerW );
        if (NtQueryValueKey( hDbgConf, &nameW, KeyValuePartialInformation,
                             NULL, 0, &format_size ) == STATUS_BUFFER_OVERFLOW)
        {
            char *data = HeapAlloc(GetProcessHeap(), 0, format_size);
            NtQueryValueKey( hDbgConf, &nameW, KeyValuePartialInformation,
                             data, format_size, &format_size );
            info = (KEY_VALUE_PARTIAL_INFORMATION *)data;
            RtlUnicodeToMultiByteSize( &format_size, (WCHAR *)info->Data, info->DataLength );
            format = HeapAlloc( GetProcessHeap(), 0, format_size+1 );
            RtlUnicodeToMultiByteN( format, format_size, NULL,
                                    (WCHAR *)info->Data, info->DataLength );
            format[format_size] = 0;

            if (info->Type == REG_EXPAND_SZ)
            {
                char* tmp;

                /* Expand environment variable references */
                format_size=ExpandEnvironmentStringsA(format,NULL,0);
                tmp=HeapAlloc(GetProcessHeap(), 0, format_size);
                ExpandEnvironmentStringsA(format,tmp,format_size);
                HeapFree(GetProcessHeap(), 0, format);
                format=tmp;
            }
            HeapFree( GetProcessHeap(), 0, data );
        }

        RtlInitUnicodeString( &nameW, AutoW );
        if (!NtQueryValueKey( hDbgConf, &nameW, KeyValuePartialInformation,
                              buffer, sizeof(buffer)-sizeof(WCHAR), &format_size ))
       {
           info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
           if (info->Type == REG_DWORD) memcpy( &bAuto, info->Data, sizeof(DWORD) );
           else if (info->Type == REG_SZ)
           {
               WCHAR *str = (WCHAR *)info->Data;
               str[info->DataLength/sizeof(WCHAR)] = 0;
               bAuto = atoiW( str );
           }
       }

       NtClose(hDbgConf);
    }

    if (format)
    {
        cmdline = HeapAlloc(GetProcessHeap(), 0, strlen(format) + 2*20);
        sprintf(cmdline, format, GetCurrentProcessId(), hEvent);
        HeapFree(GetProcessHeap(), 0, format);
    }
    else
    {
        cmdline = HeapAlloc(GetProcessHeap(), 0, 80);
        sprintf(cmdline, "winedbg --auto %d %ld",
                GetCurrentProcessId(), (ULONG_PTR)hEvent);
    }

    if (!bAuto)
    {
	HMODULE			mod = GetModuleHandleA( "user32.dll" );
	MessageBoxA_funcptr	pMessageBoxA = NULL;

	if (mod) pMessageBoxA = (MessageBoxA_funcptr)GetProcAddress( mod, "MessageBoxA" );
	if (pMessageBoxA)
	{
            static const char msg[] = ".\nDo you wish to debug it?";
	    char buffer[256];

            format_exception_msg( epointers, buffer, sizeof(buffer)-sizeof(msg) );
            strcat( buffer, msg );
	    if (pMessageBoxA( 0, buffer, "Exception raised", MB_YESNO | MB_ICONHAND ) == IDNO)
	    {
		TRACE("Killing process\n");
		goto EXIT;
	    }
	}
    }

    /* make WINEDEBUG empty in the environment */
    env = GetEnvironmentStringsA();
    for (p = env; *p; p += strlen(p) + 1)
    {
        if (!memcmp( p, "WINEDEBUG=", sizeof("WINEDEBUG=")-1 ))
        {
            char *next = p + strlen(p);
            char *end = next + 1;
            while (*end) end += strlen(end) + 1;
            memmove( p + sizeof("WINEDEBUG=") - 1, next, end + 1 - next );
            break;
        }
    }

    TRACE("Starting debugger %s\n", debugstr_a(cmdline));
    memset(&startup, 0, sizeof(startup));
    startup.cb = sizeof(startup);
    startup.dwFlags = STARTF_USESHOWWINDOW;
    startup.wShowWindow = SW_SHOWNORMAL;
    ret = CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0, env, NULL, &startup, &info);
    FreeEnvironmentStringsA( env );

    if (ret)
    {
        /* wait for debugger to come up... */
        HANDLE handles[2];
        CloseHandle(info.hThread);
        handles[0]=hEvent;
        handles[1]=info.hProcess;
        WaitForMultipleObjects(2, handles, FALSE, INFINITE);
        CloseHandle(info.hProcess);
    }
    else ERR("Couldn't start debugger (%s) (%d)\n"
             "Read the Wine Developers Guide on how to set up winedbg or another debugger\n",
             debugstr_a(cmdline), GetLastError());
EXIT:
    HeapFree(GetProcessHeap(), 0, cmdline);
    return ret;
}
コード例 #11
0
ファイル: module.c プロジェクト: howard5888/wineT
static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk, WORD par_env_seg )
{
  IMAGE_DOS_HEADER mz_header;
  DWORD image_start,image_size,min_size,max_size,avail;
  BYTE*psp_start,*load_start;
  LPSTR oldenv = 0;
  int x, old_com=0, alloc;
  SEGPTR reloc;
  WORD env_seg, load_seg, rel_seg, oldpsp_seg;
  DWORD len;

  if (DOSVM_psp) {
    /* DOS process already running, inherit from it */
    PDB16* par_psp;
    alloc=0;
    oldpsp_seg = DOSVM_psp;
    if( !par_env_seg) {  
        par_psp = (PDB16*)((DWORD)DOSVM_psp << 4);
        oldenv = (LPSTR)((DWORD)par_psp->environment << 4);
    }
  } else {
    /* allocate new DOS process, inheriting from Wine environment */
    alloc=1;
    oldpsp_seg = 0;
    if( !par_env_seg)
        oldenv = GetEnvironmentStringsA();
  }

 SetFilePointer(hFile,0,NULL,FILE_BEGIN);
 if (   !ReadFile(hFile,&mz_header,sizeof(mz_header),&len,NULL)
     || len != sizeof(mz_header)
     || mz_header.e_magic != IMAGE_DOS_SIGNATURE) {
  char *p = strrchr( filename, '.' );
  if (!p || strcasecmp( p, ".com" ))  /* check for .COM extension */
  {
      SetLastError(ERROR_BAD_FORMAT);
      goto load_error;
  }
  old_com=1; /* assume .COM file */
  image_start=0;
  image_size=GetFileSize(hFile,NULL);
  min_size=0x10000; max_size=0x100000;
  mz_header.e_crlc=0;
  mz_header.e_ss=0; mz_header.e_sp=0xFFFE;
  mz_header.e_cs=0; mz_header.e_ip=0x100;
 } else {
  /* calculate load size */
  image_start=mz_header.e_cparhdr<<4;
  image_size=mz_header.e_cp<<9; /* pages are 512 bytes */
  /* From Ralf Brown Interrupt List: If the word at offset 02h is 4, it should
   * be treated as 00h, since pre-1.10 versions of the MS linker set it that
   * way. */
  if ((mz_header.e_cblp!=0)&&(mz_header.e_cblp!=4)) image_size-=512-mz_header.e_cblp;
  image_size-=image_start;
  min_size=image_size+((DWORD)mz_header.e_minalloc<<4)+(PSP_SIZE<<4);
  max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4);
 }

  if (alloc) MZ_InitMemory();

  if (oblk) {
    /* load overlay into preallocated memory */
    load_seg=oblk->load_seg;
    rel_seg=oblk->rel_seg;
    load_start=(LPBYTE)((DWORD)load_seg<<4);
  } else {
    /* allocate environment block */
    if( par_env_seg)
        env_seg = par_env_seg;
    else
        env_seg=MZ_InitEnvironment(oldenv, filename);
    if( alloc && oldenv)
        FreeEnvironmentStringsA( oldenv);

    /* allocate memory for the executable */
    TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
    avail=DOSMEM_Available();
    if (avail<min_size) {
      ERR("insufficient DOS memory\n");
      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
      goto load_error;
    }
    if (avail>max_size) avail=max_size;
    psp_start=DOSMEM_AllocBlock(avail,&DOSVM_psp);
    if (!psp_start) {
      ERR("error allocating DOS memory\n");
      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
      goto load_error;
    }
    load_seg=DOSVM_psp+(old_com?0:PSP_SIZE);
    rel_seg=load_seg;
    load_start=psp_start+(PSP_SIZE<<4);
    MZ_CreatePSP(psp_start, env_seg, oldpsp_seg);
  }

 /* load executable image */
 TRACE("loading DOS %s image, %08lx bytes\n",old_com?"COM":"EXE",image_size);
 SetFilePointer(hFile,image_start,NULL,FILE_BEGIN);
 if (!ReadFile(hFile,load_start,image_size,&len,NULL) || len != image_size) {
  /* check if this is due to the workaround for the pre-1.10 MS linker and we
     realy had only 4 bytes on the last page */
  if (mz_header.e_cblp != 4 || image_size - len != 512 - 4) {
    SetLastError(ERROR_BAD_FORMAT);
    goto load_error;
  }
 }

 if (mz_header.e_crlc) {
  /* load relocation table */
  TRACE("loading DOS EXE relocation table, %d entries\n",mz_header.e_crlc);
  /* FIXME: is this too slow without read buffering? */
  SetFilePointer(hFile,mz_header.e_lfarlc,NULL,FILE_BEGIN);
  for (x=0; x<mz_header.e_crlc; x++) {
   if (!ReadFile(hFile,&reloc,sizeof(reloc),&len,NULL) || len != sizeof(reloc)) {
    SetLastError(ERROR_BAD_FORMAT);
    goto load_error;
   }
   *(WORD*)SEGPTR16(load_start,reloc)+=rel_seg;
  }
 }

  if (!oblk) {
    init_cs = load_seg+mz_header.e_cs;
    init_ip = mz_header.e_ip;
    init_ss = load_seg+mz_header.e_ss;
    init_sp = mz_header.e_sp;
    if (old_com){
      /* .COM files exit with ret. Make sure they jump to psp start (=int 20) */
      WORD* stack = PTR_REAL_TO_LIN(init_ss, init_sp);
      *stack = 0;
    }

    TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
  }

  if (alloc && !MZ_InitTask()) {
    SetLastError(ERROR_GEN_FAILURE);
    return FALSE;
  }

  return TRUE;

load_error:
  DOSVM_psp = oldpsp_seg;

  return FALSE;
}