source: branches/gcc-kmk/src/kernel32/initterm.cpp@ 21837

Last change on this file since 21837 was 21837, checked in by dmik, 14 years ago

Use pid instead of the ordinal number in log file names.

This in particular fixes the problem when WGSS50 writes to the log
before the ordinal is correctly initialized by KERNEL32 which resulted
into two processes writing to the same log file.

This also guarantees that a subsequent re-run will not vanish the
previous log file which is also useful sometimes.

File size: 11.9 KB
Line 
1/* $Id: initkernel32.cpp,v 1.28 2004-05-24 08:56:06 sandervl Exp $
2 *
3 * KERNEL32 DLL entry point
4 *
5 * Copyright 1998 Sander van Leeuwen
6 * Copyright 1998 Peter Fitzsimmons
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 */
10
11#define INCL_DOSMODULEMGR
12#define INCL_DOSMISC
13#define INCL_DOSPROCESS
14#define INCL_DOSSEMAPHORES
15#include <os2wrap.h> //Odin32 OS/2 api wrappers
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <misc.h>
20#include <wprocess.h>
21#include "handlemanager.h"
22#include "profile.h"
23#include <options.h>
24#include "initterm.h"
25#include <win32type.h>
26#include <win32api.h>
27#include <odinlx.h>
28#include "oslibmisc.h"
29#include <heapshared.h>
30#include <heapcode.h>
31#include "mmap.h"
32#include "directory.h"
33#include "hmdevio.h"
34#include "hmcomm.h"
35#include "windllbase.h"
36#include "winexepe2lx.h"
37#include <exitlist.h>
38#include "oslibdos.h"
39#include "osliblvm.h"
40#include <cpuhlp.h>
41#include <Win32k.h>
42#include <initdll.h>
43#include <codepage.h>
44#include <process.h>
45#include <stats.h>
46#include <heapshared.h>
47#include <heapstring.h>
48#include <_ras.h>
49
50#define DBG_LOCALLOG DBG_initterm
51#include "dbglocal.h"
52
53PVOID SYSTEM _O32_GetEnvironmentStrings( VOID );
54
55// Win32 resource table (produced by wrc)
56extern DWORD kernel32_PEResTab;
57
58static HMODULE dllHandle = 0;
59
60extern PFN pfnImSetMsgQueueProperty;
61
62BOOL fVersionWarp3 = FALSE;
63BOOL fCustomBuild = FALSE;
64
65ULONG flAllocMem = 0; /* flag to optimize DosAllocMem to use all the memory on SMP machines */
66ULONG ulMaxAddr = 0x20000000; /* end of user address space. */
67char kernel32Path[CCHMAXPATH] = "";
68BOOL fInit = FALSE;
69BOOL fWin32k = FALSE;
70HMODULE imHandle = 0;
71char szModName[ 256 ] = "";
72
73static ULONG DLL_InitKernel32_internal(ULONG hModule)
74{
75 size_t i;
76 APIRET rc;
77 ULONG ulSysinfo, version[2];
78
79 if (fInit)
80 return EXITLIST_KERNEL32; // already initialized
81
82 rc = DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR,
83 version, sizeof(version));
84 if (rc == 0)
85 if(version[0] >= 20 && version[1] <= 30)
86 fVersionWarp3 = TRUE;
87
88 // This always must be the first thing to do.
89 RasInitialize (hModule);
90#ifdef RAS
91 extern void rasInitVirtual (void);
92 rasInitVirtual ();
93#endif
94
95 ParseLogStatusKERNEL32();
96
97 /*
98 * Init the win32k library.
99 * We will also need to tell win32k where the Odin32 environment is
100 * located. Currently that is within Open32. I'm quite sure that it's
101 * not relocated during run, so we're pretty well off.
102 */
103 //Note: we do NOT want to use any win32k services with custom builds
104 if (fCustomBuild == FALSE && !libWin32kInit())
105 {
106 rc = libWin32kSetEnvironment((PSZ)_O32_GetEnvironmentStrings(), 0, 0);
107 if (rc)
108 {
109 dprintf(("KERNEL32: initterm: libWin32kSetEnvironment failed with rc=%d\n", rc));
110 }
111 else fWin32k = TRUE;
112 }
113
114 char *kernel32Name = OSLibGetDllName(hModule);
115 if (!kernel32Name)
116 return -1; // failure
117
118 strcpy(kernel32Path, kernel32Name);
119 char *endofpath = strrchr(kernel32Path, '\\');
120 *(endofpath+1) = 0;
121
122 CheckVersionFromHMOD(PE2LX_VERSION, hModule); /*PLF Wed 98-03-18 05:28:48*/
123
124 /* knut: check for high memory support */
125 rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo));
126 if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB
127 {
128 flAllocMem = PAG_ANY; // high memory support. Let's use it!
129 ulMaxAddr = ulSysinfo * (1024*1024);
130 }
131 else
132 flAllocMem = 0; // no high memory support
133
134 dprintf(("kernel32 init %s %s (%x) Win32k - %s", __DATE__, __TIME__, DLL_InitKernel32_internal,
135 libWin32kInstalled() ? "Installed" : "Not Installed"));
136
137 OpenPrivateLogFiles();
138
139 //SvL: Do it here instead of during the exe object creation
140 //(std handles can be used in win32 dll initialization routines
141 if (HMInitialize() != NO_ERROR)
142 return -1;
143
144 // VP: Shared heap should be initialized before call to PROFILE_*
145 // because they use a critical section which in turn uses smalloc
146 // in debug build
147 if (!InitializeSharedHeap())
148 return -1;
149
150 // VP: initialize profile internal data (critical section actually).
151 // This was done in PROFILE_LoadOdinIni but PROFILE_GetOdinIniInt
152 // is called earlier and this lead to a handle leak.
153 PROFILE_Initialize();
154
155 if(flAllocMem == PAG_ANY)
156 {
157 OSLibInitWSeBFileIO();
158 if (PROFILE_GetOdinIniInt(ODINSYSTEM_SECTION, HIGHMEM_KEY, 1) == 0)
159 {
160 dprintf(("WARNING: OS/2 kernel supports high memory, but support is DISABLED because of HIGHMEM odin.ini key"));
161 flAllocMem = 0;
162 }
163 }
164
165 if (!InitializeCodeHeap())
166 return -1;
167
168 InitializeMemMaps();
169
170 PROFILE_LoadOdinIni();
171 dllHandle = RegisterLxDll(hModule, 0, (PVOID)&kernel32_PEResTab);
172 if (dllHandle == 0)
173 return -1;
174
175 //SvL: Kernel32 is a special case; pe.exe loads it, so increase
176 // the reference count here
177 Win32DllBase *module = Win32DllBase::findModule(dllHandle);
178 if (module)
179 {
180 module->AddRef();
181 module->DisableUnload();
182 }
183
184 OSLibDosSetInitialMaxFileHandles(ODIN_DEFAULT_MAX_FILEHANDLES);
185
186#ifdef DEBUG
187 {
188 LPSTR WIN32API GetEnvironmentStringsA();
189
190 char *tmpenvnew = GetEnvironmentStringsA();
191 dprintf(("Environment:"));
192 while(*tmpenvnew) {
193 dprintf(("%s", tmpenvnew));
194 tmpenvnew += strlen(tmpenvnew)+1;
195 }
196 }
197#endif
198
199 // Must be done before InitializeTIB (which loads NTDLL -> USER32)
200 InitDirectories();
201
202 // Must be done after HMInitialize!
203 if (InitializeMainThread() == NULL)
204 return -1;
205
206 RegisterDevices();
207 Win32DllBase::setDefaultRenaming();
208
209 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
210 &ulSysinfo, sizeof(ulSysinfo));
211 if (rc != 0)
212 ulSysinfo = 1;
213
214 // Setup codepage info
215 CODEPAGE_Init();
216
217 if (IsDBCSEnv() && DosLoadModule(szModName, sizeof( szModName ),
218 "OS2IM", &imHandle) == 0)
219 DosQueryProcAddr(imHandle, 140, NULL, &pfnImSetMsgQueueProperty);
220
221 InitSystemInfo(ulSysinfo);
222
223 // Set up environment as found in NT
224 InitEnvironment(ulSysinfo);
225
226 // InitDynamicRegistry creates/changes keys that may change (i.e.
227 // odin.ini keys that affect windows version)
228 InitDynamicRegistry();
229
230 // Set the process affinity mask to the system affinity mask
231 DWORD dwProcessAffinityMask, dwSystemAffinityMask;
232 GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask,
233 &dwSystemAffinityMask);
234 SetProcessAffinityMask(GetCurrentProcess(), dwSystemAffinityMask);
235
236 // Set default paths for PE & NE loaders
237 if (!InitLoaders())
238 return -1;
239
240 RasEntry(RAS_EVENT_Kernel32InitComplete,
241 &dllHandle, sizeof (dllHandle));
242
243 fInit = TRUE;
244
245 return EXITLIST_KERNEL32;
246}
247
248ULONG SYSTEM DLL_InitKernel32(ULONG hModule)
249{
250 ULONG code = DLL_InitKernel32_internal(hModule);
251
252 if (code == -1)
253 ReportFatalDllInitError("KERNEL32");
254
255 return code;
256}
257
258void SYSTEM DLL_TermKernel32(ULONG hModule)
259{
260 if (!fInit)
261 {
262 // The initialization sequence was not complete; attempting to
263 // uninitialize some things may crash (yeah, dirty code that doesn't
264 // analyze its own state)
265 return;
266 }
267
268 dprintf(("kernel32 exit"));
269
270 if( IsDBCSEnv() && imHandle )
271 DosFreeModule( imHandle );
272
273 //Flush and delete all open memory mapped files
274 Win32MemMap::deleteAll();
275 WinExe = NULL;
276
277 FinalizeMemMaps();
278
279 WriteOutProfiles();
280 //Unload LVM subsystem for volume/mountpoint win32 functions
281 OSLibLVMExit();
282
283 // Note: unwinding win32 exceptions before destroying TEB like we do in
284 // ExitThread()/ExitProcess() is impossible here since the stack is already
285 // vanished at this point. In cases where process termination is not coming
286 // from ExitThread()/ExitProcess(), unwinding is to be done by
287 // OS2ExceptionHandler2ndLevel() in responce to the normal unwind procedure.
288
289 TEB *teb = GetThreadTEB();
290 if(teb) DestroyTEB(teb);
291
292 DestroySharedHeap();
293 DestroyCodeHeap();
294
295 HMTerminate(); /* shutdown handlemanager */
296
297#ifdef DEBUG
298 extern void printCriticalSectionStatistic (void);
299 printCriticalSectionStatistic ();
300#endif
301
302#if defined(DEBUG) && defined(__IBMCPP__) && __IBMCPP__ == 300
303 ULONG totalmemalloc, nrcalls_malloc, nrcalls_free;
304
305 getcrtstat(&nrcalls_malloc, &nrcalls_free, &totalmemalloc);
306 dprintf(("************* KERNEL32 STATISTICS BEGIN *****************"));
307 dprintf(("Total nr of malloc calls %d", nrcalls_malloc));
308 dprintf(("Total nr of free calls %d", nrcalls_free));
309 dprintf(("Leaked memory: %d bytes", totalmemalloc));
310 dprintf(("************* KERNEL32 STATISTICS END *****************"));
311
312 //SvL: This can cause an exitlist hang; disabled for now
313//// _dump_allocated(0);
314#endif
315
316 //NOTE: Must be done after DestroyTIB
317 ClosePrivateLogFiles();
318
319#ifndef DEBUG
320 //if we do a dump of the shared heap, then we'll need the logging facility
321 //for a little while longer
322 CloseLogFile();
323#endif
324
325 /*
326 * Terminate win32k library.
327 */
328 libWin32kSetEnvironment(NULL, 0, 0);
329 libWin32kTerm();
330
331 RasUninitialize ();
332
333 if (dllHandle)
334 UnregisterLxDll(dllHandle);
335}
336
337ULONG SYSTEM DLL_Init(ULONG hModule)
338{
339 if (DLL_InitDefault(hModule) == -1)
340 return -1;
341 return DLL_InitKernel32(hModule);
342}
343
344void SYSTEM DLL_Term(ULONG hModule)
345{
346 DLL_TermKernel32(hModule);
347 DLL_TermDefault(hModule);
348}
349
350ULONG APIENTRY _O32__DLL_InitTerm(ULONG handle, ULONG flag);
351
352BOOL APIENTRY InitializeKernel32()
353{
354 HMODULE hModule;
355
356 BOOL WGSS_OK = FALSE;
357
358 if (DosQueryModuleHandleStrict("WGSS50", &hModule) == NO_ERROR)
359 {
360 if (_O32__DLL_InitTerm(hModule, 0) != 0)
361 {
362 WGSS_OK = TRUE;
363
364 if (DosQueryModuleHandleStrict("KERNEL32", &hModule) == NO_ERROR &&
365 DLL_Init(hModule) != -1)
366 return TRUE;
367
368 ReportFatalDllInitError("KERNEL32");
369 }
370 }
371
372 if (!WGSS_OK)
373 ReportFatalDllInitError("WGSS50");
374
375 return FALSE; // failure
376}
377
378VOID APIENTRY ReportFatalDllInitError(PCSZ pszModName)
379{
380 static const char msg1[] =
381 "Failed to initialize the ";
382 static const char msg2[] =
383 " library while starting \"";
384 static const char msg3[] =
385 "\".\n\r"
386 "\n\r"
387 "It is possible that there is not enough memory in the system to "
388 "run this application. Please close other applications and try "
389 "again. If the problem persists, please report the details by "
390 "creating a ticket at http://svn.netlabs.org/odin32/.\n\r";
391
392 char msg[sizeof(msg1) + 8 + sizeof(msg2) + CCHMAXPATH + sizeof(msg3)];
393
394 strcpy(msg, msg1);
395 strncat(msg, pszModName, 8);
396 strcat(msg, msg2);
397
398 PPIB ppib;
399 DosGetInfoBlocks(NULL, &ppib);
400 if (DosQueryModuleName(ppib->pib_hmte, CCHMAXPATH,
401 msg + strlen(msg)) != NO_ERROR)
402 strcat(msg, "<unknown executable>");
403 strcat(msg, msg3);
404
405 BOOL haveHMQ = FALSE;
406 MQINFO mqinfo;
407 if (WinQueryQueueInfo(1 /*HMQ_CURRENT*/, &mqinfo, sizeof(mqinfo)) == FALSE)
408 {
409 // attempt to initialize PM and try again
410 HAB hab = WinInitialize(0);
411 if (hab)
412 {
413 HMQ hmq = WinCreateMsgQueue(hab, 0);
414 if (hmq)
415 haveHMQ = TRUE;
416 }
417 }
418 else
419 haveHMQ = TRUE;
420
421 WinMessageBox(HWND_DESKTOP, NULL, msg, "Odin: Fatal Error", 0,
422 MB_APPLMODAL | MB_MOVEABLE | MB_ERROR | MB_OK);
423
424 // duplicate the message to the console just in case (PM may be not
425 // available)
426 ULONG dummy;
427 DosWrite((HFILE)1, (PVOID)&msg, strlen(msg), &dummy);
428}
429
Note: See TracBrowser for help on using the repository browser.