1998-04-13 14:21:30 +02:00
|
|
|
/*
|
|
|
|
* Process environment management
|
|
|
|
*
|
|
|
|
* Copyright 1996, 1998 Alexandre Julliard
|
2002-03-10 00:29:33 +01:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-18 23:04:23 +02:00
|
|
|
#include "config.h"
|
|
|
|
#include "wine/port.h"
|
|
|
|
|
1998-04-13 14:21:30 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2003-06-18 05:23:22 +02:00
|
|
|
#include <assert.h>
|
2001-07-18 23:04:23 +02:00
|
|
|
|
2000-02-10 20:03:02 +01:00
|
|
|
#include "windef.h"
|
2000-11-28 23:40:56 +01:00
|
|
|
#include "winerror.h"
|
2001-07-18 23:04:23 +02:00
|
|
|
|
|
|
|
#include "wine/winbase16.h"
|
2002-03-29 19:28:56 +01:00
|
|
|
#include "wine/server.h"
|
2002-05-17 01:16:01 +02:00
|
|
|
#include "wine/library.h"
|
1998-04-13 14:21:30 +02:00
|
|
|
#include "heap.h"
|
2002-09-13 00:07:02 +02:00
|
|
|
#include "winternl.h"
|
1998-04-13 14:21:30 +02:00
|
|
|
#include "selectors.h"
|
2003-06-18 05:23:22 +02:00
|
|
|
#include "wine/unicode.h"
|
|
|
|
#include "wine/debug.h"
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(environ);
|
2000-12-11 04:48:15 +01:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
/* TODO:
|
|
|
|
* - 16 bit environment ??? (see generate_env_block16 for the details)
|
|
|
|
*/
|
2000-12-11 04:48:15 +01:00
|
|
|
|
1998-04-13 14:21:30 +02:00
|
|
|
/* Format of an 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)
|
|
|
|
*
|
|
|
|
* Notes:
|
|
|
|
* - contrary to Microsoft docs, the environment strings do not appear
|
|
|
|
* to be sorted on Win95 (although they are on NT); so we don't bother
|
|
|
|
* to sort them either.
|
2003-06-18 05:23:22 +02:00
|
|
|
* - on Win2K (and likely most of NT versions) the last part (WORD 1 and
|
|
|
|
* program name no longer appear in the environment block (from the 32
|
|
|
|
* bit interface)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
static const char ENV_program_name[] = "C:\\WINDOWS\\SYSTEM\\KRNL386.EXE";
|
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
static STARTUPINFOW startup_infoW;
|
|
|
|
static STARTUPINFOA startup_infoA;
|
|
|
|
|
Release 980503
Thu Apr 30 16:28:12 1998 James Juran <jrj120@psu.edu>
* [scheduler/process.c]
Implemented GetExitCodeProcess. The code is a direct translation
of GetExitCodeThread.
Mon Apr 27 22:20:25 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [loader/pe_image.c]
Unload dummy module when PE_LoadLibraryEx32A fails with
PE_LoadImage (makes Encarta 98 installer proceed).
* [files/drive.c]
Make GetDriveType16 return DRIVE_REMOVABLE for TYPE_CDROM.
Make GetCurrentDirectory32 behave like the code does and not
like the help describes.
* [files/profile.c]
Revoke recent change in PROFILE_GetSection and try better
handling of special case.
* [include/windows.h]
Change definition of ACCEL32.
* [misc/commdlg.c]
Replace the GetXXXFilename32 macros by normal code.
Fix two reported bugs in my changes to commdlg.
* [windows/win.c]
Add a hook to catch bogus WM_SIZE messages by emitting a warning
in the appropriate case.
* [objects/bitmap.c]
Reject unreasonbable large size arguments in
CreateCompatibleBitmap32 and add an fixme for that situation.
Sun Apr 26 18:30:07 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/ldt.h] [debugger/*.c] [miscemu/instr.c]
Added IS_SELECTOR_SYSTEM and IS_SELECTOR_32BIT macros.
Make instruction emulation support system selectors.
* [loader/*.c]
Started moving NE specific functions to the new loader/ne
directory.
* [memory/environ.c]
Enforce the 127 chars limit only when creating the environment of
a Win16 process.
Sun Apr 26 12:22:23 1998 Andreas Mohr <100.30936@germany.net>
* [files/file.c]
Fixed an incredible typo in CopyFile32A that made it unusable
since a rewrite in 970112 (!!).
* [files/directory.c]
Fixed GetTempPath32A/W to include trailing backslash.
* [misc/ver.c]
Make find_pe_resource "work" with corrupt files.
* [misc/wsprintf.c]
Altered WPRINTF_ParseFormatA/W to treat invalid format chars
as normal output, too.
* [msdos/dpmi.c]
Implemented "Allocate/Free real mode callback" (0x0303/0x0304).
Cross your fingers if you need to use it ;) (completely untested)
Implemented "Call real mode proc with far return" (0x0301, tested).
* [msdos/int21.c]
Fixed ioctlGenericBlkDevReq/0x60.
* [relay32/dplayx.spec] [relay32/builtin32.c] [relay32/Makefile.in]
Added built-in DPLAYX.DLL.
* [windows/win.c]
Fixed GetWindowWord()/GWW_HWNDPARENT to return the window's owner
if it has no parent (SDK).
Sat Apr 25 15:09:53 1998 M.T.Fortescue <mark@mtfhpc.demon.co.uk>
* [debugger/db_disasm.c]
Fixed disassemble bug for no-display option and 'lock',
'repne' and 'repe' prefixes.
* [debugger/registers.c]
Added textual flag description output on 'info regs'.
Sat Apr 25 14:18:26 1998 Matthew Becker <mbecker@glasscity.net>
* [*/*.c]
Added stubs and/or documentation for the following functions:
LookupPrivilegeValue, OpenService, ControlService, RegGetKeySecurity,
StartService, SetComputerName, DeleteService, CloseServiceHandle,
OpenProcessToken, OpenSCManager, DeregisterEventSource,
WaitForDebugEvent, WaitForInputIdle, RegisterEventSource,
SetDebugErrorLevel, SetConsoleCursorPosition, ChoosePixelFormat,
SetPixelFormat, GetPixelFormat, DescribePixelFormat, SwapBuffers,
PolyBezier, AbortPath, DestroyAcceleratorTable, HeapWalk,
DdeInitialize, DdeUninitialize, DdeConnectList, DdeDisconnectList,
DdeCreateStringHandle, DdePostAdvise, DdeGetData, DdeNameService,
DdeGetLastError, WNetGetDirectoryType, EnumPrinters, RegFlushKey,
RegGetKeySecurity, DllGetClassObject, DllCanUnloadNow, CreateBitmap,
CreateCompatibleBitmap, CreateBitmapIndirect, GetBitmapBits,
SetBitmapBits, LoadImage, CopyImage, LoadBitmap, DrawIcon,
CreateDiscardableBitmap, SetDIBits, GetCharABCWidths, LoadTypeLib,
SetConsoleCtrlHandler, CreateConsoleScreenBuffer, ReadConsoleInput,
GetConsoleCursorInfo, SetConsoleCursorInfo, SetConsoleWindowInfo,
SetConsoleTextAttribute, SetConsoleScreenBufferSize,
FillConsoleOutputCharacter, FillConsoleOutputAttribute,
CreateMailslot, GetMailslotInfo, GetCompressedFileSize,
GetProcessWindowStation, GetThreadDesktop, SetDebugErrorLevel,
WaitForDebugEvent, SetComputerName, CreateMDIWindow.
Thu Apr 23 23:54:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [include/windows.h] [objects/enhmetafile.c] [relay32/gdi32.spec]
Implement CopyEnhMetaFile, Get/SetEnhMetaFileBits, other fixes.
* [include/windows.h] [objects/metafile.c] [relay32/gdi32.spec]
32-bit metafile fixes, implement EnumMetaFile32, GetMetaFileBitsEx.
* [objects/font.c] [graphics/x11drv/xfont.c] [graphics/x11drv/text.c]
Some rotated text support for X11R6 displays.
* [win32/newfns.c] [ole/ole2nls.c]
Moved GetNumberFormat32A.
Wed Apr 22 17:38:20 1998 David Lee Lambert <lamber45@egr.msu.edu>
* [ole/ole2nls.c] [misc/network.c]
Changed some function documentation to the new style.
* [misc/network.c] [include/windows.h] [if1632/user.spec]
[relay32/mpr.spec] [misc/mpr.c]
Added stubs for some Win32 network functions; renamed some
16-bit ones with 32-bit counterparts, as well as
WNetGetDirectoryType; moved the stubs in misc/mpr.c (three of
them!) to misc/network.c.
* [ole/compobj.c] [ole/storage.c] [ole/ole2disp.c]
[ole/ole2nls.c] [ole/folders.c] [ole/moniker.c] [ole/ole2.c]
[graphics/fontengine.c] [graphics/ddraw.c] [graphics/env.c]
[graphics/driver.c] [graphics/escape.c]
Changed fprintf's to proper debug-macros.
* [include/winnls.h]
Added some flags (for internal use).
* [ole/ole2nls.c]
Added the Unicode core function, and worked out a way to hide
the commonality of the core.
* [relay32/kernel32.spec]
Added support for GetDate/Time32A/W.
Wed Apr 22 09:16:03 1998 Gordon Chaffee <chaffee@cs.berkeley.edu>
* [win32/code_page.c]
Fixed problem with MultiByteToWideChar that was introduced in
last release. Made MultiByteToWideChar more compatible with Win32.
* [graphics/x11drv/graphics.c]
Fixed problem with drawing arcs.
Tue Apr 21 11:24:58 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [ole/ole2nls.c]
Move stuff from 0x409 case to Lang_En.
* [relay32/user32.spec] [windows/winpos.c]
Added stubs for GetWindowRgn32 and SetWindowRgn32. Makes Office
Paperclip happy.
Tue Apr 21 11:16:16 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [loader/pe_image.c]
If image is relocated, TLS addresses need to be adjusted.
* [debugger/*.c]
Generalized tests for 32-bit segments.
Tue Apr 21 02:04:59 1998 James Juran <jrj120@psu.edu>
* [misc/*.c] [miscemu/*.c] [msdos/*.c] [if1632/*.c]
[include/*.h] [loader/*.c] [memory/*.c] [multimedia/*.c]
[objects/*.c]
Almost all fprintf statements converted to appropriate
debug messages.
* [README]
Updated "GETTING MORE INFORMATION" section to include WineHQ.
* [documentation/debugger]
Fixed typo.
* [windows/defwnd.c]
Added function documentation.
Sun Apr 19 16:30:58 1998 Marcus Meissner <marcus@mud.de>
* [Make.rules.in]
Added lint target (using lclint).
* [relay32/oleaut32.spec][relay32/Makefile.in][ole/typelib.c]
[ole/ole2disp.c]
Added oleaut32 spec, added some SysString functions.
* [if1632/signal.c]
Added printing of faultaddress in Linux (using CR2 debug register).
* [configure.in]
Added <sys/types.h> for statfs checks.
* [loader/*.c][debugger/break.c][debugger/hash.c]
Started to split win32/win16 module handling, preparing support
for other binary formats (like ELF).
Sat Apr 18 10:07:41 1998 Rein Klazes <rklazes@casema.net>
* [misc/registry.c]
Fixed a bug that made RegQueryValuexxx returning
incorrect registry values.
Fri Apr 17 22:59:22 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/lstr.c]
FormatMessage32*: remove linefeed when nolinefeed set;
check for target underflow.
Fri Apr 17 00:38:14 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/crtdll.c]
Implement xlat_file_ptr for CRT stdin/stdout/stderr address
translation.
Wed Apr 15 20:43:56 1998 Jim Peterson <jspeter@birch.ee.vt.edu>
* [controls/menu.c]
Added 'odaction' parameter to MENU_DrawMenuItem() and redirected
WM_DRAWITEM messages to GetWindow(hwnd,GW_OWNER).
Tue Apr 14 16:17:55 1998 Berend Reitsma <berend@united-info.com>
* [graphics/metafiledrv/init.c] [graphics/painting.c]
[graphics/win16drv/init.c] [graphics/x11drv/graphics.c]
[graphics/x11drv/init.c] [include/gdi.h] [include/x11drv.h]
[relay32/gdi32.spec]
Added PolyPolyline routine.
* [windows/winproc.c]
Changed WINPROC_GetProc() to return proc instead of &(jmp proc).
1998-05-03 21:01:20 +02:00
|
|
|
/* Maximum length of a Win16 environment string (including NULL) */
|
|
|
|
#define MAX_WIN16_LEN 128
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
static WORD env_sel; /* selector to the 16 bit environment */
|
2002-05-17 01:16:01 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
/******************************************************************
|
|
|
|
* generate_env_block16
|
2002-05-17 01:16:01 +02:00
|
|
|
*
|
2003-06-18 05:23:22 +02:00
|
|
|
* This internal function generates a suitable environment for the 16 bit
|
|
|
|
* subsystem and returns the value as a segmented pointer.
|
2000-12-11 04:48:15 +01:00
|
|
|
*
|
2003-06-18 05:23:22 +02:00
|
|
|
* FIXME: current implementation will allocate a private copy of the
|
|
|
|
* environment strings, but will not follow the modifications (if any)
|
|
|
|
* from the unicode env block stored in the PEB
|
|
|
|
* => how should this be updated from the ntdll modifications ?
|
|
|
|
* should we use the peb->EnvironmentUpdateCount field to
|
|
|
|
* know when environment has changed ???
|
|
|
|
* we currently regenerate this block each time an environment
|
|
|
|
* variable is modified from a Win32 API call, but we'll miss all
|
|
|
|
* direct access to the NTDLL APIs
|
2000-12-11 04:48:15 +01:00
|
|
|
*/
|
2003-06-18 05:23:22 +02:00
|
|
|
static SEGPTR generate_env_block16(void)
|
2000-12-11 04:48:15 +01:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
static LPSTR env16;
|
2002-05-17 01:16:01 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
DWORD size, new_size;
|
|
|
|
WORD one = 1;
|
2002-03-29 19:28:56 +01:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
if (env16) FreeEnvironmentStringsA( env16 );
|
2001-09-20 21:05:11 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
env16 = GetEnvironmentStringsA();
|
|
|
|
size = HeapSize(GetProcessHeap(), 0, env16);
|
|
|
|
new_size = size + sizeof(WORD) + sizeof(ENV_program_name);
|
|
|
|
if (!(env16 = HeapReAlloc( GetProcessHeap(), 0, env16, new_size ))) return 0;
|
2001-09-20 21:05:11 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
memcpy(env16 + size, &one, sizeof(one));
|
|
|
|
memcpy(env16 + size + sizeof(WORD), ENV_program_name, sizeof(ENV_program_name));
|
|
|
|
if (env_sel)
|
|
|
|
env_sel = SELECTOR_ReallocBlock( env_sel, env16, new_size );
|
|
|
|
else
|
|
|
|
env_sel = SELECTOR_AllocBlock( env16, 0x10000, WINE_LDT_FLAGS_DATA );
|
2001-09-20 21:05:11 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
return MAKESEGPTR( env_sel, 0 );
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetCommandLineA (KERNEL32.@)
|
2001-10-02 19:49:20 +02:00
|
|
|
*
|
|
|
|
* WARNING: there's a Windows incompatibility lurking here !
|
|
|
|
* Win32s always includes the full path of the program file,
|
|
|
|
* whereas Windows NT only returns the full file path plus arguments
|
|
|
|
* in case the program has been started with a full path.
|
|
|
|
* Win9x seems to have inherited NT behaviour.
|
2002-06-01 01:06:46 +02:00
|
|
|
*
|
2001-10-02 19:49:20 +02:00
|
|
|
* Note that both Start Menu Execute and Explorer start programs with
|
|
|
|
* fully specified quoted app file paths, which is why probably the only case
|
|
|
|
* where you'll see single file names is in case of direct launch
|
|
|
|
* via CreateProcess or WinExec.
|
|
|
|
*
|
|
|
|
* Perhaps we should take care of Win3.1 programs here (Win32s "feature").
|
2002-06-01 01:06:46 +02:00
|
|
|
*
|
2001-10-02 19:49:20 +02:00
|
|
|
* References: MS KB article q102762.txt (special Win32s handling)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
2000-06-24 15:37:05 +02:00
|
|
|
LPSTR WINAPI GetCommandLineA(void)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
static char *cmdlineA; /* ASCII command line */
|
|
|
|
|
|
|
|
if (!cmdlineA) /* make an ansi version if we don't have it */
|
|
|
|
{
|
|
|
|
ANSI_STRING ansi;
|
|
|
|
RtlAcquirePebLock();
|
|
|
|
|
|
|
|
cmdlineA = (RtlUnicodeStringToAnsiString( &ansi, &NtCurrentTeb()->Peb->ProcessParameters->CommandLine, TRUE) == STATUS_SUCCESS) ?
|
|
|
|
ansi.Buffer : NULL;
|
|
|
|
RtlReleasePebLock();
|
|
|
|
}
|
|
|
|
return cmdlineA;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetCommandLineW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
2000-06-24 15:37:05 +02:00
|
|
|
LPWSTR WINAPI GetCommandLineW(void)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
return NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-07-11 20:56:41 +02:00
|
|
|
* GetEnvironmentStrings (KERNEL32.@)
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetEnvironmentStringsA (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
LPSTR WINAPI GetEnvironmentStringsA(void)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
LPWSTR ptrW;
|
|
|
|
unsigned len, slen;
|
|
|
|
LPSTR ret, ptrA;
|
|
|
|
|
|
|
|
RtlAcquirePebLock();
|
|
|
|
|
|
|
|
len = 1;
|
|
|
|
|
|
|
|
ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment;
|
|
|
|
while (*ptrW)
|
|
|
|
{
|
|
|
|
slen = strlenW(ptrW) + 1;
|
|
|
|
len += WideCharToMultiByte( CP_ACP, 0, ptrW, slen, NULL, 0, NULL, NULL );
|
|
|
|
ptrW += slen;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = HeapAlloc( GetProcessHeap(), 0, len )) != NULL)
|
|
|
|
{
|
|
|
|
ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment;
|
|
|
|
ptrA = ret;
|
|
|
|
while (*ptrW)
|
|
|
|
{
|
|
|
|
slen = strlenW(ptrW) + 1;
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, ptrW, slen, ptrA, len, NULL, NULL );
|
|
|
|
ptrW += slen;
|
|
|
|
ptrA += strlen(ptrA) + 1;
|
|
|
|
}
|
|
|
|
*ptrA = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlReleasePebLock();
|
|
|
|
return ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetEnvironmentStringsW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
LPWSTR WINAPI GetEnvironmentStringsW(void)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
return NtCurrentTeb()->Peb->ProcessParameters->Environment;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* FreeEnvironmentStringsA (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
BOOL WINAPI FreeEnvironmentStringsA( LPSTR ptr )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
return HeapFree( GetProcessHeap(), 0, ptr );
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* FreeEnvironmentStringsW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
BOOL WINAPI FreeEnvironmentStringsW( LPWSTR ptr )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
return TRUE;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetEnvironmentVariableA (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
DWORD WINAPI GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_name;
|
|
|
|
PWSTR valueW;
|
|
|
|
DWORD ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
|
|
|
|
if (!name || !*name)
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
1998-04-13 14:21:30 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2002-08-20 02:22:29 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
if (!(valueW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR))))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz( &us_name, name );
|
|
|
|
SetLastError(0);
|
|
|
|
ret = GetEnvironmentVariableW( us_name.Buffer, valueW, size);
|
|
|
|
if (ret && ret < size)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
WideCharToMultiByte( CP_ACP, 0, valueW, ret + 1, value, size, NULL, NULL );
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
2003-06-18 05:23:22 +02:00
|
|
|
/* this is needed to tell, with 0 as a return value, the difference between:
|
|
|
|
* - an error (GetLastError() != 0)
|
|
|
|
* - returning an empty string (in this case, we need to update the buffer)
|
|
|
|
*/
|
|
|
|
if (ret == 0 && size && GetLastError() == 0)
|
|
|
|
value[0] = '\0';
|
|
|
|
|
|
|
|
RtlFreeUnicodeString( &us_name );
|
|
|
|
HeapFree(GetProcessHeap(), 0, valueW);
|
|
|
|
|
2000-09-22 22:58:23 +02:00
|
|
|
return ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetEnvironmentVariableW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
2003-06-18 05:23:22 +02:00
|
|
|
DWORD WINAPI GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_name;
|
|
|
|
UNICODE_STRING us_value;
|
|
|
|
NTSTATUS status;
|
|
|
|
unsigned len;
|
2002-08-20 02:22:29 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
TRACE("(%s %p %lu)\n", debugstr_w(name), val, size);
|
|
|
|
|
|
|
|
if (!name || !*name)
|
2002-08-20 02:22:29 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
2002-08-20 02:22:29 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlInitUnicodeString(&us_name, name);
|
|
|
|
us_value.Length = 0;
|
|
|
|
us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
|
|
|
|
us_value.Buffer = val;
|
|
|
|
|
|
|
|
status = RtlQueryEnvironmentVariable_U(NULL, &us_name, &us_value);
|
|
|
|
len = us_value.Length / sizeof(WCHAR);
|
|
|
|
if (status != STATUS_SUCCESS)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
SetLastError( RtlNtStatusToDosError(status) );
|
|
|
|
return (status == STATUS_BUFFER_TOO_SMALL) ? len + 1 : 0;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
2003-06-18 05:23:22 +02:00
|
|
|
if (size) val[len] = '\0';
|
|
|
|
|
|
|
|
return us_value.Length / sizeof(WCHAR);
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* SetEnvironmentVariableA (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_name;
|
|
|
|
BOOL ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
if (!name)
|
2002-08-20 02:22:29 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
|
|
|
return 0;
|
2002-08-20 02:22:29 +02:00
|
|
|
}
|
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlCreateUnicodeStringFromAsciiz( &us_name, name );
|
|
|
|
if (value)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_value;
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlCreateUnicodeStringFromAsciiz( &us_value, value );
|
|
|
|
ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer );
|
|
|
|
RtlFreeUnicodeString( &us_value );
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
2003-06-18 05:23:22 +02:00
|
|
|
else ret = SetEnvironmentVariableW( us_name.Buffer, NULL );
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlFreeUnicodeString( &us_name );
|
1998-04-13 14:21:30 +02:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* SetEnvironmentVariableW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
BOOL WINAPI SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_name;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
TRACE("(%s %s)\n", debugstr_w(name), debugstr_w(value));
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&us_name, name);
|
|
|
|
if (value)
|
|
|
|
{
|
|
|
|
UNICODE_STRING us_value;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&us_value, value);
|
|
|
|
status = RtlSetEnvironmentVariable(NULL, &us_name, &us_value);
|
|
|
|
}
|
|
|
|
else status = RtlSetEnvironmentVariable(NULL, &us_name, NULL);
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
SetLastError( RtlNtStatusToDosError(status) );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: see comments in generate_env_block16 */
|
|
|
|
if (env_sel) generate_env_block16();
|
|
|
|
return TRUE;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* ExpandEnvironmentStringsA (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*
|
|
|
|
* Note: overlapping buffers are not supported; this is how it should be.
|
2003-06-18 05:23:22 +02:00
|
|
|
* FIXME: return value is wrong for MBCS
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
DWORD WINAPI ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_src;
|
|
|
|
PWSTR dstW = NULL;
|
|
|
|
DWORD ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlCreateUnicodeStringFromAsciiz( &us_src, src );
|
|
|
|
if (count)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
if (!(dstW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
|
|
|
|
return 0;
|
|
|
|
ret = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count);
|
|
|
|
if (ret)
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, dstW, ret, dst, count, NULL, NULL );
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
2003-06-18 05:23:22 +02:00
|
|
|
else ret = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0);
|
1998-04-13 14:21:30 +02:00
|
|
|
|
2003-06-18 05:23:22 +02:00
|
|
|
RtlFreeUnicodeString( &us_src );
|
|
|
|
if (dstW) HeapFree(GetProcessHeap(), 0, dstW);
|
|
|
|
|
|
|
|
return ret;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* ExpandEnvironmentStringsW (KERNEL32.@)
|
1998-04-13 14:21:30 +02:00
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
DWORD WINAPI ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
UNICODE_STRING us_src;
|
|
|
|
UNICODE_STRING us_dst;
|
|
|
|
NTSTATUS status;
|
|
|
|
DWORD res;
|
|
|
|
|
|
|
|
TRACE("(%s %p %lu)\n", debugstr_w(src), dst, len);
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&us_src, src);
|
|
|
|
us_dst.Length = 0;
|
|
|
|
us_dst.MaximumLength = len * sizeof(WCHAR);
|
|
|
|
us_dst.Buffer = dst;
|
|
|
|
|
|
|
|
res = 0;
|
|
|
|
status = RtlExpandEnvironmentStrings_U(NULL, &us_src, &us_dst, &res);
|
|
|
|
res /= sizeof(WCHAR);
|
|
|
|
if (status != STATUS_SUCCESS)
|
1998-04-13 14:21:30 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
SetLastError( RtlNtStatusToDosError(status) );
|
|
|
|
if (status != STATUS_BUFFER_TOO_SMALL) return 0;
|
|
|
|
if (len && dst) dst[len - 1] = '\0';
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
2003-06-18 05:23:22 +02:00
|
|
|
|
|
|
|
return res;
|
1998-04-13 14:21:30 +02:00
|
|
|
}
|
|
|
|
|
2000-08-10 00:33:42 +02:00
|
|
|
|
2000-12-11 04:48:15 +01:00
|
|
|
/***********************************************************************
|
2001-07-11 20:56:41 +02:00
|
|
|
* GetDOSEnvironment (KERNEL.131)
|
2000-12-11 04:48:15 +01:00
|
|
|
*/
|
|
|
|
SEGPTR WINAPI GetDOSEnvironment16(void)
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
return generate_env_block16();
|
2000-12-11 04:48:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-10 00:33:42 +02:00
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetStdHandle (KERNEL32.@)
|
2000-08-10 00:33:42 +02:00
|
|
|
*/
|
|
|
|
HANDLE WINAPI GetStdHandle( DWORD std_handle )
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
switch (std_handle)
|
2000-08-10 00:33:42 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
|
|
|
|
case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
|
|
|
|
case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError;
|
2000-08-10 00:33:42 +02:00
|
|
|
}
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* SetStdHandle (KERNEL32.@)
|
2000-08-10 00:33:42 +02:00
|
|
|
*/
|
|
|
|
BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
switch (std_handle)
|
2000-08-10 00:33:42 +02:00
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE;
|
|
|
|
case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE;
|
|
|
|
case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE;
|
2000-08-10 00:33:42 +02:00
|
|
|
}
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetStartupInfoA (KERNEL32.@)
|
2000-08-10 00:33:42 +02:00
|
|
|
*/
|
|
|
|
VOID WINAPI GetStartupInfoA( LPSTARTUPINFOA info )
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
assert(startup_infoA.cb);
|
|
|
|
memcpy(info, &startup_infoA, sizeof(startup_infoA));
|
2000-08-10 00:33:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2001-06-13 22:13:18 +02:00
|
|
|
* GetStartupInfoW (KERNEL32.@)
|
2000-08-10 00:33:42 +02:00
|
|
|
*/
|
|
|
|
VOID WINAPI GetStartupInfoW( LPSTARTUPINFOW info )
|
|
|
|
{
|
2003-06-18 05:23:22 +02:00
|
|
|
assert(startup_infoW.cb);
|
|
|
|
memcpy(info, &startup_infoW, sizeof(startup_infoW));
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
* ENV_CopyStartupInformation (internal)
|
|
|
|
*
|
|
|
|
* Creates the STARTUPINFO information from the ntdll information
|
|
|
|
*/
|
|
|
|
void ENV_CopyStartupInformation(void)
|
|
|
|
{
|
|
|
|
RTL_USER_PROCESS_PARAMETERS* rupp;
|
|
|
|
ANSI_STRING ansi;
|
|
|
|
|
|
|
|
RtlAcquirePebLock();
|
|
|
|
|
|
|
|
rupp = NtCurrentTeb()->Peb->ProcessParameters;
|
|
|
|
|
|
|
|
startup_infoW.cb = sizeof(startup_infoW);
|
|
|
|
startup_infoW.lpReserved = NULL;
|
|
|
|
startup_infoW.lpDesktop = rupp->Desktop.Buffer;
|
|
|
|
startup_infoW.lpTitle = rupp->WindowTitle.Buffer;
|
|
|
|
startup_infoW.dwX = rupp->dwX;
|
|
|
|
startup_infoW.dwY = rupp->dwY;
|
|
|
|
startup_infoW.dwXSize = rupp->dwXSize;
|
|
|
|
startup_infoW.dwYSize = rupp->dwYSize;
|
|
|
|
startup_infoW.dwXCountChars = rupp->dwXCountChars;
|
|
|
|
startup_infoW.dwYCountChars = rupp->dwYCountChars;
|
|
|
|
startup_infoW.dwFillAttribute = rupp->dwFillAttribute;
|
|
|
|
startup_infoW.dwFlags = rupp->dwFlags;
|
|
|
|
startup_infoW.wShowWindow = rupp->wShowWindow;
|
|
|
|
startup_infoW.cbReserved2 = 0;
|
|
|
|
startup_infoW.lpReserved2 = NULL;
|
|
|
|
startup_infoW.hStdInput = rupp->hStdInput;
|
|
|
|
startup_infoW.hStdOutput = rupp->hStdOutput;
|
|
|
|
startup_infoW.hStdError = rupp->hStdError;
|
|
|
|
|
|
|
|
startup_infoA.cb = sizeof(startup_infoW);
|
|
|
|
startup_infoA.lpReserved = NULL;
|
|
|
|
startup_infoA.lpDesktop = (rupp->Desktop.Length &&
|
|
|
|
RtlUnicodeStringToAnsiString( &ansi, &rupp->Desktop, TRUE) == STATUS_SUCCESS) ?
|
|
|
|
ansi.Buffer : NULL;
|
|
|
|
startup_infoA.lpTitle = (rupp->WindowTitle.Length &&
|
|
|
|
RtlUnicodeStringToAnsiString( &ansi, &rupp->WindowTitle, TRUE) == STATUS_SUCCESS) ?
|
|
|
|
ansi.Buffer : NULL;
|
|
|
|
startup_infoA.dwX = rupp->dwX;
|
|
|
|
startup_infoA.dwY = rupp->dwY;
|
|
|
|
startup_infoA.dwXSize = rupp->dwXSize;
|
|
|
|
startup_infoA.dwYSize = rupp->dwYSize;
|
|
|
|
startup_infoA.dwXCountChars = rupp->dwXCountChars;
|
|
|
|
startup_infoA.dwYCountChars = rupp->dwYCountChars;
|
|
|
|
startup_infoA.dwFillAttribute = rupp->dwFillAttribute;
|
|
|
|
startup_infoA.dwFlags = rupp->dwFlags;
|
|
|
|
startup_infoA.wShowWindow = rupp->wShowWindow;
|
|
|
|
startup_infoA.cbReserved2 = 0;
|
|
|
|
startup_infoA.lpReserved2 = NULL;
|
|
|
|
startup_infoA.hStdInput = rupp->hStdInput;
|
|
|
|
startup_infoA.hStdOutput = rupp->hStdOutput;
|
|
|
|
startup_infoA.hStdError = rupp->hStdError;
|
|
|
|
|
|
|
|
RtlReleasePebLock();
|
2000-08-10 00:33:42 +02:00
|
|
|
}
|