Do not check for non NULL pointer before HeapFree'ing it. It's
[wine] / dlls / msvcrt / data.c
1 /*
2  * msvcrt.dll dll data items
3  *
4  * Copyright 2000 Jon Griffiths
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <math.h>
25 #include "msvcrt.h"
26 #include "wine/library.h"
27 #include "wine/unicode.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
31
32 unsigned int MSVCRT___argc;
33 unsigned int MSVCRT_basemajor;/* FIXME: */
34 unsigned int MSVCRT_baseminor;/* FIXME: */
35 unsigned int MSVCRT_baseversion; /* FIXME: */
36 unsigned int MSVCRT__commode;
37 unsigned int MSVCRT__fmode;
38 unsigned int MSVCRT_osmajor;/* FIXME: */
39 unsigned int MSVCRT_osminor;/* FIXME: */
40 unsigned int MSVCRT_osmode;/* FIXME: */
41 unsigned int MSVCRT__osver;
42 unsigned int MSVCRT_osversion; /* FIXME: */
43 unsigned int MSVCRT__winmajor;
44 unsigned int MSVCRT__winminor;
45 unsigned int MSVCRT__winver;
46 unsigned int MSVCRT__sys_nerr; /* FIXME: not accessible from Winelib apps */
47 char**       MSVCRT__sys_errlist; /* FIXME: not accessible from Winelib apps */
48 unsigned int MSVCRT___setlc_active;
49 unsigned int MSVCRT___unguarded_readlc_active;
50 double MSVCRT__HUGE;
51 char **MSVCRT___argv;
52 MSVCRT_wchar_t **MSVCRT___wargv;
53 char *MSVCRT__acmdln;
54 MSVCRT_wchar_t *MSVCRT__wcmdln;
55 char **_environ = 0;
56 MSVCRT_wchar_t **_wenviron = 0;
57 char **MSVCRT___initenv = 0;
58 MSVCRT_wchar_t **MSVCRT___winitenv = 0;
59 int MSVCRT_timezone;
60 int MSVCRT_app_type;
61 char* MSVCRT__pgmptr = 0;
62 WCHAR* MSVCRT__wpgmptr = 0;
63
64 /* Get a snapshot of the current environment
65  * and construct the __p__environ array
66  *
67  * The pointer returned from GetEnvironmentStrings may get invalid when
68  * some other module cause a reallocation of the env-variable block
69  *
70  * blk is an array of pointers to environment strings, ending with a NULL
71  * and after that the actual copy of the environment strings, ending in a \0
72  */
73 char ** msvcrt_SnapshotOfEnvironmentA(char **blk)
74 {
75   char* environ_strings = GetEnvironmentStringsA();
76   int count = 1, len = 1, i = 0; /* keep space for the trailing NULLS */
77   char *ptr;
78
79   for (ptr = environ_strings; *ptr; ptr += strlen(ptr) + 1)
80   {
81     count++;
82     len += strlen(ptr) + 1;
83   }
84   if (blk)
85       blk = HeapReAlloc( GetProcessHeap(), 0, blk, count* sizeof(char*) + len );
86   else
87     blk = HeapAlloc(GetProcessHeap(), 0, count* sizeof(char*) + len );
88
89   if (blk)
90     {
91       if (count)
92         {
93           memcpy(&blk[count],environ_strings,len);
94           for (ptr = (char*) &blk[count]; *ptr; ptr += strlen(ptr) + 1)
95             {
96               blk[i++] = ptr;
97             }
98         }
99       blk[i] = NULL;
100     }
101   FreeEnvironmentStringsA(environ_strings);
102   return blk;
103 }
104
105 MSVCRT_wchar_t ** msvcrt_SnapshotOfEnvironmentW(MSVCRT_wchar_t **wblk)
106 {
107   MSVCRT_wchar_t* wenviron_strings = GetEnvironmentStringsW();
108   int count = 1, len = 1, i = 0; /* keep space for the trailing NULLS */
109   MSVCRT_wchar_t *wptr;
110
111   for (wptr = wenviron_strings; *wptr; wptr += strlenW(wptr) + 1)
112   {
113     count++;
114     len += strlenW(wptr) + 1;
115   }
116   if (wblk)
117       wblk = HeapReAlloc( GetProcessHeap(), 0, wblk, count* sizeof(MSVCRT_wchar_t*) + len * sizeof(MSVCRT_wchar_t));
118   else
119     wblk = HeapAlloc(GetProcessHeap(), 0, count* sizeof(MSVCRT_wchar_t*) + len * sizeof(MSVCRT_wchar_t));
120   if (wblk)
121     {
122       if (count)
123         {
124           memcpy(&wblk[count],wenviron_strings,len * sizeof(MSVCRT_wchar_t));
125           for (wptr = (MSVCRT_wchar_t*)&wblk[count]; *wptr; wptr += strlenW(wptr) + 1)
126             {
127               wblk[i++] = wptr;
128             }
129         }
130       wblk[i] = NULL;
131     }
132   FreeEnvironmentStringsW(wenviron_strings);
133   return wblk;
134 }
135
136 typedef void (*_INITTERMFUN)(void);
137
138 /***********************************************************************
139  *              __p___argc (MSVCRT.@)
140  */
141 int* __p___argc(void) { return &MSVCRT___argc; }
142
143 /***********************************************************************
144  *              __p__commode (MSVCRT.@)
145  */
146 unsigned int* __p__commode(void) { return &MSVCRT__commode; }
147
148
149 /***********************************************************************
150  *              __p__pgmptr (MSVCRT.@)
151  */
152 char** __p__pgmptr(void) { return &MSVCRT__pgmptr; }
153
154 /***********************************************************************
155  *              __p__wpgmptr (MSVCRT.@)
156  */
157 WCHAR** __p__wpgmptr(void) { return &MSVCRT__wpgmptr; }
158
159 /***********************************************************************
160  *              __p__fmode (MSVCRT.@)
161  */
162 unsigned int* __p__fmode(void) { return &MSVCRT__fmode; }
163
164 /***********************************************************************
165  *              __p__osver (MSVCRT.@)
166  */
167 unsigned int* __p__osver(void) { return &MSVCRT__osver; }
168
169 /***********************************************************************
170  *              __p__winmajor (MSVCRT.@)
171  */
172 unsigned int* __p__winmajor(void) { return &MSVCRT__winmajor; }
173
174 /***********************************************************************
175  *              __p__winminor (MSVCRT.@)
176  */
177 unsigned int* __p__winminor(void) { return &MSVCRT__winminor; }
178
179 /***********************************************************************
180  *              __p__winver (MSVCRT.@)
181  */
182 unsigned int* __p__winver(void) { return &MSVCRT__winver; }
183
184 /*********************************************************************
185  *              __p__acmdln (MSVCRT.@)
186  */
187 char** __p__acmdln(void) { return &MSVCRT__acmdln; }
188
189 /*********************************************************************
190  *              __p__wcmdln (MSVCRT.@)
191  */
192 MSVCRT_wchar_t** __p__wcmdln(void) { return &MSVCRT__wcmdln; }
193
194 /*********************************************************************
195  *              __p___argv (MSVCRT.@)
196  */
197 char*** __p___argv(void) { return &MSVCRT___argv; }
198
199 /*********************************************************************
200  *              __p___wargv (MSVCRT.@)
201  */
202 MSVCRT_wchar_t*** __p___wargv(void) { return &MSVCRT___wargv; }
203
204 /*********************************************************************
205  *              __p__environ (MSVCRT.@)
206  */
207 char*** __p__environ(void)
208 {
209   if (!_environ)
210     _environ = msvcrt_SnapshotOfEnvironmentA(NULL);
211   return &_environ;
212 }
213
214 /*********************************************************************
215  *              __p__wenviron (MSVCRT.@)
216  */
217 MSVCRT_wchar_t*** __p__wenviron(void)
218 {
219   if (!_wenviron)
220     _wenviron = msvcrt_SnapshotOfEnvironmentW(NULL);
221   return &_wenviron;
222 }
223
224 /*********************************************************************
225  *              __p___initenv (MSVCRT.@)
226  */
227 char*** __p___initenv(void) { return &MSVCRT___initenv; }
228
229 /*********************************************************************
230  *              __p___winitenv (MSVCRT.@)
231  */
232 MSVCRT_wchar_t*** __p___winitenv(void) { return &MSVCRT___winitenv; }
233
234 /*********************************************************************
235  *              __p__timezone (MSVCRT.@)
236  */
237 int* __p__timezone(void) { return &MSVCRT_timezone; }
238
239 /* INTERNAL: Create a wide string from an ascii string */
240 static MSVCRT_wchar_t *wstrdupa(const char *str)
241 {
242   const size_t len = strlen(str) + 1 ;
243   MSVCRT_wchar_t *wstr = MSVCRT_malloc(len* sizeof (MSVCRT_wchar_t));
244   if (!wstr)
245     return NULL;
246    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len);
247   return wstr;
248 }
249
250 /* INTERNAL: Since we can't rely on Winelib startup code calling w/getmainargs,
251  * we initialise data values during DLL loading. When called by a native
252  * program we simply return the data we've already initialised. This also means
253  * you can call multiple times without leaking
254  */
255 void msvcrt_init_args(void)
256 {
257   DWORD version;
258
259   MSVCRT__acmdln = _strdup( GetCommandLineA() );
260   MSVCRT__wcmdln = wstrdupa(MSVCRT__acmdln);
261   MSVCRT___argc = __wine_main_argc;
262   MSVCRT___argv = __wine_main_argv;
263   MSVCRT___wargv = __wine_main_wargv;
264
265   TRACE("got %s, wide = %s argc=%d\n", debugstr_a(MSVCRT__acmdln),
266         debugstr_w(MSVCRT__wcmdln),MSVCRT___argc);
267
268   version = GetVersion();
269   MSVCRT__osver       = version >> 16;
270   MSVCRT__winminor    = version & 0xFF;
271   MSVCRT__winmajor    = (version>>8) & 0xFF;
272   MSVCRT_baseversion = version >> 16;
273   MSVCRT__winver     = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
274   MSVCRT_baseminor   = (version >> 16) & 0xFF;
275   MSVCRT_basemajor   = (version >> 24) & 0xFF;
276   MSVCRT_osversion   = version & 0xFFFF;
277   MSVCRT_osminor     = version & 0xFF;
278   MSVCRT_osmajor     = (version>>8) & 0xFF;
279   MSVCRT__sys_nerr   = 43;
280   MSVCRT__HUGE = HUGE_VAL;
281   MSVCRT___setlc_active = 0;
282   MSVCRT___unguarded_readlc_active = 0;
283   MSVCRT_timezone = 0;
284   MSVCRT__fmode = MSVCRT__O_TEXT;
285   
286   MSVCRT___initenv= msvcrt_SnapshotOfEnvironmentA(NULL);
287   MSVCRT___winitenv= msvcrt_SnapshotOfEnvironmentW(NULL);
288
289   MSVCRT__pgmptr = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
290   if (MSVCRT__pgmptr)
291   {
292     if (!GetModuleFileNameA(0, MSVCRT__pgmptr, MAX_PATH))
293       MSVCRT__pgmptr[0] = '\0';
294     else
295       MSVCRT__pgmptr[MAX_PATH - 1] = '\0';
296   }
297
298   MSVCRT__wpgmptr = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
299   if (MSVCRT__wpgmptr)
300   {
301     if (!GetModuleFileNameW(0, MSVCRT__wpgmptr, MAX_PATH))
302       MSVCRT__wpgmptr[0] = '\0';
303     else
304       MSVCRT__wpgmptr[MAX_PATH - 1] = '\0';
305   }
306 }
307
308
309 /* INTERNAL: free memory used by args */
310 void msvcrt_free_args(void)
311 {
312   /* FIXME: more things to free */
313   HeapFree(GetProcessHeap(), 0, MSVCRT___initenv);
314   HeapFree(GetProcessHeap(), 0, MSVCRT___winitenv);
315   HeapFree(GetProcessHeap(), 0, _environ);
316   HeapFree(GetProcessHeap(), 0, _wenviron);
317   HeapFree(GetProcessHeap(), 0, MSVCRT__pgmptr);
318   HeapFree(GetProcessHeap(), 0, MSVCRT__wpgmptr);
319 }
320
321 /*********************************************************************
322  *              __getmainargs (MSVCRT.@)
323  */
324 void __getmainargs(int *argc, char** *argv, char** *envp,
325                                   int expand_wildcards, int *new_mode)
326 {
327   TRACE("(%p,%p,%p,%d,%p).\n", argc, argv, envp, expand_wildcards, new_mode);
328   *argc = MSVCRT___argc;
329   *argv = MSVCRT___argv;
330   *envp = MSVCRT___initenv;
331   if (new_mode)
332     MSVCRT__set_new_mode( *new_mode );
333 }
334
335 /*********************************************************************
336  *              __wgetmainargs (MSVCRT.@)
337  */
338 void __wgetmainargs(int *argc, MSVCRT_wchar_t** *wargv, MSVCRT_wchar_t** *wenvp,
339                     int expand_wildcards, int *new_mode)
340 {
341   TRACE("(%p,%p,%p,%d,%p).\n", argc, wargv, wenvp, expand_wildcards, new_mode);
342   *argc = MSVCRT___argc;
343   *wargv = MSVCRT___wargv;
344   *wenvp = MSVCRT___winitenv;
345   if (new_mode)
346     MSVCRT__set_new_mode( *new_mode );
347 }
348
349 /*********************************************************************
350  *              _initterm (MSVCRT.@)
351  */
352 unsigned int _initterm(_INITTERMFUN *start,_INITTERMFUN *end)
353 {
354   _INITTERMFUN* current = start;
355
356   TRACE("(%p,%p)\n",start,end);
357   while (current<end)
358   {
359     if (*current)
360     {
361       TRACE("Call init function %p\n",*current);
362       (**current)();
363       TRACE("returned\n");
364     }
365     current++;
366   }
367   return 0;
368 }
369
370 /*********************************************************************
371  *              __set_app_type (MSVCRT.@)
372  */
373 void MSVCRT___set_app_type(int app_type)
374 {
375   TRACE("(%d) %s application\n", app_type, app_type == 2 ? "Gui" : "Console");
376   MSVCRT_app_type = app_type;
377 }