www.pudn.com > STBIHOST.rar > mainwnd.cpp


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// Use of this source code is subject to the terms of the Microsoft end-user 
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT. 
// If you did not accept the terms of the EULA, you are not authorized to use 
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your 
// install media. 
// 
/*++ 
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
PARTICULAR PURPOSE. 
 
Module Name:  mainwnd.cpp 
 
Abstract:  Implements the main window, the container for the webbrowser 
 
Functions: 
 
Notes: Most of the code resides here. The container and its interaction with the webbrowser control, 
        commandbar, statusbar etc. 
 
--*/ 
#include  
 
#include "stdafx.h" 
#include "stbihost.h" 
#include "mainwnd.h" 
#include "mshtmcid.h" 
#include "resource.h" 
#include "external.h" 
#include "rctlkeys.h" 
 
#define INITGUID 
#include "initguid.h" 
#include  
 
CComModule _Module; 
 
BEGIN_OBJECT_MAP(ObjectMap) 
    OBJECT_ENTRY_NON_CREATEABLE(CHostExternal) 
END_OBJECT_MAP() 
 
#define WINCLS_UUID TEXT("55efda90-063f-419c-9ce4-18c3d26c2ae2")	// window class 
#define REG_ROOTKEY TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main") 
#define REG_WMPVALUE TEXT("Windows Media Page") 
#define SAFEAREA_MARGIN 0.82	// SHDOCVW will display within this area of the container window 
 
DEFINE_GUID(CLSID_WebBrowser,       0x8856F961L, 0x340A, 0x11D0, 0xA9, 0x6B, 0x00, 0xC0, 0x4F, 0xD7, 0x05, 0xA2); 
DEFINE_GUID(IID_IWebBrowser,        0xEAB22AC1L, 0x30C1, 0x11CF, 0xA7, 0xEB, 0x00, 0x00, 0xC0, 0x5B, 0xAE, 0x0B); 
DEFINE_GUID(IID_IWebBrowser2,       0xD30C1661L, 0xCDAF, 0x11D0, 0x8A, 0x3E, 0x00, 0xC0, 0x4F, 0xC9, 0xE2, 0x6E); 
DEFINE_GUID(DIID_DWebBrowserEvents, 0xEAB22AC2L, 0x30C1, 0x11CF, 0xA7, 0xEB, 0x00, 0x00, 0xC0, 0x5B, 0xAE, 0x0B); 
DEFINE_GUID(DIID_DWebBrowserEvents2, 0x34A715A0L, 0x6587, 0x11D0, 0x92, 0x4A, 0x00, 0x20, 0xAF, 0xC7, 0xAC, 0x4D); 
DEFINE_GUID(IID_IWebBrowserApp,     0x0002DF05L, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); 
 
const GUID SID_SDocHost = { 0xc6504990, 0xd43e, 0x11cf, { 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a}}; 
 
LONG        glThreadCount	= 0; 
HWND		ghWndAddressEdit= NULL; 
HANDLE      ghExitEvent		= NULL; 
HINSTANCE   g_hInstance		= NULL; 
DWORD      g_dwMainWindowStackSize = 0x20000; 
 
void GetProxyOption(); 
 
 
static HRESULT FindString(); 
HRESULT HandleNewWindow2(LPTSTR lpszUrl, DISPPARAMS FAR* pdparams); 
BOOL RegisterMainWnd(); 
 
 
DWORD WINAPI NewWindow(LPVOID pParam) 
{ 
 
    CMainWnd *pWnd = (CMainWnd *)pParam; 
    MSG msg; 
    BOOL fRet; 
 
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 
 
    fRet = pWnd->Create(); 
 
    SetEvent(pWnd->hEvent); 
 
    if (!fRet) 
    { 
        pWnd->_pBrowser = NULL; 
        return 0; 
    } 
 
    while (GetMessage( &msg, NULL, 0, 0 ) ) 
    { 
        if(msg.message == WM_QUIT) 
            break; 
 
        if (!pWnd->PreTranslateMessage(&msg) && !(msg.message == WM_CHAR && msg.wParam == VK_TAB)) 
        { 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        } 
    } 
 
    pWnd->Release(); 
 
    CoUninitialize(); 
 
    InterlockedDecrement(&glThreadCount); 
    SetEvent(ghExitEvent); 
 
    return msg.wParam; 
} 
 
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow) 
{ 
	DEBUGMSG (1, (TEXT("\r\n\r\n### New instance of StbIHost ###\r\n") 
				  TEXT("### Command line is: %s"), lpCmdLine)); 
	// allow only one instance 
	HWND hWnd = FindWindow(WINCLS_UUID, NULL);	 
	if (hWnd) 
	{ 
		SetForegroundWindow((HWND)(((DWORD)hWnd) | 0x01)); 
		if (*lpCmdLine) 
		{ 
			COPYDATASTRUCT cds = { 1, 
								   sizeof(TCHAR)*(_tcslen(lpCmdLine) + 1), 
								   lpCmdLine }; 
			SendMessage(hWnd, WM_COPYDATA, NULL, (LPARAM)&cds); 
		} 
		return 0; 
	} 
 
    INITCOMMONCONTROLSEX iccsex; 
    HKEY hKey; 
    DWORD dwSize = sizeof(DWORD); 
    MSG msg; 
 
    // HKCU is where IE\Main settings are 
    if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_ROOTKEY, 0, 0, &hKey)) 
    { 
            RegQueryValueEx(hKey, TEXT("StackRes"), NULL, NULL, (LPBYTE)&g_dwMainWindowStackSize, &dwSize); 
            RegCloseKey(hKey); 
    } 
 
    // provide a default stack size if the one given is too small or too large.  
    if(g_dwMainWindowStackSize < 0x10000 || g_dwMainWindowStackSize > 0x80000) 
    { 
            // default to 128k 
            g_dwMainWindowStackSize = 0x20000; 
    } 
    RETAILMSG(1,(L"STBIHOST Using stack size: %x", g_dwMainWindowStackSize)); 
 
 
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 
    if (FAILED(hr)) 
    { 
        return FALSE; 
    } 
 
    hr = _Module.Init(ObjectMap, hInst, &LIBID_STBIHOSTLib); 
    ASSERT(SUCCEEDED(hr)); 
    hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); 
    ASSERT(SUCCEEDED(hr)); 
    hr = _Module.RegisterTypeLib(); 
    ASSERT(SUCCEEDED(hr)); 
 
    if (!RegisterMainWnd()) 
        return FALSE; 
     
    ghExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    if (!ghExitEvent) 
    { 
        return FALSE; 
    } 
 
    iccsex.dwSize = sizeof(INITCOMMONCONTROLSEX); 
    iccsex.dwICC = ICC_COOL_CLASSES; 
 
    InitCommonControlsEx(&iccsex); 
 
    g_hInstance = hInst; 
 
    // Create  a message queue on this thread 
    PeekMessage(&msg, NULL, 0,0,PM_NOREMOVE); 
 
    if(HandleNewWindow2(lpCmdLine, NULL)) 
    { 
        goto Cleanup; 
    } 
 
 
    while (glThreadCount > 0) 
    { 
        WaitForSingleObject(ghExitEvent, INFINITE); 
    } 
     
Cleanup: 
	_Module.UnRegisterTypeLib(); 
	_Module.RevokeClassObjects(); 
	_Module.Term(); 
    CoUninitialize(); 
 
    RETAILMSG(1, (L"STBIHOST exited. Cmdline was: %s\r\n",lpCmdLine ? lpCmdLine : L"")); 
 
    return TRUE; 
} 
 
 
CMainWnd::CMainWnd() 
{ 
    _ulRefs = 1; 
    _hWnd = NULL; 
    _pBrowser = NULL; 
    _pObject = NULL; 
    _pCP = NULL; 
    _lpszUrl = NULL; 
    _fEmpty = FALSE; 
    _szTitle[0] = 0; 
    _fSafeArea = FALSE; 
    _lSafeWidth = 0; 
	_lSafeHeight = 0; 
	_ptSafe.x = 0; 
	_ptSafe.y = 0; 
 
    _wZoom = 2; // default zoom 
    _wDLCCounter = 0; // counter for Download Completes 
 
    _pUnkExternal = NULL; 
 
    _hAccelTblNew = NULL; 
    _cNewAccels = 0; 
    _rgNewAccels = NULL; 
    _fUseNewAccels = NULL; 
} 
 
CMainWnd::~CMainWnd() 
{ 
	RETAILMSG(1,(L"STBIHOST Exiting ~CMainWnd\r\n")); 
 
	if (_pBrowser) 
		_pBrowser->Release(); 
 
	if (_pUnkExternal) 
		_pUnkExternal->Release(); 
 
	if (_rgNewAccels) 
		delete [] _rgNewAccels; 
 
	if (_hAccelTblNew) 
		DestroyAcceleratorTable(_hAccelTblNew); 
}    
 
BOOL RegisterMainWnd() 
{ 
    WNDCLASS        wc; 
    wc.style         = 0; 
    wc.lpfnWndProc   = (WNDPROC)CMainWnd::MainWndProc; 
    wc.cbClsExtra    = 0; 
    wc.cbWndExtra    = 0; 
    wc.hInstance     = g_hInstance; 
    wc.hIcon         = NULL; // LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_IE)); 
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = CreateSolidBrush(RGB(50,50,50)); 
    wc.lpszMenuName  = NULL; 
    wc.lpszClassName = WINCLS_UUID; 
 
    if (!(RegisterClass(&wc))) 
        return FALSE; 
 
    return TRUE; 
} 
 
 
BOOL CMainWnd::Create() 
{ 
    RECT rcArea; 
 
    DWORD dwStyle = WS_VISIBLE; 
    DWORD dwExStyle = 0; 
 
    HMENU hMenu = NULL; 
 
    SystemParametersInfo(SPI_GETWORKAREA, 0, &rcArea, 0); 
 
    _hWnd = ::CreateWindowEx(dwExStyle, 
                             WINCLS_UUID, 
                             (WCHAR *)LoadString(g_hInstance, IDS_STBIHOST, NULL, 0), 
                             dwStyle, 
                             rcArea.left, 
                             rcArea.top, 
                             rcArea.right - rcArea.left, 
                             rcArea.bottom - rcArea.top, 
                             NULL, hMenu, g_hInstance, 0); 
    if (!_hWnd) 
        return FALSE; 
 
    SetWindowLong(_hWnd, GWL_USERDATA, (DWORD)this); 
    GetWindowRect(_hWnd, &_rcWnd); 
 
    // create a "safe area" to prevent the browser 
    // control (and the progress bar) from displaying 
    // graphics that bleed off the edges of the TV screen 
    _lSafeWidth = (LONG)((_rcWnd.right - _rcWnd.left) * SAFEAREA_MARGIN); 
    _lSafeHeight = (LONG)((_rcWnd.bottom - _rcWnd.top) * SAFEAREA_MARGIN); 
    _ptSafe.x = (LONG)((_rcWnd.right - _rcWnd.left - _lSafeWidth)/2); 
    _ptSafe.y = (LONG)((_rcWnd.bottom - _rcWnd.top - _lSafeHeight)/2); 
 
 
    // create a progress bar 
    _rcProgress.left = _ptSafe.x + 5; 
    _rcProgress.top = _ptSafe.y + 5; 
    _rcProgress.right = _rcProgress.left + _lSafeWidth/3; 
    _rcProgress.bottom = _rcProgress.top + 15; 
 
    _hwndProgress = CreateWindowEx(WS_EX_NOACTIVATE, PROGRESS_CLASS, 
                                   _T(""), WS_CHILD|PBS_SMOOTH|WS_BORDER, 
                                   _rcProgress.left, _rcProgress.top, 
                                   _rcProgress.right-_rcProgress.left, 
                                   _rcProgress.bottom-_rcProgress.top, 
                                   _hWnd, NULL, g_hInstance, NULL); 
     
    if (_hwndProgress) 
        SendMessage(_hwndProgress, PBM_SETRANGE32, 0, 1000); 
 
    if (!(_hWndBrowser = CreateBrowser())) 
        return FALSE; 
 
    // LONG lStyle = GetWindowLong(_hWndBrowser, GWL_STYLE); 
    // SetWindowLong(_hWndBrowser, GWL_STYLE, lStyle|WS_BORDER); 
 
	// use the safe area to resize the web control 
	EnableSafeArea(TRUE); 
  
	SetFocus(_hWnd); 
 
    _hAccelTblDef = LoadAccelerators(g_hInstance,  
    					MAKEINTRESOURCE(IDR_ACCELERATOR)); 
 
    return TRUE; 
} 
 
 
 
void GetProxyOption() 
{ 
	INTERNET_PER_CONN_OPTION_LIST	iOptionList; 
	INTERNET_PER_CONN_OPTION		iOptions[3]; 
	ULONG							uSize = sizeof(iOptionList); 
 
	iOptionList.dwSize			= uSize; 
	iOptionList.pszConnection	= NULL; 
	iOptionList.dwOptionCount	= 3; 
	iOptionList.pOptions		= iOptions; 
 
	// set proxy type direct or proxy server 
	iOptions[0].dwOption	= INTERNET_PER_CONN_FLAGS; 
	iOptions[1].dwOption	= INTERNET_PER_CONN_PROXY_SERVER; 
	iOptions[2].dwOption	= INTERNET_PER_CONN_PROXY_BYPASS; 
	 
	if(InternetQueryOption(NULL,INTERNET_OPTION_PER_CONNECTION_OPTION ,(LPVOID)(&iOptionList),&uSize)) 
	{ 
		GlobalFree(iOptionList.pOptions[1].Value.pszValue); 
		GlobalFree(iOptionList.pOptions[2].Value.pszValue); 
	} 
} 
 
HWND CMainWnd::CreateBrowser() 
{ 
    HRESULT hr; 
    IUnknown *pUnk = NULL; 
    IOleObject *pObject = NULL; 
 
 
    if (!_pBrowser) 
    { 
		GetProxyOption(); 
        hr = CoCreateInstance(CLSID_WebBrowser, NULL, 
                              CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, 
                              IID_IUnknown, (LPVOID *)(&pUnk)); 
        if (hr) 
            return FALSE; 
 
        hr = pUnk->QueryInterface(IID_IOleObject, (LPVOID *)(&pObject)); 
        if (hr) 
            goto Cleanup; 
 
        DWORD dwFlags; 
        hr = pObject->GetMiscStatus(DVASPECT_CONTENT, &dwFlags); 
        if (hr) 
            goto Cleanup; 
 
        if (dwFlags & OLEMISC_SETCLIENTSITEFIRST) 
        { 
            IOleClientSite *pClientSite; 
            hr = QueryInterface(IID_IOleClientSite, (LPVOID *)(&pClientSite)); 
            if (hr) 
                goto Cleanup; 
 
            hr = pObject->SetClientSite(pClientSite); 
            pClientSite->Release(); 
            if (hr) 
                goto Cleanup; 
        } 
 
        hr = Activate(pObject); 
        if (hr) 
            goto Cleanup; 
 
        hr = _pObject->QueryInterface(IID_IWebBrowser2, (void **)&_pBrowser); 
        if (hr) 
            goto Cleanup; 
 
        // See if there might be a url in lpszUrl 
        hr = pUnk->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)(&_pIPActiveObj)); 
        if (S_OK!=hr) 
			_pIPActiveObj = NULL; 
 
        hr = S_FALSE; 
 
        if (_fEmpty) 
        { 
            if (_lpszUrl) 
            { 
                LPTSTR lpszUrlAlpha = _lpszUrl; 
 
                while (hr == S_FALSE && *lpszUrlAlpha != _T('\0')) 
                { 
                    if (_istalpha(*lpszUrlAlpha)) 
                        hr = S_OK; 
 
                    lpszUrlAlpha++; 
                } 
            } 
 
            if (hr == S_OK) 
                _pBrowser->Navigate(_lpszUrl, NULL, NULL, NULL, NULL); 
            else 
                _pBrowser->GoHome(); 
        } 
        hr = InitEvents(); 
    } 
 
Cleanup: 
    if (pUnk) 
        pUnk->Release(); 
    if (pObject) 
        pObject->Release(); 
 
    IOleWindow *pWnd = NULL; 
    HWND hwndBrowser = NULL; 
 
    if (_pBrowser) 
    { 
        hr = _pBrowser->QueryInterface(IID_IOleWindow, (LPVOID *)(&pWnd)); 
        if (hr) 
            return NULL; 
    } 
 
    if (pWnd) 
    { 
        hr = pWnd->GetWindow(&hwndBrowser); 
        pWnd->Release(); 
    } 
    return hwndBrowser; 
} 
 
HRESULT CMainWnd::Activate(IOleObject *pObject) 
{ 
    _pObject = pObject; 
    _pObject->AddRef(); 
 
    RECT rc; 
    ::GetClientRect(_hWnd, &rc); 
 
    HRESULT hr; 
    hr    =    _pObject->DoVerb(   OLEIVERB_UIACTIVATE,    NULL,    this,    0,    _hWnd,    &rc); 
 
    if (hr) 
        goto Cleanup; 
 
    Cleanup: 
    return hr; 
} 
 
HRESULT CMainWnd::InitEvents() 
{ 
    HRESULT                     hr; 
    IConnectionPointContainer  *pCPCont = NULL; 
    DWebBrowserEvents          *pEvents = NULL; 
 
    if (!_pBrowser) 
        return S_FALSE; 
    hr = _pBrowser->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPCont); 
    if (hr) 
        return S_FALSE; 
    hr = pCPCont->FindConnectionPoint(DIID_DWebBrowserEvents2, &_pCP); 
    if (hr) 
	{ 
		_pCP = NULL; 
        goto Cleanup; 
	} 
 
    hr = QueryInterface(DIID_DWebBrowserEvents2, (LPVOID *)(&pEvents)); 
    if (hr) 
        goto Cleanup; 
    hr = _pCP->Advise(pEvents, &(_dwEventCookie)); 
    if (hr) 
        goto Cleanup; 
 
 
    Cleanup: 
    if (pCPCont) 
        pCPCont->Release(); 
    if (pEvents) 
        pEvents->Release(); 
    return hr; 
} 
 
 
 
HRESULT HandleNewWindow2(LPTSTR lpszUrl, DISPPARAMS FAR* pdparams) 
{ 
 
        HANDLE hThread; 
        CMainWnd *pNewWnd; 
        IDispatch *pDispatch; 
        HRESULT hr = S_OK; 
 
        pNewWnd = new CMainWnd; 
 
        if (!pNewWnd) 
        { 
            return E_OUTOFMEMORY; 
        } 
 
        pNewWnd->_lpszUrl = lpszUrl; 
        if(!pdparams) 
            pNewWnd->_fEmpty = TRUE; 
             
        pNewWnd->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
 
        if (!pNewWnd->hEvent) 
        { 
 
        } 
 
        InterlockedIncrement(&glThreadCount); 
 
        hThread = CreateThread(NULL, g_dwMainWindowStackSize, NewWindow, (LPVOID)pNewWnd, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); 
 
        if (!hThread) 
        { 
            delete pNewWnd; 
            InterlockedDecrement(&glThreadCount); 
            return E_OUTOFMEMORY; 
        } 
 
        WaitForSingleObject(pNewWnd->hEvent, INFINITE); 
	CloseHandle(hThread); 
        if(pdparams) 
        { 
            if (pNewWnd->_pBrowser) 
            { 
                hr = pNewWnd->_pBrowser->QueryInterface(IID_IDispatch, (LPVOID *)(&pDispatch)); 
            } 
            else 
            { 
                hr = E_FAIL; 
                pDispatch = NULL; 
            } 
 
            *(pdparams->rgvarg[0].pboolVal) = 0; 
            *(pdparams->rgvarg[1].ppdispVal) = pDispatch; 
        } 
        return hr; 
} 
 
 
STDMETHODIMP CMainWnd::GetExternal(IDispatch **ppDispatch) 
{ 
	HRESULT hr = S_OK; 
 
	if (!ppDispatch) return E_POINTER; 
 
	if (*ppDispatch) 
		*ppDispatch = NULL; 
 
	if (!_pUnkExternal) 
	{ 
		_pUnkExternal = new CComObject(); 
		if (!_pUnkExternal) return E_OUTOFMEMORY; 
		_pUnkExternal->AddRef(); 
		(reinterpret_cast(_pUnkExternal))->SetInst(this); 
	} 
 
	return _pUnkExternal->QueryInterface(IID_IDispatch, (PVOID*)(ppDispatch)); 
} 
 
STDMETHODIMP CMainWnd::GetHostInfo(DOCHOSTUIINFO *pInfo) 
{ 
	 
	pInfo->cbSize = sizeof(DOCHOSTUIINFO); 
	//pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER|DOCHOSTUIFLAG_FLAT_SCROLLBAR; 
	//pInfo->dwFlags |= DOCHOSTUIFLAG_SCROLL_NO; 
 
	return S_OK; 
 
} 
 
STDMETHODIMP CMainWnd::Invoke ( 
                              DISPID dispidMember, 
                              REFIID riid, 
                              LCID lcid, 
                              WORD wFlags, 
                              DISPPARAMS FAR* pdparams, 
                              VARIANT FAR* pvarResult, 
                              EXCEPINFO FAR* pexcepinfo, 
                              UINT FAR* puArgErr 
                              ) 
{ 
    switch (dispidMember) 
    { 
    case DISPID_AMBIENT_DLCONTROL: 
	if(pvarResult) 
	{ 
		V_VT(pvarResult) = VT_I4; 
		// always set these three unless they should be disabled 
		pvarResult->lVal = DLCTL_DLIMAGES|DLCTL_VIDEOS|DLCTL_BGSOUNDS; 
		 
		// put the browser in download only mode 
		// pvarResult->lVal |= DLCTL_DOWNLOADONLY; 
	} 
	break; 
 
    case DISPID_STATUSTEXTCHANGE: 
        { 
        } 
        break; 
         
    case DISPID_SETSECURELOCKICON: 
        { 
        } 
        break; 
 
    case DISPID_PROGRESSCHANGE: 
        { 
            LONG lProgMax = pdparams->rgvarg[0].lVal; 
            LONG lProg = pdparams->rgvarg[1].lVal; 
            UINT nPos = (lProg == -1) ? 999 : ((lProg-1)%1000); 
   
            SendMessage(_hwndProgress, PBM_SETPOS, nPos, 0); 
        } 
        break; 
 
    // notification for file download 
    case DISPID_FILEDOWNLOAD: 
	break; 
 
 
    case DISPID_NAVIGATECOMPLETE2: 
        break; 
 
    case DISPID_COMMANDSTATECHANGE: 
        break; 
 
    case DISPID_TITLECHANGE: 
            if (pdparams && pdparams->rgvarg[0].vt == VT_BSTR) 
            { 
                TCHAR szTitle[85]; 
                int len = wcslen(pdparams->rgvarg[0].bstrVal); 
                     
                _tcsncpy(_szTitle, pdparams->rgvarg[0].bstrVal, MAX_URL-1); 
                _tcsncpy(szTitle, pdparams->rgvarg[0].bstrVal, 80); 
                if(len > 80) 
                    _tcscat(szTitle, L"..."); 
 
                SetWindowText(_hWnd, szTitle); 
            } 
            break; 
 
    case DISPID_ONQUIT: 
        PostMessage(_hWnd, WM_CLOSE, 0, 0L); 
        break; 
 
    case DISPID_DOWNLOADBEGIN: 
	_wDLCCounter++; 
        SetWindowPos(_hwndProgress, HWND_TOP, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW); 
        break; 
    case DISPID_DOWNLOADCOMPLETE: 
    case DISPID_DOCUMENTCOMPLETE: 
	_wDLCCounter--; 
	if(_wDLCCounter <= 0) 
	{ 
        	SetWindowPos(_hwndProgress,NULL, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); 
        	ChangeFontSize(TRUE); 
		_wDLCCounter = 0; 
	} 
        break; 
 
    case DISPID_NEWWINDOW2: 
        //pdparams->rgvarg[1].boolVal = VARIANT_TRUE; 
        //break;         
        return HandleNewWindow2(NULL, pdparams); 
            break; 
 
 
    case DISPID_PROPERTYCHANGE: 
    case DISPID_BEFORENAVIGATE2: 
        break; 
    default: 
        return DISP_E_MEMBERNOTFOUND; 
    } 
    return S_OK; 
} 
 
 
STDMETHODIMP CMainWnd::moveTo( LONG x, LONG y) 
{ 
    SetWindowPos(_hWnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); 
    return S_OK; 
} 
 
STDMETHODIMP CMainWnd::moveBy( LONG x, LONG y)  
{ 
    RECT rcWindow; 
 
    GetWindowRect(_hWnd, &rcWindow); 
 
    SetWindowPos(_hWnd, NULL, rcWindow.left + x, rcWindow.top + y, 0, 0, 
                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); 
    return S_OK; 
} 
 
 
STDMETHODIMP CMainWnd::resizeTo( LONG x, LONG y)  
{ 
                // We do not want the size to be less then 100 for top level windows in browser 
    if (x < 100) 
        x = 100; 
 
    if (y < 100) 
        y = 100; 
 
    SetWindowPos(_hWnd, NULL, 0, 0, x, y, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); 
 
    return S_OK;              
} 
 
STDMETHODIMP CMainWnd::resizeBy( LONG x, LONG y)  
{ 
    RECT rcWindow; 
    long w, h; 
 
    GetWindowRect(_hWnd, &rcWindow); 
 
    w = rcWindow.right - rcWindow.left + x; 
    h = rcWindow.bottom - rcWindow.top + y; 
 
    if (w < 100) 
        w = 100; 
 
    if (h < 100) 
        h = 100; 
 
    SetWindowPos(_hWnd, NULL, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); 
    return S_OK; 
} 
 
 
EXTERN_C const GUID CGID_MSHTML; 
extern "C" BOOL APIENTRY OpenURLDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam); 
 
LRESULT CMainWnd::HandleCommand(WPARAM wParam, LPARAM lParam) 
{ 
    UINT nID = LOWORD(wParam); 
    switch (nID) 
    { 
	case ID_INTERNET_OPTIONS: 
	{ 
	   SHELLEXECUTEINFO sei; 
           sei.cbSize = sizeof(sei); 
           sei.fMask = SEE_MASK_FLAG_NO_UI; 
           sei.hwnd = _hWnd; 
           sei.lpVerb = NULL; 
           sei.lpFile = L"ctlpnl"; 
           sei.lpParameters = L"inetcpl.cpl"; 
           sei.lpDirectory = NULL; 
           sei.nShow = SW_SHOWNORMAL; 
 
       	   ShellExecuteEx(&sei);  
	 } 
	   break; 
	case ID_FIND: 
		FindString(); 
	    break; 
    case ID_GO_BACK: 
        _pBrowser->GoBack(); 
        return 0; 
    case ID_GO_FORWARD: 
        _pBrowser->GoForward(); 
        return 0; 
    case ID_GO_HOME: 
        _pBrowser->GoHome(); 
        return 0; 
    case ID_GO_SEARCH: 
        _pBrowser->GoSearch(); 
        return 0; 
    case ID_VIEW_REFRESH: 
        _pBrowser->Refresh(); 
        return 0; 
    case ID_VIEW_STOP: 
        _pBrowser->Stop(); 
        return 0; 
    case ID_SCROLL_PAGEUP: 
    case ID_SCROLL_PAGEDOWN: 
    	{	// TODO: this isn't working... 
            ASSERT(_pBrowser); 
            LPDISPATCH pDisp = NULL; 
            LPOLECOMMANDTARGET pCmdTarg = NULL; 
            VARIANTARG var; 
            HRESULT hr; 
 
            UINT nCmdId = (ID_SCROLL_PAGEUP == nID  
                           ? IDM_SCROLL_PAGEUP 
                           : IDM_SCROLL_PAGEDOWN); 
 
            hr = _pBrowser->get_Document(&pDisp); 
            if (FAILED(hr) || !pDisp) break; 
 
            hr = pDisp->QueryInterface(IID_IOleCommandTarget, 
                                       (LPVOID*)&pCmdTarg); 
            if (FAILED(hr) || !pCmdTarg) 
            { 
                pDisp->Release(); 
                break; 
            } 
 
            var.vt = VT_I4; 
            var.lVal = 0; 
            hr = pCmdTarg->Exec(&CGID_MSHTML, nCmdId, 0, 0, 0); 
 
            if (pCmdTarg) pCmdTarg->Release(); 
            if (pDisp) pDisp->Release(); 
        } 
        break; 
 
    case ID_ZOOMUP: 
        _wZoom++; 
        if(_wZoom > 4) 
            _wZoom = 4; 
        ChangeFontSize(FALSE); 
        return 0; 
 
    case ID_ZOOMDOWN: 
        _wZoom--; 
        if(_wZoom < 0) 
            _wZoom = 0; 
        ChangeFontSize(FALSE); 
        return 0; 
    case ID_CLOSE: 
        _pBrowser->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DODEFAULT, NULL, NULL); 
        return 0; 
    case ID_FOCUS_URL: 
    case ID_OPEN: 
        { 
            WCHAR *szURL = new TCHAR[MAX_URL]; 
            if (szURL) 
            { 
                int nRet = 0;                 
                BSTR bstrUrl = NULL; 
                _pBrowser->get_LocationURL(&bstrUrl); 
                StringCchCopy(szURL, MAX_URL, (LPCTSTR)bstrUrl); 
                SysFreeString(bstrUrl); 
                nRet =  DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_OPEN_DIALOG), _hWnd, OpenURLDlgProc, (long)szURL); 
                if(nRet == 1) 
                { 
                    _pBrowser->Navigate(szURL, NULL, NULL, NULL, NULL); 
                } 
                else if(nRet == 2) 
                { 
                    HandleNewWindow2(szURL, NULL); 
                } 
                delete[] szURL; 
            } 
        } 
        return 0; 
    } 
    return 0; 
} 
 
 
 
 
 
EXTERN_C const GUID CGID_ShellDocView; 
 
LRESULT CALLBACK CMainWnd::MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	CMainWnd *pMainWnd = (CMainWnd*)GetWindowLong(hwnd, GWL_USERDATA); 
 
	if (pMainWnd) 
	{ 
		switch (message) 
		{ 
		case WM_CLOSE: 
		case WM_DESTROY: 
			if(pMainWnd) 
				pMainWnd->Close(); 
			SetWindowLong(hwnd, GWL_USERDATA, (DWORD)0); 
			::PostQuitMessage(0); 
			break; 
 
		case WM_SETFOCUS: 
			if (pMainWnd->_pIPActiveObj) 
			{ 
				pMainWnd->_pIPActiveObj->OnFrameWindowActivate(LOWORD(wParam) != WA_INACTIVE); 
			} 
			return 0; 
 
		case WM_SIZE: 
			{ 
				RECT rcWnd; 
				GetClientRect(hwnd, &rcWnd); 
				SetWindowPos(pMainWnd->_hWndBrowser,   
							 NULL, 0, 0, 
							 rcWnd.right-rcWnd.left, 
							 rcWnd.bottom - rcWnd.top, 
							 SWP_NOZORDER);		 
			} 
			// FALL THROUGH 
 
		case WM_MOVE: 
			break; 
 
		case WM_COMMAND: 
			return pMainWnd->HandleCommand(wParam, lParam); 
 
		case WM_NOTIFY: 
			break; 
 
		case WM_INITMENUPOPUP: 
			break; 
 
		case WM_SETTINGCHANGE: 
			if(wParam == SPI_SETWORKAREA) 
			{ 
				ASSERT(FALSE); 
			} 
			break; 
 
		// TODO:  We currently only use WM_COPYDATA for the WMP page. 
		// TODO:  If we load other types of pages as well, we'll need to develop 
		// TODO:  a protocol to determine who sent the WM_COPYDATA message. 
		// TODO:  e.g. - "type=stbihostwmp&url=" 
		case WM_COPYDATA: 
			// navigate to the WMP webpage, passing it the copied link 
			if( lParam ) 
			{ 
				HKEY hKey; 
				DWORD cbData, dwType, cbDummy; 
				LONG lRet; 
				LPTSTR szNavURL; 
 
				lRet = RegOpenKeyEx(HKEY_CURRENT_USER, REG_ROOTKEY, 0, 0, &hKey); 
				ASSERT(ERROR_SUCCESS == lRet); 
				if (ERROR_SUCCESS != lRet) 
				{ 
					DEBUGMSG(1, (TEXT("Error (%u) getting registry key: ") 
								REG_ROOTKEY TEXT("\r\n"), GetLastError())); 
					break; 
				} 
 
				// just get the size first 
				lRet = RegQueryValueEx(hKey, REG_WMPVALUE, NULL, 
									   &dwType, NULL, &cbData); 
				ASSERT(ERROR_SUCCESS == lRet); 
				if (ERROR_SUCCESS != lRet) 
				{ 
					DEBUGMSG(1, (TEXT("Error (%u) getting registry value: ") 
								REG_ROOTKEY REG_WMPVALUE, GetLastError())); 
					RegCloseKey(hKey); 
					break; 
				} 
 
				ASSERT(REG_SZ == dwType); 
				cbData += _tcslen(TEXT("#")) * sizeof(TCHAR); 
 
				PCOPYDATASTRUCT lpCDS = (PCOPYDATASTRUCT)lParam; 
				ASSERT(lpCDS->cbData ==  
					(_tcslen((LPTSTR)lpCDS->lpData) + 1) * sizeof(TCHAR)); 
				cbData += lpCDS->cbData + sizeof(TCHAR);	// extra TCHAR for null term 
 
				// now that we know the size, create the URL 
				szNavURL = new TCHAR[cbData/sizeof(TCHAR)]; 
				ASSERT(szNavURL); 
				if (!szNavURL) 
				{ 
					DEBUGMSG(1, (TEXT("Error creating Windows Media ") 
								  TEXT("Navigation URL string!\r\n"))); 
					break; 
				} 
 
				cbDummy = cbData; 
				lRet = RegQueryValueEx(hKey, REG_WMPVALUE, NULL, NULL, 
									   (LPBYTE)szNavURL, &cbDummy); 
				ASSERT(ERROR_SUCCESS == lRet); 
				RegCloseKey(hKey); 
				if (ERROR_SUCCESS != lRet) 
				{ 
					DEBUGMSG(1, (TEXT("Error (%u) getting registry value: ") 
								REG_ROOTKEY REG_WMPVALUE, GetLastError())); 
					break; 
				} 
 
				_tcscat(szNavURL, TEXT("#")); 
				_tcscat(szNavURL, (LPTSTR)lpCDS->lpData); 
				szNavURL[cbData/sizeof(TCHAR) - 1] = 0; 
 
				HRESULT hr = pMainWnd->_pBrowser->Navigate(szNavURL,  
								NULL, NULL, NULL, NULL); 
				ASSERT(S_OK == hr); 
				if (FAILED(hr)) 
				{ 
					DEBUGMSG(1, (TEXT("IWebBrowser2::Navigate(\"%s\") failed!\r\n"), 
								 szNavURL)); 
				} 
				return 1; 
			} 
			break; 
 
		default: 
			break; 
		} 
	} 
 
	return DefWindowProc(hwnd, message, wParam, lParam); 
} 
 
BOOL CMainWnd::PreTranslateMessage(LPMSG pMsg) 
{ 
	// main frame gets first shot 
	if (_fUseNewAccels) 
	{ 
		if (::TranslateAccelerator(_hWnd, _hAccelTblNew, pMsg)) 
			return TRUE; 
	} 
	else 
	{ 
	    if (::TranslateAccelerator(_hWnd, _hAccelTblDef, pMsg)) 
	        return TRUE; 
	} 
 
    // then to mshtml 
    if (_pIPActiveObj && pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) 
    { 
        HRESULT hr = _pIPActiveObj->TranslateAccelerator(pMsg); 
        return (hr != S_FALSE); 
    } 
    return FALSE; 
} 
 
VOID CMainWnd::ChangeFontSize(BOOL fInit) 
{ 
        VARIANT vaSize; 
        vaSize.vt = VT_I4; 
 
	if (fInit) { 
		// Setting initial value 
		vaSize.vt = 0; 
		HRESULT hr = _pBrowser->ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, 
									   NULL, &vaSize); 
		_wZoom = vaSize.lVal; 
	} else { 
		vaSize.lVal = _wZoom; 
		HRESULT hr = _pBrowser->ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, 
									   &vaSize, NULL); 
	} 
} 
 
VOID CMainWnd::Close() 
{ 
    RETAILMSG(1,(L"STBIHOST CMainWnd::Close")); 
 
    // Tell the shell to die off 
    SendMessage(_hWndBrowser, WM_CLOSE, 0,0); 
 
 
	if(_pIPActiveObj) 
	{ 
		_pIPActiveObj->Release(); 
	} 
    _pIPActiveObj = NULL; 
	if(_pCP) 
	{ 
		_pCP->Unadvise(_dwEventCookie); 
		_pCP->Release(); 
	} 
    _pCP = NULL; 
	if(_pObject) 
	{ 
		_pObject->Close(FALSE); 
		_pObject->Release(); 
	} 
    _pObject = NULL; 
	if(_pBrowser) 
	    _pBrowser->Release(); 
    _pBrowser = NULL; 
 
} 
 
 
 
 
HRESULT CMainWnd::FindString() 
{ 
    LPDISPATCH pDisp = NULL; 
    LPOLECOMMANDTARGET pCmdTarg = NULL; 
    HRESULT sts = S_OK; 
    VARIANTARG var; 
 
#define GOERROR_S(bNotCond)  {if (!(bNotCond)) goto errorS; } 
 
    if (!_pBrowser) 
        return S_OK; 
    sts = _pBrowser->get_Document(&pDisp); 
    GOERROR_S(pDisp); 
    sts = pDisp->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&pCmdTarg); 
    GOERROR_S(pCmdTarg); 
 
    var.vt   = VT_I4; 
    var.lVal = 0; 
    sts = pCmdTarg->Exec( 
                        NULL, 
                        OLECMDID_FIND, 
                        MSOCMDEXECOPT_PROMPTUSER, 
                        NULL, 
                        &var); 
 
    errorS: 
    if (pCmdTarg) 
        pCmdTarg->Release(); // release document's command target 
    if (pDisp) 
        pDisp->Release();    // release document's dispatch interface 
    return sts; 
} 
 
 
BOOL CMainWnd::EnableSafeArea(BOOL fEnable) 
{ 
	BOOL fRet; 
 
	if (fEnable) 
	{ 
		fRet = SetWindowPos(_hWndBrowser, NULL, _ptSafe.x, _ptSafe.y, 
							_lSafeWidth, _lSafeHeight, SWP_NOZORDER); 
		if (!fRet) 
		{ 
			ASSERT(FALSE); 
			RETAILMSG(1, (TEXT("SetWindowPos(x=%i, y=%i, cx=%i, cy=%i) ") 
						  TEXT("failed in CMainWnd::EnableSafeArea()"), 
						  _ptSafe.x, _ptSafe.y, _lSafeWidth, _lSafeHeight)); 
		} 
	} 
	else 
	{ 
		fRet = SetWindowPos(_hWndBrowser, NULL, 
							_rcWnd.left, _rcWnd.top, 
							_rcWnd.right - _rcWnd.left, 
							_rcWnd.bottom - _rcWnd.top, 
							SWP_NOZORDER); 
		if (!fRet) 
		{ 
			ASSERT(FALSE); 
			RETAILMSG(1, (TEXT("SetWindowPos(x=%i, y=%i, cx=%i, cy=%i) ") 
						  TEXT("failed in CMainWnd::EnableSafeArea()"), 
						  _rcWnd.left, _rcWnd.top, 
						  _rcWnd.right - _rcWnd.left, 
						  _rcWnd.bottom - _rcWnd.top)); 
		} 
	} 
 
	if (fRet) 
	{ 
		_fSafeArea = fEnable; 
	} 
 
	return fRet; 
} 
 
 
BOOL CMainWnd::AssignAccelerator(ACCEL accel, SHORT nKey) 
{ 
	accel.fVirt = FNOINVERT | FVIRTKEY; 
	switch (nKey) 
	{ 
	case RCTL_STOP: 
		accel.key = VK_MEDIA_STOP; 
		accel.cmd = ID_VIEW_STOP;	 
		break; 
 
	case RCTL_PLAY: 
		accel.key = VK_PLAY; 
		accel.cmd = ID_VIEW_REFRESH;	 
		break; 
 
	case RCTL_PREV: 
		accel.key = VK_MEDIA_PREV_TRACK; 
		accel.cmd = ID_GO_HOME; 
		break; 
 
	case RCTL_NEXT: 
		accel.key = VK_MEDIA_NEXT_TRACK; 
		accel.cmd = ID_GO_SEARCH; 
		break; 
 
	case RCTL_BACK: 
		accel.key = VK_PRIOR; 
		accel.cmd = ID_GO_BACK; 
		break; 
 
	case RCTL_FWD: 
		accel.key = VK_NEXT; 
		accel.cmd = ID_GO_FORWARD; 
 
	case RCTL_VOLUP: 
		accel.key = VK_VOLUME_UP; 
		accel.cmd = ID_SCROLL_PAGEUP; 
		break; 
 
	case RCTL_VOLDN: 
		accel.key = VK_VOLUME_DOWN; 
		accel.cmd = ID_SCROLL_PAGEDOWN; 
		break; 
 
	default: 
		ASSERT(FALSE); 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
 
// This bitmask defines the keys that StbIHost doesn't 
// have in its default accelerator table). We need this 
// to insure that StbIHost doesn't suddenly start 
// handling these keys when a new table overrides the 
// default. 
// 
// We simply have no use for pause, mute, or menu, and 
// SHDOCVW uses left, right, up, down, and select for 
// TVLENS tab navigation. 
#define RCTLKEYS_BM_DONTCARE  ( RCTL_BM_PAUSE | RCTL_BM_MUTE | RCTL_BM_MENU	\ 
								| RCTL_BM_LEFT | RCTL_BM_RIGHT | RCTL_BM_UP	\ 
								| RCTL_BM_DOWN | RCTL_BM_SELECT ) 
 
BOOL CMainWnd::CreateAccelTbl(ULONG bmKeys) 
{ 
	// if this ASSERT fails, then the datatype 
	// for bmKeys needs to be larger 
	ASSERT(RCTL_NUMKEYS < sizeof(bmKeys) * 8); 
 
	_fUseNewAccels = TRUE; 
 
	// all the bit fields in bmKeys with value=1 are 
	// the ones the current web page wants to use, so 
	// we care about the left-overs--the bitfields with 
	// value=0 
	bmKeys = (~bmKeys & ~RCTLKEYS_BM_DONTCARE & ((1 << RCTL_NUMKEYS) - 1)); 
 
	if (!bmKeys) 
		return TRUE; 
 
	ULONG bmKeysTmp = bmKeys; 
 
	// determine length of new accelerator table 
	_cNewAccels = 0; 
	while (0 != bmKeysTmp) 
	{ 
		if (bmKeysTmp & 1) 
			_cNewAccels++; 
		bmKeysTmp >>= 1; 
	} 
 
	// create table 
	if (_rgNewAccels) 
		delete [] _rgNewAccels; 
 
	_rgNewAccels = new ACCEL[_cNewAccels]; 
	if (!_rgNewAccels) 
	{ 
		_cNewAccels = 0; 
		_fUseNewAccels = FALSE; 
		return FALSE; 
	} 
 
	SHORT nKeys = 0, nBit = 0; 
	while (0 != bmKeys) 
	{ 
		if (bmKeys & 1) 
		{ 
			if (!AssignAccelerator(_rgNewAccels[nKeys], nBit)) 
			{ 
				_cNewAccels = 0; 
				delete [] _rgNewAccels; 
				_fUseNewAccels = FALSE; 
				return FALSE; 
			} 
			nKeys++; 
		} 
 
		bmKeys >>= 1; 
		nBit++; 
	} 
 
	// finally, register new table 
	if (_hAccelTblNew) 
		DestroyAcceleratorTable(_hAccelTblNew); 
		 
	_hAccelTblNew = CreateAcceleratorTable(_rgNewAccels, _cNewAccels); 
	if (!_hAccelTblNew) 
	{ 
		ASSERT(FALSE); 
		_cNewAccels = 0; 
		delete [] _rgNewAccels; 
		_fUseNewAccels = FALSE; 
		return FALSE; 
	} 
	 
	return TRUE; 
} 
 
 
BOOL CMainWnd::DestroyAccelTbl() 
{ 
	if (_rgNewAccels) 
	{ 
		delete [] _rgNewAccels; 
		_rgNewAccels = NULL; 
	} 
 
	if (_hAccelTblNew) 
	{ 
		DestroyAcceleratorTable(_hAccelTblNew); 
		_hAccelTblNew = NULL; 
	} 
 
	_cNewAccels = 0; 
	_fUseNewAccels = FALSE; 
 
	return TRUE; 
} 
 
 
BOOL HandleBrowse(HWND hwndOwner, WCHAR *szURL); 
        
extern "C" BOOL APIENTRY OpenURLDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam) 
{ 
 
    WCHAR *szURL = (WCHAR *)GetWindowLong(hDlg,DWL_USER);  
    int         nRet = 4; 
     
    switch(message) 
    { 
 
        case WM_INITDIALOG: 
            { 
                    if(!lParam) 
                    { 
                         EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);   
                         EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), FALSE); 
                    } 
                    else 
                    { 
                            szURL = (WCHAR *)lParam; 
                            SetWindowLong(hDlg, DWL_USER, (LONG)szURL); 
                            SendMessage(GetDlgItem(hDlg, IDC_URL_EDIT), EM_LIMITTEXT, MAX_URL-1, 0); 
                            if(szURL[0]) 
                            { 
                             
                                   SetDlgItemText(hDlg, IDC_URL_EDIT, szURL); 
                            } 
                    } 
 
            } 
            return TRUE; 
 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            {	 
 
                case IDOK: 
                { 
                    GetDlgItemText(hDlg, IDC_URL_EDIT, szURL, MAX_URL-1);     
                    BOOL bNewWnd = SendMessage(GetDlgItem(hDlg, IDC_NEWWINDOW), BM_GETCHECK, 0L, 0L); 
                    nRet = (bNewWnd) ? 2 : 1;  
                } 
               case IDCANCEL: 
                    EndDialog(hDlg, nRet); 
                    return TRUE; 
                     
                     
	        case IDC_BROWSE: 
                    if(HandleBrowse(hDlg, szURL)) 
                    { 
                        SetDlgItemText(hDlg, IDC_URL_EDIT, szURL); 
                    }        
                     
                default: 
                    return (TRUE); 
            } 
            break; 
 
        case WM_DESTROY: 
            SetWindowLong(hDlg, DWL_USER, 0); 
            break; 
 
    } 
    return (FALSE); 
 
 
} 
 
 
extern HINSTANCE   g_hInstance; 
BOOL HandleBrowse(HWND hwndOwner, WCHAR *szURL) 
{ 
 
    OPENFILENAME    ofn; 
    WCHAR           wchFilter[MAX_PATH]; 
    WCHAR           wchFile[MAX_PATH+8];  
    int             cbLen; 
 
  
    // Initialize ofn struct 
    memset(&ofn, 0, sizeof(ofn)); 
    ofn.lStructSize = sizeof(ofn); 
    ofn.hwndOwner   = hwndOwner; 
    ofn.Flags       = OFN_FILEMUSTEXIST 
                      | OFN_PATHMUSTEXIST 
                      | OFN_OVERWRITEPROMPT 
                      | OFN_HIDEREADONLY; 
 
    cbLen = LoadString(g_hInstance, IDS_BROWSEFILTER, 
                       wchFilter, MAX_PATH-2); 
 
    if (cbLen>0) 
    { 
        for (; cbLen >= 0; cbLen--) 
        { 
            if (wchFilter[cbLen]== L'@') 
            { 
                wchFilter[cbLen] = 0; 
            } 
        } 
    } 
    else 
    { 
        return FALSE; 
    } 
    
     
    ofn.lpstrFilter = wchFilter; 
    ofn.nFilterIndex = 1; 
    wcscpy(wchFile, L"file://"); 
     
    ofn.lpstrFile = wchFile+wcslen(wchFile);  // prefix the string with "file://" 
    ofn.nMaxFile = MAX_PATH; 
    if (GetOpenFileName(&ofn)) 
    { 
        wcsncpy(szURL, wchFile, MAX_URL-1); 
        return TRUE; 
    } 
 
    return FALSE; 
 
}