SHDOCVW: download the Mozilla Active X control on demand (take 2)

Mike McCormack mike at codeweavers.com
Thu Oct 28 23:52:27 CDT 2004


[This version adds a semaphore to prevent two downloads from occuring at 
the same time.]

This patch downloads the mozilla active control on demand.  It needs the 
following registry key to be present to function correctly:

[Software\\Wine\\Mozilla Control] 1089668326
"Url"="http://www.iol.ie/~locka/mozilla/MozillaControl16.exe"
"Prog"="%TEMP%\\MozillaControl16.exe"

I think we should not put Adam's page in our registry by default, but 
perhaps host the control on WineHQ somewhere and use the URL for that 
instead, so as not to direct too much traffic to Adam's page...

Mike


ChangeLog:
* download the Mozilla Active X control on demand
-------------- next part --------------
Index: dlls/shdocvw/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/shdocvw/Makefile.in,v
retrieving revision 1.13
diff -u -r1.13 Makefile.in
--- dlls/shdocvw/Makefile.in	27 Jan 2004 00:11:16 -0000	1.13
+++ dlls/shdocvw/Makefile.in	29 Oct 2004 04:41:43 -0000
@@ -4,7 +4,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = shdocvw.dll
-IMPORTS   = ole32 user32 advapi32 kernel32
+IMPORTS   = urlmon ole32 user32 advapi32 kernel32
 EXTRALIBS = -luuid
 
 C_SRCS = \
@@ -18,7 +18,7 @@
 	shdocvw_main.c \
 	webbrowser.c
 
-RC_SRCS = version.rc
+RC_SRCS = shdocvw.rc version.rc
 
 @MAKE_DLL_RULES@
 
Index: dlls/shdocvw/shdocvw_main.c
===================================================================
RCS file: /home/wine/wine/dlls/shdocvw/shdocvw_main.c,v
retrieving revision 1.21
diff -u -r1.21 shdocvw_main.c
--- dlls/shdocvw/shdocvw_main.c	7 Oct 2004 03:06:48 -0000	1.21
+++ dlls/shdocvw/shdocvw_main.c	29 Oct 2004 04:41:44 -0000
@@ -2,6 +2,7 @@
  * SHDOCVW - Internet Explorer Web Control
  *
  * Copyright 2001 John R. Sheets (for CodeWeavers)
+ * Copyright 2004 Mike McCormack (for CodeWeavers)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,6 +38,7 @@
 
 #include "shdocvw.h"
 #include "uuids.h"
+#include "urlmon.h"
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -45,8 +47,10 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
 
-#define MOZILLA_ACTIVEX_MESSAGE "You need to install the Mozilla ActiveX control to\n" \
-                                "use Wine's builtin CLSID_WebBrowser from SHDOCVW.DLL"
+static const WCHAR szMozDlPath[] = {
+    'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
+    'M','o','z','i','l','l','a',' ','C','o','n','t','r','o','l',0
+}; 
 
 DEFINE_GUID( CLSID_MozillaBrowser, 0x1339B54C,0x3453,0x11D2,0x93,0xB9,0x00,0x00,0x00,0x00,0x00,0x00);
 
@@ -128,26 +132,288 @@
     return S_FALSE;
 }
 
+/*************************************************************************
+ *              SHDOCVW_TryDownloadMozillaControl
+ */
+typedef struct _IBindStatusCallbackImpl {
+    IBindStatusCallbackVtbl *vtbl;
+    DWORD ref;
+    HWND hDialog;
+    BOOL *pbCancelled;
+} IBindStatusCallbackImpl;
+
+static HRESULT WINAPI
+dlQueryInterface( IBindStatusCallback* This, REFIID riid, void** ppvObject )
+{
+    if( IsEqualIID(riid, &IID_IUnknown) ||
+        IsEqualIID(riid, &IID_IBindStatusCallback))
+    {
+        IBindStatusCallback_AddRef( This );
+        *ppvObject = This;
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dlAddRef( IBindStatusCallback* iface )
+{
+    IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+    return InterlockedIncrement( &This->ref );
+}
+
+static ULONG WINAPI dlRelease( IBindStatusCallback* iface )
+{
+    IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+    DWORD ref = InterlockedDecrement( &This->ref );
+    if( !ref )
+    {
+        DestroyWindow( This->hDialog );
+        HeapFree( GetProcessHeap(), 0, This );
+    }
+    return ref;
+}
+
+static HRESULT WINAPI
+dlOnStartBinding( IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlGetPriority( IBindStatusCallback* iface, LONG* pnPriority)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnLowResource( IBindStatusCallback* iface, DWORD reserved)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnProgress( IBindStatusCallback* iface, ULONG ulProgress,
+              ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+    IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+    HWND hItem;
+    LONG r;
+
+    hItem = GetDlgItem( This->hDialog, 1000 );
+    if( hItem && ulProgressMax )
+        SendMessageW(hItem,PBM_SETPOS,(ulProgress*100)/ulProgressMax,0);
+
+    hItem = GetDlgItem(This->hDialog, 104);
+    if( hItem )
+        SendMessageW(hItem,WM_SETTEXT, 0, (LPARAM) szStatusText);
+
+    SetLastError(0);
+    r = GetWindowLongPtrW( This->hDialog, GWLP_USERDATA );
+    if( r || GetLastError() )
+    {
+        *This->pbCancelled = TRUE;
+        ERR("Cancelled\n");
+        return E_ABORT;
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnStopBinding( IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlGetBindInfo( IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnDataAvailable( IBindStatusCallback* iface, DWORD grfBSCF,
+                   DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnObjectAvailable( IBindStatusCallback* iface, REFIID riid, IUnknown* punk)
+{
+    ERR("\n");
+    return S_OK;
+}
+
+struct IBindStatusCallbackVtbl dlVtbl =
+{
+    dlQueryInterface,
+    dlAddRef,
+    dlRelease,
+    dlOnStartBinding,
+    dlGetPriority,
+    dlOnLowResource,
+    dlOnProgress,
+    dlOnStopBinding,
+    dlGetBindInfo,
+    dlOnDataAvailable,
+    dlOnObjectAvailable
+};
+
+static IBindStatusCallback* create_dl(HWND dlg, BOOL *pbCancelled)
+{
+    IBindStatusCallbackImpl *This;
+
+    This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
+    This->vtbl = &dlVtbl;
+    This->ref = 1;
+    This->hDialog = dlg;
+    This->pbCancelled = pbCancelled;
 
+    return (IBindStatusCallback*) This;
+}
+
+static DWORD WINAPI ThreadFunc( LPVOID info )
+{
+    IBindStatusCallback *dl;
+    static const WCHAR szUrlVal[] = {'U','r','l',0};
+    static const WCHAR szProgVal[] = {'P','r','o','g',0};
+    WCHAR szProg[MAX_PATH], path[MAX_PATH], szUrl[MAX_PATH];
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    HWND hDlg = info;
+    DWORD r, sz, type;
+    HKEY hkey;
+    BOOL bCancelled = FALSE;
+
+    /* find the name of the thing to download */
+    szProg[0] = 0;
+    szUrl[0] = 0;
+    r = RegOpenKeyW( HKEY_LOCAL_MACHINE, szMozDlPath, &hkey );
+    if( r == ERROR_SUCCESS )
+    {
+        sz = MAX_PATH;
+        r = RegQueryValueExW( hkey, szProgVal, NULL, &type, (LPBYTE)szProg, &sz );
+        if( r == ERROR_SUCCESS )
+        {
+            sz = MAX_PATH;
+            r = RegQueryValueExW( hkey, szUrlVal, NULL, &type, (LPBYTE)szUrl, &sz );
+        }
+        RegCloseKey( hkey );
+    }
+    if( r != ERROR_SUCCESS )
+        goto end;
+    r = ExpandEnvironmentStringsW( szProg, path, MAX_PATH );
+    if( !r )
+        goto end;
+    
+    /* download it */
+    dl = create_dl(info, &bCancelled);
+    r = URLDownloadToFileW( NULL, szUrl, path, 0, dl );
+    if( dl )
+        IBindStatusCallback_Release( dl );
+    if( (r != S_OK) || bCancelled )
+        goto end;
+
+    /* run it */
+    memset( &si, 0, sizeof si );
+    si.cb = sizeof si;
+    r = CreateProcessW( path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi );
+    if( !r )
+        goto end;
+    WaitForSingleObject( pi.hProcess, INFINITE );
+
+end:
+    EndDialog( hDlg, 0 );
+    return 0;
+}
+
+static INT_PTR CALLBACK
+dlProc ( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    HANDLE hThread;
+    DWORD ThreadId;
+    HWND hItem;
+
+    switch (uMsg)
+    {
+    case WM_INITDIALOG:
+        SetWindowLongPtrW( hwndDlg, GWLP_USERDATA, 0 );
+        hItem = GetDlgItem(hwndDlg, 1000);
+        if( hItem )
+        {
+            SendMessageW(hItem,PBM_SETRANGE,0,MAKELPARAM(0,100));
+            SendMessageW(hItem,PBM_SETPOS,0,0);
+        }
+        hThread = CreateThread(NULL,0,ThreadFunc,hwndDlg,0,&ThreadId);
+        if (!hThread)
+            return FALSE;
+        return TRUE;
+    case WM_COMMAND:
+        if( wParam == IDCANCEL )
+            SetWindowLongPtrW( hwndDlg, GWLP_USERDATA, 1 );
+        return FALSE;
+    default:
+        return FALSE;
+    }
+}
+
+static BOOL SHDOCVW_TryDownloadMozillaControl()
+{
+    DWORD r;
+    WCHAR buf[0x100];
+    static const WCHAR szWine[] = { 'W','i','n','e',0 };
+    HANDLE hsem;
+
+    SetLastError( ERROR_SUCCESS );
+    hsem = CreateSemaphoreA( NULL, 0, 1, "mozctl_install_semaphore");
+    if( GetLastError() != ERROR_ALREADY_EXISTS )
+    {
+        LoadStringW( shdocvw_hinstance, 1001, buf, sizeof buf/sizeof(WCHAR) );
+        r = MessageBoxW(NULL, buf, szWine, MB_YESNO | MB_ICONQUESTION);
+        if( r != IDYES )
+            return FALSE;
+
+        DialogBoxW(shdocvw_hinstance, MAKEINTRESOURCEW(100), 0, dlProc);
+    }
+    else
+        WaitForSingleObject( hsem, INFINITE );
+    ReleaseSemaphore( hsem, 1, NULL );
+    CloseHandle( hsem );
+    
+    return TRUE;
+}
+ 
 static BOOL SHDOCVW_TryLoadMozillaControl()
 {
     WCHAR szPath[MAX_PATH];
+    BOOL bTried = FALSE;
 
     if( hMozCtl != (HMODULE)~0UL )
         return hMozCtl ? TRUE : FALSE;
 
-    if( !SHDOCVW_GetMozctlPath( szPath, sizeof szPath ) )
+    while( 1 )
     {
-        MESSAGE(MOZILLA_ACTIVEX_MESSAGE "\n");
-        MessageBoxA(NULL, MOZILLA_ACTIVEX_MESSAGE, "Wine", MB_OK | MB_ICONEXCLAMATION);
-        hMozCtl = 0;
-        return FALSE;
-    }
-    hMozCtl = LoadLibraryExW(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
-    if( !hMozCtl )
-    {
-        ERR("Can't load the Mozilla ActiveX control\n");
-        return FALSE;
+        if( SHDOCVW_GetMozctlPath( szPath, sizeof szPath ) )
+        {
+            hMozCtl = LoadLibraryExW(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+            if( hMozCtl )
+                return TRUE;
+        }
+        if( bTried )
+        {
+            MESSAGE("You need to install the Mozilla ActiveX control to\n");
+            MESSAGE("use Wine's builtin CLSID_WebBrowser from SHDOCVW.DLL\n");
+            return FALSE;
+        }
+        SHDOCVW_TryDownloadMozillaControl();
+        bTried = TRUE;
     }
     return TRUE;
 }
--- /dev/null	1994-07-18 08:46:18.000000000 +0900
+++ dlls/shdocvw/shdocvw.rc	2004-09-22 18:38:41.000000000 +0900
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2004 Mike McCormack for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "windef.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "commctrl.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+100 DIALOG LOADONCALL MOVEABLE DISCARDABLE  0, 0, 220, 62
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Downloading the Mozilla Active X control"
+FONT 8, "Helv"
+{
+ CONTROL "Progress1",1000,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12
+ LTEXT "", 104, 10, 30, 200, 10, SS_CENTER
+ PUSHBUTTON "Cancel", IDCANCEL, 85, 44, 50, 15, WS_GROUP | WS_TABSTOP
+}
+
+STRINGTABLE
+BEGIN
+ 1001	"This application is requesting an ActiveX browser object\n" \
+        "but the Mozilla Active X control is currently not installed." \
+        "Do you wish to download and install it?"
+END


More information about the wine-patches mailing list