source: branches/swt/src/kernel32/initterm.cpp@ 22145

Last change on this file since 22145 was 22102, checked in by rousseau, 10 years ago

Correct debug-message format

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