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_HIDEREADONLY;
260 int ret = write ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
261 return ret == 0 ? NULL : JvNewStringLatin1(buf);
264 void org::xwt::plat::Win32::__detectProxy(JArray<jstring>* container) {
270 LONG result = RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &hkey);
271 if (result != ERROR_SUCCESS) return;
276 result = RegQueryValueEx(hkey, "AutoConfigURL", NULL, &type, (LPBYTE)buf, &buflen);
278 if (result == ERROR_SUCCESS) elements(container)[2] = JvNewStringLatin1(buf);
282 RegQueryValueEx(hkey, "ProxyEnable", NULL, &type, (LPBYTE)buf, &buflen);
283 if (buf[0] != 1) return;
288 RegQueryValueEx(hkey, "ProxyServer", NULL, &type, (LPBYTE)buf, &buflen);
290 elements(container)[0] = JvNewStringLatin1(buf);
294 RegQueryValueEx(hkey, "ProxyOverride", NULL, &type, (LPBYTE)buf, &buflen);
296 elements(container)[1] = JvNewStringLatin1(buf);
299 jstring org::xwt::plat::Win32::_getClipBoard() {
300 OpenClipboard((HWND)desktop_handle);
301 HGLOBAL hmem = GetClipboardData(CF_TEXT);
302 if (hmem == NULL) return NULL;
303 char* buf = (char*)GlobalLock(hmem);
304 if (buf == NULL) return NULL;
305 jstring ret = JvNewStringLatin1(buf);
311 void org::xwt::plat::Win32::_setClipBoard(jstring s) {
312 OpenClipboard((HWND)desktop_handle);
313 HGLOBAL hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, JvGetStringUTFLength(s) + 1);
314 if (hmem == NULL) return;
315 char* buf = (char*)GlobalLock(hmem);
316 if (buf == NULL) return;
317 JvGetStringUTFRegion(s, 0, JvGetStringUTFLength(s), buf);
318 buf[JvGetStringUTFLength(s)] = '\0';
320 SetClipboardData(CF_TEXT, hmem);
324 void org::xwt::plat::Win32::_criticalAbort(jstring message) {
325 char buf[JvGetStringUTFLength(message) + 1];
326 buf[JvGetStringUTFLength(message)] = '\0';
327 JvGetStringUTFRegion(message, 0, JvGetStringUTFLength(message), buf);
328 MessageBox (NULL, buf, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
329 java::lang::System::exit(-1);
332 jint org::xwt::plat::Win32::_getScreenWidth() {
334 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
335 return rect.right - rect.left;
338 jint org::xwt::plat::Win32::_getScreenHeight() {
340 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
341 return rect.bottom - rect.top;
344 org::xwt::plat::Win32$Win32Font* org::xwt::plat::Win32::mapFont(org::xwt::Platform$ParsedFont* pf) {
345 org::xwt::plat::Win32$Win32Font* ret = new org::xwt::plat::Win32$Win32Font();
347 memset(&logfont, 0, sizeof(LOGFONT));
348 logfont.lfHeight = -MulDiv(pf->size, GetDeviceCaps((HDC)org::xwt::plat::Win32::desktop_dc, LOGPIXELSY), 72);
349 if (pf->italic) logfont.lfItalic = 1;
350 if (pf->bold) logfont.lfWeight = FW_BOLD;
351 logfont.lfCharSet = ANSI_CHARSET;
353 JvGetStringUTFRegion(pf->name, 0, min(31, JvGetStringUTFLength(pf->name)), logfont.lfFaceName);
354 logfont.lfFaceName[min(31, JvGetStringUTFLength(pf->name))] = 0;
356 ret->hfont = (jint)CreateFontIndirect(&logfont);
357 SelectObject((HDC)desktop_dc, (HFONT)(ret->hfont));
360 GetTextMetrics((HDC)desktop_dc, &tm);
362 p.x = 0; p.y = tm.tmAscent;
363 LPtoDP((HDC)desktop_dc, &p, 1);
364 ret->maxAscent = p.y;
366 p.x = 0; p.y = tm.tmDescent;
367 LPtoDP((HDC)desktop_dc, &p, 1);
368 ret->maxDescent = p.y;
373 jint org::xwt::plat::Win32::_stringWidth(jstring font, jstring text) {
375 HFONT hfont = (HFONT)(getFont(font)->hfont);
376 SelectObject((HDC)org::xwt::plat::Win32::desktop_dc, hfont);
378 int len = min(1024, JvGetStringUTFLength(text));
381 JvGetStringUTFRegion(text, 0, len, buf);
384 GetTextExtentPoint32((HDC)org::xwt::plat::Win32::desktop_dc, buf, len, &size);
388 jboolean org::xwt::plat::Win32::_newBrowserWindow_(jstring url) {
390 int len = min(2048, JvGetStringUTFLength(url));
392 JvGetStringUTFRegion(url, 0, len, buf);
396 memset(&ei, 0, sizeof(ei));
397 ei.cbSize = sizeof(ei);
400 ei.fMask = SEE_MASK_NOCLOSEPROCESS;
401 ei.nShow = SW_SHOWDEFAULT;
402 return (ShellExecuteEx(&ei) == 0);
407 // Win32DoubleBuffer /////////////////////////////////////////////////////////////////////////
409 // This is a scratch area; when blitting a translucent image, we copy the underlying data here first.
410 // Since all drawing operations are single-threaded, it's safe to use a global here.
411 static HBITMAP scratch = NULL;
412 static HDC scratch_dc = NULL;
413 static jint* scratch_bits = NULL;
414 static jint scratch_w = 0;
415 static jint scratch_h = 0;
417 #define BLT(dest, dx1, dy1, dx2, dy2, src, sx1, sy1, sx2, sy2, op) \
418 if ((dx2 - dx1 == sx2 - sx1) && (dy2 - dy1 == sy2 - sy1)) \
419 BitBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, op); \
421 StretchBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, sx2 - sx1, sy2 - sy1, op);
423 void org::xwt::plat::Win32$Win32DoubleBuffer::drawPicture(org::xwt::Picture* source0,
424 jint dx1, jint dy1, jint dx2, jint dy2,
425 jint sx1, jint sy1, jint sx2, jint sy2) {
427 org::xwt::plat::Win32$Win32Picture* source = (org::xwt::plat::Win32$Win32Picture*)source0;
429 if (source->hasalpha) {
431 if (scratch == NULL || scratch_w < dx2 - dx1 || scratch_h < dy2 - dy1) {
432 if (scratch_dc != NULL) DeleteDC(scratch_dc);
433 if (scratch != NULL) DeleteObject(scratch);
434 scratch_w = max(dx2 - dx1, scratch_w);
435 scratch_h = max(dy2 - dy1, scratch_h);
437 BITMAPINFO bitmapinfo;
438 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
439 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
440 bitmapinfo.bmiHeader.biWidth = scratch_w;
441 bitmapinfo.bmiHeader.biHeight = -1 * scratch_h;
442 bitmapinfo.bmiHeader.biPlanes = 1;
443 bitmapinfo.bmiHeader.biBitCount = 32;
444 bitmapinfo.bmiHeader.biCompression = BI_RGB;
446 // create section DIB
447 scratch = CreateDIBSection(NULL, &bitmapinfo, DIB_RGB_COLORS, (void**)&scratch_bits, NULL, 0);
448 scratch_dc = CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
449 SelectObject(scratch_dc, scratch);
452 // copy from screen to scratch
453 BitBlt((HDC)scratch_dc, 0, 0, dx2 - dx1, dy2 - dy1, (HDC)hdc, dx1, dy1, SRCCOPY);
455 // apply alpha-blending to scratch
456 jint* dat = elements(source->data);
458 for(int x = max(clipx1, dx1) - dx1; x < min(clipx2, dx2) - dx1; x++)
459 for(int y = max(clipy1, dy1) - dy1; y < min(clipy2, dy2) - dy1; y++) {
460 int sx = (x * (sx2 - sx1)) / (dx2 - dx1) + sx1;
461 int sy = (y * (sy2 - sy1)) / (dy2 - dy1) + sy1;
462 jint dst = scratch_bits[y * scratch_w + x];
463 jint src = dat[sy * source->getWidth() + sx];
464 jint alpha = (src & 0xFF000000) >> 24;
465 jint r = (((src & 0x00FF0000) >> 16) * alpha + ((dst & 0x00FF0000) >> 16) * (0xFF - alpha)) / 0xFF;
466 jint g = (((src & 0x0000FF00) >> 8) * alpha + ((dst & 0x0000FF00) >> 8) * (0xFF - alpha)) / 0xFF;
467 jint b = (((src & 0x000000FF)) * alpha + ((dst & 0x000000FF)) * (0xFF - alpha)) / 0xFF;
468 scratch_bits[y * scratch_w + x] = (r << 16) | (g << 8) | b;
471 // copy back from scratch to screen
472 BitBlt((HDC)hdc, dx1, dy1, dx2 - dx1, dy2 - dy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
475 if (source->hasmask) {
476 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->maskdc, sx1, sy1, sx2, sy2, SRCAND);
477 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCPAINT);
479 BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCCOPY);
486 void org::xwt::plat::Win32$Win32DoubleBuffer::drawString(jstring font, jstring text, jint x, jint y, jint color) {
488 org::xwt::plat::Win32$Win32Font* wf = org::xwt::plat::Win32::getFont(font);
489 SelectObject((HDC)hdc, (HFONT)(wf->hfont));
491 // Platform API passes us the y-pos of the bottom of the text; we need the top
494 int len = min(1024, JvGetStringUTFLength(text));
497 JvGetStringUTFRegion(text, 0, len, buf);
499 SetTextColor((HDC)hdc, PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
500 TextOut((HDC)hdc, x, y, buf, len);
503 void org::xwt::plat::Win32$Win32DoubleBuffer::fillRect(jint x, jint y, jint x2, jint y2, jint color) {
507 // sadly, the ability to change the color of a brush didn't arrive until Win2k...
508 HBRUSH brush = CreateSolidBrush(PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
510 RECT rect = { x, y, x + w, y + h };
511 FillRect((HDC)hdc, &rect, brush);
515 void org::xwt::plat::Win32$Win32Surface::blit(org::xwt::DoubleBuffer* s, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
516 BitBlt((HDC)hdc, dx, dy, dx2 - dx, dy2 - dy, (HDC)(((org::xwt::plat::Win32$Win32DoubleBuffer*)s)->hdc), sx, sy, SRCCOPY);
519 void org::xwt::plat::Win32$Win32DoubleBuffer::natInit() {
520 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
521 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
522 SetBkMode((HDC)hdc, TRANSPARENT);
523 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
526 void org::xwt::plat::Win32$Win32DoubleBuffer::setClip(jint x, jint y, jint x2, jint y2) {
527 clipx1 = x; clipx2 = x2; clipy1 = y; clipy2 = y2;
528 HRGN hrgn = CreateRectRgn(x, y, x2, y2);
529 SelectClipRgn((HDC)hdc, hrgn);
533 void org::xwt::plat::Win32$Win32DoubleBuffer::finalize() {
534 DeleteObject((void*)hdc);
535 DeleteObject((void*)hbitmap);
540 // Win32Picture /////////////////////////////////////////////////////////////////////////
542 void org::xwt::plat::Win32$Win32Picture::natInit() {
544 BITMAPINFO bitmapinfo;
545 memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
546 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
547 bitmapinfo.bmiHeader.biWidth = w;
548 bitmapinfo.bmiHeader.biHeight = -1 * h;
549 bitmapinfo.bmiHeader.biPlanes = 1;
550 bitmapinfo.bmiHeader.biBitCount = 32;
551 bitmapinfo.bmiHeader.biCompression = BI_RGB;
553 hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
554 hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
555 SelectObject((HDC)hdc, (HBITMAP)hbitmap);
556 uint32_t* dat = (uint32_t*)elements(data);
557 for(int i=0; i<data->length; i++) if ((dat[i] & 0xFF000000) == 0x00000000) dat[i] = 0x00000000;
558 StretchDIBits((HDC)hdc, 0, 0, w, h, 0, 0, w, h, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
560 jint _copy[min(1024, data->length)];
561 jint* copy = data->length > 1024 ? (jint*)malloc(data->length * 4) : _copy;
563 memcpy(copy, elements(data), data->length * 4);
564 for(int i=0; i<data->length; i++)
565 if ((copy[i] & 0xFF000000) == 0x00000000) {
567 copy[i] = 0x00FFFFFF;
568 } else if ((copy[i] & 0xFF000000) == 0xFF000000) {
569 copy[i] = 0x00000000;
573 if (data->length > 1024) free(copy);
578 if (data->length > 1024) free(copy);
582 // hmask = (jint)CreateBitmap(w, h, 1, 1, NULL);
583 hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
584 maskdc = (jint)CreateCompatibleDC(NULL);
585 SelectObject((HDC)maskdc, (HBITMAP)hmask);
586 StretchDIBits((HDC)maskdc, 0, 0, w, h, 0, 0, w, h, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
587 if (data->length > 1024) free(copy);
592 // Win32Surface /////////////////////////////////////////////////////////////////////////////
594 void org::xwt::plat::Win32$Win32Surface::natInit(jboolean framed) {
596 // Ask the message-handling thread to create a window for us
597 PostThreadMessage((DWORD)org::xwt::plat::Win32::messagePumpThread, WM_USER + 2, (WPARAM)framed, (LPARAM)this);
598 hwndCreated->block();
600 // turn on incremental GC now that we have a user-visible interface
601 // [[this is causing segfaults; enable it later...]]
602 // GC_enable_incremental();
604 ShowWindow ((HWND)hwnd, SW_SHOWDEFAULT);
605 hdc = (jint)GetDC((HWND)hwnd);
608 void org::xwt::plat::Win32$Win32Surface::finalize() { /* DeleteObject((void*)hwnd); */ }
609 void org::xwt::plat::Win32$Win32Surface::toFront() { BringWindowToTop((HWND)hwnd); }
610 void org::xwt::plat::Win32$Win32Surface::toBack() { SetWindowPos((HWND)hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
611 void org::xwt::plat::Win32$Win32Surface::_dispose() { PostMessage((HWND)hwnd, WM_USER_DISPOSE, 0, 0); }
612 void org::xwt::plat::Win32$Win32Surface::setInvisible(jboolean h) { ShowWindow((HWND)hwnd, h ? SW_HIDE : SW_SHOWNORMAL); }
613 void org::xwt::plat::Win32$Win32Surface::_setMinimized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMINIMIZED : SW_SHOWNORMAL); }
614 void org::xwt::plat::Win32$Win32Surface::_setMaximized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL); }
615 void org::xwt::plat::Win32$Win32Surface::postCursorChange() { PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0); }
617 void org::xwt::plat::Win32$Win32Surface::setLocation(jint x, jint y) {
622 ClientToScreen((HWND)hwnd, &point);
623 GetWindowRect((HWND)hwnd, &rect);
624 SetWindowPos((HWND)hwnd, NULL, x - (point.x - rect.left), y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
627 void org::xwt::plat::Win32$Win32Surface::setSize(jint w, jint h) {
628 RECT client_rect, window_rect;
629 GetClientRect((HWND)hwnd, &client_rect);
630 GetWindowRect((HWND)hwnd, &window_rect);
631 int addwidth = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
632 int addheight = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
633 SetWindowPos((HWND)hwnd, NULL, 0, 0, w + addwidth, h + addheight, SWP_NOZORDER | SWP_NOMOVE);
636 void org::xwt::plat::Win32$Win32Surface::setTitleBarText(java::lang::String* title) {
637 int len = min(1024, JvGetStringUTFLength(title));
640 JvGetStringUTFRegion(title, 0, len, buf);
641 SetWindowText((HWND)hwnd, buf);
644 void org::xwt::plat::Win32$Win32Surface::setIcon(org::xwt::Picture* p0) {
646 org::xwt::plat::Win32$Win32Picture* p = (org::xwt::plat::Win32$Win32Picture*)p0;
647 int icon_width = GetSystemMetrics(SM_CXSMICON);
648 int icon_height = GetSystemMetrics(SM_CYSMICON);
651 HBITMAP bit = CreateCompatibleBitmap((HDC)hdc, icon_width, icon_height);
652 HDC memdc = CreateCompatibleDC((HDC)hdc);
653 SelectObject(memdc, bit);
654 BLT((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, p->getWidth(), p->getHeight(), SRCCOPY);
657 jint* dat = elements(p->data);
658 HBITMAP bit_mask = CreateBitmap(icon_width, icon_height * 2, 1, 1, NULL);
659 SelectObject(memdc, bit_mask);
660 for(int x=0; x<icon_width; x++)
661 for(int y=0; y<icon_height; y++) {
662 int source = dat[(x * p->getWidth()) / icon_width + ((y * p->getHeight()) / icon_height) * (p->getWidth())];
663 if ((source & 0xFF000000) != 0x00000000) SetPixel(memdc, x, y, PALETTERGB(0, 0, 0));
664 else SetPixel(memdc, x, y, PALETTERGB(255, 255, 255));
667 // instantiate the icon and assign it to the window class
670 ici.hbmMask = bit_mask;
672 HICON hicon = CreateIconIndirect(&ici);
673 HICON oldicon = (HICON)SetClassLong((HWND)hwnd, GCL_HICONSM, (LONG)hicon);
674 if (oldicon != NULL) DestroyIcon(oldicon);
678 static jstring keyToString(WPARAM wParam);
679 jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _wParam, jint _lParam) {
681 UINT iMsg = (UINT)_iMsg;
682 WPARAM wParam = (WPARAM)_wParam;
683 LPARAM lParam = (LPARAM)_lParam;
685 int oldmousex, oldmousey;
695 case WM_DEVMODECHANGE: break; // FEATURE: color depth changed
696 case WM_DISPLAYCHANGE: break; // FEATURE: screen size changed
697 case WM_FONTCHANGE: break; // FEATURE: set of fonts changed
698 case WM_MOUSEWHEEL: break; // FEATURE: Mouse Wheel
700 case WM_SYSKEYDOWN: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
702 KeyPressed(keyToString(wParam));
705 case WM_SYSKEYUP: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
707 KeyReleased(keyToString(wParam));
710 case WM_SETFOCUS: Focused(true); return 0;
711 case WM_KILLFOCUS: Focused(false); return 0;
712 case WM_LBUTTONDBLCLK: DoubleClick(1); return 0;
713 case WM_RBUTTONDBLCLK: DoubleClick(2); return 0;
714 case WM_MBUTTONDBLCLK: DoubleClick(3); return 0;
715 case WM_LBUTTONDOWN: Press(1); return 0;
716 case WM_RBUTTONDOWN: Press(2); return 0;
717 case WM_MBUTTONDOWN: Press(3); return 0;
718 case WM_CLOSE: Close(); return 0;
719 case WM_ERASEBKGND: return 0;
724 Release(iMsg == WM_LBUTTONUP ? 1 : (iMsg == WM_RBUTTONUP ? 2 : 3));
725 if (captured && !inside) {
727 SetCursor((HCURSOR)previous_cursor);
732 GetClientRect((HWND)hwnd, &rect);
733 PosChange(rect.left, rect.top);
737 if (wParam == SIZE_MINIMIZED) {
738 if (maximized) Maximized(false);
740 } else if (wParam == SIZE_MAXIMIZED) {
741 if (minimized) Minimized(false);
744 if (minimized) Minimized(false);
745 if (maximized) Maximized(false);
747 // deliberately fall through to WM_SIZING
750 GetClientRect((HWND)hwnd, &rect);
751 SizeChange(rect.right - rect.left, rect.bottom - rect.top);
755 if (mousex == lParam & 0xFFFF && mousey == (lParam & 0xFFFF0000) >> 16) return 0;
757 GetClientRect((HWND)hwnd, &rect);
758 point.x = mouse_x = lParam & 0xFFFF;
759 point.y = mouse_y = (lParam & 0xFFFF0000) >> 16;
760 ClientToScreen((HWND)hwnd, &point);
761 hwnd2 = WindowFromPoint(point);
763 newinside = hwnd2 == (HWND)hwnd && mouse_x > 0 && mouse_y > 0 && mouse_x < (rect.right - rect.left) && mouse_y < (rect.bottom - rect.top) ? 1 : 0;
765 Move(mouse_x, mouse_y);
767 if (newinside && !inside) {
769 SetCapture((HWND)hwnd);
771 previous_cursor = (jint)GetCursor();
772 PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0);
774 } else if (!newinside && inside) {
776 if (!button1 && !button2 && !button3) {
779 SetCursor((HCURSOR)previous_cursor);
785 case WM_USER_SETCURSOR:
786 // I can't find documentation of this anywhere, but in my experience, an event must be received between an invocation
787 // of SetCapture() and SetCursor(). Furthermore, it seems that after calling SetCursor(), the cursor will not change until a
788 // return from WndProc (ie the completion of the processing of some event). Hence, we use WM_USER to indicate that the screen
789 // cursor should be re-set to "current_cursor".
790 SetCursor((HCURSOR)current_cursor);
793 case WM_USER_DISPOSE:
794 // used to signal that we should destroy ourselves
795 DestroyWindow((HWND)hwnd);
798 case WM_GETMINMAXINFO:
799 mmi = (MINMAXINFO*)lParam;
800 mmi->ptMinTrackSize.x = root->dmin(0);
801 mmi->ptMinTrackSize.y = root->dmin(1);
802 mmi->ptMaxTrackSize.x = root->dmax(0);
803 mmi->ptMaxTrackSize.y = root->dmax(1);
808 BeginPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
809 Dirty(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
810 EndPaint((HWND)org::xwt::plat::Win32$Win32Surface::hwnd, &ps);
816 return DefWindowProc((HWND)hwnd, iMsg, wParam, lParam);
820 // Key Translator Helper /////////////////////////////////////////////////////////////////////
822 static char keyarr [256] = { 0 };
823 static jstring keyToString(WPARAM wParam) {
825 keyarr[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
826 keyarr[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
827 keyarr[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
828 keyarr[VK_SHIFT] = GetKeyState(VK_SHIFT);
830 if (ToAsciiEx(wParam, 0, (BYTE*)keyarr, (WORD*)arr, 0, GetKeyboardLayout(0)) == 1) {
832 case '\t': return JvNewStringLatin1("tab");
833 case 0x1b: return JvNewStringLatin1("escape");
834 case '\n': return JvNewStringLatin1("enter");
835 case '\r': return JvNewStringLatin1("enter");
836 case 0x08: return JvNewStringLatin1("back_space");
837 default: return JvNewStringLatin1(arr, 1);
840 } else switch (wParam) {
841 case VK_CLEAR: return JvNewStringLatin1("clear");
842 case VK_SHIFT: return JvNewStringLatin1("shift");
843 case VK_CONTROL: return JvNewStringLatin1("control");
844 case VK_CAPITAL: return JvNewStringLatin1("caps_lock");
845 case VK_MENU: return JvNewStringLatin1("alt");
846 case VK_PAUSE: return JvNewStringLatin1("pause");
847 case VK_PRIOR: return JvNewStringLatin1("page_up");
848 case VK_NEXT: return JvNewStringLatin1("page_down");
849 case VK_END: return JvNewStringLatin1("end");
850 case VK_HOME: return JvNewStringLatin1("home");
851 case VK_LEFT: return JvNewStringLatin1("left");
852 case VK_UP: return JvNewStringLatin1("up");
853 case VK_RIGHT: return JvNewStringLatin1("right");
854 case VK_DOWN: return JvNewStringLatin1("down");
855 case VK_INSERT: return JvNewStringLatin1("insert");
856 case VK_DELETE: return JvNewStringLatin1("delete");
857 case VK_NUMPAD0: return JvNewStringLatin1("numpad0");
858 case VK_NUMPAD1: return JvNewStringLatin1("numpad1");
859 case VK_NUMPAD2: return JvNewStringLatin1("numpad2");
860 case VK_NUMPAD3: return JvNewStringLatin1("numpad3");
861 case VK_NUMPAD4: return JvNewStringLatin1("numpad4");
862 case VK_NUMPAD5: return JvNewStringLatin1("numpad5");
863 case VK_NUMPAD6: return JvNewStringLatin1("numpad6");
864 case VK_NUMPAD7: return JvNewStringLatin1("numpad7");
865 case VK_NUMPAD8: return JvNewStringLatin1("numpad8");
866 case VK_NUMPAD9: return JvNewStringLatin1("numpad9");
867 case VK_F1: return JvNewStringLatin1("f1");
868 case VK_F2: return JvNewStringLatin1("f2");
869 case VK_F3: return JvNewStringLatin1("f3");
870 case VK_F4: return JvNewStringLatin1("f4");
871 case VK_F5: return JvNewStringLatin1("f5");
872 case VK_F6: return JvNewStringLatin1("f6");
873 case VK_F7: return JvNewStringLatin1("f7");
874 case VK_F8: return JvNewStringLatin1("f8");
875 case VK_F9: return JvNewStringLatin1("f9");
876 case VK_F10: return JvNewStringLatin1("f10");
877 case VK_F11: return JvNewStringLatin1("f11");
878 case VK_F12: return JvNewStringLatin1("f12");
879 case VK_NUMLOCK: return JvNewStringLatin1("num_lock");
880 case VK_SCROLL: return JvNewStringLatin1("scroll_lock");
881 case VK_LSHIFT: return JvNewStringLatin1("shift");
882 case VK_RSHIFT: return JvNewStringLatin1("shift");
883 case VK_LCONTROL: return JvNewStringLatin1("control");
884 case VK_RCONTROL: return JvNewStringLatin1("control");
892 ///////////////////////////////////////////////////////////////////////////////////////
893 ///////////////////////////////////////////////////////////////////////////////////////
894 ///////////////////////////////////////////////////////////////////////////////////////
896 #else /* COMPILE_DLL */
900 // A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
904 #include <initguid.h>
911 // Globals ////////////////////////////////////////////////////////////////////////
915 #define CLSID_STRING_SIZE 39
917 const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
918 const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
919 const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
920 extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
921 static HMODULE g_hModule = NULL; //DLL handle
926 // Superclasses ////////////////////////////////////////////////////////////////////////
928 // Option bit definitions for IObjectSafety:
929 #define INTERFACESAFE_FOR_UNTRUSTED_CALLER 0x00000001 // Caller of interface may be untrusted
930 #define INTERFACESAFE_FOR_UNTRUSTED_DATA 0x00000002 // Data passed into interface may be untrusted
932 // {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
933 DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
935 interface IObjectSafety : public IUnknown {
937 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
938 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
941 interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
945 // Entry Points ////////////////////////////////////////////////////////////////////////
947 // to get mingw to stop nagging me
948 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
950 // determines whether or not the DLL can be unloaded; always allow this since we don't do too much
951 STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
953 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
954 if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
960 // Other ///////////////////////////////////////////////////////////////////////////////////
962 // simple assert() replacement that pops open a message box if there are errors
963 void check(int val, char* message) {
965 MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
970 void clsidToString(const CLSID& clsid, char* str, int length) {
971 check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
972 LPOLESTR wide_str = NULL;
973 HRESULT hr = StringFromCLSID(clsid, &wide_str);
974 check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
975 wcstombs(str, wide_str, length);
976 CoTaskMemFree(wide_str);
979 void setRegistryKey(const char* key, const char* subkey, const char* value) {
983 if (subkey != NULL) {
984 strcat(keyBuf, "\\");
985 strcat(keyBuf, subkey );
987 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
989 check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
990 "RegSetValueEx() failed in setRegistryKey()");
994 void deleteRegistryKey(HKEY parent, const char* target) {
996 RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
998 // Iterate over children, deleting them
1002 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
1003 deleteRegistryKey(hKeyChild, szBuffer);
1007 RegCloseKey(hKeyChild);
1008 RegDeleteKey(parent, target);
1011 STDAPI __declspec(dllexport) DllRegisterServer(void) {
1012 char moduleName[512];
1013 HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
1014 check(result, "GetModuleFileName() failed in RegisterServer()");
1016 char clsidString[CLSID_STRING_SIZE];
1017 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
1021 strcpy(key, "CLSID\\");
1022 strcat(key, clsidString);
1024 setRegistryKey(key, NULL, XWT_friendlyName);
1025 setRegistryKey(key, "InprocServer32", moduleName);
1026 setRegistryKey(key, "ProgID", XWT_programID);
1027 setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
1028 setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName);
1029 setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
1030 setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
1031 setRegistryKey(XWT_programID, NULL, XWT_friendlyName);
1032 setRegistryKey(XWT_programID, "CLSID", clsidString);
1036 STDAPI __declspec(dllexport) DllUnregisterServer(void) {
1037 char clsidString[CLSID_STRING_SIZE];
1038 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
1042 strcpy(key, "CLSID\\");
1043 strcat(key, clsidString);
1045 deleteRegistryKey(HKEY_CLASSES_ROOT, key);
1046 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
1047 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
1053 // ShoeHorn //////////////////////////////////////////////////////////////////////////////////
1055 class ShoeHorn : public IShoeHorn {
1057 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
1058 if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
1059 else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
1060 else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
1061 else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
1062 else { *ppv = NULL; return E_NOINTERFACE; }
1063 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1066 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1067 virtual ULONG __stdcall Release() {
1068 if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
1071 virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
1072 virtual HRESULT __stdcall InitNew() { return S_OK; }
1073 virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
1074 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
1075 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
1076 if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1077 if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
1081 virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
1089 MultiByteToWideChar(CP_ACP, 0, "initial-xwar-url", -1, wc, 100);
1090 pPropBag->Read(wc, &v, pErrorLog);
1091 check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
1092 "WideCharToMultiByte() failed in ShoeHorn::Load()");
1095 LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
1096 check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
1098 // iterate over all the activex cache locations until we find ourselves
1099 for(int i=0; i<9; i++) {
1108 result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
1109 if (result != ERROR_SUCCESS)
1111 check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
1118 for(int i=0; i<200; i++) cmdline[i] = '\0';
1119 strncpy(cmdline, buf, 200);
1120 strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
1121 strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
1122 strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
1124 PROCESS_INFORMATION pInfo;
1126 sInfo.cb = sizeof(STARTUPINFO);
1127 sInfo.lpReserved = NULL;
1128 sInfo.lpReserved2 = NULL;
1129 sInfo.cbReserved2 = 0;
1130 sInfo.lpDesktop = NULL;
1131 sInfo.lpTitle = NULL;
1135 sInfo.dwFillAttribute = 0;
1136 sInfo.wShowWindow = SW_SHOW;
1137 BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
1141 check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
1144 ShoeHorn() : m_cRef(1) { };
1146 private: long m_cRef;
1152 // ClassFactory //////////////////////////////////////////////////////////////////////////
1154 class ClassFactory : public IClassFactory {
1156 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
1157 if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
1158 else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
1161 return E_NOINTERFACE;
1163 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
1167 ClassFactory() : m_cRef(1) { }
1169 virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
1170 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
1171 virtual ULONG __stdcall Release() {
1172 if(InterlockedDecrement(&m_cRef) == 0) {
1179 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
1180 if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
1181 ShoeHorn* s = new ShoeHorn;
1182 if(s == NULL) return E_OUTOFMEMORY;
1183 HRESULT hr = s->QueryInterface(iid, ppv);
1188 private: long m_cRef;
1192 extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
1193 if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
1194 ClassFactory* pFactory = new ClassFactory;
1195 if(pFactory == NULL) return E_OUTOFMEMORY;
1196 HRESULT hr = pFactory->QueryInterface(iid, ppv);
1197 pFactory->Release();