441 lines
12 KiB
C
441 lines
12 KiB
C
|
#include "kernel.h"
|
||
|
|
||
|
#define WINAPI _far _pascal _loadds
|
||
|
typedef unsigned int UINT;
|
||
|
typedef const char _far* LPCSTR;
|
||
|
typedef HANDLE HTASK;
|
||
|
|
||
|
#include "logerror.h"
|
||
|
|
||
|
int WINAPI FatalExitC(WORD);
|
||
|
void WINAPI OutputDebugString(LPCSTR);
|
||
|
|
||
|
void DebugLogParamError(VOID FAR* param, FARPROC lpfn, WORD err);
|
||
|
void DebugLogError(WORD err, VOID FAR* lpInfo);
|
||
|
int WINAPI GetOwnerName(WORD sel, char far *buf, WORD buflen);
|
||
|
int WINAPI FarGetOwner(WORD sel);
|
||
|
|
||
|
#define CODESEG _based(_segname("_CODE"))
|
||
|
|
||
|
#define SELECTOROF(lp) HIWORD(lp)
|
||
|
#define OFFSETOF(lp) LOWORD((DWORD)lp)
|
||
|
#define MAKELONG(a, b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))
|
||
|
#define MAKELP(sel, off) ((VOID FAR *)MAKELONG(off, sel))
|
||
|
|
||
|
#if KDEBUG
|
||
|
|
||
|
UINT DebugOptions = 0;
|
||
|
UINT DebugFilter = 0;
|
||
|
|
||
|
#define FMT_WORD 0
|
||
|
#define FMT_DWORD 1
|
||
|
#define FMT_LP 2
|
||
|
|
||
|
struct TYPEMAP
|
||
|
{
|
||
|
UINT err;
|
||
|
char CODESEG* szType; // Compiler bug: this can't be _based
|
||
|
char CODESEG* szFmt;
|
||
|
};
|
||
|
|
||
|
static char CODESEG szParam[] = "parameter";
|
||
|
static char CODESEG szD16[] = "%s: Invalid %s: %d\r\n";
|
||
|
static char CODESEG szD32[] = "%s: Invalid %s: %ld\r\n";
|
||
|
static char CODESEG szX16[] = "%s: Invalid %s: %#04x\r\n";
|
||
|
static char CODESEG szX32[] = "%s: Invalid %s: %#08lx\r\n";
|
||
|
static char CODESEG szLP[] = "%s: Invalid %s: %#04x:%#04x\r\n";
|
||
|
|
||
|
static char CODESEG sz_value[] = "value";
|
||
|
static char CODESEG sz_index[] = "index";
|
||
|
static char CODESEG sz_flags[] = "flags";
|
||
|
static char CODESEG sz_selector[] = "selector";
|
||
|
static char CODESEG sz_pointer[] = "pointer";
|
||
|
static char CODESEG sz_function_pointer [] = "function pointer";
|
||
|
static char CODESEG sz_string_pointer [] = "string pointer";
|
||
|
static char CODESEG sz_HINSTANCE[] = "HINSTANCE";
|
||
|
static char CODESEG sz_HMODULE[] = "HMODULE";
|
||
|
static char CODESEG sz_global_handle [] = "global handle";
|
||
|
static char CODESEG sz_local_handle [] = "local handle";
|
||
|
static char CODESEG sz_atom[] = "atom";
|
||
|
static char CODESEG sz_HWND[] = "HWND";
|
||
|
static char CODESEG sz_HMENU[] = "HMENU";
|
||
|
static char CODESEG sz_HCURSOR[] = "HCURSOR";
|
||
|
static char CODESEG sz_HICON[] = "HICON";
|
||
|
static char CODESEG sz_HGDIOBJ[] = "HGDIOBJ";
|
||
|
static char CODESEG sz_HDC[] = "HDC";
|
||
|
static char CODESEG sz_HPEN[] = "HPEN";
|
||
|
static char CODESEG sz_HFONT[] = "HFONT";
|
||
|
static char CODESEG sz_HBRUSH[] = "HBRUSH";
|
||
|
static char CODESEG sz_HBITMAP[] = "HBITMAP";
|
||
|
static char CODESEG sz_HRGN[] = "HRGN";
|
||
|
static char CODESEG sz_HPALETTE[] = "HPALETTE";
|
||
|
static char CODESEG sz_HANDLE[] = "HANDLE";
|
||
|
static char CODESEG sz_HFILE[] = "HFILE";
|
||
|
static char CODESEG sz_HMETAFILE[] = "HMETAFILE";
|
||
|
static char CODESEG sz_CID[] = "CID";
|
||
|
static char CODESEG sz_HDRVR[] = "HDRVR";
|
||
|
static char CODESEG sz_HDWP[] = "HDWP";
|
||
|
|
||
|
static char CODESEG*pszLP = szLP;
|
||
|
static char CODESEG*pszD32 = szD32;
|
||
|
static char CODESEG*pszX32 = szX32;
|
||
|
|
||
|
#define DEFMAP(err, type, fmt) \
|
||
|
{ err, type, fmt }
|
||
|
struct TYPEMAP CODESEG typemap[] =
|
||
|
{
|
||
|
DEFMAP(ERR_BAD_VALUE, sz_value, szD16),
|
||
|
DEFMAP(ERR_BAD_INDEX, sz_index, szD16),
|
||
|
DEFMAP(ERR_BAD_FLAGS, sz_flags, szX16),
|
||
|
DEFMAP(ERR_BAD_SELECTOR, sz_selector, szX16),
|
||
|
DEFMAP(ERR_BAD_DFLAGS, sz_flags, szX32),
|
||
|
DEFMAP(ERR_BAD_DVALUE, sz_value, szD32),
|
||
|
DEFMAP(ERR_BAD_DINDEX, sz_index, szD32),
|
||
|
DEFMAP(ERR_BAD_PTR, sz_pointer, szLP),
|
||
|
DEFMAP(ERR_BAD_FUNC_PTR, sz_function_pointer, szLP),
|
||
|
DEFMAP(ERR_BAD_STRING_PTR, sz_string_pointer, szLP),
|
||
|
DEFMAP(ERR_BAD_HINSTANCE, sz_HINSTANCE, szX16),
|
||
|
DEFMAP(ERR_BAD_HMODULE, sz_HMODULE, szX16),
|
||
|
DEFMAP(ERR_BAD_GLOBAL_HANDLE,sz_global_handle, szX16),
|
||
|
DEFMAP(ERR_BAD_LOCAL_HANDLE, sz_local_handle, szX16),
|
||
|
DEFMAP(ERR_BAD_ATOM, sz_atom, szX16),
|
||
|
DEFMAP(ERR_BAD_HWND, sz_HWND, szX16),
|
||
|
DEFMAP(ERR_BAD_HMENU, sz_HMENU, szX16),
|
||
|
DEFMAP(ERR_BAD_HCURSOR, sz_HCURSOR, szX16),
|
||
|
DEFMAP(ERR_BAD_HICON, sz_HICON, szX16),
|
||
|
DEFMAP(ERR_BAD_GDI_OBJECT, sz_HGDIOBJ, szX16),
|
||
|
DEFMAP(ERR_BAD_HDC, sz_HDC, szX16),
|
||
|
DEFMAP(ERR_BAD_HPEN, sz_HPEN, szX16),
|
||
|
DEFMAP(ERR_BAD_HFONT, sz_HFONT, szX16),
|
||
|
DEFMAP(ERR_BAD_HBRUSH, sz_HBRUSH, szX16),
|
||
|
DEFMAP(ERR_BAD_HBITMAP, sz_HBITMAP, szX16),
|
||
|
DEFMAP(ERR_BAD_HRGN, sz_HRGN, szX16),
|
||
|
DEFMAP(ERR_BAD_HPALETTE, sz_HPALETTE, szX16),
|
||
|
DEFMAP(ERR_BAD_HANDLE, sz_HANDLE, szX16),
|
||
|
DEFMAP(ERR_BAD_HFILE, sz_HFILE, szX16),
|
||
|
DEFMAP(ERR_BAD_HMETAFILE, sz_HMETAFILE, szX16),
|
||
|
DEFMAP(ERR_BAD_CID, sz_CID, szX16),
|
||
|
DEFMAP(ERR_BAD_HDRVR, sz_HDRVR, szX16),
|
||
|
DEFMAP(ERR_BAD_HDWP, sz_HDWP, szX16)
|
||
|
};
|
||
|
|
||
|
int (_cdecl _far *wsprintf)(LPSTR, LPCSTR, ...) = NULL;
|
||
|
int (WINAPI *wvsprintf)(LPSTR lpszOut, LPCSTR lpszFmt, const void FAR* lpParams) = NULL;
|
||
|
|
||
|
#define ORD_WSPRINTF 420
|
||
|
#define ORD_WVSPRINTF 421
|
||
|
|
||
|
BOOL _fastcall LoadWsprintf(void)
|
||
|
{
|
||
|
static char CODESEG rgchUSER[] = "USER";
|
||
|
|
||
|
HANDLE hmod;
|
||
|
|
||
|
hmod = GetModuleHandle(rgchUSER);
|
||
|
|
||
|
if (!hmod)
|
||
|
return FALSE;
|
||
|
|
||
|
(FARPROC)wsprintf = GetProcAddress(hmod, MAKELP(NULL, ORD_WSPRINTF));
|
||
|
(FARPROC)wvsprintf = GetProcAddress(hmod, MAKELP(NULL, ORD_WVSPRINTF));
|
||
|
|
||
|
if (!SELECTOROF(wsprintf))
|
||
|
{
|
||
|
static char CODESEG rgch[] = "KERNEL: Can't call wsprintf: USER not initialized\r\n";
|
||
|
OutputDebugString(rgch);
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
UINT flags;
|
||
|
LPCSTR lpszFmt;
|
||
|
WORD args[1];
|
||
|
} DOPARAMS;
|
||
|
|
||
|
#define BUFFERSLOP 32
|
||
|
|
||
|
BOOL DebugOutput2(DOPARAMS FAR* pparams)
|
||
|
{
|
||
|
UINT flags = pparams->flags;
|
||
|
BOOL fBreak = FALSE;
|
||
|
BOOL fPrint = TRUE;
|
||
|
char rgch[80*2 + BUFFERSLOP]; // max 2 lines (don't want to hog too much stack space)
|
||
|
static char CODESEG szCRLF[] = "\r\n";
|
||
|
char far *prefix, far *prefix1;
|
||
|
|
||
|
switch (flags & DBF_SEVMASK)
|
||
|
{
|
||
|
case DBF_TRACE:
|
||
|
// If the flags don't match the debug filter,
|
||
|
// don't print the trace message.
|
||
|
// If the trace matches the filter, check for TRACEBREAK.
|
||
|
//
|
||
|
prefix = "t ";
|
||
|
if (!((flags & DBF_FILTERMASK) & DebugFilter))
|
||
|
fPrint = FALSE;
|
||
|
else if (DebugOptions & DBO_TRACEBREAK)
|
||
|
fBreak = TRUE;
|
||
|
break;
|
||
|
|
||
|
case DBF_WARNING:
|
||
|
prefix = "wn ";
|
||
|
if (DebugOptions & DBO_WARNINGBREAK)
|
||
|
fBreak = TRUE;
|
||
|
break;
|
||
|
|
||
|
case DBF_ERROR:
|
||
|
prefix = "err ";
|
||
|
if (!(DebugOptions & DBO_NOERRORBREAK))
|
||
|
fBreak = TRUE;
|
||
|
break;
|
||
|
|
||
|
case DBF_FATAL:
|
||
|
prefix = "fatl ";
|
||
|
if (!(DebugOptions & DBO_NOFATALBREAK))
|
||
|
fBreak = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If DBO_SILENT is specified, don't print anything.
|
||
|
//
|
||
|
if (DebugOptions & DBO_SILENT)
|
||
|
fPrint = FALSE;
|
||
|
|
||
|
if ((lstrlen((LPSTR)pparams->lpszFmt) <= sizeof(rgch) - BUFFERSLOP) &&
|
||
|
(SELECTOROF(wsprintf) || LoadWsprintf()) && (fPrint || fBreak))
|
||
|
{
|
||
|
int hinst = HIWORD(pparams);
|
||
|
|
||
|
for (prefix1 = rgch; *prefix; ) *prefix1++ = *prefix++;
|
||
|
prefix1 += GetOwnerName(hinst, prefix1, 16);
|
||
|
*prefix1++ = ' ';
|
||
|
wvsprintf(prefix1, pparams->lpszFmt, (void FAR*)pparams->args);
|
||
|
OutputDebugString(rgch);
|
||
|
OutputDebugString(szCRLF);
|
||
|
}
|
||
|
|
||
|
if (fBreak)
|
||
|
{
|
||
|
// If we are supposed to break with an int 3, then return TRUE.
|
||
|
//
|
||
|
if (DebugOptions & DBO_INT3BREAK)
|
||
|
return TRUE;
|
||
|
|
||
|
return FatalExitC(flags);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL LogParamError2(WORD err, FARPROC lpfn, VOID FAR* param, WORD caller)
|
||
|
{
|
||
|
BOOL fBreak;
|
||
|
|
||
|
fBreak = FALSE;
|
||
|
if (err & ERR_WARNING)
|
||
|
{
|
||
|
if (DebugOptions & DBO_WARNINGBREAK)
|
||
|
fBreak = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!(DebugOptions & DBO_NOERRORBREAK))
|
||
|
fBreak = TRUE;
|
||
|
}
|
||
|
|
||
|
// If we're not breaking and SILENT is specified, just return.
|
||
|
//
|
||
|
if (!fBreak && (DebugOptions & DBO_SILENT))
|
||
|
return FALSE;
|
||
|
|
||
|
if (SELECTOROF(wsprintf) || LoadWsprintf())
|
||
|
{
|
||
|
char rgch[128];
|
||
|
char rgchProcName[50], far *rpn;
|
||
|
char CODESEG* pszType; // compiler bug: see above
|
||
|
char CODESEG* pszFmt;
|
||
|
int i, hinst;
|
||
|
WORD errT;
|
||
|
void FAR GetProcName(FARPROC lpfn, LPSTR lpch, int cch);
|
||
|
char far *prefix1;
|
||
|
|
||
|
GetProcName(lpfn, rgchProcName, sizeof(rgchProcName));
|
||
|
/* if we got a real proc name, then copy just the proc name */
|
||
|
for (rpn = rgchProcName; *rpn && (*rpn != '(') && (*rpn != ':'); rpn++)
|
||
|
;
|
||
|
if (*rpn == ':') {
|
||
|
lstrcpy(rgchProcName, rpn+1);
|
||
|
}
|
||
|
|
||
|
pszFmt = szX32;
|
||
|
pszType = szParam;
|
||
|
errT = (err & ~ERR_WARNING);
|
||
|
for (i = 0; i < (sizeof(typemap) / sizeof(struct TYPEMAP)); i++)
|
||
|
{
|
||
|
if (typemap[i].err == errT)
|
||
|
{
|
||
|
pszFmt = typemap[i].szFmt;
|
||
|
pszType = typemap[i].szType;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (err & ERR_WARNING) {
|
||
|
lstrcpy(rgch, "wn ");
|
||
|
prefix1 = rgch+3;
|
||
|
} else {
|
||
|
lstrcpy(rgch, "err ");
|
||
|
prefix1 = rgch+4;
|
||
|
}
|
||
|
hinst = HIWORD(prefix1);
|
||
|
prefix1 += GetOwnerName(hinst, prefix1, 16);
|
||
|
if (FarGetOwner(hinst) != FarGetOwner(caller)) {
|
||
|
*prefix1++ = '-';
|
||
|
*prefix1++ = '>';
|
||
|
prefix1 += GetOwnerName(caller, prefix1, 16);
|
||
|
}
|
||
|
*prefix1++ = ' ';
|
||
|
|
||
|
if (pszFmt == pszLP)
|
||
|
wsprintf(prefix1, pszFmt, (LPSTR)rgchProcName, (LPSTR)pszType, SELECTOROF(param), OFFSETOF(param));
|
||
|
else if (pszFmt == pszD32 || pszFmt == pszX32)
|
||
|
wsprintf(prefix1, pszFmt, (LPSTR)rgchProcName, (LPSTR)pszType, (DWORD)param);
|
||
|
else
|
||
|
wsprintf(prefix1, pszFmt, (LPSTR)rgchProcName, (LPSTR)pszType, (WORD)(DWORD)param);
|
||
|
|
||
|
OutputDebugString(rgch);
|
||
|
}
|
||
|
|
||
|
if (fBreak)
|
||
|
{
|
||
|
// If we are supposed to break with an int 3, then return TRUE.
|
||
|
//
|
||
|
if (DebugOptions & DBO_INT3BREAK)
|
||
|
return TRUE;
|
||
|
|
||
|
return FatalExitC(err);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
extern HTASK allocTask;
|
||
|
extern DWORD allocCount;
|
||
|
extern DWORD allocBreak;
|
||
|
extern char allocModName[8];
|
||
|
|
||
|
void FAR _loadds SetupAllocBreak(HTASK htask);
|
||
|
char far* GetTaskModNamePtr(HTASK htask);
|
||
|
|
||
|
BOOL WINAPI IGetWinDebugInfo(WINDEBUGINFO FAR* lpwdi, UINT flags)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
lpwdi->flags = flags;
|
||
|
|
||
|
if (flags & WDI_OPTIONS)
|
||
|
lpwdi->dwOptions = DebugOptions;
|
||
|
|
||
|
if (flags & WDI_FILTER)
|
||
|
lpwdi->dwFilter = DebugFilter;
|
||
|
|
||
|
if (flags & WDI_ALLOCBREAK)
|
||
|
{
|
||
|
lpwdi->dwAllocBreak = allocBreak;
|
||
|
lpwdi->dwAllocCount = allocCount;
|
||
|
for (i = 0; i < 8; i++)
|
||
|
lpwdi->achAllocModule[i] = allocModName[i];
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI ISetWinDebugInfo(const WINDEBUGINFO FAR* lpwdi)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (lpwdi->flags & WDI_OPTIONS)
|
||
|
DebugOptions = (UINT)lpwdi->dwOptions;
|
||
|
|
||
|
if (lpwdi->flags & WDI_FILTER)
|
||
|
DebugFilter = (UINT)lpwdi->dwFilter;
|
||
|
|
||
|
if (lpwdi->flags & WDI_ALLOCBREAK)
|
||
|
{
|
||
|
allocTask = NULL;
|
||
|
allocBreak = lpwdi->dwAllocBreak;
|
||
|
allocCount = 0; // Always reset count to 0.
|
||
|
|
||
|
for (i = 0; i < 8; i++)
|
||
|
allocModName[i] = lpwdi->achAllocModule[i];
|
||
|
|
||
|
{
|
||
|
extern HTASK headTDB;
|
||
|
HTASK htask;
|
||
|
|
||
|
// Enumerate all current tasks to see if any match
|
||
|
//
|
||
|
#define TDB_next 0
|
||
|
for (htask = headTDB; htask; htask = *((HTASK FAR*)MAKELP(htask, TDB_next)))
|
||
|
SetupAllocBreak(htask);
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void FAR _loadds SetupAllocBreak(HTASK htask)
|
||
|
{
|
||
|
int i;
|
||
|
char far* pchAlloc;
|
||
|
char far* pchTask;
|
||
|
|
||
|
// If alloc break task already set up, exit.
|
||
|
//
|
||
|
if (allocTask)
|
||
|
return;
|
||
|
|
||
|
// If no alloc break in effect, nothing to do.
|
||
|
//
|
||
|
if (allocModName[0] == 0)
|
||
|
return;
|
||
|
|
||
|
pchAlloc = allocModName;
|
||
|
pchTask = GetTaskModNamePtr(htask);
|
||
|
|
||
|
for (i = 8; --i != 0; pchAlloc++, pchTask++)
|
||
|
{
|
||
|
char ch1 = *pchAlloc;
|
||
|
char ch2 = *pchTask;
|
||
|
|
||
|
if (ch1 >= 'a' && ch1 <= 'z')
|
||
|
ch1 -= ('a' - 'A');
|
||
|
|
||
|
if (ch2 >= 'a' && ch2 <= 'z')
|
||
|
ch2 -= ('a' - 'A');
|
||
|
|
||
|
if (ch1 != ch2)
|
||
|
return;
|
||
|
|
||
|
if (ch1 == 0 || ch2 == 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Set the alloc break task, and init the count to 0.
|
||
|
//
|
||
|
allocTask = htask;
|
||
|
allocCount = 0;
|
||
|
}
|
||
|
|
||
|
#else // !KDEBUG
|
||
|
|
||
|
BOOL WINAPI GetWinDebugInfo(WINDEBUGINFO FAR* lpwdi, UINT flags)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI SetWinDebugInfo(const WINDEBUGINFO FAR* lpwdi)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#endif // !KDEBUG
|