#include <9pm/windows.h>
#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/thread.h>
#include <9pm/ns.h>
#include <9pm/syscall.h>
static HWND window;
static LRESULT CALLBACK SyscallProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static HANDLE me;
void
threadmain(int argc, char **argv)
{
WNDCLASS wc;
HANDLE inst;
MSG msg;
threadprint(1, "hello world\n");
inst = GetModuleHandle(nil);
wc.style = 0;
wc.lpfnWndProc = SyscallProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = inst;
wc.hIcon = LoadIcon(inst, nil);
wc.hCursor = LoadCursor(nil, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"Plan 9 Kernel";
RegisterClass(&wc);
me = GetCurrentProcess();
window = CreateWindowEx(
WS_EX_TOOLWINDOW,
L"Plan 9 Kernel",
L"Plan 9 Kernel",
WS_OVERLAPPEDWINDOW|
WS_MINIMIZE|WS_DISABLED,
CW_USEDEFAULT,
CW_USEDEFAULT,
100,
100,
NULL,
NULL,
inst,
NULL
);
if(window == nil){
oserror();
sysfatal("can't allocate window: %r");
}
dprint(~0, "allocated window\n");
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
threadexits(nil);
}
DWORD WINAPI
SyscallThread(void *arg)
{
int i;
HANDLE harr[2];
Handles *h;
int status;
ulong *call;
h = arg;
harr[0] = h->hserversig;
harr[1] = h->hclientproc;
call = (ulong*)&h[2];
threadprint(1, "waiting\n");
for(;;){
i = WaitForMultipleObjects(2, harr, 0, INFINITE);
switch(i){
case WAIT_OBJECT_0:
threadprint(1, "Got call %d\n", *call);
*(call+1) = 67890;
Sleep(10000);
threadprint(1, "Releasing semaphore\n");
ReleaseSemaphore(h->hclientsig, 1, nil);
break;
case WAIT_OBJECT_0+1:
if(!GetExitCodeProcess(h->hclientproc, &status)){
threadprint(1, "GECP failed\n");
goto end;
}
if(status == STILL_ACTIVE){
threadprint(1, "got client proc\n");
break;
}
goto end;
default:
threadprint(1, "Confused\n");
goto end;
}
}
end:
CloseHandle(h->hserversig);
CloseHandle(h->hclientsig);
CloseHandle(h->hclientproc);
CloseHandle(h->hmem);
UnmapViewOfFile(h);
ExitThread(0);
return 0;
}
LRESULT CALLBACK
SyscallProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
Handles *h, *x;
void *mem;
HANDLE hproc, hmem, hthr;
threadprint(1, "msg %d\n", msg);
switch(msg){
case WM_USER:
hproc = OpenProcess(PROCESS_ALL_ACCESS, 0, lparam);
if(hproc == nil){
oserror();
threadprint(1, "OpenProcess %d: %r\n", lparam);
Err0:
return 0;
}
if(0){
Err1:
CloseHandle(hproc);
goto Err0;
}
hmem = CreateFileMapping(nil, nil, PAGE_READWRITE, 0, CallMem, nil);
if(hmem == nil){
oserror();
threadprint(1, "CreateFileMapping for %d: %r\n", lparam);
goto Err1;
}
if(0){
Err2:
CloseHandle(hmem);
goto Err1;
}
mem = MapViewOfFile(hmem, FILE_MAP_WRITE, 0, 0, 0);
if(mem == nil){
oserror();
threadprint(1, "MapViewOfFile for %d: %r\n", lparam);
goto Err2;
}
if(0){
Err3:
UnmapViewOfFile(mem);
goto Err2;
}
h = mem;
memset(h, 0, 2*sizeof(*h));
h->hmem = hmem;
h->hclientproc = hproc;
if((h->hserversig = CreateSemaphore(nil, 0, 1, nil)) == nil){
oserror();
threadprint(1, "CreateSemaphore: %r\n");
goto Err3;
}
if(0){
Err4:
CloseHandle(h->hserversig);
goto Err3;
}
if((h->hclientsig = CreateSemaphore(nil, 0, 1, nil)) == nil){
oserror();
threadprint(1, "CreateSemaphore: %r\n");
goto Err4;
}
if(0){
Err5:
CloseHandle(h->hclientsig);
goto Err4;
}
x = &h[1];
if(!DuplicateHandle(me, h->hserversig, hproc, &x->hserversig, 0, 0, DUPLICATE_SAME_ACCESS)){
oserror();
threadprint(1, "DuplicateHandle 0 %p for %d: %r\n", hmem, lparam);
goto Err5;
}
if(!DuplicateHandle(me, h->hclientsig, hproc, &x->hclientsig, 0, 0, DUPLICATE_SAME_ACCESS)){
oserror();
threadprint(1, "DuplicateHandle 1 %p for %d: %r\n", hmem, lparam);
goto Err5;
}
if(!DuplicateHandle(me, h->hmem, hproc, &x->hmem, 0, 0, DUPLICATE_SAME_ACCESS)){
oserror();
threadprint(1, "DuplicateHandle 2 %p for %d: %r\n", hmem, lparam);
goto Err5;
}
/*
* We can't close the other guy's handles, so if an error occurs
* we have to just leave them and only clean up after ourselves.
*/
hthr = CreateThread(nil, 16384, SyscallThread, h, 0, nil);
if(hthr == nil){
oserror();
threadprint(1, "CreateThread: %r\n");
goto Err5;
}
CloseHandle(hthr);
return (LRESULT)x->hmem;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
syntax highlighted by Code2HTML, v. 0.9.1