source: trunk/src/win32k/dev16/probkrnl.c@ 10367

Last change on this file since 10367 was 9470, checked in by bird, 23 years ago

Allways print rc in hex.

File size: 56.8 KB
Line 
1/* $Id: probkrnl.c,v 1.38 2002-12-06 02:55:33 bird Exp $
2 *
3 * Description: Autoprobes the os2krnl file and os2krnl[*].sym files.
4 * Another Hack!
5 *
6 * 16-bit inittime code.
7 *
8 * All data has to be initiated because this is 16-bit C code
9 * and is to be linked with 32-bit C/C++ code. Uninitialized
10 * data ends up in the BSS segment, and that segment can't
11 * both be 32-bit and 16-bit. I have not found any other way
12 * around this problem that initiating all data.
13 *
14 * How this works:
15 * 1. parses the device-line parameters and collects some "SysInfo".
16 * 2. gets the kernel object table and kernel info like build no. (elf$)
17 * 3. if non-debug kernel the symbol database is scanned to get the syms
18 * 4. if Syms not found THEN locates and scans the symbol-file(s) for the
19 * entrypoints which are wanted.
20 * 5. the entry points are verified. (elf$)
21 * 6. finished.
22 *
23 * Copyright (c) 1998-2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
24 *
25 * Initial pmdfvers.lst parsing:
26 * Copyright (c) 2001 Rafal Szymczak (rafalszymczak@discoverfinancial.com)
27 *
28 * Project Odin Software License can be found in LICENSE.TXT
29 *
30 */
31
32
33/*******************************************************************************
34* Defined Constants And Macros *
35*******************************************************************************/
36/* Disable logging when doing extracts */
37#if defined(EXTRACT) || defined(RING0)
38 #define NOLOGGING 1
39#endif
40
41#define fclose(a) DosClose(a)
42#define SEEK_SET FILE_BEGIN
43#define SEEK_END FILE_END
44
45#define WORD unsigned short int
46#define DWORD unsigned long int
47
48/* "@#IBM:14.039#@ os2krnl... "*/
49/* "@#IBM:8.264#@ os2krnl... "*/
50#define KERNEL_ID_STRING_LENGTH 42
51#define KERNEL_READ_SIZE 512
52
53#define INCL_BASE
54#define INCL_DOS
55#define INCL_NOPMAPI
56#define INCL_OS2KRNL_LDR
57
58/*******************************************************************************
59* Header Files *
60*******************************************************************************/
61#include <os2.h>
62
63#include <exe386.h>
64#include <strat2.h>
65#include <reqpkt.h>
66
67#include "devSegDf.h"
68#undef DATA16_INIT
69#define DATA16_INIT
70#undef CODE16_INIT
71#define CODE16_INIT
72#include "os2krnl.h" /* must be included before dev1632.h! */
73#include "sym.h"
74#include "probkrnl.h"
75#include "dev16.h"
76#include "dev1632.h"
77#include "vprntf16.h"
78#include "log.h"
79#include "options.h"
80#include "errors.h"
81
82/*******************************************************************************
83* Global Variables *
84* Note: must be inited or else we'll get BSS segment *
85*******************************************************************************/
86
87
88/*
89 * aImportTab defines the imported and overloaded OS/2 kernel functions.
90 * IMPORTANT: aImportTab has three sibling arrays, two in dev32\d32init.c (aulProc
91 * and aTstFakers), and the calltab.asm, which must match entry by entry.
92 * - obsolete warning -
93 * When adding/removing/shuffling items in aImportTab, aulProc and
94 * calltab.asm has to be updated immediately!
95 * Use the mkcalltab.exe to generate calltab.asm and aTstFakers.
96 * - obsolete warning -
97 * We'll now generate both of these files from this table.
98 *
99 */
100IMPORTKRNLSYM DATA16_GLOBAL aImportTab[NBR_OF_KRNLIMPORTS] =
101{/* iFound cchName offObject usSel fType */
102 /* iObject achName achExtra ulAddress cProlog */
103 /* Overrides */
104 {FALSE, -1, 12, "_ldrOpenPath", "@20", -1, -1, -1, -1, EPT_PROC32 | EPT_WRAPPED}, /* Must be [0]! See importTabInit. */
105 {FALSE, -1, 8, "_ldrRead", "@24", -1, -1, -1, -1, EPT_PROC32},
106 {FALSE, -1, 8, "_ldrOpen", "@12", -1, -1, -1, -1, EPT_PROC32},
107 {FALSE, -1, 9, "_ldrClose", "@4", -1, -1, -1, -1, EPT_PROC32},
108 {FALSE, -1, 12, "_LDRQAppType", "@8", -1, -1, -1, -1, EPT_PROC32},
109 {FALSE, -1, 20, "_ldrEnum32bitRelRecs", "@24", -1, -1, -1, -1, EPT_PROC32},
110 {FALSE, -1, 14, "_ldrFindModule", "@16", -1, -1, -1, -1, EPT_PROC32},
111 {FALSE, -1, 21, "_ldrCheckInternalName","@4", -1, -1, -1, -1, EPT_PROC32},
112 {FALSE, -1, 11, "g_tkExecPgm", "", -1, -1, -1, -1, EPT_PROC32},
113 {FALSE, -1, 15, "_tkStartProcess", "", -1, -1, -1, -1, EPT_PROC32},
114 {FALSE, -1, 12, "dh_SendEvent", "", -1, -1, -1, -1, EPT_PROC16},
115 {FALSE, -1, 6, "RASRST", "", -1, -1, -1, -1, EPT_PROC16},
116 {FALSE, -1, 12, "_LDRClearSem", "@0", -1, -1, -1, -1, EPT_PROCIMPORT32},
117 {FALSE, -1, 21, "_ldrASMpMTEFromHandle","@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
118 {FALSE, -1, 21, "_ldrValidateMteHandle","@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
119 {FALSE, -1, 13, "_ldrTransPath", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
120 {FALSE, -1, 15, "_ldrGetFileName", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
121 {FALSE, -1, 15, "_ldrUCaseString", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
122 {FALSE, -1, 11, "_VMAllocMem", "@36", -1, -1, -1, -1, EPT_PROCIMPORT32},
123 {FALSE, -1, 10, "_VMFreeMem", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
124 {FALSE, -1, 11, "_VMGetOwner", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
125 {FALSE, -1, 16, "_VMObjHandleInfo", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
126 {FALSE, -1, 16, "_VMMapDebugAlias", "@20", -1, -1, -1, -1, EPT_PROCIMPORT32},
127 {FALSE, -1, 21, "_VMCreatePseudoHandle","@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
128 {FALSE, -1, 19, "_VMFreePseudoHandle", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
129 {FALSE, -1, 17, "_KSEMRequestMutex", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
130 {FALSE, -1, 17, "_KSEMReleaseMutex", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
131 {FALSE, -1, 15, "_KSEMQueryMutex", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
132 {FALSE, -1, 12, "_TKPidToPTDA", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
133 {FALSE, -1, 9, "_TKSuBuff", "@16", -1, -1, -1, -1, EPT_PROCIMPORT32},
134 {FALSE, -1, 9, "_TKFuBuff", "@16", -1, -1, -1, -1, EPT_PROCIMPORT32},
135 {FALSE, -1, 11, "_TKFuBufLen", "@20", -1, -1, -1, -1, EPT_PROCIMPORT32},
136 {FALSE, -1, 11, "_TKSuFuBuff", "@16", -1, -1, -1, -1, EPT_PROCIMPORT32},
137 {FALSE, -1, 14, "_TKForceThread", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
138 {FALSE, -1, 12, "_TKForceTask", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
139 {FALSE, -1, 14, "_TKGetPriority", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
140 {FALSE, -1, 8, "_TKSleep", "@16", -1, -1, -1, -1, EPT_PROCIMPORT32},
141 {FALSE, -1, 9, "_TKWakeup", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
142 {FALSE, -1, 13, "_TKWakeThread", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
143 {FALSE, -1, 14, "_TKQueryWakeup", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
144 {FALSE, -1, 11, "f_FuStrLenZ", "", -1, -1, -1, -1, EPT_PROCIMPORT16},
145 {FALSE, -1, 10, "f_FuStrLen", "", -1, -1, -1, -1, EPT_PROCIMPORT16},
146 {FALSE, -1, 8, "f_FuBuff", "", -1, -1, -1, -1, EPT_PROCIMPORT16},
147 {FALSE, -1, 13, "h_POST_SIGNAL", "", -1, -1, -1, -1, EPT_PROCIMPORTH16},
148 {FALSE, -1, 12, "_SftFileSize", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
149 {FALSE, -1, 12, "_PGPhysAvail", "@0", -1, -1, -1, -1, EPT_PROCIMPORT32},
150 {FALSE, -1, 14, "_PGPhysPresent", "@0", -1, -1, -1, -1, EPT_PROCIMPORT32},
151 {FALSE, -1, 17, "_vmRecalcShrBound", "@8", -1, -1, -1, -1, EPT_PROCIMPORT32},
152 {FALSE, -1, 15, "KMEnterKmodeSEF", "", -1, -1, -1, -1, EPT_PROCIMPORT32},
153 {FALSE, -1, 15, "KMExitKmodeSEF8", "", -1, -1, -1, -1, EPT_PROCIMPORT32},
154 {FALSE, -1, 16, "_ldrpFileNameBuf", "", -1, -1, -1, -1, EPT_VARIMPORT32},
155 {FALSE, -1, 7, "_LdrSem", "", -1, -1, -1, -1, EPT_VARIMPORT32},
156 {FALSE, -1, 8, "_pTCBCur", "", -1, -1, -1, -1, EPT_VARIMPORT16},
157 {FALSE, -1, 9, "_pPTDACur", "", -1, -1, -1, -1, EPT_VARIMPORT16},
158 {FALSE, -1, 10, "ptda_start", "", -1, -1, -1, -1, EPT_VARIMPORT16},
159 {FALSE, -1, 12, "ptda_environ", "", -1, -1, -1, -1, EPT_VARIMPORT16},
160 {FALSE, -1, 12, "ptda_ptdasem", "", -1, -1, -1, -1, EPT_VARIMPORT16},
161 {FALSE, -1, 11, "ptda_handle", "", -1, -1, -1, -1, EPT_VARIMPORT16},
162 {FALSE, -1, 11, "ptda_module", "", -1, -1, -1, -1, EPT_VARIMPORT16},
163 {FALSE, -1, 18, "ptda_pBeginLIBPATH", "", -1, -1, -1, -1, EPT_VARIMPORT16},
164 {FALSE, -1, 11, "_LDRLibPath", "", -1, -1, -1, -1, EPT_VARIMPORT32},
165 {FALSE, -1, 6, "_mte_h", "", -1, -1, -1, -1, EPT_VARIMPORT32},
166 {FALSE, -1, 9, "_global_h", "", -1, -1, -1, -1, EPT_VARIMPORT32},
167 {FALSE, -1, 9, "_global_l", "", -1, -1, -1, -1, EPT_VARIMPORT32},
168 {FALSE, -1, 11, "_specific_h", "", -1, -1, -1, -1, EPT_VARIMPORT32},
169 {FALSE, -1, 11, "_specific_l", "", -1, -1, -1, -1, EPT_VARIMPORT32},
170 {FALSE, -1, 10, "_program_h", "", -1, -1, -1, -1, EPT_VARIMPORT32},
171 {FALSE, -1, 10, "_program_l", "", -1, -1, -1, -1, EPT_VARIMPORT32},
172 {FALSE, -1, 11, "_SMcDFInuse", "", -1, -1, -1, -1, EPT_VARIMPORT32},
173 {FALSE, -1, 11, "_smFileSize", "", -1, -1, -1, -1, EPT_VARIMPORT32},
174 {FALSE, -1, 11, "_SMswapping", "", -1, -1, -1, -1, EPT_VARIMPORT32},
175 {FALSE, -1, 12, "_smcBrokenDF", "", -1, -1, -1, -1, EPT_VARIMPORT32},
176 {FALSE, -1, 12, "_pgPhysPages", "", -1, -1, -1, -1, EPT_VARIMPORT32},
177 {FALSE, -1, 13, "_SMcInMemFile", "", -1, -1, -1, -1, EPT_VARIMPORT32},
178 {FALSE, -1, 13, "_SMCFGMinFree", "", -1, -1, -1, -1, EPT_VARIMPORT32},
179 {FALSE, -1, 13, "_smcGrowFails", "", -1, -1, -1, -1, EPT_VARIMPORT32},
180 {FALSE, -1, 14, "_PGSwapEnabled", "", -1, -1, -1, -1, EPT_VARIMPORT32},
181 {FALSE, -1, 14, "_pgcPageFaults", "", -1, -1, -1, -1, EPT_VARIMPORT32},
182 {FALSE, -1, 14, "_SMCFGSwapSize", "", -1, -1, -1, -1, EPT_VARIMPORT32},
183 {FALSE, -1, 16, "_pgResidentPages", "", -1, -1, -1, -1, EPT_VARIMPORT32},
184 {FALSE, -1, 17, "_pgSwappablePages", "", -1, -1, -1, -1, EPT_VARIMPORT32},
185 {FALSE, -1, 8, "_ahvmShr", "", -1, -1, -1, -1, EPT_VARIMPORT32},
186 {FALSE, -1, 8, "_ahvmSys", "", -1, -1, -1, -1, EPT_VARIMPORT32},
187 {FALSE, -1, 19, "_pgDiscardableInmem", "", -1, -1, -1, -1, EPT_VARIMPORT32},
188 {FALSE, -1, 19, "_pgDiscardablePages", "", -1, -1, -1, -1, EPT_VARIMPORT32},
189 {FALSE, -1, 10, "_SMMinFree", "", -1, -1, -1, -1, EPT_VARIMPORT32},
190 {FALSE, -1, 20, "_pgcPageFaultsActive", "", -1, -1, -1, -1, EPT_VARIMPORT32},
191 {FALSE, -1, 10, "_pgPhysMax", "", -1, -1, -1, -1, EPT_VARIMPORT32},
192 {FALSE, -1, 9, "_ahvmhShr", "", -1, -1, -1, -1, EPT_VARIMPORTNR32},
193 {FALSE, -1, 20, "_VirtualAddressLimit", "", -1, -1, -1, -1, EPT_VARIMPORTNR32},
194 {FALSE, -1, 14, "SecPathFromSFN", "", -1, -1, -1, -1, EPT_PROCIMPORTNR32},
195#if 0 /* not used */
196 {FALSE, -1, 9, "_KSEMInit", "@12", -1, -1, -1, -1, EPT_PROCIMPORT32},
197 {FALSE, -1, 10, "_IOSftOpen", "@20", -1, -1, -1, -1, EPT_PROCIMPORT32},
198 {FALSE, -1, 11, "_IOSftClose", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
199 {FALSE, -1, 15, "_IOSftTransPath", "@4", -1, -1, -1, -1, EPT_PROCIMPORT32},
200 {FALSE, -1, 12, "_IOSftReadAt", "@20", -1, -1, -1, -1, EPT_PROCIMPORT32},
201 {FALSE, -1, 13, "_IOSftWriteAt", "@20", -1, -1, -1, -1, EPT_PROCIMPORT32},
202#endif
203#if 0/* experimenting...*/
204 {FALSE, -1, 14, "_ldrSetVMflags", "@16", -1, -1, -1, -1, EPT_PROC32},
205#endif
206};
207
208
209/**
210 * szSymbolFile holds the name of the symbol file used.
211 *
212 */
213char DATA16_GLOBAL szSymbolFile[60] = {0};
214
215/**
216 * iProc holds the number of the procedure which failed during verify.
217 */
218int DATA16_GLOBAL iProc = -1; /* The procedure number which failed Verify. */
219
220
221
222/*
223 * private data
224 */
225static char * DATA16_INIT apszSym[] =
226{
227 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
228 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
229 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
230 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
231 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
232 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
233 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
234 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
235 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
236 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
237 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
238 {"c:\\os2\\system\\pmdf\\os2krnld.sym"}, /* warp 3 ?*/
239 {"c:\\os2\\system\\pmdf\\os2krnlb.sym"}, /* warp 3 ?*/
240 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
241 {"c:\\os2krnlr.sym"}, /* custom */
242 {"c:\\os2krnlb.sym"}, /* custom */
243 {"c:\\os2krnld.sym"}, /* custom */
244 NULL
245};
246
247/* Location of PMDF list of custom directories */
248static char DATA16_INIT szPmdfVers[] =
249 {"c:\\os2\\pdpsi\\pmdf\\pmdfvers.lst"};
250
251
252/* Result from GetKernelInfo/ReadOS2Krnl. */
253unsigned char DATA16_INIT cObjects = 0;
254POTE DATA16_INIT paKrnlOTEs = NULL;
255
256
257/*
258 *
259 */
260static struct
261{
262 short sErr;
263 const char *pszMsg;
264} DATA16_INIT aErrorMsgs[] =
265{
266 {ERROR_PROB_KRNL_OPEN_FAILED, "Krnl: Failed to open kernel file."},
267 {ERROR_PROB_KRNL_SEEK_SIZE, "Krnl: Failed to seek to end to of file."},
268 {ERROR_PROB_KRNL_SEEK_FIRST, "Krnl: Failed to start of file."},
269 {ERROR_PROB_KRNL_READ_FIRST, "Krnl: Failed to read (first)."},
270 {ERROR_PROB_KRNL_READ_NEXT, "Krnl: Failed to read."},
271 {ERROR_PROB_KRNL_TAG_NOT_FOUND, "Krnl: Build level tag was not found."},
272 {ERROR_PROB_KRNL_INV_SIGANTURE, "Krnl: Invalid build level signature."},
273 {ERROR_PROB_KRNL_INV_BUILD_NBR, "Krnl: Invalid build level number."},
274 {ERROR_PROB_KRNL_BUILD_VERSION, "Krnl: Invalid build level version."},
275 {ERROR_PROB_KRNL_MZ_SEEK, "Krnl: Failed to seek to start of file. (MZ)"},
276 {ERROR_PROB_KRNL_MZ_READ, "Krnl: Failed to read MZ header."},
277 {ERROR_PROB_KRNL_NEOFF_INVALID, "Krnl: Invalid new-header offset in MZ header."},
278 {ERROR_PROB_KRNL_NEOFF_SEEK, "Krnl: Failed to seek to new-header offset."},
279 {ERROR_PROB_KRNL_LX_READ, "Krnl: Failed to read LX header."},
280 {ERROR_PROB_KRNL_LX_SIGNATURE, "Krnl: Invalid LX header signature."},
281 {ERROR_PROB_KRNL_OBJECT_CNT, "Krnl: Object count don't match the running kernel."},
282 {ERROR_PROB_KRNL_OBJECT_CNR_10, "Krnl: Less than 10 objects - not a valid kernel file!"},
283 {ERROR_PROB_KRNL_OTE_SEEK, "Krnl: Failed to seek to OTEs."},
284 {ERROR_PROB_KRNL_OTE_READ, "Krnl: Failed to read OTEs."},
285 {ERROR_PROB_KRNL_OTE_SIZE_MIS, "Krnl: Size of a OTE didn't match the running kernel."},
286
287 /*
288 * ProbeSymFile error messages + some extra ones.
289 */
290 {ERROR_PROB_SYM_FILE_NOT_FOUND, "Sym: Symbol file was not found."},
291 {ERROR_PROB_SYM_READERROR, "Sym: Read failed."},
292 {ERROR_PROB_SYM_INVALID_MOD_NAME, "Sym: Invalid module name (not OS2KRNL)."},
293 {ERROR_PROB_SYM_SEGS_NE_OBJS, "Sym: Number of segments don't match the object count of the kernel."},
294 {ERROR_PROB_SYM_SEG_DEF_SEEK, "Sym: Failed to seek to a segment definition."},
295 {ERROR_PROB_SYM_SEG_DEF_READ, "Sym: Failed to read a segment definition."},
296 {ERROR_PROB_SYM_IMPORTS_NOTFOUND, "Sym: Some of the imports wasn't found."},
297 {ERROR_PROB_SYM_V_PROC_NOT_FND, "Sym: Verify failed: Procedure not found."},
298 {ERROR_PROB_SYM_V_OBJ_OR_ADDR, "Sym: Verify failed: Invalid object or address."},
299 {ERROR_PROB_SYM_V_ADDRESS, "Sym: Verify failed: Invalid address."},
300 {ERROR_PROB_SYM_V_PROLOG, "Sym: Verify failed: Invalid prolog."},
301 {ERROR_PROB_SYM_V_NOT_IMPL, "Sym: Verify failed: Not implemented."},
302 {ERROR_PROB_SYM_V_GETOS2KRNL, "GetOs2Krnl: failed."},
303 {ERROR_PROB_SYM_V_NO_SWAPMTE, "GetOs2Krnl: No Swap MTE."},
304 {ERROR_PROB_SYM_V_OBJECTS, "GetOs2Krnl: Too many objects."},
305 {ERROR_PROB_SYM_V_OBJECT_TABLE, "GetOs2Krnl: No object table."},
306 {ERROR_PROB_SYM_V_BUILD_INFO, "GetOs2Krnl: Build info not found."},
307 {ERROR_PROB_SYM_V_INVALID_BUILD, "GetOs2Krnl: Unsupported build."},
308 {ERROR_PROB_SYM_V_VERIFY, "importTabInit: Import failed."},
309 {ERROR_PROB_SYM_V_IPE, "importTabInit: Internal-Processing-Error."},
310 {ERROR_PROB_SYM_V_HEAPINIT, "R0Init32: HeapInit Failed."},
311 {ERROR_PROB_SYM_V_D32_LDR_INIT, "R0Init32: ldrInit Failed."},
312
313 {ERROR_PROB_SYMDB_KRNL_NOT_FOUND, "SymDB: Kernel was not found."}
314};
315
316/*
317 * Fake data for Ring-3 testing.
318 */
319#ifdef R3TST
320USHORT DATA16_INIT usFakeVerMajor = 0;
321USHORT DATA16_INIT usFakeVerMinor = 0;
322#ifdef R3TST
323static DATA16_INIT ach[11] = {0}; /* works around compiler/linker bug */
324#endif
325#endif
326
327
328/*******************************************************************************
329* Internal Functions *
330*******************************************************************************/
331/* File an output replacements */
332HFILE fopen(const char * pszFilename, const char * pszIgnored);
333int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile);
334int fseek(HFILE hfile, signed long off, int iOrg);
335unsigned long fsize(HFILE hFile);
336int feof(HFILE hFile);
337char * fgets(char * psz, int num, HFILE hFile);
338
339/* C-library replacements and additions. */
340void * kmemcpy(char *psz1, const char *psz2, int cch);
341char * kstrstr(const char *psz1, const char *psz2);
342int kstrcmp(const char *psz1, const char *psz2);
343int kstrncmp(const char *psz1, const char *psz2, int cch);
344int kstrnicmp(const char *psz1, const char *psz2, int cch);
345int kstrlen(const char *psz);
346char * kstrcpy(char * pszTarget, const char * pszSource);
347char * kstrncpy(char * pszTarget, const char * pszSource, int cch);
348char * kstrcat(char * pszTarget, const char * pszSource);
349char * kstrtok(char * pszTarget, const char * pszToken);
350int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
351
352/* Workers */
353int LookupKrnlEntry(unsigned short usBuild, unsigned short fKernel, unsigned char cObjects);
354int VerifyPrologs(void);
355int ProbeSymFile(const char *pszFilename);
356int GetKernelInfo(void);
357
358/* Ouput */
359void ShowResult(int rc);
360
361/* Others used while debugging in R3. */
362int VerifyKernelVer(void);
363int ReadOS2Krnl(char *pszFilename);
364int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl);
365
366
367
368/*******************************************************************************
369* Implementation of Internal Helper Functions *
370*******************************************************************************/
371
372/**
373 * Quick implementation of fopen.
374 * @param pszFilename name of file to open (sz)
375 * @param pszIgnored whatever - it is ignored
376 * @return Handle to file. (not pointer to a FILE stream as in C-library)
377 * @remark binary and readonly is assumed!
378 */
379HFILE fopen(const char * pszFilename, const char * pszIgnored)
380{
381 HFILE hFile = 0;
382 USHORT rc;
383 unsigned short Action = 0;
384
385 rc = DosOpen(
386 (char*)pszFilename,
387 &hFile,
388 &Action,
389 0,
390 FILE_NORMAL,
391 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
392 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
393 NULL);
394
395 pszIgnored = pszIgnored;
396 if (rc != NO_ERROR)
397 hFile = 0;
398 return hFile;
399}
400
401
402/**
403 * fread emulation
404 * @returns Number of blocks read.
405 * @param pvBuffer Buffer to read into
406 * @param cbBlock Blocksize
407 * @param cBlock Block count
408 * @param hFile Handle to file (HFILE)
409 */
410int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
411{
412 USHORT ulRead;
413 USHORT rc;
414
415 rc = DosRead(hFile, pvBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
416 if (rc == 0)
417 rc = (USHORT)cBlock;
418 else
419 rc = 0;
420
421 return rc;
422}
423
424
425/**
426 * fseek emulation
427 * @returns Same as DosChgFilePtr
428 * @param hFile Filehandle
429 * @param off offset into file from origin
430 * @param org origin
431 */
432int fseek(HFILE hFile, signed long off, int iOrg)
433{
434 ULONG ul;
435 return (int)DosChgFilePtr(hFile, off, iOrg, &ul);
436}
437
438
439/**
440 * Get filesize in bytes.
441 * @returns Filesize.
442 * @param hFile Filehandle
443 * @remark This function sets the file position to end of file.
444 */
445unsigned long fsize(HFILE hFile)
446{
447 USHORT rc;
448 ULONG cb;
449
450 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
451
452 return cb;
453}
454
455
456/**
457 * feof emulation
458 * @returns EOF (-1) if end-of-file reached, otherwise returns 0
459 * @param hFile Filehandle
460 */
461int feof(HFILE hFile)
462{
463 char achBuffer[1];
464 ULONG ulActual = 0;
465 USHORT usActual = 0;
466 USHORT rc;
467
468 rc = DosRead(hFile, (PVOID)&achBuffer[0], 1, &usActual);
469 if (rc == ERROR_NO_DATA || usActual == 0)
470 return -1;
471
472 rc = DosChgFilePtr(hFile, -1, FILE_CURRENT, &ulActual);
473 return 0;
474}
475
476
477/**
478 * fgets emulation - slow!
479 * @returns pointer to the read string, or NULL if failed
480 * @param pszBuf Pointer to the string buffer to read line into.
481 * @param cchBuf String buffer size.
482 * @param hFile Filehandle.
483 */
484char * fgets(char * pszBuf, int cchBuf, HFILE hFile)
485{
486 char * psz = pszBuf;
487 USHORT usActual;
488
489 if (cchBuf <= 1 || feof(hFile))
490 return NULL;
491
492 cchBuf--; /* terminator */
493 do
494 {
495 if (DosRead(hFile, psz, 1, &usActual))
496 {
497 if (psz == pszBuf)
498 return NULL;
499 *psz = '\0';
500 break;
501 }
502 } while (--cchBuf && *psz != '\n' && ++psz);
503
504 /* "\r\n" -> "\n" */
505 if (pszBuf < psz && *psz == '\n' && psz[-1] == '\r')
506 *(--psz) = '\n';
507 psz[1] = '\0';
508
509 return pszBuf;
510}
511
512#if 0 /* not in use */
513/**
514 * kmemcpy - memory copy - slow!
515 * @param psz1 target
516 * @param psz2 source
517 * @param cch length
518 */
519void * kmemcpy(char *psz1, const char *psz2, int cch)
520{
521 while (cch-- != 0)
522 *psz1++ = *psz2++;
523
524 return psz1;
525}
526#endif
527
528
529/**
530 * Finds psz2 in psz1.
531 * @returns Pointer to occurence of psz2 in psz1.
532 * @param psz1 String to be search.
533 * @param psz2 Substring to search for.
534 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
535 */
536char *kstrstr(const char *psz1, const char *psz2)
537{
538 while (*psz1 != '\0')
539 {
540 int i = 0;
541 while (psz2[i] != '\0' && psz1[i] == psz2[i])
542 i++;
543
544 /* found it? */
545 if (psz2[i] == '\0')
546 return (char*)psz1;
547 if (psz1[i] == '\0' )
548 break;
549 psz1++;
550 }
551
552 return NULL;
553}
554
555
556#if 0 /* not in use */
557/**
558 * kstrcmp - String compare
559 * @returns 0 - equal else !0
560 * @param psz1 String 1
561 * @param psz2 String 2
562 */
563int kstrcmp(const char *psz1, const char *psz2);
564{
565 while (*psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
566 {
567 psz1++;
568 psz2++;
569 }
570 return *psz1 - *psz2;
571}
572#endif
573
574
575/**
576 * kstrncmp - String 'n' compare.
577 * @returns 0 - equal else !0
578 * @param p1 String 1
579 * @param p2 String 2
580 * @param len length
581 */
582int kstrncmp(const char *psz1, const char *psz2, int cch)
583{
584 int i = 0;
585 while (i < cch && *psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
586 {
587 psz1++;
588 psz2++;
589 i++;
590 }
591
592 return i - cch;
593}
594
595
596#if 0 /* not in use */
597/**
598 * kstrnicmp - String 'n' compare, case-insensitive.
599 * @returns 0 - equal else !0
600 * @param p1 String 1
601 * @param p2 String 2
602 * @param len length
603 */
604int kstrnicmp(const char *psz1, const char *psz2, int cch)
605{
606 char ch1, ch2;
607
608 do
609 {
610 ch1 = *psz1++;
611 if (ch1 >= 'A' && ch1 <= 'Z')
612 ch1 += 'a' - 'A'; /* to lower case */
613 ch2 = *psz2++;
614 if (ch2 >= 'A' && ch2 <= 'Z')
615 ch2 += 'a' - 'A'; /* to lower case */
616 } while (--cch > 0 && ch1 == ch2 && ch1 != '\0' && ch2 != '\0');
617
618 return ch1 - ch2;
619}
620#endif
621
622
623/**
624 * kstrlen - String length.
625 * @returns Length of the string.
626 * @param psz Pointer to string.
627 * @status completely implemented and tested.
628 * @author knut st. osmundsen
629 */
630int kstrlen(const char * psz)
631{
632 int cch = 0;
633 while (*psz++ != '\0')
634 cch++;
635 return cch;
636}
637
638
639/**
640 * String copy (strcpy).
641 * @returns Pointer to target string.
642 * @param pszTarget Target string.
643 * @param pszSource Source string.
644 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
645 */
646char * kstrcpy(char * pszTarget, const char * pszSource)
647{
648 char *psz = pszTarget;
649
650 while (*pszSource != '\0')
651 *psz++ = *pszSource++;
652 *psz = '\0';
653 return pszTarget;
654}
655
656
657/**
658 * String 'n' copy
659 * @returns Pointer to target string.
660 * @param pszTarget Target string.
661 * @param pszSource Source string.
662 * @param cch Number of bytes to copy.
663 */
664char * kstrncpy(char * pszTarget, const char * pszSource, int cch)
665{
666 char * psz = pszTarget;
667
668 while (cch-- && *pszSource != '\0')
669 *psz++ = *pszSource++;
670
671 if (cch)
672 *psz++ = '\0';
673
674 return pszTarget;
675}
676
677
678/**
679 * String concatenation
680 * @returns Pointer to target string.
681 * @param pszTarget Target string.
682 * @param pszSource String to be appended.
683 */
684char * kstrcat(char * pszTarget, const char * pszSource)
685{
686 char * psz = pszTarget;
687
688 while (*psz != '\0')
689 psz++;
690 while (*pszSource != '\0')
691 *psz++ = *pszSource++;
692 *psz = '\0';
693 return pszTarget;
694}
695
696
697/**
698 * String tokenizer
699 * @returns Pointer to found token or NULL if failed.
700 * @param pszTarget String to be tokenized.
701 * @param pszToken Token delimiters string.
702 */
703char * kstrtok(char * pszTarget, const char * pszToken)
704{
705 static char * pszPos = NULL;
706 char * pszRet = pszTarget;
707
708 if (pszTarget)
709 pszPos = pszTarget;
710 else if (!pszPos || *pszPos == '\0')
711 return NULL;
712 pszRet = pszPos;
713
714 while (*pszPos != '\0')
715 {
716 const char *pszTokenI;
717 for (pszTokenI = pszToken; *pszTokenI; pszTokenI++)
718 if (*pszPos == *pszTokenI)
719 {
720 *pszPos++ = '\0';
721 return pszRet;
722 }
723
724 pszPos++;
725 }
726 pszPos = NULL;
727 return pszRet;
728}
729
730
731/**
732 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
733 * @returns Number of chars of pszArg that has been processed.
734 * @param pszTarget - pointer to target buffer.
735 * @param pszArg - pointer to source argument string.
736 * @param cchMaxlen - maximum chars to copy.
737 */
738int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
739{
740 int i = 0;
741 int fQuote = FALSE;
742
743 /* skip option word/letter */
744 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
745 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
746 {
747 pszArg++;
748 i++;
749 }
750
751 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
752 return 0;
753
754
755 do
756 {
757 pszArg++;
758 i++;
759 } while (*pszArg != '\0' && *pszArg == ' ');
760
761 /* copy maxlen or less */
762 /* check for quotes */
763 if (*pszArg == '"')
764 {
765 fQuote = TRUE;
766 pszArg++;
767 i++;
768 }
769 /* copy loop */
770 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
771 {
772 *pszTarget++ = *pszArg++;
773 i++;
774 cchMaxlen--;
775 }
776
777 /* terminate pszTarget */
778 pszTarget = '\0';
779
780 return i;
781}
782
783
784/**
785 * Get the message text for an error message.
786 * @returns Pointer to error text. NULL if not found.
787 * @param sErr Error code id.
788 * @status completely implemented.
789 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
790 */
791const char * GetErrorMsg(short sErr)
792{
793 int i;
794 for (i = 0; i < sizeof(aErrorMsgs) / sizeof(aErrorMsgs[0]); i++)
795 {
796 if (aErrorMsgs[i].sErr == sErr)
797 return aErrorMsgs[i].pszMsg;
798 }
799 return NULL;
800}
801
802
803
804/*******************************************************************************
805* Implementation Of The Important Functions *
806*******************************************************************************/
807/**
808 * Checks if this kernel is within the kernel symbol database.
809 * If an entry for the kernel is found, the data is copied from the
810 * database entry to aImportTab.
811 * @returns NO_ERROR on succes (0)
812 * 1 if not found.
813 * Error code on error.
814 * @param usBuild Build level.
815 * @param fKernel Kernel (type) flags. (KF_* from options.h)
816 * @param cObjects Count of object in the running kernel.
817 * @sketch Loop thru the table.
818 * @status completely implemented.
819 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
820 */
821int LookupKrnlEntry(unsigned short usBuild, unsigned short fKernel, unsigned char cObjects)
822{
823 int i;
824
825 /*
826 * Loop tru the DB entries until a NULL pointer is found.
827 */
828 for (i = 0; aKrnlSymDB[i].usBuild != 0; i++)
829 {
830 if ( aKrnlSymDB[i].usBuild == usBuild
831 && aKrnlSymDB[i].fKernel == fKernel
832 && aKrnlSymDB[i].cObjects == cObjects)
833 { /* found matching entry! */
834 int j;
835 int rc;
836 PKRNLDBENTRY pEntry = &aKrnlSymDB[i];
837
838 dprintf(("LookUpKrnlEntry - found entry for this kernel!\n"));
839 kstrcpy(szSymbolFile, "Win32k Symbol Database");
840
841 /*
842 * Copy symbol data from the DB to aImportTab.
843 */
844 for (j = 0; j < NBR_OF_KRNLIMPORTS; j++)
845 {
846 aImportTab[j].offObject = pEntry->aSyms[j].offObject;
847 aImportTab[j].iObject = pEntry->aSyms[j].iObject;
848 aImportTab[j].ulAddress = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_base
849 + pEntry->aSyms[j].offObject;
850 aImportTab[j].usSel = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_sel;
851 aImportTab[j].fFound = (char)((aImportTab[j].offObject != 0xFFFFFFFFUL) ? 1 : 0);
852 dprintf((" %-3d addr=0x%08lx off=0x%08lx %s\n",
853 j, aImportTab[j].ulAddress, aImportTab[j].offObject,
854 aImportTab[j].achName));
855 }
856
857 /* Verify prologs*/
858 rc = VerifyPrologs();
859
860 /* set sym name on success or complain on error */
861 if (rc != 0)
862 {
863 printf16("Warning: The Win32k Symbol Database entry found.\n"
864 " But, VerifyPrologs() returned rc=0x%x and iProc=%d\n", rc, iProc);
865 DosSleep(3000);
866 }
867
868 return rc;
869 }
870 }
871
872 /* not found */
873 return ERROR_PROB_SYMDB_KRNL_NOT_FOUND;
874}
875
876
877/**
878 * Verifies the that the addresses in aImportTab are valid.
879 * This is done at Ring-0 of course.
880 * @returns NO_ERROR (ie. 0) on success. iProc = -1
881 * The appropriate OS/2 or Win32k return code on success. iProc
882 * is set to the failing procedure (if appliable).
883 */
884int VerifyPrologs(void)
885{
886#if !defined(EXTRACT)
887 APIRET rc;
888 HFILE hDev0 = 0;
889 USHORT usAction = 0;
890
891 /* Set the failing procedure number to -1. */
892 iProc = -1;
893
894 /* Open the elf device driver. */
895 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
896 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
897 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
898 0UL);
899 if (rc == NO_ERROR)
900 {
901 D16VERIFYIMPORTTABDATA Data = {0};
902
903 /* Issue the VerifyImportTab IOCtl call. */
904 rc = DosDevIOCtl(&Data, "", D16_IOCTL_VERIFYIMPORTTAB, D16_IOCTL_CAT, hDev0);
905 DosClose(hDev0);
906 if (rc == NO_ERROR)
907 {
908 if (Data.usRc != NO_ERROR)
909 {
910 /* set the appropriate return values. */
911 rc = (Data.usRc & ERROR_D32_ERROR_MASK) + ERROR_PROB_SYM_D32_FIRST;
912 if (Data.usRc & ERROR_D32_PROC_FLAG)
913 iProc = (Data.usRc & ERROR_D32_PROC_MASK) >> ERROR_D32_PROC_SHIFT;
914 }/* else success */
915 }
916 else
917 {
918 dprintf(("DosDevIOCtl failed with rc=%d\n", rc));
919 DosSleep(3000);
920 }
921 }
922 else
923 {
924 dprintf(("DosOpen Failed with rc=%d\n", rc));
925 DosSleep(3000);
926 }
927
928 return rc;
929#else
930 return 0;
931#endif
932}
933
934
935/**
936 * Check a symbol file. Searches for the wanted entry-point addresses.
937 * @returns 0 on success - something else on failiure.
938 * @param pszFilename Name of file to probe.
939 * @precond Must be called after kernel-file is found and processed.
940 * @remark Error codes starts at -50.
941 */
942int ProbeSymFile(const char * pszFilename)
943{
944 HFILE hSym; /* Filehandle */
945 int cLeftToFind; /* Symbols left to find */
946 unsigned long iSeg; /* Outer search loop: Segment number */
947 unsigned iSym; /* Middle search loop: Symbol number */
948 unsigned i; /* Inner search loop: ProcTab index */
949 int rc;
950
951 MAPDEF MapDef; /* Mapfile header */
952 SEGDEF SegDef; /* Segment header */
953 SYMDEF32 SymDef32; /* Symbol definition 32-bit */
954 SYMDEF16 SymDef16; /* Symbol definition 16-bit */
955 char achBuffer[256]; /* Name buffer */
956 unsigned long offSegment; /* Segment definition offset */
957 unsigned long offSymPtr; /* Symbol pointer(offset) offset */
958 unsigned short offSym; /* Symbol definition offset */
959
960
961 /*
962 * Open the symbol file
963 */
964 hSym = fopen(pszFilename, "rb");
965 if (hSym==0)
966 {
967 dprintf(("Error opening file %s\n", pszFilename));
968 return ERROR_PROB_SYM_FILE_NOT_FOUND;
969 }
970 dprintf(("\nSuccessfully opened symbolfile: %s\n", pszFilename));
971
972
973 /*
974 * (Open were successfully.)
975 * Now read header and display it.
976 */
977 rc = fread(&MapDef, sizeof(MAPDEF), 1, hSym);
978 if (!rc)
979 { /* oops! read failed, close file and fail. */
980 fclose(hSym);
981 return ERROR_PROB_SYM_READERROR;
982 }
983 achBuffer[0] = MapDef.achModName[0];
984 fread(&achBuffer[1], 1, MapDef.cbModName, hSym);
985 achBuffer[MapDef.cbModName] = '\0';
986 dprintf(("*Module name: %s\n", achBuffer));
987 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
988 dprintf(("*ppNextMap: 0x%x\n", MapDef.ppNextMap ));
989
990
991 /*
992 * Verify that the modulename of the symbol file is OS2KRNL.
993 */
994 if (MapDef.cbModName == 7 && kstrncmp(achBuffer, "OS2KRNL", 7) != 0)
995 { /* modulename was not OS2KRNL, fail. */
996 dprintf(("Modulename verify failed\n"));
997 fclose(hSym);
998 return ERROR_PROB_SYM_INVALID_MOD_NAME;
999 }
1000
1001
1002 /*
1003 * Verify that the number of segments is equal to the number objects in OS2KRNL.
1004 */
1005 #ifndef EXTRACT
1006 if (MapDef.cSegs != cObjects)
1007 { /* incorrect count of segments. */
1008 dprintf(("Segment No. verify failed\n"));
1009 fclose(hSym);
1010 return ERROR_PROB_SYM_SEGS_NE_OBJS;
1011 }
1012 #endif /* !EXTRACT */
1013
1014
1015 /*
1016 * Reset ProcTab
1017 */
1018 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1019 {
1020 aImportTab[i].fFound = 0;
1021 #ifdef DEBUG
1022 aImportTab[i].iObject = 0;
1023 aImportTab[i].offObject = 0;
1024 aImportTab[i].ulAddress = 0;
1025 aImportTab[i].usSel = 0;
1026 #endif
1027 }
1028
1029
1030 /*
1031 * Fileoffset of the first segment.
1032 * And set cLeftToFind.
1033 */
1034 offSegment = SEGDEFOFFSET(MapDef);
1035 cLeftToFind = NBR_OF_KRNLIMPORTS;
1036
1037 /*
1038 * Search thru the entire file, segment by segment.
1039 *
1040 * ASSUME: last segment is the only 32-bit code segment.
1041 *
1042 */
1043 for (iSeg = 0; iSeg < MapDef.cSegs; iSeg++, offSegment = NEXTSEGDEFOFFSET(SegDef))
1044 {
1045 int fSegEPTBitType; /* Type of segment, 16 or 32 bit, expressed in EPT_XXBIT flags */
1046 int fCode; /* Set if this is a code segment, else clear. */
1047
1048 /*
1049 * Read the segment definition.
1050 */
1051 if (fseek(hSym, offSegment, SEEK_SET))
1052 { /* Failed to seek to the segment definition, fail! */
1053 fclose(hSym);
1054 return ERROR_PROB_SYM_SEG_DEF_SEEK;
1055 }
1056 rc = fread(&SegDef, sizeof(SEGDEF), 1, hSym);
1057 if (!rc)
1058 { /* Failed to read the segment definition, fail! */
1059 fclose(hSym);
1060 return ERROR_PROB_SYM_SEG_DEF_READ;
1061 }
1062
1063 /*
1064 * Some debugging info.
1065 */
1066 achBuffer[0] = SegDef.achSegName[0];
1067 fread(&achBuffer[1], 1, SegDef.cbSegName, hSym);
1068 achBuffer[SegDef.cbSegName] = '\0';
1069 dprintf(("Segment %.2li Flags=0x%02x cSymbols=0x%04x Name=%s\n",
1070 iSeg, SegDef.bFlags, SegDef.cSymbols, &achBuffer[0]));
1071
1072 /*
1073 * Determin segment bit type.
1074 */
1075 fSegEPTBitType = SEG32BitSegment(SegDef) ? EPT_32BIT : EPT_16BIT;
1076 fCode = kstrstr(achBuffer, "CODE") != NULL;
1077
1078 /*
1079 * Search thru all the symbols in this segment
1080 * while we look for the requested symbols in aImportTab.
1081 */
1082 for (iSym = 0; iSym < SegDef.cSymbols && cLeftToFind; iSym++)
1083 {
1084 IMPORTKRNLSYM * pImport;
1085 unsigned cchName;
1086
1087 /*
1088 * Fileoffset of the current symbol.
1089 * Set filepointer to that position.
1090 * Read word (which is the offset of the symbol).
1091 */
1092 offSymPtr = SYMDEFOFFSET(offSegment, SegDef, iSym);
1093 rc = fseek(hSym, offSymPtr, SEEK_SET);
1094 if (rc)
1095 { /* Symboloffset seek failed, try read next symbol. */
1096 dprintf(("Warning: Seek failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
1097 continue;
1098 }
1099 rc = fread(&offSym, sizeof(unsigned short int), 1, hSym);
1100 if (!rc)
1101 { /* Symboloffset read failed, try read next symbol. */
1102 dprintf(("Warning: read failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
1103 continue;
1104 }
1105 rc = fseek(hSym, offSym + offSegment, SEEK_SET);
1106 if (rc)
1107 { /* Symbol Seek failed, try read next symbol. */
1108 dprintf(("Warning: Seek failed (offSym=%d, rc=%d)\n", offSym, rc));
1109 continue;
1110 }
1111
1112
1113 /*
1114 * Read symbol and symbolname.
1115 */
1116 if (SegDef.bFlags & 0x01)
1117 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, hSym);
1118 else
1119 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, hSym);
1120 if (!rc)
1121 { /* Symbol read failed, try read next symbol */
1122 dprintf(("Warning: Read(1) failed (offSym=%d, rc=%d)\n", offSym, rc));
1123 continue;
1124 }
1125 achBuffer[0] = (SegDef.bFlags & 0x01) ? SymDef32.achSymName[0] : SymDef16.achSymName[0];
1126 cchName = (SegDef.bFlags & 0x01) ? SymDef32.cbSymName : SymDef16.cbSymName;
1127 rc = fread(&achBuffer[1], 1, cchName, hSym);
1128 if (!rc)
1129 { /* Symbol read failed, try read next symbol */
1130 dprintf(("Warning: Read(2) failed (offSym=%d, rc=%d)\n", offSym, rc));
1131 continue;
1132 }
1133 achBuffer[cchName] = '\0';
1134
1135
1136 /*
1137 * Search proctable.
1138 */
1139 for (i = 0, pImport = &aImportTab[0]; i < NBR_OF_KRNLIMPORTS; i++, pImport++)
1140 {
1141 if (!pImport->fFound /* Not allready found */
1142 && (pImport->fType & EPT_VARIMPORT ? !fCode : fCode) /* Don't look for code in a data segment */
1143 && pImport->cchName == cchName /* Equal name length */
1144 && kstrncmp(pImport->achName, achBuffer, cchName) == 0 /* Equal name */
1145 )
1146 { /* Symbol was found */
1147 pImport->offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
1148 pImport->ulAddress = pImport->offObject + paKrnlOTEs[iSeg].ote_base;
1149 pImport->iObject = (unsigned char)iSeg;
1150 pImport->usSel = paKrnlOTEs[iSeg].ote_sel;
1151 dprintf(("debug: base=%lx, size=%lx iSeg=%d\n", paKrnlOTEs[iSeg].ote_base, paKrnlOTEs[iSeg].ote_size, iSeg));
1152
1153 /* Paranoia test! */
1154 #ifndef EXTRACT
1155 if (pImport->offObject < paKrnlOTEs[iSeg].ote_size)
1156 {
1157 pImport->fFound = TRUE;
1158 cLeftToFind--;
1159 dprintf(("Found: %s at off 0x%lx addr 0x%lx, sel=0x%x\n",
1160 pImport->achName, pImport->offObject,
1161 pImport->ulAddress, pImport->usSel));
1162 }
1163 else/* test failed, continue on next symbol*/
1164 dprintf(("Error: Paranoia test failed for %s\n", pImport->achName));;
1165 #else
1166 pImport->fFound = TRUE;
1167 cLeftToFind--;
1168 #endif /* !EXTRACT */
1169 break;
1170 }
1171
1172 } /* aImportTab for-loop */
1173
1174 } /* Symbol for-loop */
1175
1176 } /* Segment for-loop */
1177
1178 /*
1179 * Close symbol file.
1180 */
1181 fclose(hSym);
1182
1183 /*
1184 * If not all procedures were found fail.
1185 */
1186 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1187 if (!aImportTab[i].fFound && !EPTNotReq(aImportTab[i]))
1188 return ERROR_PROB_SYM_IMPORTS_NOTFOUND;
1189
1190 /*
1191 * Verify function prologs and return.
1192 */
1193 return VerifyPrologs();
1194}
1195
1196
1197/**
1198 * Get kernelinformation (OTEs (object table entries), build, type, debug...)
1199 * @returns 0 on success.
1200 * options.ulBuild, fchType, fDebug, cObjects and paKrnlOTEs is set on successful return.
1201 * Not 0 on error.
1202 */
1203int GetKernelInfo(void)
1204{
1205#if !defined(EXTRACT) /* This IOCtl is not available after inittime! */
1206 static KRNLINFO DATA16_INIT KrnlInfo = {0};
1207 APIRET rc;
1208 HFILE hDev0 = 0;
1209 USHORT usAction = 0;
1210
1211 /*
1212 * Issue an IOCtl to elf$ to query kernel information.
1213 */
1214 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
1215 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
1216 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
1217 0UL);
1218 if (rc == NO_ERROR)
1219 {
1220 rc = DosDevIOCtl(&KrnlInfo, "", D16_IOCTL_GETKRNLINFO, D16_IOCTL_CAT, hDev0);
1221 if (rc == NO_ERROR)
1222 {
1223 #ifdef DEBUG
1224 unsigned i;
1225 #endif
1226
1227 /*
1228 * Set the exported parameters
1229 */
1230 options.ulBuild = KrnlInfo.ulBuild;
1231 options.fKernel = KrnlInfo.fKernel;
1232 cObjects = KrnlInfo.cObjects;
1233 paKrnlOTEs = &KrnlInfo.aObjects[0];
1234
1235 /*
1236 * If debugging probkrnl dump kernel OTEs.
1237 */
1238 #ifdef DEBUG
1239 dprintf(("debug: kernel OTE:\n"));
1240 for (i = 0; i < cObjects; i++)
1241 dprintf(("debug: no.%2d base=%lx size=%lx sel=%x\n",
1242 i,
1243 paKrnlOTEs[i].ote_base,
1244 paKrnlOTEs[i].ote_size,
1245 paKrnlOTEs[i].ote_sel));
1246 #endif
1247 }
1248 DosClose(hDev0);
1249 }
1250
1251 if (rc != NO_ERROR)
1252 printf16("Failed to get kernel OTEs. rc=%d\n", rc);
1253
1254 return rc;
1255
1256#else
1257 return 0;
1258#endif
1259}
1260
1261
1262/**
1263 * Shows result of kernelprobing if not quiet or on error.
1264 * @param rc Return code.
1265 */
1266void ShowResult(int rc)
1267{
1268 int i;
1269
1270 /*
1271 * Complain even if quiet on error
1272 */
1273 if (!options.fQuiet || rc != NO_ERROR)
1274 {
1275 printf16("\nWin32k - Odin32 support driver. (Built %s %s)\n",
1276 (NPSZ)szBuildTime, (NPSZ)szBuildDate);
1277
1278 /*
1279 * kernel stuff
1280 */
1281 if (rc == NO_ERROR || rc > ERROR_PROB_KRNL_LAST)
1282 printf16(" Build: %ld - v%d.%d\n",
1283 options.ulBuild, options.usVerMajor, options.usVerMinor);
1284 else if (rc >= ERROR_PROB_KRNL_FIRST)
1285 printf16(" Kernel probing failed with rc=%d (0x%x).\n", rc, rc);
1286 else
1287 printf16(" Failed before probing kernel.\n");
1288
1289 /*
1290 * symbol-file
1291 */
1292 if (rc == NO_ERROR || (rc > ERROR_PROB_SYM_LAST && szSymbolFile[0] != '\0'))
1293 printf16(" Found symbolfile: %s\n", (NPSZ)szSymbolFile);
1294 else if (rc >= ERROR_PROB_SYM_FIRST)
1295 printf16(" Failed to find symbolfile!\n");
1296 else
1297 printf16(" Failed before searching for symbolfile.\n");
1298
1299 /*
1300 * function listing
1301 */
1302 if (options.fLogging)/* || rc != NO_ERROR)*/
1303 {
1304 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1305 {
1306 printf16(" %-21s at ", aImportTab[i].achName);
1307 if (aImportTab[i].fFound)
1308 printf16("0x%08lx%s", aImportTab[i].ulAddress, (i % 2) == 0 ? "" : "\n");
1309 else
1310 printf16("not found!%s", (i % 2) == 0 ? "" : "\n");
1311 }
1312 if (i % 2) printf16("\n");
1313 }
1314
1315 /*
1316 * Display error code.
1317 */
1318 if (rc != NO_ERROR)
1319 {
1320 const char *psz = GetErrorMsg(rc);
1321 printf16("ProbeKernel failed with rc=%d (0x%x). iProc=%x\n", rc, rc, iProc);
1322 if (psz) printf16("%s\n", psz);
1323 printf16("\n");
1324 }
1325 }
1326}
1327
1328
1329/**
1330 * "main" function.
1331 * Note that the option -Noloader causes nothing to be done.
1332 * @returns 0 on success, something else on error.
1333 * @param pReqPack Pointer to init request packet
1334 * @remark
1335 */
1336int ProbeKernel(PRPINITIN pReqPack)
1337{
1338 int rc;
1339 int i;
1340 int n;
1341 APIRET rc2;
1342 SEL selGIS;
1343 SEL selLIS;
1344 PGINFOSEG pGIS;
1345 PLINFOSEG pLIS;
1346 USHORT usBootDrive;
1347 HFILE hPmdfVers;
1348
1349 /*----------------*/
1350 /* parse InitArgs */
1351 /*----------------*/
1352 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
1353 {
1354 n = kstrlen(pReqPack->InitArgs);
1355 for (i = 0; i < n; i++)
1356 {
1357 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
1358 {
1359 i++;
1360 switch (pReqPack->InitArgs[i])
1361 {
1362 case 'n':
1363 case 'N': /* NoLoader */
1364 options.fNoLoader = TRUE;
1365 return 0;
1366
1367 case 'q':
1368 case 'Q': /* Quiet */
1369 options.fQuiet = TRUE;
1370 break;
1371
1372 case 's':
1373 case 'S': /* Symbol file */
1374 i++;
1375 if ( pReqPack->InitArgs[i] != 'c' && pReqPack->InitArgs[i] != 'C'
1376 && pReqPack->InitArgs[i] != 'm' && pReqPack->InitArgs[i] != 'M'
1377 ) /* -script and -smp is ignored */
1378 i += kargncpy(szSymbolFile, &pReqPack->InitArgs[i], sizeof(szSymbolFile));
1379 break;
1380
1381 case 'v':
1382 case 'V': /* Verbose */
1383 options.fQuiet = FALSE;
1384 break;
1385 }
1386 }
1387 }
1388 }
1389
1390 /*---------------------*/
1391 /* determin boot drive */
1392 /*---------------------*/
1393 rc = DosGetInfoSeg(&selGIS, &selLIS);
1394 if (rc != NO_ERROR)
1395 return rc;
1396
1397 pLIS = MAKEPLINFOSEG(selLIS);
1398 pGIS = MAKEPGINFOSEG(selGIS);
1399 usBootDrive = pGIS->bootdrive;
1400#ifndef R3TST
1401 options.usVerMajor = pGIS->uchMajorVersion;
1402 options.usVerMinor = pGIS->uchMinorVersion;
1403#else
1404 if (usFakeVerMajor == 0)
1405 {
1406 usFakeVerMajor = pGIS->uchMajorVersion;
1407 usFakeVerMinor = pGIS->uchMinorVersion;
1408 }
1409 options.usVerMajor = usFakeVerMajor;
1410 options.usVerMinor = usFakeVerMinor;
1411#endif
1412 dprintf(("BootDrive: %d\n", usBootDrive));
1413
1414 /* set driveletter in constants strings */
1415 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1416 for (i = 0; apszSym[i] != NULL; i++)
1417 apszSym[i][0] = (char)usBootDrive;
1418
1419 /*-----------------*/
1420 /* get kernel info */
1421 /*-----------------*/
1422 rc = GetKernelInfo();
1423
1424 /*--------------*/
1425 /* read symfile */
1426 /*--------------*/
1427 if (!rc)
1428 {
1429 rc = 1;
1430 if (szSymbolFile[0] != '\0')
1431 {
1432 rc = ProbeSymFile(szSymbolFile);
1433 if (rc)
1434 {
1435 printf16("Warning: Invalid symbol file specified. rc=%d (0x%x) iProc=%d\n"
1436 " Tries defaults.\n", rc, rc, iProc);
1437 szSymbolFile[0] = '\0';
1438 DosSleep(3000);
1439 }
1440 }
1441 if (rc != NO_ERROR) /* if user sym failed or don't exists. */
1442 {
1443 /*
1444 * Check database - only if not a debug kernel!
1445 * You usually have a .sym-file when using a debug kernel.
1446 * (This is because I am unable to distinguish between half and
1447 * all strict kernels...)
1448 */
1449 if ((options.fKernel & KF_DEBUG) ||
1450 (rc = LookupKrnlEntry((unsigned short)options.ulBuild,
1451 (unsigned short)options.fKernel,
1452 cObjects)
1453 ) != NO_ERROR
1454 )
1455 {
1456 #if 1 /* ndef R3TST */
1457 /* search on disk */
1458 i = 0;
1459 while (apszSym[i] != NULL
1460 && (rc2 = ProbeSymFile(apszSym[i])) != NO_ERROR
1461 )
1462 {
1463 i++;
1464 if (rc2 >= ERROR_PROB_SYM_D32_FIRST)
1465 rc = rc2;
1466 }
1467 if (rc2 == NO_ERROR)
1468 {
1469 kstrcpy(szSymbolFile, apszSym[i]);
1470 rc = NO_ERROR;
1471 }
1472 #endif
1473 }
1474 }
1475
1476 if (rc != NO_ERROR) /* if symbol file still not found. */
1477 {
1478 /*
1479 * Search pmdfvers.lst for custom directories.
1480 */
1481 szPmdfVers[0] = (char)usBootDrive;
1482 hPmdfVers = fopen(szPmdfVers, "r");
1483 if (hPmdfVers)
1484 {
1485 if (!feof(hPmdfVers))
1486 {
1487 char achBuf[CCHMAXPATH];
1488 while (fgets(achBuf, sizeof(achBuf), hPmdfVers))
1489 {
1490 char * pszDirTk = kstrtok(achBuf, ":;,");
1491 char * pszBuild = kstrtok(NULL, ":;,");
1492 ULONG ulBuild = 0;
1493 ULONG fKernel = 0;
1494
1495 /*
1496 * Parse build number.
1497 * (Note, not all kernel flags are set.)
1498 */
1499 if (pszBuild)
1500 {
1501 for (; (*pszBuild >= '0' && *pszBuild <= '9') || *pszBuild == '.'; pszBuild++)
1502 if (*pszBuild != '.')
1503 ulBuild = (ulBuild * 10) + *pszBuild - '0';
1504
1505 if ((*pszBuild >= 'A' && *pszBuild <= 'Z') || (*pszBuild >= 'a' && *pszBuild <= 'z'))
1506 {
1507 fKernel |= (USHORT)((*pszBuild - (*pszBuild >= 'a' ? 'a'-1 : 'A'-1)) << KF_REV_SHIFT);
1508 pszBuild++;
1509 }
1510 if (*pszBuild == ',') /* This is ignored! */
1511 *pszBuild++;
1512
1513 if (pszBuild[0] == '_' && (pszBuild[1] == 'S' || pszBuild[1] == 's')) /* _SMP */
1514 fKernel |= KF_SMP;
1515 else
1516 if (*pszBuild != ','
1517 && ( (pszBuild[0] == '_' && pszBuild[1] == 'W' && pszBuild[2] == '4') /* _W4 */
1518 || (pszBuild[0] == '_' && pszBuild[1] == 'U' && pszBuild[2] == 'N' && pszBuild[3] == 'I' && pszBuild[4] == '4') /* _UNI4 */
1519 )
1520 )
1521 fKernel |= KF_W4 | KF_UNI;
1522 else
1523 fKernel |= KF_UNI;
1524 }
1525 else
1526 {
1527 ulBuild = options.ulBuild;
1528 fKernel = options.fKernel;
1529 }
1530
1531 /*
1532 * Consider this entry?
1533 */
1534 if ( pszDirTk
1535 && *pszDirTk
1536 && ulBuild == options.ulBuild
1537 && (fKernel & (KF_REV_MASK | KF_UNI | KF_SMP | KF_W4)) == (options.fKernel & (KF_REV_MASK | KF_UNI | KF_SMP | KF_W4))
1538 && (kstrlen(pszDirTk) + 1 + sizeof(szPmdfVers)) < CCHMAXPATH /* no -13 because of os2krnl.sym is appended. */
1539 )
1540 {
1541 char szName[CCHMAXPATH];
1542 char *pszName;
1543 kstrcpy(szName, szPmdfVers);
1544 kstrcpy(&szName[sizeof(szPmdfVers) - 13], pszDirTk); /* 13 = strlen("pmdfvers.lst")+1 */
1545 pszName = &szName[kstrlen(szName)];
1546 *pszName++ = '\\';
1547
1548 /* search custom kernel first */
1549 kstrcpy(pszName, "os2krnl.sym");
1550 rc2 = ProbeSymFile(szName);
1551 if (rc2 >= ERROR_PROB_SYM_D32_FIRST)
1552 rc = rc2;
1553 if (rc2 == NO_ERROR)
1554 {
1555 kstrcpy(szSymbolFile, szName);
1556 rc = NO_ERROR;
1557 break;
1558 }
1559
1560 /* search retail kernel */
1561 if (!(options.fKernel & KF_DEBUG))
1562 {
1563 kstrcpy(pszName, "os2krnlr.sym");
1564 rc2 = ProbeSymFile(szName);
1565 if (rc2 >= ERROR_PROB_SYM_D32_FIRST)
1566 rc = rc2;
1567 if (rc2 == NO_ERROR)
1568 {
1569 kstrcpy(szSymbolFile, szName);
1570 rc = NO_ERROR;
1571 break;
1572 }
1573 }
1574
1575 /* search allstrict kernel */
1576 if (options.fKernel & KF_DEBUG)
1577 {
1578 kstrcpy(pszName, "os2krnld.sym");
1579 rc2 = ProbeSymFile(szName);
1580 if (rc2 >= ERROR_PROB_SYM_D32_FIRST)
1581 rc = rc2;
1582 if (rc2 == NO_ERROR)
1583 {
1584 kstrcpy(szSymbolFile, szName);
1585 rc = NO_ERROR;
1586 break;
1587 }
1588 }
1589
1590 }
1591 } /* while */
1592 }
1593 fclose(hPmdfVers);
1594 }
1595 }
1596 }
1597
1598 /* Show the result and set return-value */
1599 dprintf(("rc=%d(0x%x); i=%d; iProc=%d\n", rc, rc, i, iProc));
1600 ShowResult(rc);
1601
1602 return rc;
1603}
1604
Note: See TracBrowser for help on using the repository browser.