1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
3 // kinda ugly; we use -DCOMPILE_DLL to combine two .cc files into one
6 // this has to precede the others so we don't get collisions on min/max
7 #include <org/xwt/Box.h>
19 #include <java/lang/Integer.h>
20 #include <java/util/Hashtable.h>
21 #include <org/xwt/Box.h>
22 #include <org/xwt/Surface.h>
23 #include <org/xwt/DoubleBuffer.h>
24 #include <org/xwt/Picture.h>
25 #include <org/xwt/Platform.h>
26 #include <org/xwt/Platform$ParsedFont.h>
27 #include <org/xwt/plat/Win32.h>
28 #include <org/xwt/plat/Win32$Win32Font.h>
29 #include <org/xwt/plat/Win32$Win32Surface.h>
30 #include <org/xwt/plat/Win32$Win32DoubleBuffer.h>
31 #include <org/xwt/plat/Win32$Win32Picture.h>
32 #include <org/xwt/util/Semaphore.h>
35 #include <java/lang/System.h>
36 #include <java/io/PrintStream.h>
38 #define WM_USER_SETCURSOR WM_USER
39 #define WM_USER_DISPOSE (WM_USER + 1)
40 #define WM_USER_CREATEWINDOW (WM_USER + 2)
41 #define WS_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
43 // FEATURE: there are lots of places where HANDLE's get casted to jint's -- this will break on Win64
44 // a clean way to do this would be to '#define jraw (gnu::gcj::RawData*)'
46 // Callbacks ////////////////////////////////////////////////////////////////////
48 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
49 org::xwt::plat::Win32$Win32Surface* surface =
50 (org::xwt::plat::Win32$Win32Surface*)org::xwt::plat::Win32::hwndToWin32SurfaceMap->get(new java::lang::Integer((jint)hwnd));
52 if (surface != NULL) {
53 return (LRESULT)surface->WndProc((jint)hwnd, (jint)iMsg, (jint)wParam, (jint)lParam);
56 java::lang::System::out->print(JvNewStringLatin1("miss on hwnd "));
57 java::lang::System::out->println((jint)hwnd);
58 // this is really lame -- Win32 insists on being able to call your WndProc BEFORE CreateWindow returns...
59 return DefWindowProc(hwnd, iMsg, wParam, lParam);
63 // This function iterates over each family (lparam == 0), and then over each size (lparam == 1)
64 int CALLBACK fontproc(const LOGFONTA* enumlogfont, const TEXTMETRICA* tm, long unsigned int type, LPARAM lparam) {
68 lf.lfCharSet = ANSI_CHARSET;
69 strncpy(lf.lfFaceName, enumlogfont->lfFaceName, 32);
70 lf.lfPitchAndFamily = 0;
71 EnumFontFamiliesEx((HDC)org::xwt::plat::Win32::desktop_dc, &lf, fontproc, 1, 0);
74 org::xwt::plat::Win32::addFont(JvNewStringLatin1(enumlogfont->lfFaceName),
75 ((type & RASTER_FONTTYPE) == 0) ? 0 : tm->tmHeight,
76 tm->tmItalic == 0 ? 0 : 1,
77 tm->tmWeight <= 400 ? 0 : 1);
83 // Initialization ////////////////////////////////////////////////////////////////////
85 static int window_class_counter = 0;
87 jstring org::xwt::plat::Win32::getTempPath() {
89 DWORD ret = GetTempPath(1024, buf);
90 if (ret == 0) criticalAbort(JvNewStringLatin1("GetTempPath() failed"));
91 return JvNewStringLatin1(buf);
94 // XOR mask for the hand cursor
95 static unsigned char hand_cursor_xor[32 * 4] = {
96 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x0C, 0x00, 0x00,
98 0x00, 0x0C, 0x00, 0x00,
99 0x00, 0x0C, 0x00, 0x00,
100 0x00, 0x0C, 0x00, 0x00,
101 0x00, 0x0C, 0x00, 0x00,
102 0x00, 0x0D, 0x80, 0x00,
103 0x00, 0x0D, 0xB0, 0x00,
104 0x00, 0x0D, 0xB4, 0x00,
105 0x00, 0x0D, 0xB6, 0x00,
106 0x00, 0xCF, 0xF6, 0x00,
107 0x00, 0xEF, 0xFE, 0x00,
108 0x00, 0x6F, 0xFE, 0x00,
109 0x00, 0x2F, 0xFE, 0x00,
110 0x00, 0x3F, 0xFE, 0x00,
111 0x00, 0x1F, 0xFE, 0x00,
112 0x00, 0x1F, 0xFC, 0x00,
113 0x00, 0x0F, 0xFC, 0x00,
114 0x00, 0x0F, 0xFC, 0x00,
115 0x00, 0x07, 0xF8, 0x00,
116 0x00, 0x07, 0xF8, 0x00,
117 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00
130 // AND mask for the hand cursor
131 static unsigned char hand_cursor_and[32 * 4] = {
132 0xFF, 0xF3, 0xFF, 0xFF,
133 0xFF, 0xE1, 0xFF, 0xFF,
134 0xFF, 0xE1, 0xFF, 0xFF,
135 0xFF, 0xE1, 0xFF, 0xFF,
136 0xFF, 0xE1, 0xFF, 0xFF,
137 0xFF, 0xE0, 0x7F, 0xFF,
138 0xFF, 0xE0, 0x0F, 0xFF,
139 0xFF, 0xE0, 0x03, 0xFF,
140 0xFF, 0xE0, 0x01, 0xFF,
141 0xFF, 0x20, 0x00, 0xFF,
142 0xFE, 0x00, 0x00, 0xFF,
143 0xFE, 0x00, 0x00, 0xFF,
144 0xFF, 0x00, 0x00, 0xFF,
145 0xFF, 0x80, 0x00, 0xFF,
146 0xFF, 0x80, 0x00, 0xFF,
147 0xFF, 0xC0, 0x00, 0xFF,
148 0xFF, 0xC0, 0x01, 0xFF,
149 0xFF, 0xE0, 0x01, 0xFF,
150 0xFF, 0xE0, 0x01, 0xFF,
151 0xFF, 0xF0, 0x03, 0xFF,
152 0xFF, 0xF0, 0x03, 0xFF,
153 0xFF, 0xF0, 0x03, 0xFF,
154 0xFF, 0xFF, 0xFF, 0xFF,
155 0xFF, 0xFF, 0xFF, 0xFF,
156 0xFF, 0xFF, 0xFF, 0xFF,
157 0xFF, 0xFF, 0xFF, 0xFF,
158 0xFF, 0xFF, 0xFF, 0xFF,
159 0xFF, 0xFF, 0xFF, 0xFF,
160 0xFF, 0xFF, 0xFF, 0xFF,
161 0xFF, 0xFF, 0xFF, 0xFF,
162 0xFF, 0xFF, 0xFF, 0xFF,
163 0xFF, 0xFF, 0xFF, 0xFF
166 void org::xwt::plat::Win32::natInit() {
168 // grab desktop dc/handle
169 desktop_handle = (jint)GetDesktopWindow();
170 desktop_dc = (jint)GetDC((HWND)desktop_handle);
173 org::xwt::plat::Win32::wait_cursor = (jint)LoadCursor(NULL, IDC_WAIT);
174 org::xwt::plat::Win32::default_cursor = (jint)LoadCursor(NULL, IDC_ARROW);
175 org::xwt::plat::Win32::crosshair_cursor = (jint)LoadCursor(NULL, IDC_CROSS);
176 org::xwt::plat::Win32::text_cursor = (jint)LoadCursor(NULL, IDC_IBEAM);
177 org::xwt::plat::Win32::move_cursor = (jint)LoadCursor(NULL, IDC_SIZEALL);
178 org::xwt::plat::Win32::sizenesw_cursor = (jint)LoadCursor(NULL, IDC_SIZENESW);
179 org::xwt::plat::Win32::sizens_cursor = (jint)LoadCursor(NULL, IDC_SIZENS);
180 org::xwt::plat::Win32::sizenwse_cursor = (jint)LoadCursor(NULL, IDC_SIZENWSE);
181 org::xwt::plat::Win32::sizewe_cursor = (jint)LoadCursor(NULL, IDC_SIZEWE);
182 org::xwt::plat::Win32::hand_cursor = (jint)CreateCursor(GetModuleHandle(NULL), 14, 1, 32, 32, hand_cursor_and, hand_cursor_xor);
186 lf.lfCharSet = ANSI_CHARSET;
187 lf.lfFaceName[0] = 0;
188 lf.lfPitchAndFamily = 0;
189 EnumFontFamiliesEx((HDC)desktop_dc, &lf, fontproc, 0, 0);
191 messagePumpThread = (jint)GetCurrentThreadId();
192 messagePumpStarted->release();
195 while(GetMessage(&msg, (HWND)NULL, 0, 0) > 0) {
197 if (msg.message == WM_USER_CREATEWINDOW) {
198 org::xwt::plat::Win32$Win32Surface *surface = (org::xwt::plat::Win32$Win32Surface*)msg.lParam;
200 // we must create a unique window class name for each
201 // window so that minimization icons can be set independantly
203 sprintf(buf, "XWT_WINDOW_CLASS_%i", window_class_counter++);
206 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
207 wc.lpfnWndProc = WndProc;
209 wc.cbSize = sizeof(WNDCLASSEX);
211 wc.hInstance = GetModuleHandle(NULL);
215 wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR + 1);
216 wc.lpszMenuName = NULL;
217 wc.lpszClassName = buf;
218 RegisterClassEx(&wc);
220 surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""), msg.wParam ? WS_NORMAL : WS_POPUP, 200, 200, 100, 100,
221 (HWND__*)NULL, (HMENU__*)NULL, GetModuleHandle(NULL), (LPVOID)NULL);
222 SetFocus((HWND)surface->hwnd);
223 surface->hwndCreated->release();
226 TranslateMessage(&msg);
227 if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN) SetFocus(msg.hwnd);
228 DispatchMessage(&msg);
232 java::lang::System::exit(-1);
236 // Platform Methods ///////////////////////////////////////////////////////////////////
238 jstring org::xwt::plat::Win32::_getClipBoard() {
239 OpenClipboard((HWND)desktop_handle);
240 HGLOBAL hmem = GetClipboardData(CF_TEXT);
241 if (hmem == NULL) return NULL;
242 char* buf = (char*)GlobalLock(hmem);
243 if (buf == NULL) return NULL;
244 jstring ret = JvNewStringLatin1(buf);
250 void org::xwt::plat::Win32::_setClipBoard(jstring s) {
251 OpenClipboard((HWND)desktop_handle);
252 HGLOBAL hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, JvGetStringUTFLength(s) + 1);
253 if (hmem == NULL) return;
254 char* buf = (char*)GlobalLock(hmem);
255 if (buf == NULL) return;
256 JvGetStringUTFRegion(s, 0, JvGetStringUTFLength(s), buf);
257 buf[JvGetStringUTFLength(s)] = '\0';
259 SetClipboardData(CF_TEXT, hmem);
263 void org::xwt::plat::Win32::_criticalAbort(jstring message) {
264 char buf[JvGetStringUTFLength(message) + 1];
265 buf[JvGetStringUTFLength(message)] = '\0';
266 JvGetStringUTFRegion(message, 0, JvGetStringUTFLength(message), buf);
267 MessageBox (NULL, buf, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
268 java::lang::System::exit(-1);
271 jint org::xwt::plat::Win32::_getScreenWidth() {
273 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
274 return rect.right - rect.left;
277 jint org::xwt::plat::Win32::_getScreenHeight() {
279 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
280 return rect.bottom - rect.top;
283 org::xwt::plat::Win32$Win32Font* org::xwt::plat::Win32::mapFont(org::xwt::Platform$ParsedFont* pf) {
284 org::xwt::plat::Win32$Win32Font* ret = new org::xwt::plat::Win32$Win32Font();
286 memset(&logfont, 0, sizeof(LOGFONT));
287 logfont.lfHeight = -MulDiv(pf->size, GetDeviceCaps((HDC)org::xwt::plat::Win32::desktop_dc, LOGPIXELSY), 72);
288 if (pf->italic) logfont.lfItalic = 1;
289 if (pf->bold) logfont.lfWeight = FW_BOLD;
290 logfont.lfCharSet = ANSI_CHARSET;
292 JvGetStringUTFRegion(pf->name, 0, min(31, JvGetStringUTFLength(pf->name)), logfont.lfFaceName);
293 logfont.lfFaceName[min(31, JvGetStringUTFLength(pf->name))] = 0;
295 ret->hfont = (jint)CreateFontIndirect(&logfont);
296 SelectObject((HDC)desktop_dc, (HFONT)(ret->hfont));
299 GetTextMetrics((HDC)desktop_dc, &tm);
301 p.x = 0; p.y = tm.tmAscent;
302 LPtoDP((HDC)desktop_dc, &p, 1);
303 ret->maxAscent = p.y;
305 p.x = 0; p.y = tm.tmDescent;
306 LPtoDP((HDC)desktop_dc, &p, 1);
307 ret->maxDescent = p.y;
312 jint org::xwt::plat::Win32::_stringWidth(jstring font, jstring text) {
314 HFONT hfont = (HFONT)(getFont(font)->hfont);
315 SelectObject((HDC)org::xwt::plat::Win32::desktop_dc, hfont);
317 int len = min(1024, JvGetStringUTFLength(text));
320 JvGetStringUTFRegion(text, 0, len, buf);
323 GetTextExtentPoint32((HDC)org::xwt::plat::Win32::desktop_dc, buf, len, &size);
327 jboolean org::xwt::plat::Win32::_newBrowserWindow_(jstring url) {
329 int len = min(2048, JvGetStringUTFLength(url));
331 JvGetStringUTFRegion(url, 0, len, buf);
335 memset(&ei, 0, sizeof(ei));
336 ei.cbSize = sizeof(ei);
339 ei.fMask = SEE_MASK_NOCLOSEPROCESS;
340 ei.nShow = SW_SHOWDEFAULT;
341 return (ShellExecuteEx(&ei) == 0);
346 // Win32DoubleBuffer /////////////////////////////////////////////////////////////////////////
348 // This is a scratch area; when blitting a translucent image, we copy the underlying data here first.
349 // Since all drawing operations are single-threaded, it's safe to use a global here.
350 static HBITMAP scratch = NULL;
351 static HDC scratch_dc = NULL;
352 static jint* scratch_bits = NULL;
353 static jint scratch_w = 0;
354 static jint scratch_h = 0;
356 #define BLT(dest, dx1, dy1, dx2, dy2, src, sx1, sy1, sx2, sy2, op) \
357 if ((dx2 - dx1 == sx2 - sx1) && (dy2 - dy1 == sy2 - sy1)) \
358 BitBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, op); \
360 StretchBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, sx2 - sx1, sy2 - sy1, op);
362 void org::xwt::plat::Win32$Win32DoubleBuffer::drawPicture(org::xwt::Picture* source0,
363 jint dx1, jint dy1, jint dx2, jint dy2,
364 jint sx1, jint sy1, jint sx2, jint sy2) {
366 org::xwt::plat::Win32$Win32Picture* source = (org::xwt::plat::Win32$Win32Picture*)source0;
368 if (source->hasalpha) {
370 if (scratch == NULL || scratch_w < dx2 - dx1 || scratch_h < dy2 - dy1) {
371 if (scratch_dc != NULL) DeleteDC(scratch_dc);
372 if (scratch != NULL) DeleteObject(scratch);
373 scratch_w = max(dx2 - dx1, scratch_w);
374 scratch_h = max(dy2 - dy1, scratch_h);
376 BITMAPINFO bitmapinfo;
377 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
378 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
379 bitmapinfo.bmiHeader.biWidth = scratch_w;
380 bitmapinfo.bmiHeader.biHeight = -1 * scratch_h;
381 bitmapinfo.bmiHeader.biPlanes = 1;
382 bitmapinfo.bmiHeader.biBitCount = 32;
383 bitmapinfo.bmiHeader.biCompression = BI_RGB;
385 // create section DIB
386 scratch = CreateDIBSection(NULL, &bitmapinfo, DIB_RGB_COLORS, (void**)&scratch_bits, NULL, 0);
387 scratch_dc = CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
388 SelectObject(scratch_dc, scratch);
391 // copy from screen to scratch
392 BitBlt((HDC)scratch_dc, 0, 0, dx2 - dx1, dy2 - dy1, (HDC)hdc, dx1, dy1, SRCCOPY);
394 // apply alpha-blending to scratch
395 jint* dat = elements(source->data);
397 for(int x = max(clipx1, dx1) - dx1; x < min(clipx2, dx2) - dx1; x++)
398 for(int y = max(clipy1, dy1) - dy1; y < min(clipy2, dy2) - dy1; y++) {
399 int sx = (x * (sx2 - sx1)) / (dx2 - dx1) + sx1;
400 int sy = (y * (sy2 - sy1)) / (dy2 - dy1) + sy1;
401 jint dst = scratch_bits[y * scratch_w + x];
402 jint src = dat[sy * source->getWidth() + sx];
403 jint alpha = (src & 0xFF000000) >> 24;
404 jint r = (((src & 0x00FF0000) >> 16) * alpha + ((dst & 0x00FF0000) >> 16) * (0xFF - alpha)) / 0xFF;
405 jint g = (((src & 0x0000FF00) >> 8) * alpha + ((dst & 0x0000FF00) >> 8) * (0xFF - alpha)) / 0xFF;
406 jint b = (((src & 0x000000FF)) * alpha + ((dst & 0x000000FF)) * (0xFF - alpha)) / 0xFF;
407 scratch_bits[y * scratch_w + x] = (r << 16) | (g << 8) | b;
410 // copy back from scratch to screen
411 BitBlt((HDC)hdc, dx1, dy1, dx2 - dx1, dy2 - dy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
414 if (source->hasmask) {
415 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->maskdc, sx1, sy1, sx2, sy2, SRCAND);
416 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCPAINT);
418 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCCOPY);
425 void org::xwt::plat::Win32$Win32DoubleBuffer::drawString(jstring font, jstring text, jint x, jint y, jint color) {
427 org::xwt::plat::Win32$Win32Font* wf = org::xwt::plat::Win32::getFont(font);
428 SelectObject((HDC)hdc, (HFONT)(wf->hfont));
430 // Platform API passes us the y-pos of the bottom of the text; we need the top
433 int len = min(1024, JvGetStringUTFLength(text));
436 JvGetStringUTFRegion(text, 0, len, buf);
438 SetTextColor((HDC)hdc, PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
439 TextOut((HDC)hdc, x, y, buf, len);
442 void org::xwt::plat::Win32$Win32DoubleBuffer::fillRect(jint x, jint y, jint x2, jint y2, jint color) {
446 // sadly, the ability to change the color of a brush didn't arrive until Win2k...
447 HBRUSH brush = CreateSolidBrush(PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
449 RECT rect = { x, y, x + w, y + h };
450 FillRect((HDC)hdc, &rect, brush);
454 void org::xwt::plat::Win32$Win32Surface::blit(org::xwt::DoubleBuffer* s, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
455 BitBlt((HDC)hdc, dx, dy, dx2 - dx, dy2 - dy, (HDC)(((org::xwt::plat::Win32$Win32DoubleBuffer*)s)->hdc), sx, sy, SRCCOPY);
458 void org::xwt::plat::Win32$Win32DoubleBuffer::natInit() {
459 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
460 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
461 SetBkMode((HDC)hdc, TRANSPARENT);
462 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
465 void org::xwt::plat::Win32$Win32DoubleBuffer::setClip(jint x, jint y, jint x2, jint y2) {
466 clipx1 = x; clipx2 = x2; clipy1 = y; clipy2 = y2;
467 HRGN hrgn = CreateRectRgn(x, y, x2, y2);
468 SelectClipRgn((HDC)hdc, hrgn);
472 void org::xwt::plat::Win32$Win32DoubleBuffer::finalize() {
473 DeleteObject((void*)hdc);
474 DeleteObject((void*)hbitmap);
479 // Win32Picture /////////////////////////////////////////////////////////////////////////
481 void org::xwt::plat::Win32$Win32Picture::natInit() {
483 BITMAPINFO bitmapinfo;
484 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
485 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
486 bitmapinfo.bmiHeader.biWidth = w;
487 bitmapinfo.bmiHeader.biHeight = -1 * h;
488 bitmapinfo.bmiHeader.biPlanes = 1;
489 bitmapinfo.bmiHeader.biBitCount = 32;
490 bitmapinfo.bmiHeader.biCompression = BI_RGB;
492 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
493 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
494 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
495 uint32_t* dat = (uint32_t*)elements(data);
496 for(int i=0; i<data->length; i++) if ((dat[i] & 0xFF000000) == 0x00000000) dat[i] = 0x00000000;
497 StretchDIBits((HDC)hdc, 0, 0, w, h, 0, 0, w, h, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
499 jint _copy[min(1024, data->length)];
500 jint* copy = data->length > 1024 ? (jint*)malloc(data->length * 4) : _copy;
502 memcpy(copy, elements(data), data->length * 4);
503 for(int i=0; i<data->length; i++)
504 if ((copy[i] & 0xFF000000) == 0x00000000) {
506 copy[i] = 0x00FFFFFF;
507 } else if ((copy[i] & 0xFF000000) == 0xFF000000) {
508 copy[i] = 0x00000000;
512 if (data->length > 1024) free(copy);
517 if (data->length > 1024) free(copy);
521 // hmask = (jint)CreateBitmap(w, h, 1, 1, NULL);
522 hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
523 maskdc = (jint)CreateCompatibleDC(NULL);
524 SelectObject((HDC)maskdc, (HBITMAP)hmask);
525 StretchDIBits((HDC)maskdc, 0, 0, w, h, 0, 0, w, h, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
526 if (data->length > 1024) free(copy);
531 // Win32Surface /////////////////////////////////////////////////////////////////////////////
533 void org::xwt::plat::Win32$Win32Surface::natInit(jboolean framed) {
535 // Ask the message-handling thread to create a window for us
536 PostThreadMessage((DWORD)org::xwt::plat::Win32::messagePumpThread, WM_USER + 2, (WPARAM)framed, (LPARAM)this);
537 hwndCreated->block();
539 // turn on incremental GC now that we have a user-visible interface
540 // [[this is causing segfaults; enable it later...]]
541 // GC_enable_incremental();
543 ShowWindow ((HWND)hwnd, SW_SHOWDEFAULT);
544 hdc = (jint)GetDC((HWND)hwnd);
547 void org::xwt::plat::Win32$Win32Surface::finalize() { /* DeleteObject((void*)hwnd); */ }
548 void org::xwt::plat::Win32$Win32Surface::toFront() { BringWindowToTop((HWND)hwnd); }
549 void org::xwt::plat::Win32$Win32Surface::toBack() { SetWindowPos((HWND)hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
550 void org::xwt::plat::Win32$Win32Surface::_dispose() { PostMessage((HWND)hwnd, WM_USER_DISPOSE, 0, 0); }
551 void org::xwt::plat::Win32$Win32Surface::setInvisible(jboolean h) { ShowWindow((HWND)hwnd, h ? SW_HIDE : SW_SHOWNORMAL); }
552 void org::xwt::plat::Win32$Win32Surface::_setMinimized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMINIMIZED : SW_SHOWNORMAL); }
553 void org::xwt::plat::Win32$Win32Surface::_setMaximized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL); }
554 void org::xwt::plat::Win32$Win32Surface::postCursorChange() { PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0); }
556 void org::xwt::plat::Win32$Win32Surface::setLocation(jint x, jint y) {
561 ClientToScreen((HWND)hwnd, &point);
562 GetWindowRect((HWND)hwnd, &rect);
563 SetWindowPos((HWND)hwnd, NULL, x - (point.x - rect.left), y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
566 void org::xwt::plat::Win32$Win32Surface::setSize(jint w, jint h) {
567 RECT client_rect, window_rect;
568 GetClientRect((HWND)hwnd, &client_rect);
569 GetWindowRect((HWND)hwnd, &window_rect);
570 int addwidth = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
571 int addheight = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
572 SetWindowPos((HWND)hwnd, NULL, 0, 0, w + addwidth, h + addheight, SWP_NOZORDER | SWP_NOMOVE);
575 void org::xwt::plat::Win32$Win32Surface::setTitleBarText(java::lang::String* title) {
576 int len = min(1024, JvGetStringUTFLength(title));
579 JvGetStringUTFRegion(title, 0, len, buf);
580 SetWindowText((HWND)hwnd, buf);
583 void org::xwt::plat::Win32$Win32Surface::setIcon(org::xwt::Picture* p0) {
585 org::xwt::plat::Win32$Win32Picture* p = (org::xwt::plat::Win32$Win32Picture*)p0;
586 int icon_width = GetSystemMetrics(SM_CXSMICON);
587 int icon_height = GetSystemMetrics(SM_CYSMICON);
590 HBITMAP bit = CreateCompatibleBitmap((HDC)hdc, icon_width, icon_height);
591 HDC memdc = CreateCompatibleDC((HDC)hdc);
592 SelectObject(memdc, bit);
593 BLT((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, p->getWidth(), p->getHeight(), SRCCOPY);
596 jint* dat = elements(p->data);
597 HBITMAP bit_mask = CreateBitmap(icon_width, icon_height * 2, 1, 1, NULL);
598 SelectObject(memdc, bit_mask);
599 for(int x=0; x<icon_width; x++)
600 for(int y=0; y<icon_height; y++) {
601 int source = dat[(x * p->getWidth()) / icon_width + ((y * p->getHeight()) / icon_height) * (p->getWidth())];
602 if ((source & 0xFF000000) != 0x00000000) SetPixel(memdc, x, y, PALETTERGB(0, 0, 0));
603 else SetPixel(memdc, x, y, PALETTERGB(255, 255, 255));
606 // instantiate the icon and assign it to the window class
609 ici.hbmMask = bit_mask;
611 HICON hicon = CreateIconIndirect(&ici);
612 HICON oldicon = (HICON)SetClassLong((HWND)hwnd, GCL_HICONSM, (LONG)hicon);
613 if (oldicon != NULL) DestroyIcon(oldicon);
617 static jstring keyToString(WPARAM wParam);
618 jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _wParam, jint _lParam) {
620 UINT iMsg = (UINT)_iMsg;
621 WPARAM wParam = (WPARAM)_wParam;
622 LPARAM lParam = (LPARAM)_lParam;
623 int oldmousex, oldmousey;
633 case WM_DEVMODECHANGE: break; // FEATURE: color depth changed
634 case WM_DISPLAYCHANGE: break; // FEATURE: screen size changed
635 case WM_FONTCHANGE: break; // FEATURE: set of fonts changed
636 case WM_MOUSEWHEEL: break; // FEATURE: Mouse Wheel
638 case WM_SYSKEYDOWN: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
640 KeyPressed(keyToString(wParam));
643 case WM_SYSKEYUP: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
645 KeyReleased(keyToString(wParam));
648 case WM_SETFOCUS: Focused(true); return 0;
649 case WM_KILLFOCUS: Focused(false); return 0;
650 case WM_LBUTTONDBLCLK: DoubleClick(1); return 0;
651 case WM_RBUTTONDBLCLK: DoubleClick(2); return 0;
652 case WM_MBUTTONDBLCLK: DoubleClick(3); return 0;
653 case WM_LBUTTONDOWN: Press(1); return 0;
654 case WM_RBUTTONDOWN: Press(2); return 0;
655 case WM_MBUTTONDOWN: Press(3); return 0;
656 case WM_CLOSE: Close(); return 0;
657 case WM_ERASEBKGND: return 0;
662 Release(iMsg == WM_LBUTTONUP ? 1 : (iMsg == WM_RBUTTONUP ? 2 : 3));
663 if (captured && !inside) {
665 SetCursor((HCURSOR)previous_cursor);
670 GetClientRect((HWND)hwnd, &rect);
671 PosChange(rect.left, rect.top);
675 if (wParam == SIZE_MINIMIZED) {
676 if (maximized) Maximized(false);
678 } else if (wParam == SIZE_MAXIMIZED) {
679 if (minimized) Minimized(false);
682 if (minimized) Minimized(false);
683 if (maximized) Maximized(false);
685 // deliberately fall through to WM_SIZING
688 GetClientRect((HWND)hwnd, &rect);
689 SizeChange(rect.right - rect.left, rect.bottom - rect.top);
693 if (mousex == lParam & 0xFFFF && mousey == (lParam & 0xFFFF0000) >> 16) return 0;
695 GetClientRect((HWND)hwnd, &rect);
696 point.x = mouse_x = lParam & 0xFFFF;
697 point.y = mouse_y = (lParam & 0xFFFF0000) >> 16;
698 ClientToScreen((HWND)hwnd, &point);
699 hwnd2 = WindowFromPoint(point);
701 newinside = hwnd2 == (HWND)hwnd && mouse_x > 0 && mouse_y > 0 && mouse_x < (rect.right - rect.left) && mouse_y < (rect.bottom - rect.top) ? 1 : 0;
703 Move(mouse_x, mouse_y);
705 if (newinside && !inside) {
707 SetCapture((HWND)hwnd);
709 previous_cursor = (jint)GetCursor();
710 PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0);
712 } else if (!newinside && inside) {
714 if (!button1 && !button2 && !button3) {
717 SetCursor((HCURSOR)previous_cursor);
723 case WM_USER_SETCURSOR:
724 // I can't find documentation of this anywhere, but in my experience, an event must be received between an invocation
725 // of SetCapture() and SetCursor(). Furthermore, it seems that after calling SetCursor(), the cursor will not change until a
726 // return from WndProc (ie the completion of the processing of some event). Hence, we use WM_USER to indicate that the screen
727 // cursor should be re-set to "current_cursor".
728 SetCursor((HCURSOR)current_cursor);
731 case WM_USER_DISPOSE:
732 // used to signal that we should destroy ourselves
733 DestroyWindow((HWND)hwnd);
736 case WM_GETMINMAXINFO:
737 mmi = (MINMAXINFO*)lParam;
738 mmi->ptMinTrackSize.x = root->dmin(0);
739 mmi->ptMinTrackSize.y = root->dmin(1);
740 mmi->ptMaxTrackSize.x = root->dmax(0);
741 mmi->ptMaxTrackSize.y = root->dmax(1);
746 BeginPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
747 Dirty(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
749 EndPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
755 return DefWindowProc((HWND)hwnd, iMsg, wParam, lParam);
759 // Key Translator Helper /////////////////////////////////////////////////////////////////////
761 static char keyarr [256] = { 0 };
762 static jstring keyToString(WPARAM wParam) {
764 keyarr[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
765 keyarr[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
766 keyarr[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
767 keyarr[VK_SHIFT] = GetKeyState(VK_SHIFT);
769 if (ToAscii(wParam, 0, (BYTE*)keyarr, (WORD*)arr, 0) == 1) {
771 case '\t': return JvNewStringLatin1("tab");
772 case 0x1b: return JvNewStringLatin1("escape");
773 case '\n': return JvNewStringLatin1("enter");
774 case '\r': return JvNewStringLatin1("enter");
775 case 0x08: return JvNewStringLatin1("back_space");
776 default: return JvNewStringLatin1(arr, 1);
779 } else switch (wParam) {
780 case VK_CLEAR: return JvNewStringLatin1("clear");
781 case VK_SHIFT: return JvNewStringLatin1("shift");
782 case VK_CONTROL: return JvNewStringLatin1("control");
783 case VK_CAPITAL: return JvNewStringLatin1("caps_lock");
784 case VK_MENU: return JvNewStringLatin1("alt");
785 case VK_PAUSE: return JvNewStringLatin1("pause");
786 case VK_PRIOR: return JvNewStringLatin1("page_up");
787 case VK_NEXT: return JvNewStringLatin1("page_down");
788 case VK_END: return JvNewStringLatin1("end");
789 case VK_HOME: return JvNewStringLatin1("home");
790 case VK_LEFT: return JvNewStringLatin1("left");
791 case VK_UP: return JvNewStringLatin1("up");
792 case VK_RIGHT: return JvNewStringLatin1("right");
793 case VK_DOWN: return JvNewStringLatin1("down");
794 case VK_INSERT: return JvNewStringLatin1("insert");
795 case VK_DELETE: return JvNewStringLatin1("delete");
796 case VK_NUMPAD0: return JvNewStringLatin1("numpad0");
797 case VK_NUMPAD1: return JvNewStringLatin1("numpad1");
798 case VK_NUMPAD2: return JvNewStringLatin1("numpad2");
799 case VK_NUMPAD3: return JvNewStringLatin1("numpad3");
800 case VK_NUMPAD4: return JvNewStringLatin1("numpad4");
801 case VK_NUMPAD5: return JvNewStringLatin1("numpad5");
802 case VK_NUMPAD6: return JvNewStringLatin1("numpad6");
803 case VK_NUMPAD7: return JvNewStringLatin1("numpad7");
804 case VK_NUMPAD8: return JvNewStringLatin1("numpad8");
805 case VK_NUMPAD9: return JvNewStringLatin1("numpad9");
806 case VK_F1: return JvNewStringLatin1("f1");
807 case VK_F2: return JvNewStringLatin1("f2");
808 case VK_F3: return JvNewStringLatin1("f3");
809 case VK_F4: return JvNewStringLatin1("f4");
810 case VK_F5: return JvNewStringLatin1("f5");
811 case VK_F6: return JvNewStringLatin1("f6");
812 case VK_F7: return JvNewStringLatin1("f7");
813 case VK_F8: return JvNewStringLatin1("f8");
814 case VK_F9: return JvNewStringLatin1("f9");
815 case VK_F10: return JvNewStringLatin1("f10");
816 case VK_F11: return JvNewStringLatin1("f11");
817 case VK_F12: return JvNewStringLatin1("f12");
818 case VK_NUMLOCK: return JvNewStringLatin1("num_lock");
819 case VK_SCROLL: return JvNewStringLatin1("scroll_lock");
820 case VK_LSHIFT: return JvNewStringLatin1("shift");
821 case VK_RSHIFT: return JvNewStringLatin1("shift");
822 case VK_LCONTROL: return JvNewStringLatin1("control");
823 case VK_RCONTROL: return JvNewStringLatin1("control");
831 ///////////////////////////////////////////////////////////////////////////////////////
832 ///////////////////////////////////////////////////////////////////////////////////////
833 ///////////////////////////////////////////////////////////////////////////////////////
835 #else /* COMPILE_DLL */
839 // A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
843 #include <initguid.h>
850 // Globals ////////////////////////////////////////////////////////////////////////
854 #define CLSID_STRING_SIZE 39
856 const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
857 const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
858 const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
859 extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
860 static HMODULE g_hModule = NULL; //DLL handle
865 // Superclasses ////////////////////////////////////////////////////////////////////////
867 // Option bit definitions for IObjectSafety:
868 #define INTERFACESAFE_FOR_UNTRUSTED_CALLER 0x00000001 // Caller of interface may be untrusted
869 #define INTERFACESAFE_FOR_UNTRUSTED_DATA 0x00000002 // Data passed into interface may be untrusted
871 // {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
872 DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
874 interface IObjectSafety : public IUnknown {
876 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
877 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
880 interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
884 // Entry Points ////////////////////////////////////////////////////////////////////////
886 // to get mingw to stop nagging me
887 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
889 // determines whether or not the DLL can be unloaded; always allow this since we don't do too much
890 STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
892 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
893 if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
899 // Other ///////////////////////////////////////////////////////////////////////////////////
901 // simple assert() replacement that pops open a message box if there are errors
902 void check(int val, char* message) {
904 MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
909 void clsidToString(const CLSID& clsid, char* str, int length) {
910 check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
911 LPOLESTR wide_str = NULL;
912 HRESULT hr = StringFromCLSID(clsid, &wide_str);
913 check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
914 wcstombs(str, wide_str, length);
915 CoTaskMemFree(wide_str);
918 void setRegistryKey(const char* key, const char* subkey, const char* value) {
922 if (subkey != NULL) {
923 strcat(keyBuf, "\\");
924 strcat(keyBuf, subkey );
926 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
928 check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
929 "RegSetValueEx() failed in setRegistryKey()");
933 void deleteRegistryKey(HKEY parent, const char* target) {
935 RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
937 // Iterate over children, deleting them
941 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
942 deleteRegistryKey(hKeyChild, szBuffer);
946 RegCloseKey(hKeyChild);
947 RegDeleteKey(parent, target);
950 STDAPI __declspec(dllexport) DllRegisterServer(void) {
951 char moduleName[512];
952 HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
953 check(result, "GetModuleFileName() failed in RegisterServer()");
955 char clsidString[CLSID_STRING_SIZE];
956 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
960 strcpy(key, "CLSID\\");
961 strcat(key, clsidString);
963 setRegistryKey(key, NULL, XWT_friendlyName);
964 setRegistryKey(key, "InprocServer32", moduleName);
965 setRegistryKey(key, "ProgID", XWT_programID);
966 setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
967 setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName);
968 setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
969 setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
970 setRegistryKey(XWT_programID, NULL, XWT_friendlyName);
971 setRegistryKey(XWT_programID, "CLSID", clsidString);
975 STDAPI __declspec(dllexport) DllUnregisterServer(void) {
976 char clsidString[CLSID_STRING_SIZE];
977 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
981 strcpy(key, "CLSID\\");
982 strcat(key, clsidString);
984 deleteRegistryKey(HKEY_CLASSES_ROOT, key);
985 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
986 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
992 // ShoeHorn //////////////////////////////////////////////////////////////////////////////////
994 class ShoeHorn : public IShoeHorn {
996 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
997 if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
998 else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
999 else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
1000 else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
1001 else { *ppv = NULL; return E_NOINTERFACE; }
1002 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1005 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1006 virtual ULONG __stdcall Release() {
1007 if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
1010 virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
1011 virtual HRESULT __stdcall InitNew() { return S_OK; }
1012 virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
1013 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
1014 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
1015 if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1016 if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1020 virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
1028 MultiByteToWideChar(CP_ACP, 0, "initial-xwar-url", -1, wc, 100);
1029 pPropBag->Read(wc, &v, pErrorLog);
1030 check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
1031 "WideCharToMultiByte() failed in ShoeHorn::Load()");
1034 LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
1035 check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
1037 // iterate over all the activex cache locations until we find ourselves
1038 for(int i=0; i<9; i++) {
1047 result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
1048 if (result != ERROR_SUCCESS)
1050 check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
1057 for(int i=0; i<200; i++) cmdline[i] = '\0';
1058 strncpy(cmdline, buf, 200);
1059 strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
1060 strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
1061 strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
1063 PROCESS_INFORMATION pInfo;
1065 sInfo.cb = sizeof(STARTUPINFO);
1066 sInfo.lpReserved = NULL;
1067 sInfo.lpReserved2 = NULL;
1068 sInfo.cbReserved2 = 0;
1069 sInfo.lpDesktop = NULL;
1070 sInfo.lpTitle = NULL;
1074 sInfo.dwFillAttribute = 0;
1075 sInfo.wShowWindow = SW_SHOW;
1076 BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
1080 check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
1083 ShoeHorn() : m_cRef(1) { };
1085 private: long m_cRef;
1091 // ClassFactory //////////////////////////////////////////////////////////////////////////
1093 class ClassFactory : public IClassFactory {
1095 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
1096 if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
1097 else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
1100 return E_NOINTERFACE;
1102 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1106 ClassFactory() : m_cRef(1) { }
1108 virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
1109 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1110 virtual ULONG __stdcall Release() {
1111 if(InterlockedDecrement(&m_cRef) == 0) {
1118 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
1119 if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
1120 ShoeHorn* s = new ShoeHorn;
1121 if(s == NULL) return E_OUTOFMEMORY;
1122 HRESULT hr = s->QueryInterface(iid, ppv);
1127 private: long m_cRef;
1131 extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
1132 if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
1133 ClassFactory* pFactory = new ClassFactory;
1134 if(pFactory == NULL) return E_OUTOFMEMORY;
1135 HRESULT hr = pFactory->QueryInterface(iid, ppv);
1136 pFactory->Release();