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

Last change on this file since 1330 was 847, checked in by bird, 26 years ago

Initial checkin of Win32k. (not tested & pe2lx not up-to-date!)

File size: 27.4 KB
Line 
1/* $Id: probkrnl.c,v 1.1 1999-09-06 02:19:55 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 file is to be compiled into assembly,
9 * automaticly modified and run thru an assembler to produce an object-file. This
10 * because there is no other known way to combine 32-bit and 16-bit C/C++ code into
11 * the same device driver which works.
12 *
13 * How this works:
14 * 1. parses the device-line parameters and collects some "SysInfo".
15 * 2. gets the kernel object table. (win32i$)
16 * 3. finds the kernel image and scans it for a build number.
17 * 4. locates and scans the symbol-file(s) for the entrypoints which are wanted.
18 * 5. the entry points are verified. (win32i$)
19 * 6. finished.
20 *
21 * Copyright (c) 1998-1999 knut st. osmundsen
22 *
23 */
24
25
26/*******************************************************************************
27* Defined Constants And Macros *
28*******************************************************************************/
29#ifdef DEBUGR3
30 #if 1
31 #define dprintf(a) printf a
32 #else
33 #define dprintf(a)
34 #endif
35#else
36 #define dprintf(a)
37#endif
38
39#define fclose(a) DosClose(a)
40#define SEEK_SET FILE_BEGIN
41#define SEEK_END FILE_END
42
43#define WORD unsigned short int
44#define DWORD unsigned long int
45
46/* "@#IBM:14.020#@ os2krnl... "*/
47#define KERNEL_ID_STRING_LENGTH 42
48#define KERNEL_READ_SIZE 512
49
50#define INCL_BASE
51#define INCL_DOS
52
53
54/*******************************************************************************
55* Header Files *
56*******************************************************************************/
57#include <os2.h>
58
59#include <exe386.h>
60#include <strat2.h>
61#include <reqpkt.h>
62
63#include "os2krnl.h" /* must be included before dev1632.h! */
64#include "sym.h"
65#include "probkrnl.h"
66#include "dev16.h"
67#include "dev1632.h"
68
69
70/*******************************************************************************
71* Global Variables *
72* Note: must be inited or else we'll get BSS segment *
73*******************************************************************************/
74/*
75 * kernel data - !only valid during init!
76 */
77PROCS aProcTab[NUMBER_OF_PROCS] =
78{/* iFound cchName offObject fType */
79 /* iObject achName ulAddress */
80 {FALSE, -1, 8, "_ldrRead", -1, -1, EPT_PROC},
81 {FALSE, -1, 8, "_ldrOpen", -1, -1, EPT_PROC},
82 {FALSE, -1, 9, "_ldrClose", -1, -1, EPT_PROC},
83 {FALSE, -1, 12, "_LDRQAppType", -1, -1, EPT_PROC},
84};
85
86unsigned long int fInitSuccess = 0;
87unsigned long int ulBuild = 0;
88unsigned short usVerMajor = 0;
89unsigned short usVerMinor = 0;
90
91
92/*
93 * privat data
94 */
95static int fQuiet = 0;
96
97static char szUsrOS2Krnl[50] = {0};
98static char szOS2Krnl[] = {"c:\\os2krnl"};
99
100static char szUsrSym[50] = {0};
101static char *apszSym[] =
102{
103 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
104 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
105 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
106 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
107 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
108 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
109 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
110 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
111 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
112 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
113 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
114 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
115 {"c:\\os2krnlr.sym"}, /* custom */
116 {"c:\\os2krnlh.sym"}, /* custom */
117 {"c:\\os2krnld.sym"}, /* custom */
118 NULL
119};
120
121static KRNLOBJTABLE KrnlOTEs = {0};
122
123/* messages */
124static char szBanner[] = "Win32k - Odin32 support driver.";
125static char szMsg1[] = "\n\r\tFound kernel: ";
126static char szMsg1a[] = "\n\r\tBuild: ";
127static char szMsg2[] = "\n\r\n\r\tFound symbolfile: ";
128static char szMsg4[] = "\n\r\tFailed to find symbolfile!\n\r";
129static char szMsgfailed[]= "failed!";
130
131
132/*******************************************************************************
133* Internal Functions *
134*******************************************************************************/
135static void kmemcpy(char *p1, const char *p2, int len);
136static int kstrcmp(const char *p1, const char *p2);
137static int kstrncmp(const char *p1, const char *p2, int len);
138static int kstrlen(const char *p);
139static HFILE fopen(char * filename, char * ignored);
140static int fread(void * pBuffer, USHORT i1, USHORT i2, HFILE hfile);
141static int fseek(HFILE hfile, signed long off, int org);
142static unsigned long fsize(HFILE hFile);
143static void puts(char *psz);
144static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
145
146static int VerifyPrologs(void);
147static int ProbeSymFile(char *pszFilename);
148static int VerifyKernelVer(void);
149static int ReadOS2Krnl(char *filename);
150static int ReadOS2Krnl2(HFILE krnl, unsigned long cbKrnl);
151static int GetKernelOTEs(void);
152
153static void ShowDecNumber(unsigned long n);
154static void ShowHexNumber(unsigned long int n);
155static void ShowResult(int rc, int iSym);
156
157
158
159/**
160 * Quick implementation of fopen.
161 * @param filename name of file to open (sz)
162 * @param ignored whatever - it is ignored
163 * @return Handle to file. (not pointer to a FILE stream as in C-library)
164 * @remark binary and readonly is assumed!
165 */
166static HFILE fopen(char * filename, char * ignored)
167{
168 HFILE hFile = 0;
169 USHORT rc;
170 unsigned short Action = 0;
171
172 rc = DosOpen(
173 filename,
174 &hFile,
175 &Action,
176 0,
177 FILE_NORMAL,
178 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
179 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
180 NULL
181 );
182
183 ignored = ignored;
184 return hFile;
185}
186
187
188/**
189 * fread emulation
190 * @returns Number of blocks read.
191 * @param pBuffer Buffer to read into
192 * @param i1 blocksize
193 * @param i2 block count
194 * @param hFile Handle to file (HFILE)
195 */
196static int fread(void * pBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
197{
198 USHORT ulRead;
199 USHORT rc;
200
201 rc = DosRead(hFile, pBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
202 if (rc == 0)
203 rc = (USHORT)cBlock;
204 else
205 rc = 0;
206
207 return rc;
208}
209
210
211/**
212 * fseek emultation
213 * @returns Same as DosChgFilePtr
214 * @param hFile Filehandle
215 * @param off offset into file from origin
216 * @param org origin
217 */
218static int fseek(HFILE hFile, signed long off, int org)
219{
220 USHORT rc;
221 ULONG ole;
222
223 rc = DosChgFilePtr(hFile, off, org, &ole);
224
225 return rc;
226}
227
228
229/**
230 * Get filesize in bytes.
231 * @returns Filesize.
232 * @param hFile Filehandle
233 * @remark This function sets the file position to end of file.
234 */
235static unsigned long fsize(HFILE hFile)
236{
237 USHORT rc;
238 unsigned long cb;
239
240 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
241
242 return cb;
243}
244
245
246/**
247 * puts lookalike
248 */
249static void puts(char * psz)
250{
251 DosPutMessage(0, kstrlen(psz), psz);
252}
253
254
255/**
256 * kmemcpy - memory copy - slow!
257 * @param p1 target
258 * @param p2 source
259 * @param len length
260 */
261static void kmemcpy(char * p1, const char * p2, int len)
262{
263 while (len != 0)
264 {
265 *p1 = *p2;
266 p1++;
267 p2++;
268 len--;
269 }
270}
271
272#if 0 /* not in use */
273/**
274 * kstrcmp - String compare
275 * @returns 0 - equal else !0
276 * @param p1 String 1
277 * @param p2 String 2
278 */
279static int kstrcmp(const char * p1, const char * p2)
280{
281 while (*p1 == *p2 && *p1 != '\0' && *p2 != '\0')
282 {
283 p1++;
284 p2++;
285 }
286 return *p1 - *p2;
287}
288#endif
289
290/**
291 * kstrncmp - String 'n' compare.
292 * @returns
293 * @returns 0 - equal else !0
294 * @param p1 String 1
295 * @param p2 String 2
296 * @param len length
297 */
298static int kstrncmp(const char * p1, const char * p2, int len)
299{
300 int i = 0;
301 while (i < len && *p1 == *p2 && *p1 != '\0' && *p2 != '\0')
302 {
303 p1++;
304 p2++;
305 i++;
306 }
307
308 return i - len;
309}
310
311
312/**
313 * kstrlen - String length
314 * @returns length of string
315 * @param p Pointer to string
316 */
317static int kstrlen(const char * p)
318{
319 int len = 0;
320 while ( p[len++] != '\0');
321 return len-1;
322}
323
324
325/**
326 * Copy an argument to a buffer. Ie. "-K c:\os2krnl ....". Supports quotes
327 * @returns Number of chars of pszArg that has been processed.
328 * @param pszTarget - pointer to target buffer.
329 * @param pszArg - pointer to source argument string.
330 * @param cchMaxlen - maximum chars to copy.
331 */
332static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
333{
334 int i = 0;
335 int fQuote = FALSE;
336
337 /* skip trailing spaces*/
338 while (*pszArg != '\0' && (*pszArg == ' ' || *pszArg == ':' || *pszArg == '='))
339 {
340 pszArg++;
341 i++;
342 }
343
344 if (*pszArg == '-' || *pszArg == '/' && *pszArg == '\0')
345 return 0;
346
347
348 /* copy maxlen or less */
349 /* check for quotes */
350 if (*pszArg == '"')
351 {
352 fQuote = TRUE;
353 pszArg++;
354 i++;
355 }
356 /* copy loop */
357 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
358 {
359 *pszTarget++ = *pszArg++;
360 i++;
361 cchMaxlen--;
362 }
363
364 /* terminate pszTarget */
365 pszTarget = '\0';
366
367 return i;
368}
369
370
371/**
372 * Verifies the that the addresses in aProcTab are valid.
373 * This is done at Ring-0 of course.
374 * @returns 0 if ok, not 0 if not ok.
375 */
376static int VerifyPrologs(void)
377{
378#ifndef DEBUGR3
379 APIRET rc;
380 HFILE hDev0 = 0;
381 USHORT usAction = 0;
382
383 rc = DosOpen("\\dev\\win32i$", &hDev0, &usAction, 0UL, FILE_NORMAL,
384 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
385 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
386 0UL);
387 if (rc == NO_ERROR)
388 {
389 rc = DosDevIOCtl("", "", D16_IOCTL_VERIFYPROCTAB, D16_IOCTL_CAT, hDev0);
390 DosClose(hDev0);
391 }
392
393 return rc;
394#else
395 return 0;
396#endif
397}
398
399
400/**
401 * Check a symbole file. Searches for the wanted entry-point addresses.
402 * @returns 0 on success - something else on failiure.
403 * @param pszFilename Name of file to probe.
404 * @precond Must be called after kernel-file is found and processed.
405 * @remark Error codes starts at -50.
406 */
407static int ProbeSymFile(char * pszFilename)
408{
409 HFILE SymFile;
410 MAPDEF MapDef;
411 SEGDEF SegDef;
412 SYMDEF32 SymDef32;
413 SYMDEF16 SymDef16;
414 char Buffer[256];
415 unsigned long SymNum;
416 unsigned long SegOffset, SymOffset, SymPtrOffset;
417 unsigned long i;
418 unsigned long ulSegments;
419 int LeftToFind;
420 int rc;
421
422 /* open symbole file */
423 SymFile = fopen(pszFilename, "rb");
424 if (SymFile==0)
425 {
426 dprintf(("Error opening file %s\n", pszFilename));
427 return -50;
428 }
429
430 /* read header and display it */
431 rc = fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
432 if ( rc )
433 {
434 Buffer[0] = MapDef.achModName[0];
435 fread(&Buffer[1], 1, MapDef.cbModName, SymFile);
436 Buffer[MapDef.cbModName] = '\0';
437 dprintf(("*Module name: %s\n", Buffer));
438 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
439 dprintf(("*ppNextMap: 0x%x\n\n", MapDef.ppNextMap ));
440 }
441 else
442 {
443 fclose(SymFile);
444 return -51;
445 }
446
447 /* verify module name */
448 if (MapDef.cbModName == 7 && kstrncmp(Buffer, "OS2KRNL", 7) != 0)
449 {
450 dprintf(("Modulename verify failed\n"));
451 fclose(SymFile);
452 return -51;
453 }
454
455 /* verify correct number of segments */
456 ulSegments = MapDef.cSegs;
457 if (ulSegments != KrnlOTEs.cObjects)
458 {
459 dprintf(("Segment No. verify failed\n"));
460 fclose(SymFile);
461 return -52;
462 }
463
464 SegOffset= SEGDEFOFFSET(MapDef);
465 /* skip to last segment - ASSUMES all imports located in 32-bit code segment. */
466 for (i = 0; i < ulSegments; i++ )
467 {
468 if (fseek(SymFile, SegOffset, SEEK_SET))
469 {
470 fclose(SymFile);
471 return -53;
472 }
473 rc = fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
474 if (i+1 < ulSegments)
475 SegOffset = NEXTSEGDEFOFFSET(SegDef);
476 }
477
478 Buffer[0] = SegDef.achSegName[0];
479 rc = fread(&Buffer[1], 1, SegDef.cbSegName, SymFile);
480
481 /* verify that this is DOSHIGH32CODE */
482 if (SegDef.cbSegName != 13 && kstrncmp(Buffer, "DOSHIGH32CODE", 13) != 0)
483 {
484 dprintf(("DOSHIGH32CODE verify failed \n"));
485 fclose(SymFile);
486 return -54;
487 }
488
489 for (i = 0; i < NUMBER_OF_PROCS; i++)
490 aProcTab[i].fFound = 0 ;
491
492 /* search for the entry-point names */
493 for (LeftToFind = NUMBER_OF_PROCS, SymNum = 0; SymNum < SegDef.cSymbols && LeftToFind; SymNum++)
494 {
495 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
496 rc = fseek(SymFile, SymPtrOffset, SEEK_SET);
497 rc = fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
498 SymOffset &=0xffff;
499 rc = fseek(SymFile, SymOffset+SegOffset, SEEK_SET);
500
501 if (SegDef.bFlags & 0x01)
502 {
503 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
504 Buffer[0] = SymDef32.achSymName[0];
505 rc = fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
506 Buffer[SymDef32.cbSymName] = '\0';
507 } else
508 {
509 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
510 Buffer[0] = SymDef16.achSymName[0];
511 rc = fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
512 Buffer[SymDef16.cbSymName] = '\0';
513 }
514
515 /* search proctable */
516 for (i = 0; i < NUMBER_OF_PROCS; i++)
517 {
518 if (!aProcTab[i].fFound && aProcTab[i].cchName == (SegDef.bFlags & 0x01 ? SymDef32.cbSymName : SymDef16.cbSymName))
519 {
520 if (kstrncmp(aProcTab[i].achName, Buffer, aProcTab[i].cchName) == 0)
521 {
522 aProcTab[i].offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
523 aProcTab[i].ulAddress= aProcTab[i].offObject + KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_base;
524
525 if (aProcTab[i].offObject < KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_size)
526 {
527 aProcTab[i].fFound = TRUE;
528 LeftToFind--;
529 dprintf(("Found: %s at off 0x%lx addr 0x%lx\n", aProcTab[i].achName, aProcTab[i].offObject, aProcTab[i].ulAddress));
530 break;
531 }
532 else
533 {
534 fclose(SymFile);
535 return -56;
536 }
537 }
538 }
539 }
540 }
541
542 fclose(SymFile);
543 return LeftToFind == 0 ? VerifyPrologs() : -57;
544}
545
546
547/**
548 * Verifies that build no, matches kernel number.
549 * @returns 0 on equal, !0 on error.
550 */
551static int VerifyKernelVer(void)
552{
553 int VerMinor, VerMajor;
554
555 VerMajor = ulBuild < 20000 ? 20 : 30/*?*/;
556 VerMinor = ulBuild < 6600 ? 10 : ulBuild < 8000 ? 11 : ulBuild < 9000 ? 30 :
557 ulBuild < 10000 ? 40 : ulBuild < 15000 ? 45 : 50;
558
559 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
560}
561
562
563/**
564 * Reads and verifies OS/2 kernel.
565 * @returns 0 on success, not 0 on failure.
566 * @param filename Filename of the OS/2 kernel.
567 * @result ulBuild is set.
568 */
569static int ReadOS2Krnl(char * filename)
570{
571 HFILE krnl;
572 unsigned long cbKrnl;
573 int rc;
574
575 krnl = fopen(filename, "rb");
576 if (krnl != 0)
577 {
578 cbKrnl = fsize(krnl);
579 if (!fseek(krnl, 0, SEEK_SET))
580 rc = ReadOS2Krnl2(krnl, cbKrnl);
581 else
582 rc = -2;
583 fclose(krnl);
584 }
585 else
586 {
587 dprintf(("Could not open file\n"));
588 rc = -1;
589 }
590 return rc;
591}
592
593/* Worker function for ReadOS2Krnl */
594static int ReadOS2Krnl2(HFILE krnl, unsigned long cbKrnl)
595{
596 int i, j;
597 int rc = 0;
598 char Buffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
599 unsigned long offLXHdr;
600 struct e32_exe *pLXHdr;
601
602
603 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
604 cbKrnl = fsize(krnl);
605 if (fseek(krnl, 0, SEEK_SET))
606 return -2;
607
608 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, krnl))
609 return -3;
610
611 i = KERNEL_ID_STRING_LENGTH;
612 while (cbKrnl > 0)
613 {
614 if (i == KERNEL_READ_SIZE)
615 {
616
617 kmemcpy(Buffer, &Buffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
618 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, krnl))
619 return -3;
620
621 i = 0;
622 }
623
624 if (kstrncmp("@#IBM:", &Buffer[i], 6) == 0)
625 break;
626
627 /* next */
628 i++;
629 cbKrnl--;
630 }
631
632 if (cbKrnl == 0)
633 {
634 fclose(krnl);
635 return -4;
636 }
637
638 /* displacement */
639 j = 0;
640 while (j < 6 && Buffer[i+10+j] != '#')
641 j++;
642
643 /* verify signature */
644 if (kstrncmp(&Buffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
645 return -5;
646
647 /* read ulBuild */
648 ulBuild = (char)(Buffer[i+6] - '0') * 1000;
649 if (Buffer[i+7] != '.')
650 {
651 /* this code is for Warp5 */
652 ulBuild *= 10;
653 ulBuild += (char)(Buffer[i+7] - '0') * 1000;
654 i++;
655 j--;
656 if (Buffer[i+7] != '.')
657 {
658 ulBuild = ulBuild * 10;
659 ulBuild = ulBuild + (unsigned long)(Buffer[i+7] - '0') * 1000;
660 i++;
661 j--;
662 }
663 }
664
665 if (j == 0)
666 {
667 ulBuild += (Buffer[i+ 8] - '0') * 10;
668 ulBuild += (Buffer[i+ 9] - '0') * 1;
669 } else
670 {
671 if (j == 3)
672 return -9;
673 ulBuild += (Buffer[i+ 8] - '0') * 100;
674 ulBuild += (Buffer[i+ 9] - '0') * 10;
675 ulBuild += (Buffer[i+10] - '0');
676 }
677
678 if (VerifyKernelVer())
679 return -9;
680 dprintf(("ulBuild: %d\n",ulBuild));
681
682 /* get segment number */
683 /* read-MZheader */
684 if (fseek(krnl,0,SEEK_SET))
685 return -2;
686
687 if (!fread(Buffer, 1, 0x40, krnl))
688 return -3;
689
690 offLXHdr = *(unsigned long int *)&Buffer[0x3c];
691
692 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
693 return -6;
694
695 if (fseek(krnl, offLXHdr, SEEK_SET))
696 return -2;
697
698 if (!fread(Buffer, 1, sizeof(struct e32_exe), krnl))
699 return -3;
700
701 /* check LX-magic */
702 if (Buffer[0] != 'L' || Buffer[1] != 'X')
703 return -7;
704
705#ifndef DEBUGR3
706 /* check object count - match it with what we got from the kernel. */
707 pLXHdr = (struct e32_exe *)Buffer;
708 if ((UCHAR)pLXHdr->e32_objcnt != KrnlOTEs.cObjects)
709 return -8;
710
711 if (pLXHdr->e32_objcnt < 10)
712 return -9;
713
714 /* check objects (sizes and flags(?)) */
715 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
716 {
717 struct o32_obj *pObj = (struct o32_obj *)Buffer;
718 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
719 {
720 if (!fread(Buffer, 1, sizeof(OTE), krnl))
721 return -11;
722 if (pObj->o32_size < KrnlOTEs.aObjects[i].ote_size)
723 return -12;
724 if ((pObj->o32_flags & 0xffffUL) != (KrnlOTEs.aObjects[i].ote_flags & 0xffffUL))
725 return -14;
726 }
727 }
728 else
729 return -10;
730#else
731 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
732 * we'll use what we find in the kernel.
733 */
734
735 /* object count */
736 pLXHdr = (struct e32_exe *)Buffer;
737 KrnlOTEs.cObjects = (UCHAR)pLXHdr->e32_objcnt;
738
739 /* get OTEs */
740 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
741 {
742 struct o32_obj *pObj = (struct o32_obj *)Buffer;
743 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
744 if (!fread(&KrnlOTEs.aObjects[i], 1, sizeof(struct o32_obj), krnl))
745 return -11;
746 }
747 else
748 return -10;
749#endif
750
751 return 0;
752}
753
754
755/**
756 * Gets the os/2 kernel OTE's (object table entries).
757 * @returns 0 on success. Not 0 on error.
758 */
759static int GetKernelOTEs(void)
760{
761#ifndef DEBUGR3
762 APIRET rc;
763 HFILE hDev0 = 0;
764 USHORT usAction = 0;
765
766 rc = DosOpen("\\dev\\win32i$", &hDev0, &usAction, 0UL, FILE_NORMAL,
767 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
768 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
769 0UL);
770 if (rc == NO_ERROR)
771 {
772 rc = DosDevIOCtl(&KrnlOTEs, "", D16_IOCTL_GETKRNLOTES, D16_IOCTL_CAT, hDev0);
773 DosClose(hDev0);
774 }
775
776 if (rc != NO_ERROR)
777 puts("Failed to get kernel OTEs\r\n");
778
779 return rc;
780#else
781 return 0;
782#endif
783}
784
785
786/**
787 * Displays an ULONG in decimal notation using DosPutMessage
788 * @param n ULONG to show.
789 */
790static void ShowDecNumber(unsigned long n)
791{
792 int f = 0;
793 unsigned long div;
794 char sif;
795
796 for (div = 1000000; div > 0; div /= 10)
797 {
798 sif = (char)(n/div);
799 n %= div;
800 if (sif != 0 || f)
801 {
802 f = 1;
803 sif += '0';
804 DosPutMessage(0, 1, &sif);
805 }
806 }
807}
808
809
810/**
811 * Displays an ULONG in hexadecimal notation using DosPutMessage
812 * @param n ULONG to show.
813 */
814static void ShowHexNumber(unsigned long int n)
815{
816 signed int div;
817 char sif;
818 DosPutMessage(0, 2, "0x");
819 for (div = 28; div >= 0; div -= 4)
820 {
821 sif = (char)(n >> div) & (char)0xF;
822 sif += (sif < 10 ? '0' : 'a' - 10);
823 DosPutMessage(0, 1, &sif);
824 }
825}
826
827
828
829/**
830 * Shows result of kernelprobing if not quiet or on error.
831 * @param rc Return code.
832 * @param iSym index of .sym-file into static struct.
833 */
834static void ShowResult(int rc, int iSym)
835{
836 int i, j;
837
838 /* complain even if quiet on error */
839 if (!fQuiet || rc != 0)
840 {
841 puts(szBanner);
842
843 /* kernel stuff */
844 puts(szMsg1);
845 if (rc <= -50 || rc == 0)
846 {
847 puts(szOS2Krnl);
848 puts(szMsg1a);
849 ShowDecNumber(ulBuild);
850 puts(" - v");
851 ShowDecNumber(usVerMajor);
852 puts(".");
853 ShowDecNumber(usVerMinor);
854 }
855 else
856 puts(szMsgfailed);
857
858 /* functions */
859 if (rc > -50)
860 {
861 puts(szMsg2);
862 if (szUsrSym[0] == '\0')
863 puts(apszSym[iSym]);
864 else
865 puts(szUsrSym);
866
867 for (i = 0; i < NUMBER_OF_PROCS; i++)
868 {
869 puts("\n\r\t");
870 puts(aProcTab[i].achName);
871 for (j = aProcTab[i].cchName; j < 17; j++)
872 puts(" ");
873
874 puts(" at ");
875 if (aProcTab[i].fFound)
876 ShowHexNumber(aProcTab[i].ulAddress);
877 else
878 puts(szMsgfailed);
879 }
880 }
881 else
882 puts(szMsg4);
883 puts("\n\r");
884 }
885
886 /* if error: write rc */
887 if (rc != 0)
888 {
889 puts("rc = ");
890 ShowHexNumber((unsigned long)rc);
891 puts("\n\r");
892 }
893}
894
895
896
897/**
898 * "main" function.
899 * @returns 0 on success, something else on error.
900 * @param pReqPack Pointer to init request packet
901 * @remark
902 * @result init_success
903 */
904int ProbeKernel(PRPINITIN pReqPack)
905{
906 int rc;
907 int i;
908 int n;
909 SEL GDT;
910 SEL LDT;
911 PGINFOSEG pInfoSeg;
912 USHORT usBootDrive;
913
914 /*----------------*/
915 /* parse InitArgs */
916 /*----------------*/
917 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
918 {
919 n = kstrlen(pReqPack->InitArgs);
920 for (i = 0; i < n; i++)
921 {
922 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
923 {
924 i++;
925 if (pReqPack->InitArgs[i] == 'V' || pReqPack->InitArgs[i] == 'v')
926 fQuiet = 0;
927 else if (pReqPack->InitArgs[i] == 'Q' || pReqPack->InitArgs[i] == 'q')
928 fQuiet = 1;
929 else if (pReqPack->InitArgs[i] == 'K' || pReqPack->InitArgs[i] == 'k')
930 { /* kernel file */
931 i++;
932 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
933 }
934 else if (pReqPack->InitArgs[i] == 'S' || pReqPack->InitArgs[i] == 's')
935 { /* symbol file */
936 i++;
937 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
938 }
939 }
940 }
941 }
942
943 /*---------------------*/
944 /* determin boot drive */
945 /*---------------------*/
946 rc = DosGetInfoSeg(&GDT, &LDT);
947 if (rc != NO_ERROR)
948 return rc;
949
950 pInfoSeg = MAKEPGINFOSEG(GDT);
951 usBootDrive = pInfoSeg->bootdrive;
952 usVerMajor = pInfoSeg->uchMajorVersion;
953 usVerMinor = pInfoSeg->uchMinorVersion;
954 dprintf(("BootDrive: %d\n", usBootDrive));
955
956 /* set driveletter in constants strings */
957 usBootDrive = (char)usBootDrive + (char)'a' - 1;
958 szOS2Krnl[0] = (char)usBootDrive;
959 for (i = 0; apszSym[i] != NULL; i++)
960 apszSym[i][0] = (char)usBootDrive;
961
962 /*-----------------*/
963 /* get kernel OTEs */
964 /*-----------------*/
965 rc = GetKernelOTEs();
966 if (rc != NO_ERROR)
967 return rc;
968
969 /*--------------*/
970 /* read kernel */
971 /*--------------*/
972 if (szUsrOS2Krnl[0] != '\0')
973 {
974 rc = ReadOS2Krnl(szUsrOS2Krnl);
975 if (rc != 0)
976 {
977 puts("Warning: Invalid kernel file specified. Tries defaults.\n\r");
978 szUsrOS2Krnl[0] = '\0';
979 rc = ReadOS2Krnl(szOS2Krnl);
980 }
981 }
982 else
983 rc = ReadOS2Krnl(szOS2Krnl);
984
985 /*--------------*/
986 /* read symfile */
987 /*--------------*/
988 if (!rc)
989 {
990 rc = 1;
991 if (szUsrSym[0] != '\0')
992 {
993 rc = ProbeSymFile(szUsrSym);
994 if (rc)
995 {
996 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
997 szUsrSym[0] = '\0';
998 }
999 }
1000 if (rc != 0) /* if user sym failed or don't exists */
1001 {
1002 i = 0;
1003 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1004 i++;
1005 }
1006 }
1007
1008 /* show the result and set return-value */
1009 dprintf(("rc=%d; i=%d\n", rc, i));
1010 ShowResult(rc, i);
1011 fInitSuccess = rc = 0;
1012
1013 return rc;
1014}
1015
1016
1017
1018#ifdef DEBUGR3
1019/**
1020 * Debug - Main procedure for standalone testing.
1021 */
1022void main(int argc, char **argv)
1023{
1024 char szParm[512];
1025 RPINITIN ReqPack;
1026 int j;
1027 int i = 0;
1028 int argi = 0;
1029
1030 while (argi < argc)
1031 {
1032 j = 0;
1033 while (argv[argi][j] != '\0')
1034 szParm[i++] = argv[argi][j++];
1035 szParm[i++] = ' ';
1036
1037 /* next */
1038 argi++;
1039 }
1040 szParm[i++] = '\0';
1041
1042 ReqPack.InitArgs = szParm;
1043
1044 ProbeKernel(&ReqPack);
1045}
1046
1047#endif
1048
Note: See TracBrowser for help on using the repository browser.