#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <os/os.h>
#include <os/pe.h>
#include <os/console.h>
wchar_t *_getws(wchar_t *buffer)
{
wchar_t* ch = buffer;
while (true)
{
*ch = _wgetch();
switch (*ch)
{
case 0:
break;
case L'\n':
*ch = 0;
putwchar(L'\n');
return buffer;
case L'\b':
if (ch > buffer)
{
_cputws(L"\b \b");
ch--;
}
break;
default:
putwchar(*ch);
ch++;
}
}
}
#if 0
typedef struct exception_pointers_t exception_pointers_t;
struct exception_pointers_t
{
exception_info_t* info;
context_t* ctx;
};
// Data structure(s) pointed to by Visual C++ extended exception frame
struct scopetable_entry
{
dword previousTryLevel;
void* lpfnFilter;
void* lpfnHandler;
};
typedef struct exception_registration_vc_t exception_registration_vc_t;
struct exception_registration_vc_t
{
exception_registration_t reg;
struct scopetable_entry *scopetable;
int trylevel;
int _ebp;
exception_pointers_t* xpointers;
};
#define TRYLEVEL_NONE 0xffffffff
#define EXCEPTION_CONTINUE_EXECUTION -1
#define EXCEPTION_CONTINUE_SEARCH 0
#define EXCEPTION_EXECUTE_HANDLER 1
// The extended exception frame used by Visual C++
struct VC_EXCEPTION_REGISTRATION
{
exception_registration_t reg;
struct scopetable_entry * scopetable;
int trylevel;
int _ebp;
};
ExceptionDisposition _except_handler3(
exception_info_t *ExceptionRecord,
void * EstablisherFrame,
context_t *ContextRecord,
void * DispatcherContext);
//----------------------------------------------------------------------------
// Code
//----------------------------------------------------------------------------
//
// Display the information in one exception frame, along with its scopetable
//
void ShowSEHFrame( struct VC_EXCEPTION_REGISTRATION * pVCExcRec )
{
struct scopetable_entry * pScopeTableEntry = pVCExcRec->scopetable;
int i;
wprintf( L"Frame: %08X Handler: %08X Prev: %08X Scopetable: %08X\n",
pVCExcRec, pVCExcRec->reg.handler, pVCExcRec->reg.prev,
pVCExcRec->scopetable );
for (i = 0; i <= pVCExcRec->trylevel; i++ )
{
wprintf( L" scopetable[%u] PrevTryLevel: %08X "
L"filter: %08X __except: %08X\n", i,
pScopeTableEntry->previousTryLevel,
pScopeTableEntry->lpfnFilter,
pScopeTableEntry->lpfnHandler );
pScopeTableEntry++;
}
//wprintf( L"\n" );
}
//
// Walk the linked list of frames, displaying each in turn
//
void WalkSEHFrames( void )
{
struct VC_EXCEPTION_REGISTRATION * pVCExcRec;
// Print out the location of the __except_handler3 function
wprintf( L"_except_handler3 is at address: %08X\n", _except_handler3 );
//wprintf( L"\n" );
// Get a pointer to the head of the chain at FS:[0]
asm("mov %%fs(0), %%eax" : "=a" (pVCExcRec));
// Walk the linked list of frames. 0xFFFFFFFF indicates the end of list
while ( NULL != pVCExcRec )
{
ShowSEHFrame( pVCExcRec );
pVCExcRec = (struct VC_EXCEPTION_REGISTRATION *)(pVCExcRec->reg.prev);
}
}
ExceptionDisposition _except_handler3(
exception_info_t *ExceptionRecord,
void * EstablisherFrame,
context_t *ContextRecord,
void * DispatcherContext)
{
struct VC_EXCEPTION_REGISTRATION * pVCExcRec;
unsigned tryLevel, temp;
int val;
dword func;
exception_pointers_t exceptPtrs;
wprintf(L"Exception: %08x at %08x\n", ExceptionRecord->code, ExceptionRecord->address);
//WalkSEHFrames();
// Build the EXCEPTION_POINTERS structure on the stack
exceptPtrs.info = ExceptionRecord;
exceptPtrs.ctx = ContextRecord;
// Get a pointer to the head of the chain at FS:[0]
//__asm mov eax, FS:[0]
//__asm mov [pVCExcRec], EAX
pVCExcRec = (struct VC_EXCEPTION_REGISTRATION*) EstablisherFrame;
// Put the pointer to the EXCEPTION_POINTERS 4 bytes below the
// establisher frame. See ASM code for GetExceptionInformation
*(dword*)((byte*)pVCExcRec - 4) = (dword) &exceptPtrs;
tryLevel = pVCExcRec->trylevel;
while (tryLevel != -1)
{
temp = pVCExcRec->_ebp;
func = (dword) pVCExcRec->scopetable[tryLevel].lpfnFilter;
wprintf(L"tryLevel = %d, ebp = %x, filter = %x\n",
tryLevel, temp, func);
__asm
{
mov eax, func
push ebp
mov ebp, temp
call eax
pop ebp
mov val, eax
}
switch (val)
{
case EXCEPTION_CONTINUE_SEARCH:
wprintf(L"Continue search\n");
break;
case EXCEPTION_EXECUTE_HANDLER:
func = (dword) pVCExcRec->scopetable[tryLevel].lpfnHandler;
wprintf(L"Execute handler = %x, ebp = %x, esp = %x\n",
func, temp, ((dword*) temp)[-0x18]);
__asm
{
mov eax, func
push ebp
mov ebp, temp
call eax
pop ebp
}
wprintf(L"Returned\n");
break;
case EXCEPTION_CONTINUE_EXECUTION:
wprintf(L"Continue execution\n");
return ExceptionContinueExecution;
}
//pVCExcRec = (struct VC_EXCEPTION_REGISTRATION *)(pVCExcRec->reg.prev);
tryLevel = pVCExcRec->scopetable[tryLevel].previousTryLevel;
}
wprintf(L"Returning\n");
return ExceptionContinueSearch;
}
#endif
int main()
{
wchar_t buf[256], args[256], *ch;
addr_t proc;
bool async;
if (resLoadString(procBase(), 1, buf, countof(buf)))
_cputws(buf);
while (true)
{
wprintf(L"[%s] ", thrGetInfo()->process->cwd);
if (*_getws(buf))
{
ch = wcschr(buf, ' ');
if (ch)
{
size_t len;
wcscpy(args, ch + 1);
*ch = '\0';
len = wcslen(args);
if (args[len - 1] == '&')
{
args[len - 1] = 0;
async = true;
}
else
async = false;
}
else
{
args[0] = '\0';
async = false;
}
//for (i = 0; i < 800; i++)
{
//wprintf(L"%3d\t", i);
if (wcsicmp(buf, L"exit") == 0)
break;
else if (wcsicmp(buf, L"cd") == 0)
wcscpy(thrGetInfo()->process->cwd, args);
else if (wcsicmp(buf, L"break") == 0)
asm("int3");
else
{
if (!(proc = procLoad(buf, args, 16, NULL, NULL)))
{
wcscat(buf, L".exe");
if (!(proc = procLoad(buf, args, 16, NULL, NULL)))
{
wprintf(L"%s: not found\n", buf);
continue;
}
}
if (!async)
thrWaitHandle(&proc, 1, false);
}
}
}
}
return 0;
}