user32: Add current keyboard layout to thread data.
[wine.git] / dlls / browseui / progressdlg.c
blob89e70e90201b051f72b9234157afe3985fdfce75
1 /*
2 * Progress dialog
4 * Copyright 2007 Mikolaj Zalewski
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
34 #include "shlguid.h"
35 #include "shlobj.h"
37 #include "wine/heap.h"
39 #include "browseui.h"
40 #include "resids.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(browseui);
44 #define CANCEL_MSG_LINE 2
46 /* Note: to avoid a deadlock we don't want to send messages to the dialog
47 * with the critical section held. Instead we only mark what fields should be
48 * updated and the dialog proc does the update */
49 #define UPDATE_PROGRESS 0x1
50 #define UPDATE_TITLE 0x2
51 #define UPDATE_LINE1 0x4
52 #define UPDATE_LINE2 (UPDATE_LINE1<<1)
53 #define UPDATE_LINE3 (UPDATE_LINE2<<2)
56 #define WM_DLG_UPDATE (WM_APP+1) /* set to the dialog when it should update */
57 #define WM_DLG_DESTROY (WM_APP+2) /* DestroyWindow must be called from the owning thread */
59 typedef struct tagProgressDialog {
60 IProgressDialog IProgressDialog_iface;
61 IOleWindow IOleWindow_iface;
62 LONG refCount;
63 CRITICAL_SECTION cs;
64 HWND hwnd;
65 DWORD dwFlags;
66 DWORD dwUpdate;
67 LPWSTR lines[3];
68 LPWSTR cancelMsg;
69 LPWSTR title;
70 BOOL isCancelled;
71 ULONGLONG ullCompleted;
72 ULONGLONG ullTotal;
73 HWND hwndDisabledParent; /* For modal dialog: the parent that need to be re-enabled when the dialog ends */
74 ULONGLONG startTime;
75 LPWSTR remainingMsg[2];
76 LPWSTR timeMsg[3];
77 } ProgressDialog;
79 static inline ProgressDialog *impl_from_IProgressDialog(IProgressDialog *iface)
81 return CONTAINING_RECORD(iface, ProgressDialog, IProgressDialog_iface);
84 static inline ProgressDialog *impl_from_IOleWindow(IOleWindow *iface)
86 return CONTAINING_RECORD(iface, ProgressDialog, IOleWindow_iface);
89 static void set_buffer(LPWSTR *buffer, LPCWSTR string)
91 IMalloc *malloc;
92 ULONG cb;
94 if (string == NULL)
95 string = L"";
96 CoGetMalloc(MEMCTX_TASK, &malloc);
98 cb = (lstrlenW(string) + 1)*sizeof(WCHAR);
99 if (*buffer == NULL || cb > IMalloc_GetSize(malloc, *buffer))
100 *buffer = IMalloc_Realloc(malloc, *buffer, cb);
101 memcpy(*buffer, string, cb);
104 struct create_params
106 ProgressDialog *This;
107 HANDLE hEvent;
108 HWND hwndParent;
111 static LPWSTR load_string(HINSTANCE hInstance, UINT uiResourceId)
113 WCHAR string[256];
114 LPWSTR ret;
116 LoadStringW(hInstance, uiResourceId, string, ARRAY_SIZE(string));
117 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(string) + 1) * sizeof(WCHAR));
118 lstrcpyW(ret, string);
119 return ret;
122 static void set_progress_marquee(ProgressDialog *This)
124 HWND hProgress = GetDlgItem(This->hwnd, IDC_PROGRESS_BAR);
125 SetWindowLongW(hProgress, GWL_STYLE,
126 GetWindowLongW(hProgress, GWL_STYLE)|PBS_MARQUEE);
129 static void update_dialog(ProgressDialog *This, DWORD dwUpdate)
131 if (dwUpdate & UPDATE_TITLE)
132 SetWindowTextW(This->hwnd, This->title);
134 if (dwUpdate & UPDATE_LINE1)
135 SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE, (This->isCancelled ? L"" : This->lines[0]));
136 if (dwUpdate & UPDATE_LINE2)
137 SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE+1, (This->isCancelled ? L"" : This->lines[1]));
138 if (dwUpdate & UPDATE_LINE3)
139 SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE+2, (This->isCancelled ? This->cancelMsg : This->lines[2]));
141 if (dwUpdate & UPDATE_PROGRESS)
143 ULONGLONG ullTotal = This->ullTotal;
144 ULONGLONG ullCompleted = This->ullCompleted;
146 /* progress bar requires 32-bit coordinates */
147 while (ullTotal >> 32)
149 ullTotal >>= 1;
150 ullCompleted >>= 1;
153 SendDlgItemMessageW(This->hwnd, IDC_PROGRESS_BAR, PBM_SETRANGE32, 0, (DWORD)ullTotal);
154 SendDlgItemMessageW(This->hwnd, IDC_PROGRESS_BAR, PBM_SETPOS, (DWORD)ullCompleted, 0);
158 static void load_time_strings(ProgressDialog *This)
160 int i;
162 for (i = 0; i < 2; i++)
164 if (!This->remainingMsg[i])
165 This->remainingMsg[i] = load_string(BROWSEUI_hinstance, IDS_REMAINING1 + i);
167 for (i = 0; i < 3; i++)
169 if (!This->timeMsg[i])
170 This->timeMsg[i] = load_string(BROWSEUI_hinstance, IDS_SECONDS + i);
174 static void end_dialog(ProgressDialog *This)
176 SendMessageW(This->hwnd, WM_DLG_DESTROY, 0, 0);
177 /* native doesn't re-enable the window? */
178 if (This->hwndDisabledParent)
179 EnableWindow(This->hwndDisabledParent, TRUE);
180 This->hwnd = NULL;
183 static INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
185 ProgressDialog *This = (ProgressDialog *)GetWindowLongPtrW(hwnd, DWLP_USER);
187 switch (msg)
189 case WM_INITDIALOG:
191 struct create_params *params = (struct create_params *)lParam;
193 /* Note: until we set the hEvent, the object is protected by
194 * the critical section held by StartProgress */
195 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)params->This);
196 This = params->This;
197 This->hwnd = hwnd;
199 if (This->dwFlags & PROGDLG_NOPROGRESSBAR)
200 ShowWindow(GetDlgItem(hwnd, IDC_PROGRESS_BAR), SW_HIDE);
201 if (This->dwFlags & PROGDLG_NOCANCEL)
202 ShowWindow(GetDlgItem(hwnd, IDCANCEL), SW_HIDE);
203 if (This->dwFlags & PROGDLG_MARQUEEPROGRESS)
204 set_progress_marquee(This);
205 if (This->dwFlags & PROGDLG_NOMINIMIZE)
206 SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) & (~WS_MINIMIZEBOX));
208 update_dialog(This, 0xffffffff);
209 This->dwUpdate = 0;
210 This->isCancelled = FALSE;
211 SetEvent(params->hEvent);
212 return TRUE;
215 case WM_DLG_UPDATE:
216 EnterCriticalSection(&This->cs);
217 update_dialog(This, This->dwUpdate);
218 This->dwUpdate = 0;
219 LeaveCriticalSection(&This->cs);
220 return TRUE;
222 case WM_DLG_DESTROY:
223 DestroyWindow(hwnd);
224 PostThreadMessageW(GetCurrentThreadId(), WM_NULL, 0, 0); /* wake up the GetMessage */
225 return TRUE;
227 case WM_CLOSE:
228 case WM_COMMAND:
229 if (msg == WM_CLOSE || wParam == IDCANCEL)
231 EnterCriticalSection(&This->cs);
232 This->isCancelled = TRUE;
234 if (!This->cancelMsg)
235 This->cancelMsg = load_string(BROWSEUI_hinstance, IDS_CANCELLING);
237 set_progress_marquee(This);
238 EnableWindow(GetDlgItem(This->hwnd, IDCANCEL), FALSE);
239 update_dialog(This, UPDATE_LINE1|UPDATE_LINE2|UPDATE_LINE3);
240 LeaveCriticalSection(&This->cs);
242 return TRUE;
244 return FALSE;
247 static DWORD WINAPI dialog_thread(LPVOID lpParameter)
249 /* Note: until we set the hEvent in WM_INITDIALOG, the ProgressDialog object
250 * is protected by the critical section held by StartProgress */
251 struct create_params *params = lpParameter;
252 ProgressDialog *This = params->This;
253 HWND hwnd;
254 MSG msg;
256 hwnd = CreateDialogParamW(BROWSEUI_hinstance, MAKEINTRESOURCEW(IDD_PROGRESS_DLG),
257 params->hwndParent, dialog_proc, (LPARAM)params);
259 while (GetMessageW(&msg, NULL, 0, 0) > 0)
261 if (!IsWindow(hwnd))
262 break;
263 if(!IsDialogMessageW(hwnd, &msg))
265 TranslateMessage(&msg);
266 DispatchMessageW(&msg);
270 IProgressDialog_Release(&This->IProgressDialog_iface);
271 return 0;
274 static void ProgressDialog_Destructor(ProgressDialog *This)
276 int i;
277 TRACE("destroying %p\n", This);
278 if (This->hwnd)
279 end_dialog(This);
280 for (i = 0; i < 3; i++)
281 heap_free(This->lines[i]);
282 heap_free(This->cancelMsg);
283 heap_free(This->title);
284 for (i = 0; i < 2; i++)
285 heap_free(This->remainingMsg[i]);
286 for (i = 0; i < 3; i++)
287 heap_free(This->timeMsg[i]);
288 This->cs.DebugInfo->Spare[0] = 0;
289 DeleteCriticalSection(&This->cs);
290 heap_free(This);
291 InterlockedDecrement(&BROWSEUI_refCount);
294 static HRESULT WINAPI ProgressDialog_QueryInterface(IProgressDialog *iface, REFIID iid, LPVOID *ppvOut)
296 ProgressDialog *This = impl_from_IProgressDialog(iface);
298 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), ppvOut);
299 if (!ppvOut)
300 return E_POINTER;
302 *ppvOut = NULL;
303 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IProgressDialog))
305 *ppvOut = iface;
307 else if (IsEqualIID(iid, &IID_IOleWindow))
309 *ppvOut = &This->IOleWindow_iface;
312 if (*ppvOut)
314 IProgressDialog_AddRef(iface);
315 return S_OK;
318 WARN("unsupported interface: %s\n", debugstr_guid(iid));
319 return E_NOINTERFACE;
322 static ULONG WINAPI ProgressDialog_AddRef(IProgressDialog *iface)
324 ProgressDialog *This = impl_from_IProgressDialog(iface);
325 return InterlockedIncrement(&This->refCount);
328 static ULONG WINAPI ProgressDialog_Release(IProgressDialog *iface)
330 ProgressDialog *This = impl_from_IProgressDialog(iface);
331 ULONG ret;
333 ret = InterlockedDecrement(&This->refCount);
334 if (ret == 0)
335 ProgressDialog_Destructor(This);
336 return ret;
339 static HRESULT WINAPI ProgressDialog_StartProgressDialog(IProgressDialog *iface, HWND hwndParent, IUnknown *punkEnableModeless, DWORD dwFlags, LPCVOID reserved)
341 static const INITCOMMONCONTROLSEX init = { sizeof(init), ICC_ANIMATE_CLASS };
342 ProgressDialog *This = impl_from_IProgressDialog(iface);
343 struct create_params params;
344 HANDLE hThread;
346 TRACE("(%p, %p, %x, %p)\n", iface, punkEnableModeless, dwFlags, reserved);
347 if (punkEnableModeless || reserved)
348 FIXME("Reserved parameters not null (%p, %p)\n", punkEnableModeless, reserved);
349 if (dwFlags & PROGDLG_NOTIME)
350 FIXME("Flags PROGDLG_NOTIME not supported\n");
352 InitCommonControlsEx( &init );
354 EnterCriticalSection(&This->cs);
356 if (This->hwnd)
358 LeaveCriticalSection(&This->cs);
359 return S_OK; /* as on XP */
361 This->dwFlags = dwFlags;
363 params.This = This;
364 params.hwndParent = hwndParent;
365 params.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
367 /* thread holds one reference to ensure clean shutdown */
368 IProgressDialog_AddRef(&This->IProgressDialog_iface);
370 hThread = CreateThread(NULL, 0, dialog_thread, &params, 0, NULL);
371 WaitForSingleObject(params.hEvent, INFINITE);
372 CloseHandle(params.hEvent);
373 CloseHandle(hThread);
375 This->hwndDisabledParent = NULL;
376 if (hwndParent && (dwFlags & PROGDLG_MODAL))
378 HWND hwndDisable = GetAncestor(hwndParent, GA_ROOT);
379 if (EnableWindow(hwndDisable, FALSE))
380 This->hwndDisabledParent = hwndDisable;
383 if (dwFlags & PROGDLG_AUTOTIME)
384 load_time_strings(This);
386 This->startTime = GetTickCount64();
387 LeaveCriticalSection(&This->cs);
389 return S_OK;
392 static HRESULT WINAPI ProgressDialog_StopProgressDialog(IProgressDialog *iface)
394 ProgressDialog *This = impl_from_IProgressDialog(iface);
396 EnterCriticalSection(&This->cs);
397 if (This->hwnd)
398 end_dialog(This);
399 LeaveCriticalSection(&This->cs);
401 return S_OK;
404 static HRESULT WINAPI ProgressDialog_SetTitle(IProgressDialog *iface, LPCWSTR pwzTitle)
406 ProgressDialog *This = impl_from_IProgressDialog(iface);
407 HWND hwnd;
409 TRACE("(%p, %s)\n", This, wine_dbgstr_w(pwzTitle));
411 EnterCriticalSection(&This->cs);
412 set_buffer(&This->title, pwzTitle);
413 This->dwUpdate |= UPDATE_TITLE;
414 hwnd = This->hwnd;
415 LeaveCriticalSection(&This->cs);
417 if (hwnd)
418 SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);
420 return S_OK;
423 static HRESULT WINAPI ProgressDialog_SetAnimation(IProgressDialog *iface, HINSTANCE hInstance, UINT uiResourceId)
425 ProgressDialog *This = impl_from_IProgressDialog(iface);
427 TRACE("(%p, %p, %u)\n", iface, hInstance, uiResourceId);
429 if (IS_INTRESOURCE(uiResourceId))
431 if (!SendDlgItemMessageW(This->hwnd, IDC_ANIMATION, ACM_OPENW, (WPARAM)hInstance, uiResourceId))
432 WARN("Failed to load animation\n");
435 return S_OK;
438 static BOOL WINAPI ProgressDialog_HasUserCancelled(IProgressDialog *iface)
440 ProgressDialog *This = impl_from_IProgressDialog(iface);
441 return This->isCancelled;
444 static void update_time_remaining(ProgressDialog *This, ULONGLONG ullCompleted, ULONGLONG ullTotal)
446 unsigned int remaining, remainder = 0;
447 ULONGLONG elapsed;
448 WCHAR line[128];
449 int i;
450 DWORD_PTR args[4];
452 if (!This->startTime || !ullCompleted || !ullTotal)
453 return;
455 elapsed = GetTickCount64() - This->startTime;
456 remaining = (elapsed * ullTotal / ullCompleted - elapsed) / 1000;
458 for (i = 0; remaining >= 60 && i < 2; i++)
460 remainder = remaining % 60;
461 remaining /= 60;
464 args[0] = remaining;
465 args[1] = (DWORD_PTR)This->timeMsg[i];
466 args[2] = remainder;
467 args[3] = (DWORD_PTR)This->timeMsg[i-1];
469 if (i > 0 && remaining < 2 && remainder != 0)
470 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
471 This->remainingMsg[1], 0, 0, line, ARRAY_SIZE(line), (__ms_va_list*)args);
472 else
473 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
474 This->remainingMsg[0], 0, 0, line, ARRAY_SIZE(line), (__ms_va_list*)args);
476 set_buffer(&This->lines[2], line);
477 This->dwUpdate |= UPDATE_LINE3;
480 static HRESULT WINAPI ProgressDialog_SetProgress64(IProgressDialog *iface, ULONGLONG ullCompleted, ULONGLONG ullTotal)
482 ProgressDialog *This = impl_from_IProgressDialog(iface);
483 HWND hwnd;
485 TRACE("(%p, 0x%s, 0x%s)\n", This, wine_dbgstr_longlong(ullCompleted), wine_dbgstr_longlong(ullTotal));
487 EnterCriticalSection(&This->cs);
488 This->ullTotal = ullTotal;
489 This->ullCompleted = ullCompleted;
490 This->dwUpdate |= UPDATE_PROGRESS;
491 hwnd = This->hwnd;
492 if (This->dwFlags & PROGDLG_AUTOTIME)
493 update_time_remaining(This, ullCompleted, ullTotal);
494 LeaveCriticalSection(&This->cs);
496 if (hwnd)
497 SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);
499 return S_OK; /* Windows sometimes returns S_FALSE */
502 static HRESULT WINAPI ProgressDialog_SetProgress(IProgressDialog *iface, DWORD dwCompleted, DWORD dwTotal)
504 return IProgressDialog_SetProgress64(iface, dwCompleted, dwTotal);
507 static HRESULT WINAPI ProgressDialog_SetLine(IProgressDialog *iface, DWORD dwLineNum, LPCWSTR pwzLine, BOOL bPath, LPCVOID reserved)
509 ProgressDialog *This = impl_from_IProgressDialog(iface);
510 HWND hwnd;
512 TRACE("(%p, %d, %s, %d)\n", This, dwLineNum, wine_dbgstr_w(pwzLine), bPath);
514 if (reserved)
515 FIXME("reserved pointer not null (%p)\n", reserved);
517 dwLineNum--;
518 if (dwLineNum >= 3) /* Windows seems to do something like that */
519 dwLineNum = 0;
521 EnterCriticalSection(&This->cs);
522 set_buffer(&This->lines[dwLineNum], pwzLine);
523 This->dwUpdate |= UPDATE_LINE1 << dwLineNum;
524 hwnd = (This->isCancelled ? NULL : This->hwnd); /* no sense to send the message if window cancelled */
525 LeaveCriticalSection(&This->cs);
527 if (hwnd)
528 SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);
530 return S_OK;
533 static HRESULT WINAPI ProgressDialog_SetCancelMsg(IProgressDialog *iface, LPCWSTR pwzMsg, LPCVOID reserved)
535 ProgressDialog *This = impl_from_IProgressDialog(iface);
536 HWND hwnd;
538 TRACE("(%p, %s)\n", This, wine_dbgstr_w(pwzMsg));
540 if (reserved)
541 FIXME("reserved pointer not null (%p)\n", reserved);
543 EnterCriticalSection(&This->cs);
544 set_buffer(&This->cancelMsg, pwzMsg);
545 This->dwUpdate |= UPDATE_LINE1 << CANCEL_MSG_LINE;
546 hwnd = (This->isCancelled ? This->hwnd : NULL); /* no sense to send the message if window not cancelled */
547 LeaveCriticalSection(&This->cs);
549 if (hwnd)
550 SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);
552 return S_OK;
555 static HRESULT WINAPI ProgressDialog_Timer(IProgressDialog *iface, DWORD dwTimerAction, LPCVOID reserved)
557 ProgressDialog *This = impl_from_IProgressDialog(iface);
559 FIXME("(%p, %d, %p) - stub\n", This, dwTimerAction, reserved);
561 if (reserved)
562 FIXME("Reserved field not NULL but %p\n", reserved);
564 return S_OK;
567 static const IProgressDialogVtbl ProgressDialogVtbl =
569 ProgressDialog_QueryInterface,
570 ProgressDialog_AddRef,
571 ProgressDialog_Release,
573 ProgressDialog_StartProgressDialog,
574 ProgressDialog_StopProgressDialog,
575 ProgressDialog_SetTitle,
576 ProgressDialog_SetAnimation,
577 ProgressDialog_HasUserCancelled,
578 ProgressDialog_SetProgress,
579 ProgressDialog_SetProgress64,
580 ProgressDialog_SetLine,
581 ProgressDialog_SetCancelMsg,
582 ProgressDialog_Timer
585 static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID iid, LPVOID *ppvOut)
587 ProgressDialog *This = impl_from_IOleWindow(iface);
588 return ProgressDialog_QueryInterface(&This->IProgressDialog_iface, iid, ppvOut);
591 static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
593 ProgressDialog *This = impl_from_IOleWindow(iface);
594 return ProgressDialog_AddRef(&This->IProgressDialog_iface);
597 static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
599 ProgressDialog *This = impl_from_IOleWindow(iface);
600 return ProgressDialog_Release(&This->IProgressDialog_iface);
603 static HRESULT WINAPI OleWindow_GetWindow(IOleWindow* iface, HWND* phwnd)
605 ProgressDialog *This = impl_from_IOleWindow(iface);
607 TRACE("(%p, %p)\n", This, phwnd);
608 EnterCriticalSection(&This->cs);
609 *phwnd = This->hwnd;
610 LeaveCriticalSection(&This->cs);
611 return S_OK;
614 static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow* iface, BOOL fEnterMode)
616 ProgressDialog *This = impl_from_IOleWindow(iface);
618 FIXME("(%p, %d): stub\n", This, fEnterMode);
619 return E_NOTIMPL;
622 static const IOleWindowVtbl OleWindowVtbl =
624 OleWindow_QueryInterface,
625 OleWindow_AddRef,
626 OleWindow_Release,
627 OleWindow_GetWindow,
628 OleWindow_ContextSensitiveHelp
632 HRESULT ProgressDialog_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
634 ProgressDialog *This;
635 if (pUnkOuter)
636 return CLASS_E_NOAGGREGATION;
638 This = heap_alloc_zero(sizeof(ProgressDialog));
639 if (This == NULL)
640 return E_OUTOFMEMORY;
642 This->IProgressDialog_iface.lpVtbl = &ProgressDialogVtbl;
643 This->IOleWindow_iface.lpVtbl = &OleWindowVtbl;
644 This->refCount = 1;
645 InitializeCriticalSection(&This->cs);
646 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ProgressDialog.cs");
648 TRACE("returning %p\n", This);
649 *ppOut = (IUnknown *)&This->IProgressDialog_iface;
650 InterlockedIncrement(&BROWSEUI_refCount);
651 return S_OK;