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>
22 #include <java/lang/Integer.h>
23 #include <java/util/Hashtable.h>
24 #include <org/xwt/Box.h>
25 #include <org/xwt/Surface.h>
26 #include <org/xwt/DoubleBuffer.h>
27 #include <org/xwt/Picture.h>
28 #include <org/xwt/ByteStream.h>
29 #include <org/xwt/Platform.h>
30 #include <org/xwt/Platform$ParsedFont.h>
31 #include <org/xwt/plat/Win32.h>
32 #include <org/xwt/plat/Win32$Win32Font.h>
33 #include <org/xwt/plat/Win32$Win32Surface.h>
34 #include <org/xwt/plat/Win32$Win32DoubleBuffer.h>
35 #include <org/xwt/plat/Win32$Win32Picture.h>
36 #include <org/xwt/util/Log.h>
37 #include <org/xwt/util/Semaphore.h>
40 #include <java/lang/System.h>
41 #include <java/io/PrintStream.h>
43 #define WM_USER_SETCURSOR WM_USER
44 #define WM_USER_DISPOSE (WM_USER + 1)
45 #define WM_USER_CREATEWINDOW (WM_USER + 2)
46 #define WS_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
48 // FEATURE: there are lots of places where HANDLE's get casted to jint's -- this will break on Win64
49 // a clean way to do this would be to '#define jraw (gnu::gcj::RawData*)'
51 // Callbacks ////////////////////////////////////////////////////////////////////
53 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
54 org::xwt::plat::Win32$Win32Surface* surface =
55 (org::xwt::plat::Win32$Win32Surface*)org::xwt::plat::Win32::hwndToWin32SurfaceMap->get(new java::lang::Integer((jint)hwnd));
57 if (surface != NULL) {
58 return (LRESULT)surface->WndProc((jint)hwnd, (jint)iMsg, (jint)wParam, (jint)lParam);
61 // this is really lame -- Win32 insists on being able to call your WndProc BEFORE CreateWindow returns...
62 return DefWindowProc(hwnd, iMsg, wParam, lParam);
66 // This function iterates over each family (lparam == 0), and then over each size (lparam == 1)
67 int CALLBACK fontproc(const LOGFONTA* enumlogfont, const TEXTMETRICA* tm, long unsigned int type, LPARAM lparam) {
71 lf.lfCharSet = ANSI_CHARSET;
72 strncpy(lf.lfFaceName, enumlogfont->lfFaceName, 32);
73 lf.lfPitchAndFamily = 0;
74 EnumFontFamiliesEx((HDC)org::xwt::plat::Win32::desktop_dc, &lf, fontproc, 1, 0);
77 org::xwt::plat::Win32::addFont(JvNewStringLatin1(enumlogfont->lfFaceName),
78 ((type & RASTER_FONTTYPE) == 0) ? 0 : tm->tmHeight,
79 tm->tmItalic == 0 ? 0 : 1,
80 tm->tmWeight <= 400 ? 0 : 1);
86 // Initialization ////////////////////////////////////////////////////////////////////
88 static int window_class_counter = 0;
90 jstring org::xwt::plat::Win32::getTempPath() {
92 DWORD ret = GetTempPath(1024, buf);
93 if (ret == 0) criticalAbort(JvNewStringLatin1("GetTempPath() failed"));
94 return JvNewStringLatin1(buf);
97 // XOR mask for the hand cursor
98 static unsigned char hand_cursor_xor[32 * 4] = {
99 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x0C, 0x00, 0x00,
101 0x00, 0x0C, 0x00, 0x00,
102 0x00, 0x0C, 0x00, 0x00,
103 0x00, 0x0C, 0x00, 0x00,
104 0x00, 0x0C, 0x00, 0x00,
105 0x00, 0x0D, 0x80, 0x00,
106 0x00, 0x0D, 0xB0, 0x00,
107 0x00, 0x0D, 0xB4, 0x00,
108 0x00, 0x0D, 0xB6, 0x00,
109 0x00, 0xCF, 0xF6, 0x00,
110 0x00, 0xEF, 0xFE, 0x00,
111 0x00, 0x6F, 0xFE, 0x00,
112 0x00, 0x2F, 0xFE, 0x00,
113 0x00, 0x3F, 0xFE, 0x00,
114 0x00, 0x1F, 0xFE, 0x00,
115 0x00, 0x1F, 0xFC, 0x00,
116 0x00, 0x0F, 0xFC, 0x00,
117 0x00, 0x0F, 0xFC, 0x00,
118 0x00, 0x07, 0xF8, 0x00,
119 0x00, 0x07, 0xF8, 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,
128 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00
133 // AND mask for the hand cursor
134 static unsigned char hand_cursor_and[32 * 4] = {
135 0xFF, 0xF3, 0xFF, 0xFF,
136 0xFF, 0xE1, 0xFF, 0xFF,
137 0xFF, 0xE1, 0xFF, 0xFF,
138 0xFF, 0xE1, 0xFF, 0xFF,
139 0xFF, 0xE1, 0xFF, 0xFF,
140 0xFF, 0xE0, 0x7F, 0xFF,
141 0xFF, 0xE0, 0x0F, 0xFF,
142 0xFF, 0xE0, 0x03, 0xFF,
143 0xFF, 0xE0, 0x01, 0xFF,
144 0xFF, 0x20, 0x00, 0xFF,
145 0xFE, 0x00, 0x00, 0xFF,
146 0xFE, 0x00, 0x00, 0xFF,
147 0xFF, 0x00, 0x00, 0xFF,
148 0xFF, 0x80, 0x00, 0xFF,
149 0xFF, 0x80, 0x00, 0xFF,
150 0xFF, 0xC0, 0x00, 0xFF,
151 0xFF, 0xC0, 0x01, 0xFF,
152 0xFF, 0xE0, 0x01, 0xFF,
153 0xFF, 0xE0, 0x01, 0xFF,
154 0xFF, 0xF0, 0x03, 0xFF,
155 0xFF, 0xF0, 0x03, 0xFF,
156 0xFF, 0xF0, 0x03, 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,
164 0xFF, 0xFF, 0xFF, 0xFF,
165 0xFF, 0xFF, 0xFF, 0xFF,
166 0xFF, 0xFF, 0xFF, 0xFF
170 void org::xwt::plat::Win32::natInit() {
172 // grab desktop dc/handle
173 desktop_handle = (jint)GetDesktopWindow();
174 desktop_dc = (jint)GetDC((HWND)desktop_handle);
177 org::xwt::plat::Win32::wait_cursor = (jint)LoadCursor(NULL, IDC_WAIT);
178 org::xwt::plat::Win32::default_cursor = (jint)LoadCursor(NULL, IDC_ARROW);
179 org::xwt::plat::Win32::crosshair_cursor = (jint)LoadCursor(NULL, IDC_CROSS);
180 org::xwt::plat::Win32::text_cursor = (jint)LoadCursor(NULL, IDC_IBEAM);
181 org::xwt::plat::Win32::move_cursor = (jint)LoadCursor(NULL, IDC_SIZEALL);
182 org::xwt::plat::Win32::sizenesw_cursor = (jint)LoadCursor(NULL, IDC_SIZENESW);
183 org::xwt::plat::Win32::sizens_cursor = (jint)LoadCursor(NULL, IDC_SIZENS);
184 org::xwt::plat::Win32::sizenwse_cursor = (jint)LoadCursor(NULL, IDC_SIZENWSE);
185 org::xwt::plat::Win32::sizewe_cursor = (jint)LoadCursor(NULL, IDC_SIZEWE);
186 org::xwt::plat::Win32::hand_cursor = (jint)CreateCursor(GetModuleHandle(NULL), 14, 1, 32, 32, hand_cursor_and, hand_cursor_xor);
190 lf.lfCharSet = ANSI_CHARSET;
191 lf.lfFaceName[0] = 0;
192 lf.lfPitchAndFamily = 0;
193 EnumFontFamiliesEx((HDC)desktop_dc, &lf, fontproc, 0, 0);
195 messagePumpThread = (jint)GetCurrentThreadId();
196 messagePumpStarted->release();
199 while(GetMessage(&msg, (HWND)NULL, 0, 0) > 0) {
201 if (msg.message == WM_USER_CREATEWINDOW) {
202 org::xwt::plat::Win32$Win32Surface *surface = (org::xwt::plat::Win32$Win32Surface*)msg.lParam;
204 // we must create a unique window class name for each
205 // window so that minimization icons can be set independantly
207 sprintf(buf, "XWT_WINDOW_CLASS_%i", window_class_counter++);
210 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
211 wc.lpfnWndProc = WndProc;
213 wc.cbSize = sizeof(WNDCLASSEX);
215 wc.hInstance = GetModuleHandle(NULL);
219 wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR + 1);
220 wc.lpszMenuName = NULL;
221 wc.lpszClassName = buf;
222 RegisterClassEx(&wc);
224 surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""), msg.wParam ? WS_NORMAL : WS_POPUP, 200, 200, 100, 100,
225 (HWND__*)NULL, (HMENU__*)NULL, GetModuleHandle(NULL), (LPVOID)NULL);
226 SetFocus((HWND)surface->hwnd);
227 surface->hwndCreated->release();
230 TranslateMessage(&msg);
231 if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN) SetFocus(msg.hwnd);
232 DispatchMessage(&msg);
236 java::lang::System::exit(-1);
240 // Platform Methods ///////////////////////////////////////////////////////////////////
242 jstring org::xwt::plat::Win32::_fileDialog(jstring suggestedFileName, jboolean write) {
246 memset(buf, 0, 1024);
247 memset(&ofn, 0, sizeof(OPENFILENAME));
249 if (suggestedFileName != NULL)
250 JvGetStringUTFRegion(suggestedFileName, 0, min(1023, JvGetStringUTFLength(suggestedFileName)), buf);
252 ofn.lStructSize = sizeof(OPENFILENAME);
253 ofn.nMaxCustFilter = 0;
257 if (write) ofn.Flags |= OFN_OVERWRITEPROMPT;
258 ofn.Flags |= OFN_NOCHANGEDIR;
259 ofn.Flags |= OFN_HIDEREADONLY;
261 int ret = write ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
262 return ret == 0 ? NULL : JvNewStringLatin1(buf);
265 void org::xwt::plat::Win32::__detectProxy(JArray<jstring>* container) {
271 LONG result = RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &hkey);
272 if (result != ERROR_SUCCESS) return;
277 result = RegQueryValueEx(hkey, "AutoConfigURL", NULL, &type, (LPBYTE)buf, &buflen);
279 if (result == ERROR_SUCCESS) elements(container)[2] = JvNewStringLatin1(buf);
283 RegQueryValueEx(hkey, "ProxyEnable", NULL, &type, (LPBYTE)buf, &buflen);
284 if (buf[0] != 1) return;
289 RegQueryValueEx(hkey, "ProxyServer", NULL, &type, (LPBYTE)buf, &buflen);
291 elements(container)[0] = JvNewStringLatin1(buf);
295 RegQueryValueEx(hkey, "ProxyOverride", NULL, &type, (LPBYTE)buf, &buflen);
297 elements(container)[1] = JvNewStringLatin1(buf);
300 jstring org::xwt::plat::Win32::_getClipBoard() {
301 OpenClipboard((HWND)desktop_handle);
302 HGLOBAL hmem = GetClipboardData(CF_TEXT);
303 if (hmem == NULL) return NULL;
304 char* buf = (char*)GlobalLock(hmem);
305 if (buf == NULL) return NULL;
306 jstring ret = JvNewStringLatin1(buf);
312 void org::xwt::plat::Win32::_setClipBoard(jstring s) {
313 OpenClipboard((HWND)desktop_handle);
314 HGLOBAL hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, JvGetStringUTFLength(s) + 1);
315 if (hmem == NULL) return;
316 char* buf = (char*)GlobalLock(hmem);
317 if (buf == NULL) return;
318 JvGetStringUTFRegion(s, 0, JvGetStringUTFLength(s), buf);
319 buf[JvGetStringUTFLength(s)] = '\0';
321 SetClipboardData(CF_TEXT, hmem);
325 void org::xwt::plat::Win32::_criticalAbort(jstring message) {
326 char buf[JvGetStringUTFLength(message) + 1];
327 buf[JvGetStringUTFLength(message)] = '\0';
328 JvGetStringUTFRegion(message, 0, JvGetStringUTFLength(message), buf);
329 MessageBox (NULL, buf, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
330 java::lang::System::exit(-1);
333 jint org::xwt::plat::Win32::_getScreenWidth() {
335 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
336 return rect.right - rect.left;
339 jint org::xwt::plat::Win32::_getScreenHeight() {
341 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
342 return rect.bottom - rect.top;
345 org::xwt::plat::Win32$Win32Font* org::xwt::plat::Win32::mapFont(org::xwt::Platform$ParsedFont* pf) {
346 org::xwt::plat::Win32$Win32Font* ret = new org::xwt::plat::Win32$Win32Font();
348 memset(&logfont, 0, sizeof(LOGFONT));
349 logfont.lfHeight = -MulDiv(pf->size, GetDeviceCaps((HDC)org::xwt::plat::Win32::desktop_dc, LOGPIXELSY), 72);
350 if (pf->italic) logfont.lfItalic = 1;
351 if (pf->bold) logfont.lfWeight = FW_BOLD;
352 logfont.lfCharSet = ANSI_CHARSET;
354 JvGetStringUTFRegion(pf->name, 0, min(31, JvGetStringUTFLength(pf->name)), logfont.lfFaceName);
355 logfont.lfFaceName[min(31, JvGetStringUTFLength(pf->name))] = 0;
357 ret->hfont = (jint)CreateFontIndirect(&logfont);
358 SelectObject((HDC)desktop_dc, (HFONT)(ret->hfont));
361 GetTextMetrics((HDC)desktop_dc, &tm);
363 p.x = 0; p.y = tm.tmAscent;
364 LPtoDP((HDC)desktop_dc, &p, 1);
365 ret->maxAscent = p.y;
367 p.x = 0; p.y = tm.tmDescent;
368 LPtoDP((HDC)desktop_dc, &p, 1);
369 ret->maxDescent = p.y;
374 jint org::xwt::plat::Win32::_stringWidth(jstring font, jstring text) {
376 HFONT hfont = (HFONT)(getFont(font)->hfont);
377 SelectObject((HDC)org::xwt::plat::Win32::desktop_dc, hfont);
379 int len = min(1024, JvGetStringUTFLength(text));
382 JvGetStringUTFRegion(text, 0, len, buf);
385 GetTextExtentPoint32((HDC)org::xwt::plat::Win32::desktop_dc, buf, len, &size);
389 jboolean org::xwt::plat::Win32::_newBrowserWindow_(jstring url) {
391 int len = min(2048, JvGetStringUTFLength(url));
393 JvGetStringUTFRegion(url, 0, len, buf);
397 memset(&ei, 0, sizeof(ei));
398 ei.cbSize = sizeof(ei);
401 ei.fMask = SEE_MASK_NOCLOSEPROCESS;
402 ei.nShow = SW_SHOWDEFAULT;
403 return (ShellExecuteEx(&ei) == 0);
408 // Win32DoubleBuffer /////////////////////////////////////////////////////////////////////////
410 // This is a scratch area; when blitting a translucent image, we copy the underlying data here first.
411 // Since all drawing operations are single-threaded, it's safe to use a global here.
412 static HBITMAP scratch = NULL;
413 static HDC scratch_dc = NULL;
414 static jint* scratch_bits = NULL;
415 static jint scratch_w = 0;
416 static jint scratch_h = 0;
418 #define BLT(dest, dx1, dy1, dx2, dy2, src, sx1, sy1, sx2, sy2, op) \
419 if ((dx2 - dx1 == sx2 - sx1) && (dy2 - dy1 == sy2 - sy1)) \
420 BitBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, op); \
422 StretchBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, sx2 - sx1, sy2 - sy1, op);
424 void org::xwt::plat::Win32$Win32DoubleBuffer::drawPicture(org::xwt::Picture* source0,
425 jint dx1, jint dy1, jint dx2, jint dy2,
426 jint sx1, jint sy1, jint sx2, jint sy2) {
428 org::xwt::plat::Win32$Win32Picture* source = (org::xwt::plat::Win32$Win32Picture*)source0;
430 if (source->hasalpha) {
432 if (scratch == NULL || scratch_w < dx2 - dx1 || scratch_h < dy2 - dy1) {
433 if (scratch_dc != NULL) DeleteDC(scratch_dc);
434 if (scratch != NULL) DeleteObject(scratch);
435 scratch_w = max(dx2 - dx1, scratch_w);
436 scratch_h = max(dy2 - dy1, scratch_h);
438 BITMAPINFO bitmapinfo;
439 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
440 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
441 bitmapinfo.bmiHeader.biWidth = scratch_w;
442 bitmapinfo.bmiHeader.biHeight = -1 * scratch_h;
443 bitmapinfo.bmiHeader.biPlanes = 1;
444 bitmapinfo.bmiHeader.biBitCount = 32;
445 bitmapinfo.bmiHeader.biCompression = BI_RGB;
447 // create section DIB
448 scratch = CreateDIBSection(NULL, &bitmapinfo, DIB_RGB_COLORS, (void**)&scratch_bits, NULL, 0);
449 scratch_dc = CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
450 SelectObject(scratch_dc, scratch);
453 // copy from screen to scratch
454 BitBlt((HDC)scratch_dc, 0, 0, dx2 - dx1, dy2 - dy1, (HDC)hdc, dx1, dy1, SRCCOPY);
456 // apply alpha-blending to scratch
457 jint* dat = elements(source->data);
459 for(int x = max(clipx1, dx1) - dx1; x < min(clipx2, dx2) - dx1; x++)
460 for(int y = max(clipy1, dy1) - dy1; y < min(clipy2, dy2) - dy1; y++) {
461 int sx = (x * (sx2 - sx1)) / (dx2 - dx1) + sx1;
462 int sy = (y * (sy2 - sy1)) / (dy2 - dy1) + sy1;
463 jint dst = scratch_bits[y * scratch_w + x];
464 jint src = dat[sy * source->getWidth() + sx];
465 jint alpha = (src & 0xFF000000) >> 24;
466 jint r = (((src & 0x00FF0000) >> 16) * alpha + ((dst & 0x00FF0000) >> 16) * (0xFF - alpha)) / 0xFF;
467 jint g = (((src & 0x0000FF00) >> 8) * alpha + ((dst & 0x0000FF00) >> 8) * (0xFF - alpha)) / 0xFF;
468 jint b = (((src & 0x000000FF)) * alpha + ((dst & 0x000000FF)) * (0xFF - alpha)) / 0xFF;
469 scratch_bits[y * scratch_w + x] = (r << 16) | (g << 8) | b;
472 // copy back from scratch to screen
473 BitBlt((HDC)hdc, dx1, dy1, dx2 - dx1, dy2 - dy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
476 if (source->hasmask) {
477 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->maskdc, sx1, sy1, sx2, sy2, SRCAND);
478 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCPAINT);
480 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCCOPY);
487 void org::xwt::plat::Win32$Win32DoubleBuffer::drawString(jstring font, jstring text, jint x, jint y, jint color) {
489 org::xwt::plat::Win32$Win32Font* wf = org::xwt::plat::Win32::getFont(font);
490 SelectObject((HDC)hdc, (HFONT)(wf->hfont));
492 // Platform API passes us the y-pos of the bottom of the text; we need the top
495 int len = min(1024, JvGetStringUTFLength(text));
498 JvGetStringUTFRegion(text, 0, len, buf);
500 SetTextColor((HDC)hdc, PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
501 TextOut((HDC)hdc, x, y, buf, len);
504 void org::xwt::plat::Win32$Win32DoubleBuffer::fillRect(jint x, jint y, jint x2, jint y2, jint color) {
508 // sadly, the ability to change the color of a brush didn't arrive until Win2k...
509 HBRUSH brush = CreateSolidBrush(PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
511 RECT rect = { x, y, x + w, y + h };
512 FillRect((HDC)hdc, &rect, brush);
516 void org::xwt::plat::Win32$Win32Surface::blit(org::xwt::DoubleBuffer* s, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
517 BitBlt((HDC)hdc, dx, dy, dx2 - dx, dy2 - dy, (HDC)(((org::xwt::plat::Win32$Win32DoubleBuffer*)s)->hdc), sx, sy, SRCCOPY);
520 void org::xwt::plat::Win32$Win32DoubleBuffer::natInit() {
521 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
522 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
523 SetBkMode((HDC)hdc, TRANSPARENT);
524 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
527 void org::xwt::plat::Win32$Win32DoubleBuffer::setClip(jint x, jint y, jint x2, jint y2) {
528 clipx1 = x; clipx2 = x2; clipy1 = y; clipy2 = y2;
529 HRGN hrgn = CreateRectRgn(x, y, x2, y2);
530 SelectClipRgn((HDC)hdc, hrgn);
534 void org::xwt::plat::Win32$Win32DoubleBuffer::finalize() {
535 DeleteObject((void*)hdc);
536 DeleteObject((void*)hbitmap);
541 // Win32Picture /////////////////////////////////////////////////////////////////////////
543 void org::xwt::plat::Win32$Win32Picture::natInit() {
545 BITMAPINFO bitmapinfo;
546 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
547 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
548 bitmapinfo.bmiHeader.biWidth = w;
549 bitmapinfo.bmiHeader.biHeight = -1 * h;
550 bitmapinfo.bmiHeader.biPlanes = 1;
551 bitmapinfo.bmiHeader.biBitCount = 32;
552 bitmapinfo.bmiHeader.biCompression = BI_RGB;
554 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
555 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
556 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
557 uint32_t* dat = (uint32_t*)elements(data);
558 for(int i=0; i<data->length; i++) if ((dat[i] & 0xFF000000) == 0x00000000) dat[i] = 0x00000000;
559 StretchDIBits((HDC)hdc, 0, 0, w, h, 0, 0, w, h, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
561 jint _copy[min(1024, data->length)];
562 jint* copy = data->length > 1024 ? (jint*)malloc(data->length * 4) : _copy;
564 memcpy(copy, elements(data), data->length * 4);
565 for(int i=0; i<data->length; i++)
566 if ((copy[i] & 0xFF000000) == 0x00000000) {
568 copy[i] = 0x00FFFFFF;
569 } else if ((copy[i] & 0xFF000000) == 0xFF000000) {
570 copy[i] = 0x00000000;
574 if (data->length > 1024) free(copy);
579 if (data->length > 1024) free(copy);
583 // hmask = (jint)CreateBitmap(w, h, 1, 1, NULL);
584 hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
585 maskdc = (jint)CreateCompatibleDC(NULL);
586 SelectObject((HDC)maskdc, (HBITMAP)hmask);
587 StretchDIBits((HDC)maskdc, 0, 0, w, h, 0, 0, w, h, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
588 if (data->length > 1024) free(copy);
593 // Win32Surface /////////////////////////////////////////////////////////////////////////////
595 void org::xwt::plat::Win32$Win32Surface::natInit(jboolean framed) {
597 // Ask the message-handling thread to create a window for us
598 PostThreadMessage((DWORD)org::xwt::plat::Win32::messagePumpThread, WM_USER + 2, (WPARAM)framed, (LPARAM)this);
599 hwndCreated->block();
601 // turn on incremental GC now that we have a user-visible interface
602 // [[this is causing segfaults; enable it later...]]
603 // GC_enable_incremental();
605 ShowWindow ((HWND)hwnd, SW_SHOWDEFAULT);
606 hdc = (jint)GetDC((HWND)hwnd);
609 void org::xwt::plat::Win32$Win32Surface::finalize() { /* DeleteObject((void*)hwnd); */ }
610 void org::xwt::plat::Win32$Win32Surface::toFront() { BringWindowToTop((HWND)hwnd); }
611 void org::xwt::plat::Win32$Win32Surface::toBack() { SetWindowPos((HWND)hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
612 void org::xwt::plat::Win32$Win32Surface::_dispose() { PostMessage((HWND)hwnd, WM_USER_DISPOSE, 0, 0); }
613 void org::xwt::plat::Win32$Win32Surface::setInvisible(jboolean h) { ShowWindow((HWND)hwnd, h ? SW_HIDE : SW_SHOWNORMAL); }
614 void org::xwt::plat::Win32$Win32Surface::_setMinimized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMINIMIZED : SW_SHOWNORMAL); }
615 void org::xwt::plat::Win32$Win32Surface::_setMaximized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL); }
616 void org::xwt::plat::Win32$Win32Surface::postCursorChange() { PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0); }
618 void org::xwt::plat::Win32$Win32Surface::setLocation(jint x, jint y) {
623 ClientToScreen((HWND)hwnd, &point);
624 GetWindowRect((HWND)hwnd, &rect);
625 SetWindowPos((HWND)hwnd, NULL, x - (point.x - rect.left), y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
628 void org::xwt::plat::Win32$Win32Surface::setSize(jint w, jint h) {
629 RECT client_rect, window_rect;
630 GetClientRect((HWND)hwnd, &client_rect);
631 GetWindowRect((HWND)hwnd, &window_rect);
632 int addwidth = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
633 int addheight = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
634 SetWindowPos((HWND)hwnd, NULL, 0, 0, w + addwidth, h + addheight, SWP_NOZORDER | SWP_NOMOVE);
637 void org::xwt::plat::Win32$Win32Surface::setTitleBarText(java::lang::String* title) {
638 int len = min(1024, JvGetStringUTFLength(title));
641 JvGetStringUTFRegion(title, 0, len, buf);
642 SetWindowText((HWND)hwnd, buf);
645 void org::xwt::plat::Win32$Win32Surface::setIcon(org::xwt::Picture* p0) {
647 org::xwt::plat::Win32$Win32Picture* p = (org::xwt::plat::Win32$Win32Picture*)p0;
648 int icon_width = GetSystemMetrics(SM_CXSMICON);
649 int icon_height = GetSystemMetrics(SM_CYSMICON);
652 HBITMAP bit = CreateCompatibleBitmap((HDC)hdc, icon_width, icon_height);
653 HDC memdc = CreateCompatibleDC((HDC)hdc);
654 SelectObject(memdc, bit);
655 BLT((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, p->getWidth(), p->getHeight(), SRCCOPY);
658 jint* dat = elements(p->data);
659 HBITMAP bit_mask = CreateBitmap(icon_width, icon_height * 2, 1, 1, NULL);
660 SelectObject(memdc, bit_mask);
661 for(int x=0; x<icon_width; x++)
662 for(int y=0; y<icon_height; y++) {
663 int source = dat[(x * p->getWidth()) / icon_width + ((y * p->getHeight()) / icon_height) * (p->getWidth())];
664 if ((source & 0xFF000000) != 0x00000000) SetPixel(memdc, x, y, PALETTERGB(0, 0, 0));
665 else SetPixel(memdc, x, y, PALETTERGB(255, 255, 255));
668 // instantiate the icon and assign it to the window class
671 ici.hbmMask = bit_mask;
673 HICON hicon = CreateIconIndirect(&ici);
674 HICON oldicon = (HICON)SetClassLong((HWND)hwnd, GCL_HICONSM, (LONG)hicon);
675 if (oldicon != NULL) DestroyIcon(oldicon);
679 static jstring keyToString(WPARAM wParam);
680 jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _wParam, jint _lParam) {
682 UINT iMsg = (UINT)_iMsg;
683 WPARAM wParam = (WPARAM)_wParam;
684 LPARAM lParam = (LPARAM)_lParam;
686 int oldmousex, oldmousey;
696 case WM_DEVMODECHANGE: break; // FEATURE: color depth changed
697 case WM_DISPLAYCHANGE: break; // FEATURE: screen size changed
698 case WM_FONTCHANGE: break; // FEATURE: set of fonts changed
699 case WM_MOUSEWHEEL: break; // FEATURE: Mouse Wheel
701 case WM_SYSKEYDOWN: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
703 KeyPressed(keyToString(wParam));
706 case WM_SYSKEYUP: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
708 KeyReleased(keyToString(wParam));
711 case WM_SETFOCUS: Focused(true); return 0;
712 case WM_KILLFOCUS: Focused(false); return 0;
713 case WM_LBUTTONDBLCLK: DoubleClick(1); return 0;
714 case WM_RBUTTONDBLCLK: DoubleClick(2); return 0;
715 case WM_MBUTTONDBLCLK: DoubleClick(3); return 0;
716 case WM_LBUTTONDOWN: Press(1); return 0;
717 case WM_RBUTTONDOWN: Press(2); return 0;
718 case WM_MBUTTONDOWN: Press(3); return 0;
719 case WM_CLOSE: Close(); return 0;
720 case WM_ERASEBKGND: return 0;
725 Release(iMsg == WM_LBUTTONUP ? 1 : (iMsg == WM_RBUTTONUP ? 2 : 3));
726 if (captured && !inside) {
728 SetCursor((HCURSOR)previous_cursor);
733 GetClientRect((HWND)hwnd, &rect);
734 PosChange(rect.left, rect.top);
738 if (wParam == SIZE_MINIMIZED) {
739 if (maximized) Maximized(false);
741 } else if (wParam == SIZE_MAXIMIZED) {
742 if (minimized) Minimized(false);
745 if (minimized) Minimized(false);
746 if (maximized) Maximized(false);
748 // deliberately fall through to WM_SIZING
751 GetClientRect((HWND)hwnd, &rect);
752 SizeChange(rect.right - rect.left, rect.bottom - rect.top);
756 if (mousex == lParam & 0xFFFF && mousey == (lParam & 0xFFFF0000) >> 16) return 0;
758 GetClientRect((HWND)hwnd, &rect);
759 point.x = mouse_x = lParam & 0xFFFF;
760 point.y = mouse_y = (lParam & 0xFFFF0000) >> 16;
761 ClientToScreen((HWND)hwnd, &point);
762 hwnd2 = WindowFromPoint(point);
764 newinside = hwnd2 == (HWND)hwnd && mouse_x > 0 && mouse_y > 0 && mouse_x < (rect.right - rect.left) && mouse_y < (rect.bottom - rect.top) ? 1 : 0;
766 Move(mouse_x, mouse_y);
768 if (newinside && !inside) {
770 SetCapture((HWND)hwnd);
772 previous_cursor = (jint)GetCursor();
773 PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0);
775 } else if (!newinside && inside) {
777 if (!button1 && !button2 && !button3) {
780 SetCursor((HCURSOR)previous_cursor);
786 case WM_USER_SETCURSOR:
787 // I can't find documentation of this anywhere, but in my experience, an event must be received between an invocation
788 // of SetCapture() and SetCursor(). Furthermore, it seems that after calling SetCursor(), the cursor will not change until a
789 // return from WndProc (ie the completion of the processing of some event). Hence, we use WM_USER to indicate that the screen
790 // cursor should be re-set to "current_cursor".
791 SetCursor((HCURSOR)current_cursor);
794 case WM_USER_DISPOSE:
795 // used to signal that we should destroy ourselves
796 DestroyWindow((HWND)hwnd);
799 case WM_GETMINMAXINFO:
800 mmi = (MINMAXINFO*)lParam;
801 mmi->ptMinTrackSize.x = root->dmin(0);
802 mmi->ptMinTrackSize.y = root->dmin(1);
803 mmi->ptMaxTrackSize.x = root->dmax(0);
804 mmi->ptMaxTrackSize.y = root->dmax(1);
809 BeginPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
810 Dirty(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
811 EndPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
817 return DefWindowProc((HWND)hwnd, iMsg, wParam, lParam);
821 // Key Translator Helper /////////////////////////////////////////////////////////////////////
823 static char keyarr [256] = { 0 };
824 static jstring keyToString(WPARAM wParam) {
826 keyarr[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
827 keyarr[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
828 keyarr[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
829 keyarr[VK_SHIFT] = GetKeyState(VK_SHIFT);
831 if (ToAscii(wParam, 0, (BYTE*)keyarr, (WORD*)arr, 0) == 1) {
833 case '\t': return JvNewStringLatin1("tab");
834 case 0x1b: return JvNewStringLatin1("escape");
835 case '\n': return JvNewStringLatin1("enter");
836 case '\r': return JvNewStringLatin1("enter");
837 case 0x08: return JvNewStringLatin1("back_space");
838 default: return JvNewStringLatin1(arr, 1);
841 } else switch (wParam) {
842 case VK_CLEAR: return JvNewStringLatin1("clear");
843 case VK_SHIFT: return JvNewStringLatin1("shift");
844 case VK_CONTROL: return JvNewStringLatin1("control");
845 case VK_CAPITAL: return JvNewStringLatin1("caps_lock");
846 case VK_MENU: return JvNewStringLatin1("alt");
847 case VK_PAUSE: return JvNewStringLatin1("pause");
848 case VK_PRIOR: return JvNewStringLatin1("page_up");
849 case VK_NEXT: return JvNewStringLatin1("page_down");
850 case VK_END: return JvNewStringLatin1("end");
851 case VK_HOME: return JvNewStringLatin1("home");
852 case VK_LEFT: return JvNewStringLatin1("left");
853 case VK_UP: return JvNewStringLatin1("up");
854 case VK_RIGHT: return JvNewStringLatin1("right");
855 case VK_DOWN: return JvNewStringLatin1("down");
856 case VK_INSERT: return JvNewStringLatin1("insert");
857 case VK_DELETE: return JvNewStringLatin1("delete");
858 case VK_NUMPAD0: return JvNewStringLatin1("numpad0");
859 case VK_NUMPAD1: return JvNewStringLatin1("numpad1");
860 case VK_NUMPAD2: return JvNewStringLatin1("numpad2");
861 case VK_NUMPAD3: return JvNewStringLatin1("numpad3");
862 case VK_NUMPAD4: return JvNewStringLatin1("numpad4");
863 case VK_NUMPAD5: return JvNewStringLatin1("numpad5");
864 case VK_NUMPAD6: return JvNewStringLatin1("numpad6");
865 case VK_NUMPAD7: return JvNewStringLatin1("numpad7");
866 case VK_NUMPAD8: return JvNewStringLatin1("numpad8");
867 case VK_NUMPAD9: return JvNewStringLatin1("numpad9");
868 case VK_F1: return JvNewStringLatin1("f1");
869 case VK_F2: return JvNewStringLatin1("f2");
870 case VK_F3: return JvNewStringLatin1("f3");
871 case VK_F4: return JvNewStringLatin1("f4");
872 case VK_F5: return JvNewStringLatin1("f5");
873 case VK_F6: return JvNewStringLatin1("f6");
874 case VK_F7: return JvNewStringLatin1("f7");
875 case VK_F8: return JvNewStringLatin1("f8");
876 case VK_F9: return JvNewStringLatin1("f9");
877 case VK_F10: return JvNewStringLatin1("f10");
878 case VK_F11: return JvNewStringLatin1("f11");
879 case VK_F12: return JvNewStringLatin1("f12");
880 case VK_NUMLOCK: return JvNewStringLatin1("num_lock");
881 case VK_SCROLL: return JvNewStringLatin1("scroll_lock");
882 case VK_LSHIFT: return JvNewStringLatin1("shift");
883 case VK_RSHIFT: return JvNewStringLatin1("shift");
884 case VK_LCONTROL: return JvNewStringLatin1("control");
885 case VK_RCONTROL: return JvNewStringLatin1("control");
893 ///////////////////////////////////////////////////////////////////////////////////////
894 ///////////////////////////////////////////////////////////////////////////////////////
895 ///////////////////////////////////////////////////////////////////////////////////////
897 #else /* COMPILE_DLL */
901 // A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
905 #include <initguid.h>
912 // Globals ////////////////////////////////////////////////////////////////////////
916 #define CLSID_STRING_SIZE 39
918 const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
919 const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
920 const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
921 extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
922 static HMODULE g_hModule = NULL; //DLL handle
927 // Superclasses ////////////////////////////////////////////////////////////////////////
929 // Option bit definitions for IObjectSafety:
930 #define INTERFACESAFE_FOR_UNTRUSTED_CALLER 0x00000001 // Caller of interface may be untrusted
931 #define INTERFACESAFE_FOR_UNTRUSTED_DATA 0x00000002 // Data passed into interface may be untrusted
933 // {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
934 DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
936 interface IObjectSafety : public IUnknown {
938 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
939 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
942 interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
946 // Entry Points ////////////////////////////////////////////////////////////////////////
948 // to get mingw to stop nagging me
949 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
951 // determines whether or not the DLL can be unloaded; always allow this since we don't do too much
952 STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
954 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
955 if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
961 // Other ///////////////////////////////////////////////////////////////////////////////////
963 // simple assert() replacement that pops open a message box if there are errors
964 void check(int val, char* message) {
966 MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
971 void clsidToString(const CLSID& clsid, char* str, int length) {
972 check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
973 LPOLESTR wide_str = NULL;
974 HRESULT hr = StringFromCLSID(clsid, &wide_str);
975 check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
976 wcstombs(str, wide_str, length);
977 CoTaskMemFree(wide_str);
980 void setRegistryKey(const char* key, const char* subkey, const char* value) {
984 if (subkey != NULL) {
985 strcat(keyBuf, "\\");
986 strcat(keyBuf, subkey );
988 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
990 check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
991 "RegSetValueEx() failed in setRegistryKey()");
995 void deleteRegistryKey(HKEY parent, const char* target) {
997 RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
999 // Iterate over children, deleting them
1003 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
1004 deleteRegistryKey(hKeyChild, szBuffer);
1008 RegCloseKey(hKeyChild);
1009 RegDeleteKey(parent, target);
1012 STDAPI __declspec(dllexport) DllRegisterServer(void) {
1013 char moduleName[512];
1014 HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
1015 check(result, "GetModuleFileName() failed in RegisterServer()");
1017 char clsidString[CLSID_STRING_SIZE];
1018 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
1022 strcpy(key, "CLSID\\");
1023 strcat(key, clsidString);
1025 setRegistryKey(key, NULL, XWT_friendlyName);
1026 setRegistryKey(key, "InprocServer32", moduleName);
1027 setRegistryKey(key, "ProgID", XWT_programID);
1028 setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
1029 setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName);
1030 setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
1031 setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
1032 setRegistryKey(XWT_programID, NULL, XWT_friendlyName);
1033 setRegistryKey(XWT_programID, "CLSID", clsidString);
1037 STDAPI __declspec(dllexport) DllUnregisterServer(void) {
1038 char clsidString[CLSID_STRING_SIZE];
1039 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
1043 strcpy(key, "CLSID\\");
1044 strcat(key, clsidString);
1046 deleteRegistryKey(HKEY_CLASSES_ROOT, key);
1047 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
1048 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
1054 // ShoeHorn //////////////////////////////////////////////////////////////////////////////////
1056 class ShoeHorn : public IShoeHorn {
1058 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
1059 if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
1060 else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
1061 else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
1062 else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
1063 else { *ppv = NULL; return E_NOINTERFACE; }
1064 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1067 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1068 virtual ULONG __stdcall Release() {
1069 if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
1072 virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
1073 virtual HRESULT __stdcall InitNew() { return S_OK; }
1074 virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
1075 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
1076 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
1077 if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1078 if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1082 virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
1090 MultiByteToWideChar(CP_ACP, 0, "initial-xwar-url", -1, wc, 100);
1091 pPropBag->Read(wc, &v, pErrorLog);
1092 check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
1093 "WideCharToMultiByte() failed in ShoeHorn::Load()");
1096 LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
1097 check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
1099 // iterate over all the activex cache locations until we find ourselves
1100 for(int i=0; i<9; i++) {
1109 result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
1110 if (result != ERROR_SUCCESS)
1112 check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
1119 for(int i=0; i<200; i++) cmdline[i] = '\0';
1120 strncpy(cmdline, buf, 200);
1121 strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
1122 strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
1123 strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
1125 PROCESS_INFORMATION pInfo;
1127 sInfo.cb = sizeof(STARTUPINFO);
1128 sInfo.lpReserved = NULL;
1129 sInfo.lpReserved2 = NULL;
1130 sInfo.cbReserved2 = 0;
1131 sInfo.lpDesktop = NULL;
1132 sInfo.lpTitle = NULL;
1136 sInfo.dwFillAttribute = 0;
1137 sInfo.wShowWindow = SW_SHOW;
1138 BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
1142 check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
1145 ShoeHorn() : m_cRef(1) { };
1147 private: long m_cRef;
1153 // ClassFactory //////////////////////////////////////////////////////////////////////////
1155 class ClassFactory : public IClassFactory {
1157 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
1158 if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
1159 else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
1162 return E_NOINTERFACE;
1164 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1168 ClassFactory() : m_cRef(1) { }
1170 virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
1171 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1172 virtual ULONG __stdcall Release() {
1173 if(InterlockedDecrement(&m_cRef) == 0) {
1180 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
1181 if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
1182 ShoeHorn* s = new ShoeHorn;
1183 if(s == NULL) return E_OUTOFMEMORY;
1184 HRESULT hr = s->QueryInterface(iid, ppv);
1189 private: long m_cRef;
1193 extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
1194 if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
1195 ClassFactory* pFactory = new ClassFactory;
1196 if(pFactory == NULL) return E_OUTOFMEMORY;
1197 HRESULT hr = pFactory->QueryInterface(iid, ppv);
1198 pFactory->Release();