#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); } }