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

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

Correct debug-message format

File size: 12.2 KB
RevLine 
[10606]1/* $Id: initkernel32.cpp,v 1.28 2004-05-24 08:56:06 sandervl Exp $
[6646]2 *
[6375]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
[22099]11//~ #undef DBG_CON
12//~ #define DBG_CON
13
[6375]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>
[22099]24#include "HandleManager.h"
[6375]25#include "profile.h"
26#include <options.h>
27#include "initterm.h"
28#include <win32type.h>
[7318]29#include <win32api.h>
[6375]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"
[7564]37#include "hmcomm.h"
[21716]38#include "windllbase.h"
[6375]39#include "winexepe2lx.h"
40#include <exitlist.h>
41#include "oslibdos.h"
[8397]42#include "osliblvm.h"
[6375]43#include <cpuhlp.h>
[22099]44#include <win32k.h>
[6375]45#include <initdll.h>
46#include <codepage.h>
47#include <process.h>
[7627]48#include <stats.h>
[10528]49#include <heapshared.h>
[21308]50#include <heapstring.h>
[21302]51#include <_ras.h>
[6375]52
53#define DBG_LOCALLOG DBG_initterm
54#include "dbglocal.h"
55
56PVOID SYSTEM _O32_GetEnvironmentStrings( VOID );
57
[21734]58// Win32 resource table (produced by wrc)
59extern DWORD kernel32_PEResTab;
[6375]60
[21734]61static HMODULE dllHandle = 0;
62
[21308]63extern PFN pfnImSetMsgQueueProperty;
64
[21734]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
[22088]76/// Exported dummy function to indicate swt-branch -- to be removed later.
77BOOL WINAPI odin32swt() {
78 return TRUE;
79}
80
[21734]81static ULONG DLL_InitKernel32_internal(ULONG hModule)
[6375]82{
83 size_t i;
84 APIRET rc;
85 ULONG ulSysinfo, version[2];
[6646]86
[21734]87 if (fInit)
[21829]88 return EXITLIST_KERNEL32; // already initialized
[6375]89
[21734]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;
[21649]95
[21734]96 // This always must be the first thing to do.
97 RasInitialize (hModule);
[21302]98#ifdef RAS
[21734]99 extern void rasInitVirtual (void);
100 rasInitVirtual ();
[21302]101#endif
102
[21734]103 ParseLogStatusKERNEL32();
[6375]104
[21734]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 }
[21650]121
[21734]122 char *kernel32Name = OSLibGetDllName(hModule);
123 if (!kernel32Name)
124 return -1; // failure
[21650]125
[21734]126 strcpy(kernel32Path, kernel32Name);
127 char *endofpath = strrchr(kernel32Path, '\\');
128 *(endofpath+1) = 0;
[8427]129
[21734]130 CheckVersionFromHMOD(PE2LX_VERSION, hModule); /*PLF Wed 98-03-18 05:28:48*/
[8427]131
[21734]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
[10528]141
[21824]142 dprintf(("kernel32 init %s %s (%x) Win32k - %s", __DATE__, __TIME__, DLL_InitKernel32_internal,
[21734]143 libWin32kInstalled() ? "Installed" : "Not Installed"));
[6375]144
[21734]145 OpenPrivateLogFiles();
[6375]146
[21734]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;
[10606]151
[21734]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;
[8898]157
[21734]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();
[10528]162
[21734]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 }
[8898]172
[21734]173 if (!InitializeCodeHeap())
174 return -1;
[6375]175
[21734]176 InitializeMemMaps();
[8203]177
[21734]178 PROFILE_LoadOdinIni();
179 dllHandle = RegisterLxDll(hModule, 0, (PVOID)&kernel32_PEResTab);
180 if (dllHandle == 0)
181 return -1;
[6375]182
[21734]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 }
[6375]191
[21734]192 OSLibDosSetInitialMaxFileHandles(ODIN_DEFAULT_MAX_FILEHANDLES);
[6375]193
[10528]194#ifdef DEBUG
[21734]195 {
196 LPSTR WIN32API GetEnvironmentStringsA();
[10528]197
[21734]198 char *tmpenvnew = GetEnvironmentStringsA();
199 dprintf(("Environment:"));
200 while(*tmpenvnew) {
201 dprintf(("%s", tmpenvnew));
202 tmpenvnew += strlen(tmpenvnew)+1;
203 }
204 }
[10528]205#endif
206
[21734]207 // Must be done before InitializeTIB (which loads NTDLL -> USER32)
208 InitDirectories();
[21650]209
[21734]210 // Must be done after HMInitialize!
211 if (InitializeMainThread() == NULL)
212 return -1;
[21650]213
[21734]214 RegisterDevices();
215 Win32DllBase::setDefaultRenaming();
[21650]216
[21734]217 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
218 &ulSysinfo, sizeof(ulSysinfo));
219 if (rc != 0)
220 ulSysinfo = 1;
[6375]221
[21734]222 // Setup codepage info
223 CODEPAGE_Init();
[6375]224
[21734]225 if (IsDBCSEnv() && DosLoadModule(szModName, sizeof( szModName ),
226 "OS2IM", &imHandle) == 0)
227 DosQueryProcAddr(imHandle, 140, NULL, &pfnImSetMsgQueueProperty);
[21308]228
[21734]229 InitSystemInfo(ulSysinfo);
[21650]230
[21734]231 // Set up environment as found in NT
232 InitEnvironment(ulSysinfo);
[6375]233
[21734]234 // InitDynamicRegistry creates/changes keys that may change (i.e.
235 // odin.ini keys that affect windows version)
236 InitDynamicRegistry();
[7318]237
[21734]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);
[9496]243
[21734]244 // Set default paths for PE & NE loaders
245 if (!InitLoaders())
246 return -1;
[21535]247
[21734]248 RasEntry(RAS_EVENT_Kernel32InitComplete,
249 &dllHandle, sizeof (dllHandle));
[21535]250
[21734]251 fInit = TRUE;
[21649]252
[21734]253 return EXITLIST_KERNEL32;
254}
[6375]255
[21734]256ULONG SYSTEM DLL_InitKernel32(ULONG hModule)
[21651]257{
[22102]258 __con_debug(2,"%s::%s@%08X(%08X)\n","KERNEL32",__FUNCTION__,DLL_InitKernel32,hModule);
[21734]259 ULONG code = DLL_InitKernel32_internal(hModule);
[21651]260
[21734]261 if (code == -1)
[21654]262 ReportFatalDllInitError("KERNEL32");
[21653]263
[21734]264 return code;
[21651]265}
[21734]266
267void SYSTEM DLL_TermKernel32(ULONG hModule)
[6375]268{
[22102]269 __con_debug(2,"%s::%s@%08X(%08X)\n","KERNEL32",__FUNCTION__,DLL_TermKernel32,hModule);
[21649]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 }
[7564]277
[21734]278 dprintf(("kernel32 exit"));
[21649]279
[21308]280 if( IsDBCSEnv() && imHandle )
281 DosFreeModule( imHandle );
282
[6375]283 //Flush and delete all open memory mapped files
284 Win32MemMap::deleteAll();
285 WinExe = NULL;
286
[21302]287 FinalizeMemMaps();
288
[6375]289 WriteOutProfiles();
[8397]290 //Unload LVM subsystem for volume/mountpoint win32 functions
291 OSLibLVMExit();
292
[21661]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();
[8648]300 if(teb) DestroyTEB(teb);
[21661]301
[6375]302 DestroySharedHeap();
303 DestroyCodeHeap();
304
[8327]305 HMTerminate(); /* shutdown handlemanager */
306
[21302]307#ifdef DEBUG
308 extern void printCriticalSectionStatistic (void);
309 printCriticalSectionStatistic ();
310#endif
311
[8010]312#if defined(DEBUG) && defined(__IBMCPP__) && __IBMCPP__ == 300
[7627]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 *****************"));
[8327]321
[8340]322 //SvL: This can cause an exitlist hang; disabled for now
323//// _dump_allocated(0);
[7627]324#endif
325
[6375]326 //NOTE: Must be done after DestroyTIB
327 ClosePrivateLogFiles();
[21302]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
[6375]332 CloseLogFile();
[21302]333#endif
[6375]334
335 /*
336 * Terminate win32k library.
337 */
338 libWin32kSetEnvironment(NULL, 0, 0);
339 libWin32kTerm();
[21302]340
341 RasUninitialize ();
[21535]342
[21734]343 if (dllHandle)
344 UnregisterLxDll(dllHandle);
[6375]345}
[21734]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.