static LRESULT CALLBACK html_proc(HWND win, UINT msg, WPARAM wp, LPARAM lp) { html_t* html = (html_t*) GetWindowLongPtr(win, 0); if(html != NULL && html->ie_win == NULL) { /* Let's try to subclass IE window. This is very dirty hack, * which allows us to forward keyboard messages properly to * IOleInPlaceActiveObject::TranslateAccelerator(). * * Normally this should be done from main app. loop but we do not * have it under control in the DLL. */ html->ie_win = html_find_ie_window(win); if(html->ie_win != NULL) { HTML_TRACE("html_proc: Subclassing MSIE."); html->ie_proc = (WNDPROC) SetWindowLongPtr(html->ie_win, GWLP_WNDPROC, (LONG_PTR) html_ie_subclass_proc); SetProp(html->ie_win, ie_prop, (HANDLE) html); if(GetFocus() == win) { SetFocus(html->ie_win); MC_SEND(html->ie_win, WM_LBUTTONDOWN, 0, 0); MC_SEND(html->ie_win, WM_LBUTTONUP, 0, 0); } } } switch(msg) { case MC_HM_GOTOURLW: case MC_HM_GOTOURLA: { int res = html_goto_url(html, (const void*)lp, (msg == MC_HM_GOTOURLW)); return (res == 0 ? TRUE : FALSE); } case MC_HM_SETTAGCONTENTSW: case MC_HM_SETTAGCONTENTSA: { int res = html_set_element_contents(html, (void*)wp, (void*)lp, (msg == MC_HM_SETTAGCONTENTSW)); return (res == 0 ? TRUE : FALSE); } case MC_HM_GOBACK: { int res = html_goto_back(html, wp); return (res == 0 ? TRUE : FALSE); } case MC_HM_CANBACK: return ((wp ? html->can_back : html->can_forward) ? TRUE : FALSE); case WM_SIZE: { IWebBrowser2* browser_iface; HRESULT hr; hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj, &IID_IWebBrowser2, (void**)&browser_iface); if(hr == S_OK && browser_iface != NULL) { browser_iface->lpVtbl->put_Width(browser_iface, LOWORD(lp)); browser_iface->lpVtbl->put_Height(browser_iface, HIWORD(lp)); browser_iface->lpVtbl->Release(browser_iface); } return 0; } case WM_STYLECHANGED: if(wp == GWL_STYLE) { STYLESTRUCT* ss = (STYLESTRUCT*) lp; html->style = ss->styleNew; RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN); } break; case WM_NOTIFYFORMAT: switch(lp) { case NF_REQUERY: html_notify_format(html); return (html->unicode_notifications ? NFR_UNICODE : NFR_ANSI); case NF_QUERY: return (MC_IS_UNICODE ? NFR_UNICODE : NFR_ANSI); } break; case CCM_SETUNICODEFORMAT: { BOOL tmp = html->unicode_notifications; html->unicode_notifications = (wp != 0); return tmp; } case CCM_GETUNICODEFORMAT: return html->unicode_notifications; case CCM_SETNOTIFYWINDOW: { HWND old = html->notify_win; html->notify_win = (wp ? (HWND) wp : GetAncestor(win, GA_PARENT)); return (LPARAM) old; } case WM_SETFOCUS: if(html->ie_win) { SetFocus(html->ie_win); MC_SEND(html->ie_win, WM_LBUTTONDOWN, 0, 0); MC_SEND(html->ie_win, WM_LBUTTONUP, 0, 0); } return 0; case WM_GETDLGCODE: return DLGC_WANTALLKEYS; case WM_SETTEXT: return FALSE; case WM_GETTEXT: if(wp > 0) ((TCHAR*)lp)[0] = _T('\0'); return 0; case WM_GETTEXTLENGTH: return 0; case WM_NCCREATE: html = html_nccreate(win, (CREATESTRUCT*)lp); if(MC_ERR(html == NULL)) return FALSE; SetWindowLongPtr(win, 0, (LONG_PTR)html); return TRUE; case WM_CREATE: return (html_create(html, (CREATESTRUCT*)lp) == 0 ? 0 : -1); case WM_DESTROY: html_destroy(html); return 0; case WM_NCDESTROY: if(html) html_ncdestroy(html); return 0; } /* Forward keystrokes to the IE */ if(WM_KEYFIRST <= msg && msg <= WM_KEYLAST) { if(html->ie_win) MC_SEND(html->ie_win, msg, wp, lp); return 0; } return DefWindowProc(win, msg, wp, lp); }
static HRESULT STDMETHODCALLTYPE dispatch_Invoke(IDispatch* self, DISPID disp_id, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* params, VARIANT* var_res, EXCEPINFO* except, UINT* arg_err) { html_t* html = MC_HTML_FROM_DISPTACH(self); switch(disp_id) { case DISPID_BEFORENAVIGATE2: { BSTR url = V_BSTR(V_VARIANTREF(¶ms->rgvarg[5])); VARIANT_BOOL* cancel = V_BOOLREF(¶ms->rgvarg[0]); HTML_TRACE("dispatch_Invoke: DISPID_BEFORENAVIGATE2(%S)", url); if(url != NULL && wcsncmp(url, L"app:", 4) == 0) { html_notify_text(html, MC_HN_APPLINK, url); *cancel = VARIANT_TRUE; } break; } #if 0 /* Unfortunately, IE does not send DISPID_DOCUMENTCOMPLETE * when refreshing the page (e.g. from context menu). So we workaround * via DISPID_PROGRESSCHANGE below. */ case DISPID_DOCUMENTCOMPLETE: { BSTR url = V_BSTR(V_VARIANTREF(¶ms->rgvarg[0])); html_notify_text(html, MC_HN_DOCUMENTCOMPLETE, url); break; } #endif case DISPID_PROGRESSCHANGE: { LONG progress_max = V_I4(¶ms->rgvarg[0]); LONG progress = V_I4(¶ms->rgvarg[1]); MC_NMHTMLPROGRESS notify; HTML_TRACE("dispatch_Invoke: DISPID_PROGRESSCHANGE(%ld, %ld)", progress, progress_max); /* Send also notification about the progress */ notify.hdr.hwndFrom = html->win; notify.hdr.idFrom = GetDlgCtrlID(html->win); notify.hdr.code = MC_HN_PROGRESS; notify.lProgress = progress; notify.lProgressMax = progress_max; MC_SEND(html->notify_win, WM_NOTIFY, notify.hdr.idFrom, ¬ify); /* This replaces DISPID_DOCUMENTCOMPLETE above */ if(progress < 0 || progress_max < 0) { IWebBrowser2* browser_iface; HRESULT hr; hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj, &IID_IWebBrowser2, (void**)&browser_iface); if(MC_ERR(hr != S_OK || browser_iface == NULL)) { MC_TRACE("dispatch_Invoke(DISPID_PROGRESSCHANGE): " "QueryInterface(IID_IWebBrowser2) failed [0x%lx]", hr); } else { BSTR url = NULL; hr = browser_iface->lpVtbl->get_LocationURL(browser_iface, &url); if(hr == S_OK && url != NULL) { html_notify_text(html, MC_HN_DOCUMENTCOMPLETE, url); html_SysFreeString(url); } browser_iface->lpVtbl->Release(browser_iface); } } break; } case DISPID_STATUSTEXTCHANGE: HTML_TRACE("dispatch_Invoke: DISPID_STATUSTEXTCHANGE"); html_notify_text(html, MC_HN_STATUSTEXT, V_BSTR(¶ms->rgvarg[0])); break; case DISPID_TITLECHANGE: HTML_TRACE("dispatch_Invoke: DISPID_TITLECHANGE"); html_notify_text(html, MC_HN_TITLETEXT, V_BSTR(¶ms->rgvarg[0])); break; case DISPID_COMMANDSTATECHANGE: { LONG cmd = V_I4(¶ms->rgvarg[1]); HTML_TRACE("dispatch_Invoke: DISPID_COMMANDSTATECHANGE"); if(cmd == CSC_NAVIGATEBACK || cmd == CSC_NAVIGATEFORWARD) { MC_NMHTMLHISTORY notify; BOOL enabled = (V_BOOL(¶ms->rgvarg[0]) != VARIANT_FALSE); if(cmd == CSC_NAVIGATEBACK) html->can_back = enabled; else html->can_forward = enabled; notify.hdr.hwndFrom = html->win; notify.hdr.idFrom = GetDlgCtrlID(html->win); notify.hdr.code = MC_HN_HISTORY; notify.bCanBack = html->can_back; notify.bCanForward = html->can_forward; MC_SEND(html->notify_win, WM_NOTIFY, notify.hdr.idFrom, ¬ify); } break; } case DISPID_NEWWINDOW2: /* This is called instead of DISPID_NEWWINDOW3 on Windows XP SP2 * and older. */ { VARIANT_BOOL* cancel = V_BOOLREF(¶ms->rgvarg[0]); HTML_TRACE("dispatch_Invoke: DISPID_NEWWINDOW2"); if(html_notify_text(html, MC_HN_NEWWINDOW, L"") == 0) { *cancel = VARIANT_TRUE; HTML_TRACE("dispatch_Invoke(DISPID_NEWWINDOW2): Canceled."); } break; } case DISPID_NEWWINDOW3: { BSTR url = V_BSTR(¶ms->rgvarg[0]); VARIANT_BOOL* cancel = V_BOOLREF(¶ms->rgvarg[3]); HTML_TRACE("dispatch_Invoke: DISPID_NEWWINDOW3"); if(html_notify_text(html, MC_HN_NEWWINDOW, url) == 0) { *cancel = VARIANT_TRUE; HTML_TRACE("dispatch_Invoke(DISPID_NEWWINDOW3, '%S'): Canceled.", url); } break; } default: HTML_TRACE("dispatch_Invoke: unsupported disp_id %d", disp_id); return DISP_E_MEMBERNOTFOUND; } return S_OK; }
static int html_create(html_t* html, CREATESTRUCT* cs) { IWebBrowser2* browser_iface = NULL; IConnectionPointContainer* conn_point_container; IConnectionPoint* conn_point; DWORD cookie; RECT rect; HRESULT hr; /* Initialize OLE. It is here and not in html_init() because it has to * be performed in the thread where OLE shall be used (i.e. where * the message loop controlling the window is running). */ hr = html_OleInitialize(NULL); if(MC_ERR(FAILED(hr))) { MC_TRACE("html_create: OleInitialize() failed [0x%lx]", hr); return -1; } html->ole_initialized = 1; /* Create browser object */ hr = html_CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC, &IID_IOleObject, (void**)&html->browser_obj); if(MC_ERR(FAILED(hr))) { MC_TRACE("html_create: CoCreateInstance(CLSID_WebBrowser) failed " "[0x%lx]", hr); return -1; } /* Embed the browser object into our host window */ hr = html->browser_obj->lpVtbl->SetClientSite(html->browser_obj, &html->client_site); if(MC_ERR(FAILED(hr))) { MC_TRACE("html_create: IOleObject::SetClientSite() failed [0x%lx]", hr); return -1; } GetClientRect(html->win, &rect); hr = html->browser_obj->lpVtbl->DoVerb(html->browser_obj, OLEIVERB_INPLACEACTIVATE, NULL, &html->client_site, 0, html->win, &rect); if(MC_ERR(FAILED(hr))) { MC_TRACE("html_create: IOleObject::DoVerb(OLEIVERB_INPLACEACTIVATE) " "failed [0x%lx]", hr); return -1; } /* Send events of DIID_DWebBrowserEvents2 to our IDispatch */ hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj, &IID_IConnectionPointContainer, (void**)&conn_point_container); if(MC_ERR(hr != S_OK || conn_point_container == NULL)) { MC_TRACE("html_create: QueryInterface(IID_IConnectionPointContainer) failed " "[0x%lx]", hr); return -1; } hr = conn_point_container->lpVtbl->FindConnectionPoint(conn_point_container, &DIID_DWebBrowserEvents2, &conn_point); conn_point_container->lpVtbl->Release(conn_point_container); if(MC_ERR(FAILED(hr))) { MC_TRACE("html_create: FindConnectionPoint(DIID_DWebBrowserEvents2) failed " "[0x%lx]", hr); return -1; } conn_point->lpVtbl->Advise(conn_point, (IUnknown*)&html->client_site, &cookie); conn_point->lpVtbl->Release(conn_point); /* Set browser position and size according to the host window */ hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj, &IID_IWebBrowser2, (void**)&browser_iface); if(MC_ERR(hr != S_OK || browser_iface == NULL)) { MC_TRACE("html_create: QueryInterface(IID_IWebBrowser2) failed " "[0x%lx]", hr); return -1; } browser_iface->lpVtbl->put_Left(browser_iface, 0); browser_iface->lpVtbl->put_Top(browser_iface, 0); #if 0 /* these are set in WM_SIZE handler */ browser_iface->lpVtbl->put_Width(browser_iface, MC_WIDTH(&rect)); browser_iface->lpVtbl->put_Height(browser_iface, MC_HEIGHT(&rect)); #endif browser_iface->lpVtbl->Release(browser_iface); /* Goto specified URL if any */ if(cs->lpszName != NULL && cs->lpszName[0] != _T('\0')) html_goto_url(html, cs->lpszName, MC_IS_UNICODE); return 0; }
static int html_set_element_contents(html_t* html, const void* id, const void* contents, BOOL unicode) { BSTR bstr_id; BSTR bstr_contents; IWebBrowser2* browser_iface; IDispatch* dispatch_iface; IHTMLDocument3* doc_iface; IHTMLElement* elem_iface; HRESULT hr; int res = -1; if(MC_ERR(id == NULL || (unicode && ((WCHAR*)id)[0] == L'\0') || (!unicode && ((char*)id)[0] == '\0'))) { MC_TRACE("html_set_element_contents: Empty element ID."); SetLastError(ERROR_INVALID_PARAMETER); goto err_id; } bstr_id = html_bstr(id, (unicode ? MC_STRW : MC_STRA)); if(MC_ERR(bstr_id == NULL)) { MC_TRACE("html_set_element_contents: html_bstr(id) failed."); mc_send_notify(html->notify_win, html->win, NM_OUTOFMEMORY); goto err_id; } bstr_contents = html_bstr(contents, (unicode ? MC_STRW : MC_STRA)); if(MC_ERR(bstr_contents == NULL)) { MC_TRACE("html_set_element_contents: html_bstr(contents) failed"); mc_send_notify(html->notify_win, html->win, NM_OUTOFMEMORY); goto err_contents; } hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj, &IID_IWebBrowser2, (void**)&browser_iface); if(MC_ERR(hr != S_OK || browser_iface == NULL)) { MC_TRACE("html_set_element_contents: " "QueryInterface(IID_IWebBrowser2) failed [0x%lx]", hr); goto err_browser; } hr = browser_iface->lpVtbl->get_Document(browser_iface, &dispatch_iface); if(MC_ERR(FAILED(hr) || dispatch_iface == NULL)) { MC_TRACE("html_set_element_contents: get_Document() failed [0x%lx]", hr); goto err_dispatch; } hr = dispatch_iface->lpVtbl->QueryInterface(dispatch_iface, &IID_IHTMLDocument3, (void**)&doc_iface); if(MC_ERR(hr != S_OK || doc_iface == NULL)) { MC_TRACE("html_set_element_contents: " "QueryInterface(IID_IHTMLDocument3) failed [0x%lx]", hr); goto err_doc; } hr = doc_iface->lpVtbl->getElementById(doc_iface, bstr_id, &elem_iface); if(MC_ERR(FAILED(hr) || elem_iface == NULL)) { MC_TRACE("html_set_element_contents: getElementById() failed [0x%lx]", hr); goto err_elem; } hr = elem_iface->lpVtbl->put_innerHTML(elem_iface, bstr_contents); if(MC_ERR(hr != S_OK)) { MC_TRACE("html_set_element_contents: put_innerHTML() failed [0x%lx]", hr); goto err_inner_html; } res = 0; err_inner_html: elem_iface->lpVtbl->Release(elem_iface); err_elem: doc_iface->lpVtbl->Release(doc_iface); err_doc: dispatch_iface->lpVtbl->Release(dispatch_iface); err_dispatch: browser_iface->lpVtbl->Release(browser_iface); err_browser: html_SysFreeString(bstr_contents); err_contents: html_SysFreeString(bstr_id); err_id: return res; }
static LRESULT CALLBACK grid_proc(HWND win, UINT msg, WPARAM wp, LPARAM lp) { grid_t* grid = (grid_t*) GetWindowLongPtr(win, 0); switch(msg) { case WM_PAINT: return generic_paint(win, grid->no_redraw, (grid->style & MC_GS_DOUBLEBUFFER), grid_paint, grid); case WM_PRINTCLIENT: return generic_printclient(win, (HDC) wp, grid_paint, grid); case WM_NCPAINT: return generic_ncpaint(win, grid->theme_listview, (HRGN) wp); case WM_ERASEBKGND: return generic_erasebkgnd(win, grid->theme_listview, (HDC) wp); case MC_GM_GETTABLE: return (LRESULT) grid->table; case MC_GM_SETTABLE: return (grid_set_table(grid, (table_t*) lp) == 0 ? TRUE : FALSE); case MC_GM_GETCOLUMNCOUNT: return grid->col_count; case MC_GM_GETROWCOUNT: return grid->row_count; case MC_GM_RESIZE: return (grid_resize_table(grid, LOWORD(wp), HIWORD(wp)) == 0 ? TRUE : FALSE); case MC_GM_CLEAR: return (grid_clear(grid, wp) == 0 ? TRUE : FALSE); case MC_GM_SETCELLW: case MC_GM_SETCELLA: return (grid_set_cell(grid, LOWORD(wp), HIWORD(wp), (MC_TABLECELL*)lp, (msg == MC_GM_SETCELLW)) == 0 ? TRUE : FALSE); case MC_GM_GETCELLW: case MC_GM_GETCELLA: return (grid_get_cell(grid, LOWORD(wp), HIWORD(wp), (MC_TABLECELL*)lp, (msg == MC_GM_GETCELLW)) == 0 ? TRUE : FALSE); case MC_GM_SETGEOMETRY: return (grid_set_geometry(grid, (MC_GGEOMETRY*)lp, TRUE) == 0 ? TRUE : FALSE); case MC_GM_GETGEOMETRY: return (grid_get_geometry(grid, (MC_GGEOMETRY*)lp) == 0 ? TRUE : FALSE); case MC_GM_REDRAWCELLS: return (grid_redraw_cells(grid, LOWORD(wp), HIWORD(wp), LOWORD(lp), LOWORD(lp)) == 0 ? TRUE : FALSE); case MC_GM_SETCOLUMNWIDTH: return (grid_set_col_width(grid, wp, LOWORD(lp)) == 0 ? TRUE : FALSE); case MC_GM_GETCOLUMNWIDTH: return grid_get_col_width(grid, wp); case MC_GM_SETROWHEIGHT: return (grid_set_row_height(grid, wp, LOWORD(lp)) == 0 ? TRUE : FALSE); case MC_GM_GETROWHEIGHT: return grid_get_row_height(grid, wp); case WM_SETREDRAW: grid->no_redraw = !wp; return 0; case WM_VSCROLL: case WM_HSCROLL: grid_scroll(grid, (msg == WM_VSCROLL), LOWORD(wp), 1); return 0; case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: grid_mouse_wheel(grid, (msg == WM_MOUSEWHEEL), (int)(SHORT)HIWORD(wp)); return 0; case WM_SIZE: if(!grid->no_redraw) { int old_scroll_x = grid->scroll_x; int old_scroll_y = grid->scroll_y; grid_setup_scrollbars(grid, FALSE); if(grid->scroll_x != old_scroll_x || grid->scroll_y != old_scroll_y) InvalidateRect(win, NULL, TRUE); } return 0; case WM_GETFONT: return (LRESULT) grid->font; case WM_SETFONT: grid->font = (HFONT) wp; if((BOOL) lp && !grid->no_redraw) InvalidateRect(win, NULL, TRUE); return 0; case WM_STYLECHANGED: if(wp == GWL_STYLE) grid_style_changed(grid, (STYLESTRUCT*) lp); break; case WM_THEMECHANGED: grid_close_theme(grid); grid_open_theme(grid); if(!grid->no_redraw) RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE); return 0; case WM_SYSCOLORCHANGE: if(!grid->no_redraw) RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE); return 0; case WM_NOTIFYFORMAT: if(lp == NF_REQUERY) grid_notify_format(grid); return (grid->unicode_notifications ? NFR_UNICODE : NFR_ANSI); case CCM_SETUNICODEFORMAT: { BOOL old = grid->unicode_notifications; grid->unicode_notifications = (wp != 0); return old; } case CCM_GETUNICODEFORMAT: return grid->unicode_notifications; case CCM_SETNOTIFYWINDOW: { HWND old = grid->notify_win; grid->notify_win = (wp ? (HWND) wp : GetAncestor(win, GA_PARENT)); return (LRESULT) old; } case CCM_SETWINDOWTHEME: mcSetWindowTheme(win, (const WCHAR*) lp, NULL); return 0; case WM_NCCREATE: grid = grid_nccreate(win, (CREATESTRUCT*)lp); if(MC_ERR(grid == NULL)) return FALSE; SetWindowLongPtr(win, 0, (LONG_PTR)grid); return TRUE; case WM_CREATE: return (grid_create(grid) == 0 ? 0 : -1); case WM_DESTROY: grid_destroy(grid); return 0; case WM_NCDESTROY: if(grid) grid_ncdestroy(grid); return 0; } return DefWindowProc(win, msg, wp, lp); }
static int grid_set_table(grid_t* grid, table_t* table) { if(table != NULL && table == grid->table) return 0; if(MC_ERR(table != NULL && (grid->style & MC_GS_OWNERDATA))) { MC_TRACE("grid_set_table: Cannot install table while having style " "MC_GS_OWNERDATA"); SetLastError(ERROR_INVALID_STATE); return -1; } if(table != NULL) { table_ref(table); } else if(!(grid->style & (MC_GS_NOTABLECREATE | MC_GS_OWNERDATA))) { table = table_create(0, 0); if(MC_ERR(table == NULL)) { MC_TRACE("grid_set_table: table_create() failed."); return -1; } } if(table != NULL) { if(MC_ERR(table_install_view(table, grid, grid_refresh)) != 0) { MC_TRACE("grid_set_table: table_install_view() failed."); table_unref(table); return -1; } } if(grid->table != NULL) { table_uninstall_view(grid->table, grid); table_unref(grid->table); } grid->table = table; if(table != NULL) { grid->col_count = table->col_count; grid->row_count = table->row_count; } else { grid->col_count = 0; grid->row_count = 0; } grid->cache_hint[0] = 0; grid->cache_hint[1] = 0; grid->cache_hint[2] = 0; grid->cache_hint[3] = 0; if(grid->col_widths != NULL) { free(grid->col_widths); grid->col_widths = NULL; } if(grid->row_heights != NULL) { free(grid->row_heights); grid->row_heights = NULL; } if(!grid->no_redraw) { InvalidateRect(grid->win, NULL, TRUE); grid_setup_scrollbars(grid, TRUE); } return 0; }
void* xcom_init_create(const CLSID* clsid, DWORD context, const IID* iid) { void* obj; HRESULT hr; redo: switch(xcom_mode) { case XCOM_MODE_APP: /* The application already initialized COM so we do not manage it * at all and just reuse app's apartment. */ hr = CoCreateInstance(clsid, NULL, context, iid, &obj); if(MC_ERR(FAILED(hr))) { MC_TRACE_HR("xcom_create_init: CoCreateInstance(1) failed."); return NULL; } return obj; case XCOM_MODE_MCTRL: /* We are responsible to initialize COM whenever we want to use * it. According to Raymond Chen, we should use single-threaded * apartment (COINIT_APARTMENTTHREADED): * http://blogs.msdn.com/b/oldnewthing/archive/2008/04/24/8420242.aspx */ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if(MC_ERR(FAILED(hr))) { MC_TRACE_HR("xcom_create_init: CoInitializeEx() failed."); return NULL; } hr = CoCreateInstance(clsid, NULL, context, iid, &obj); if(MC_ERR(FAILED(hr))) { MC_TRACE_HR("xcom_create_init: CoCreateInstance(2) failed."); CoUninitialize(); return NULL; } return obj; case XCOM_MODE_UNKNOWN: EnterCriticalSection(&xcom_lock); if(xcom_mode != XCOM_MODE_UNKNOWN) { /* Resolve a race. */ LeaveCriticalSection(&xcom_lock); goto redo; } hr = CoCreateInstance(clsid, NULL, context, iid, &obj); if(SUCCEEDED(hr)) { xcom_mode = XCOM_MODE_APP; } else if(hr == CO_E_NOTINITIALIZED) { xcom_mode = XCOM_MODE_MCTRL; } else { MC_TRACE_HR("xcom_create_init: CoCreateInstance(3) failed."); obj = NULL; } LeaveCriticalSection(&xcom_lock); if(hr == CO_E_NOTINITIALIZED) goto redo; return obj; default: MC_UNREACHABLE; return NULL; } }