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

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

Return correct EXITLIST order codes for KERNEL32 and ODINCRT.

This is needed for the correct uninitalization order (which is vital).

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