blob: e7bf71cc7ce6e2ca3838c0d8d0365b363d7697e4 [file] [log] [blame]
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001/*
2 * Process environment management
3 *
4 * Copyright 1996, 1998 Alexandre Julliard
5 */
6
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00007#include <stdlib.h>
8#include <string.h>
Ulrich Weigandcc195922000-12-27 04:18:26 +00009#include "wine/port.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000010#include "windef.h"
Alexandre Julliard24a62ab2000-11-28 22:40:56 +000011#include "winnls.h"
12#include "winerror.h"
Alexandre Julliardbecb9a32000-12-11 03:48:15 +000013#include "ntddk.h"
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000014#include "heap.h"
15#include "selectors.h"
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000016
Alexandre Julliardbecb9a32000-12-11 03:48:15 +000017/* Win32 process environment database */
18typedef struct _ENVDB
19{
20 LPSTR environ; /* 00 Process environment strings */
21 DWORD unknown1; /* 04 Unknown */
22 LPSTR cmd_line; /* 08 Command line */
23 LPSTR cur_dir; /* 0c Current directory */
24 STARTUPINFOA *startup_info; /* 10 Startup information */
25 HANDLE hStdin; /* 14 Handle for standard input */
26 HANDLE hStdout; /* 18 Handle for standard output */
27 HANDLE hStderr; /* 1c Handle for standard error */
28 DWORD unknown2; /* 20 Unknown */
29 DWORD inherit_console; /* 24 Inherit console flag */
30 DWORD break_type; /* 28 Console events flag */
31 void *break_sem; /* 2c SetConsoleCtrlHandler semaphore */
32 void *break_event; /* 30 SetConsoleCtrlHandler event */
33 void *break_thread; /* 34 SetConsoleCtrlHandler thread */
34 void *break_handlers; /* 38 List of console handlers */
35} ENVDB;
36
37
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000038/* Format of an environment block:
39 * ASCIIZ string 1 (xx=yy format)
40 * ...
41 * ASCIIZ string n
42 * BYTE 0
43 * WORD 1
44 * ASCIIZ program name (e.g. C:\WINDOWS\SYSTEM\KRNL386.EXE)
45 *
46 * Notes:
47 * - contrary to Microsoft docs, the environment strings do not appear
48 * to be sorted on Win95 (although they are on NT); so we don't bother
49 * to sort them either.
50 */
51
52static const char ENV_program_name[] = "C:\\WINDOWS\\SYSTEM\\KRNL386.EXE";
53
Alexandre Julliard46ea8b31998-05-03 19:01:20 +000054/* Maximum length of a Win16 environment string (including NULL) */
55#define MAX_WIN16_LEN 128
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000056
57/* Extra bytes to reserve at the end of an environment */
58#define EXTRA_ENV_SIZE (sizeof(BYTE) + sizeof(WORD) + sizeof(ENV_program_name))
59
60/* Fill the extra bytes with the program name and stuff */
61#define FILL_EXTRA_ENV(p) \
62 *(p) = '\0'; \
Ulrich Weigandcc195922000-12-27 04:18:26 +000063 PUT_UA_WORD( (p) + 1, 1 ); \
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000064 strcpy( (p) + 3, ENV_program_name );
65
Alexandre Julliard52900c82000-08-09 22:33:42 +000066STARTUPINFOA current_startupinfo =
67{
68 sizeof(STARTUPINFOA), /* cb */
69 0, /* lpReserved */
70 0, /* lpDesktop */
71 0, /* lpTitle */
72 0, /* dwX */
73 0, /* dwY */
74 0, /* dwXSize */
75 0, /* dwYSize */
76 0, /* dwXCountChars */
77 0, /* dwYCountChars */
78 0, /* dwFillAttribute */
79 0, /* dwFlags */
80 0, /* wShowWindow */
81 0, /* cbReserved2 */
82 0, /* lpReserved2 */
83 0, /* hStdInput */
84 0, /* hStdOutput */
85 0 /* hStdError */
86};
87
88ENVDB current_envdb =
89{
90 0, /* environ */
91 0, /* unknown1 */
92 0, /* cmd_line */
93 0, /* cur_dir */
94 &current_startupinfo, /* startup_info */
95 0, /* hStdin */
96 0, /* hStdout */
97 0, /* hStderr */
98 0, /* unknown2 */
99 0, /* inherit_console */
100 0, /* break_type */
101 0, /* break_sem */
102 0, /* break_event */
103 0, /* break_thread */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000104 0 /* break_handlers */
Alexandre Julliard52900c82000-08-09 22:33:42 +0000105};
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000106
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000107
108static WCHAR *cmdlineW; /* Unicode command line */
109static WORD env_sel; /* selector to the environment */
110
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000111/***********************************************************************
112 * ENV_FindVariable
113 *
114 * Find a variable in the environment and return a pointer to the value.
115 * Helper function for GetEnvironmentVariable and ExpandEnvironmentStrings.
116 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000117static LPCSTR ENV_FindVariable( LPCSTR env, LPCSTR name, INT len )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000118{
119 while (*env)
120 {
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000121 if (!strncasecmp( name, env, len ) && (env[len] == '='))
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000122 return env + len + 1;
123 env += strlen(env) + 1;
124 }
125 return NULL;
126}
127
128
129/***********************************************************************
130 * ENV_BuildEnvironment
131 *
132 * Build the environment for the initial process
133 */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000134ENVDB *ENV_BuildEnvironment(void)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000135{
136 extern char **environ;
137 LPSTR p, *e;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000138 int size;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000139
140 /* Compute the total size of the Unix environment */
141
142 size = EXTRA_ENV_SIZE;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000143 for (e = environ; *e; e++) size += strlen(*e) + 1;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000144
145 /* Now allocate the environment */
146
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000147 if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
Alexandre Julliard52900c82000-08-09 22:33:42 +0000148 current_envdb.environ = p;
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000149 env_sel = SELECTOR_AllocBlock( p, 0x10000, WINE_LDT_FLAGS_DATA );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000150
151 /* And fill it with the Unix environment */
152
153 for (e = environ; *e; e++)
154 {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000155 strcpy( p, *e );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000156 p += strlen(p) + 1;
157 }
158
159 /* Now add the program name */
160
161 FILL_EXTRA_ENV( p );
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000162 return &current_envdb;
163}
164
165
166/***********************************************************************
167 * ENV_BuildCommandLine
168 *
169 * Build the command line of a process from the argv array.
170 *
171 * Note that it does NOT necessarily include the file name.
172 * Sometimes we don't even have any command line options at all.
173 */
174BOOL ENV_BuildCommandLine( char **argv )
175{
176 int len, quote = 0;
177 char *p, **arg;
178
179 for (arg = argv, len = 0; *arg; arg++) len += strlen(*arg) + 1;
180 if ((argv[0]) && (quote = (strchr( argv[0], ' ' ) != NULL))) len += 2;
181 if (!(p = current_envdb.cmd_line = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
182 arg = argv;
183 if (quote)
184 {
185 *p++ = '\"';
186 strcpy( p, *arg );
187 p += strlen(p);
188 *p++ = '\"';
189 *p++ = ' ';
190 arg++;
191 }
192 while (*arg)
193 {
194 strcpy( p, *arg );
195 p += strlen(p);
196 *p++ = ' ';
197 arg++;
198 }
199 if (p > current_envdb.cmd_line) p--; /* remove last space */
200 *p = 0;
201 /* now allocate the Unicode version */
202 len = MultiByteToWideChar( CP_ACP, 0, current_envdb.cmd_line, -1, NULL, 0 );
203 if (!(cmdlineW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
204 return FALSE;
205 MultiByteToWideChar( CP_ACP, 0, current_envdb.cmd_line, -1, cmdlineW, len );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000206 return TRUE;
207}
208
209
210/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000211 * GetCommandLineA (KERNEL32.289)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000212 */
Hidenori Takeshima34e10ee2000-06-24 13:37:05 +0000213LPSTR WINAPI GetCommandLineA(void)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000214{
Alexandre Julliard52900c82000-08-09 22:33:42 +0000215 return current_envdb.cmd_line;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000216}
217
218/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000219 * GetCommandLineW (KERNEL32.290)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000220 */
Hidenori Takeshima34e10ee2000-06-24 13:37:05 +0000221LPWSTR WINAPI GetCommandLineW(void)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000222{
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000223 return cmdlineW;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000224}
225
226
227/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000228 * GetEnvironmentStringsA (KERNEL32.319) (KERNEL32.320)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000229 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000230LPSTR WINAPI GetEnvironmentStringsA(void)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000231{
Alexandre Julliard52900c82000-08-09 22:33:42 +0000232 return current_envdb.environ;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000233}
234
235
236/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000237 * GetEnvironmentStringsW (KERNEL32.321)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000238 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000239LPWSTR WINAPI GetEnvironmentStringsW(void)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000240{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000241 INT size;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000242 LPWSTR ret;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000243
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000244 RtlAcquirePebLock();
Alexandre Julliard52900c82000-08-09 22:33:42 +0000245 size = HeapSize( GetProcessHeap(), 0, current_envdb.environ );
Alexandre Julliard079fd722000-01-25 01:41:35 +0000246 if ((ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )) != NULL)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000247 {
Alexandre Julliard52900c82000-08-09 22:33:42 +0000248 LPSTR pA = current_envdb.environ;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000249 LPWSTR pW = ret;
250 while (size--) *pW++ = (WCHAR)(BYTE)*pA++;
251 }
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000252 RtlReleasePebLock();
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000253 return ret;
254}
255
256
257/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000258 * FreeEnvironmentStringsA (KERNEL32.268)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000259 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000260BOOL WINAPI FreeEnvironmentStringsA( LPSTR ptr )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000261{
Alexandre Julliard52900c82000-08-09 22:33:42 +0000262 if (ptr != current_envdb.environ)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000263 {
264 SetLastError( ERROR_INVALID_PARAMETER );
265 return FALSE;
266 }
267 return TRUE;
268}
269
270
271/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000272 * FreeEnvironmentStringsW (KERNEL32.269)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000273 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000274BOOL WINAPI FreeEnvironmentStringsW( LPWSTR ptr )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000275{
276 return HeapFree( GetProcessHeap(), 0, ptr );
277}
278
279
280/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000281 * GetEnvironmentVariableA (KERNEL32.322)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000282 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000283DWORD WINAPI GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000284{
285 LPCSTR p;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000286 INT ret = 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000287
288 if (!name || !*name)
289 {
290 SetLastError( ERROR_INVALID_PARAMETER );
291 return 0;
292 }
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000293 RtlAcquirePebLock();
Alexandre Julliard52900c82000-08-09 22:33:42 +0000294 if ((p = ENV_FindVariable( current_envdb.environ, name, strlen(name) )))
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000295 {
296 ret = strlen(p);
297 if (size <= ret)
298 {
299 /* If not enough room, include the terminating null
300 * in the returned size and return an empty string */
301 ret++;
302 if (value) *value = '\0';
303 }
304 else if (value) strcpy( value, p );
305 }
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000306 RtlReleasePebLock();
Andreas Mohr0af222c2000-09-22 20:58:23 +0000307 if (!ret)
308 SetLastError( ERROR_ENVVAR_NOT_FOUND );
309 return ret;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000310}
311
312
313/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000314 * GetEnvironmentVariableW (KERNEL32.323)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000315 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000316DWORD WINAPI GetEnvironmentVariableW( LPCWSTR nameW, LPWSTR valW, DWORD size)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000317{
318 LPSTR name = HEAP_strdupWtoA( GetProcessHeap(), 0, nameW );
319 LPSTR val = valW ? HeapAlloc( GetProcessHeap(), 0, size ) : NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000320 DWORD res = GetEnvironmentVariableA( name, val, size );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000321 HeapFree( GetProcessHeap(), 0, name );
322 if (val)
323 {
Alexandre Julliard24a62ab2000-11-28 22:40:56 +0000324 if (size > 0 && !MultiByteToWideChar( CP_ACP, 0, val, -1, valW, size ))
325 valW[size-1] = 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000326 HeapFree( GetProcessHeap(), 0, val );
327 }
328 return res;
329}
330
331
332/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000333 * SetEnvironmentVariableA (KERNEL32.641)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000334 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000335BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000336{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000337 INT old_size, len, res;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000338 LPSTR p, env, new_env;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000339 BOOL ret = FALSE;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000340
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000341 RtlAcquirePebLock();
Alexandre Julliard52900c82000-08-09 22:33:42 +0000342 env = p = current_envdb.environ;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000343
344 /* Find a place to insert the string */
345
346 res = -1;
347 len = strlen(name);
348 while (*p)
349 {
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000350 if (!strncasecmp( name, p, len ) && (p[len] == '=')) break;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000351 p += strlen(p) + 1;
352 }
353 if (!value && !*p) goto done; /* Value to remove doesn't exist */
354
355 /* Realloc the buffer */
356
357 len = value ? strlen(name) + strlen(value) + 2 : 0;
358 if (*p) len -= strlen(p) + 1; /* The name already exists */
Alexandre Julliard079fd722000-01-25 01:41:35 +0000359 old_size = HeapSize( GetProcessHeap(), 0, env );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000360 if (len < 0)
361 {
362 LPSTR next = p + strlen(p) + 1; /* We know there is a next one */
363 memmove( next + len, next, old_size - (next - env) );
364 }
Alexandre Julliard079fd722000-01-25 01:41:35 +0000365 if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, old_size + len )))
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000366 goto done;
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000367 if (env_sel) env_sel = SELECTOR_ReallocBlock( env_sel, new_env, old_size + len );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000368 p = new_env + (p - env);
369 if (len > 0) memmove( p + len, p, old_size - (p - new_env) );
370
371 /* Set the new string */
372
373 if (value)
374 {
375 strcpy( p, name );
376 strcat( p, "=" );
377 strcat( p, value );
378 }
Alexandre Julliard52900c82000-08-09 22:33:42 +0000379 current_envdb.environ = new_env;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000380 ret = TRUE;
381
382done:
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000383 RtlReleasePebLock();
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000384 return ret;
385}
386
387
388/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000389 * SetEnvironmentVariableW (KERNEL32.642)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000390 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000391BOOL WINAPI SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000392{
393 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
394 LPSTR valueA = HEAP_strdupWtoA( GetProcessHeap(), 0, value );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000395 BOOL ret = SetEnvironmentVariableA( nameA, valueA );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000396 HeapFree( GetProcessHeap(), 0, nameA );
397 HeapFree( GetProcessHeap(), 0, valueA );
398 return ret;
399}
400
401
402/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000403 * ExpandEnvironmentStringsA (KERNEL32.216)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000404 *
405 * Note: overlapping buffers are not supported; this is how it should be.
406 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000407DWORD WINAPI ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000408{
409 DWORD len, total_size = 1; /* 1 for terminating '\0' */
410 LPCSTR p, var;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000411
412 if (!count) dst = NULL;
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000413 RtlAcquirePebLock();
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000414
415 while (*src)
416 {
417 if (*src != '%')
418 {
419 if ((p = strchr( src, '%' ))) len = p - src;
420 else len = strlen(src);
421 var = src;
422 src += len;
423 }
424 else /* we are at the start of a variable */
425 {
426 if ((p = strchr( src + 1, '%' )))
427 {
428 len = p - src - 1; /* Length of the variable name */
Alexandre Julliard52900c82000-08-09 22:33:42 +0000429 if ((var = ENV_FindVariable( current_envdb.environ,
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000430 src + 1, len )))
431 {
432 src += len + 2; /* Skip the variable name */
433 len = strlen(var);
434 }
435 else
436 {
437 var = src; /* Copy original name instead */
438 len += 2;
439 src += len;
440 }
441 }
442 else /* unfinished variable name, ignore it */
443 {
444 var = src;
445 len = strlen(src); /* Copy whole string */
446 src += len;
447 }
448 }
449 total_size += len;
450 if (dst)
451 {
452 if (count < len) len = count;
453 memcpy( dst, var, len );
454 dst += len;
455 count -= len;
456 }
457 }
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000458 RtlReleasePebLock();
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000459
460 /* Null-terminate the string */
461 if (dst)
462 {
463 if (!count) dst--;
464 *dst = '\0';
465 }
466 return total_size;
467}
468
469
470/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000471 * ExpandEnvironmentStringsW (KERNEL32.217)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000472 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000473DWORD WINAPI ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000474{
475 LPSTR srcA = HEAP_strdupWtoA( GetProcessHeap(), 0, src );
476 LPSTR dstA = dst ? HeapAlloc( GetProcessHeap(), 0, len ) : NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000477 DWORD ret = ExpandEnvironmentStringsA( srcA, dstA, len );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000478 if (dstA)
479 {
Alexandre Julliard24a62ab2000-11-28 22:40:56 +0000480 ret = MultiByteToWideChar( CP_ACP, 0, dstA, -1, dst, len );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000481 HeapFree( GetProcessHeap(), 0, dstA );
482 }
483 HeapFree( GetProcessHeap(), 0, srcA );
484 return ret;
485}
486
Alexandre Julliard52900c82000-08-09 22:33:42 +0000487
488/***********************************************************************
Patrik Stridvall00b86a92000-12-16 21:55:05 +0000489 * GetDOSEnvironment16 (KERNEL.131)
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000490 */
491SEGPTR WINAPI GetDOSEnvironment16(void)
492{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000493 return MAKESEGPTR( env_sel, 0 );
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000494}
495
496
497/***********************************************************************
Alexandre Julliard52900c82000-08-09 22:33:42 +0000498 * GetStdHandle (KERNEL32.276)
499 */
500HANDLE WINAPI GetStdHandle( DWORD std_handle )
501{
502 switch(std_handle)
503 {
504 case STD_INPUT_HANDLE: return current_envdb.hStdin;
505 case STD_OUTPUT_HANDLE: return current_envdb.hStdout;
506 case STD_ERROR_HANDLE: return current_envdb.hStderr;
507 }
508 SetLastError( ERROR_INVALID_PARAMETER );
509 return INVALID_HANDLE_VALUE;
510}
511
512
513/***********************************************************************
514 * SetStdHandle (KERNEL32.506)
515 */
516BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
517{
518 switch(std_handle)
519 {
520 case STD_INPUT_HANDLE: current_envdb.hStdin = handle; return TRUE;
521 case STD_OUTPUT_HANDLE: current_envdb.hStdout = handle; return TRUE;
522 case STD_ERROR_HANDLE: current_envdb.hStderr = handle; return TRUE;
523 }
524 SetLastError( ERROR_INVALID_PARAMETER );
525 return FALSE;
526}
527
528
529/***********************************************************************
530 * GetStartupInfoA (KERNEL32.273)
531 */
532VOID WINAPI GetStartupInfoA( LPSTARTUPINFOA info )
533{
534 *info = current_startupinfo;
535}
536
537
538/***********************************************************************
539 * GetStartupInfoW (KERNEL32.274)
540 */
541VOID WINAPI GetStartupInfoW( LPSTARTUPINFOW info )
542{
543 info->cb = sizeof(STARTUPINFOW);
544 info->dwX = current_startupinfo.dwX;
545 info->dwY = current_startupinfo.dwY;
546 info->dwXSize = current_startupinfo.dwXSize;
547 info->dwXCountChars = current_startupinfo.dwXCountChars;
548 info->dwYCountChars = current_startupinfo.dwYCountChars;
549 info->dwFillAttribute = current_startupinfo.dwFillAttribute;
550 info->dwFlags = current_startupinfo.dwFlags;
551 info->wShowWindow = current_startupinfo.wShowWindow;
552 info->cbReserved2 = current_startupinfo.cbReserved2;
553 info->lpReserved2 = current_startupinfo.lpReserved2;
554 info->hStdInput = current_startupinfo.hStdInput;
555 info->hStdOutput = current_startupinfo.hStdOutput;
556 info->hStdError = current_startupinfo.hStdError;
557 info->lpReserved = HEAP_strdupAtoW (GetProcessHeap(), 0, current_startupinfo.lpReserved );
558 info->lpDesktop = HEAP_strdupAtoW (GetProcessHeap(), 0, current_startupinfo.lpDesktop );
559 info->lpTitle = HEAP_strdupAtoW (GetProcessHeap(), 0, current_startupinfo.lpTitle );
560}