[1/2] explorer: implement the explorer using IExplorerBrowser

Jay Yang jkelleyy at gmail.com
Fri Jun 3 16:05:36 CDT 2011


---
 configure.ac                  |    2 +-
 programs/explorer/Makefile.in |    6 +-
 programs/explorer/explorer.c  |  301 +++++++++++++++++++++++++++++++++++------
 programs/explorer/explorer.rc |   26 ++++
 programs/explorer/resource.h  |   26 ++++
 5 files changed, 317 insertions(+), 44 deletions(-)
 create mode 100644 programs/explorer/explorer.rc
 create mode 100644 programs/explorer/resource.h

diff --git a/configure.ac b/configure.ac
index 683bae9..8ca1284 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2946,7 +2946,7 @@ WINE_CONFIG_PROGRAM(control,,[install])
 WINE_CONFIG_PROGRAM(dxdiag,,[install])
 WINE_CONFIG_PROGRAM(eject,,[install])
 WINE_CONFIG_PROGRAM(expand,,[install])
-WINE_CONFIG_PROGRAM(explorer,,[install])
+WINE_CONFIG_PROGRAM(explorer,,[po,install])
 WINE_CONFIG_PROGRAM(extrac32,,[install])
 WINE_CONFIG_PROGRAM(hh,,[install])
 WINE_CONFIG_PROGRAM(hostname,,[po,install])
diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in
index 5537bc4..fb08774 100644
--- a/programs/explorer/Makefile.in
+++ b/programs/explorer/Makefile.in
@@ -1,7 +1,7 @@
 EXTRADEFS = -DWINE_NO_UNICODE_MACROS
 MODULE    = explorer.exe
 APPMODE   = -mwindows -municode
-IMPORTS   = rpcrt4 user32 gdi32 advapi32
+IMPORTS   = rpcrt4 user32 gdi32 advapi32 shell32 ole32
 DELAYIMPORTS = comctl32
  C_SRCS = \
@@ -10,4 +10,8 @@ C_SRCS = \
 	explorer.c \
 	systray.c
 +RC_SRCS = explorer.rc
+
+PO_SRCS = explorer.rc
+
 @MAKE_PROG_RULES@
diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c
index 16dcf72..2c84ae9 100644
--- a/programs/explorer/explorer.c
+++ b/programs/explorer/explorer.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2004 CodeWeavers, Mike Hearn
  * Copyright 2005,2006 CodeWeavers, Aric Stewart
+ * Copyright 2011 Jay Yang
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,10 +20,34 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 -#include <windows.h>
 +#define COBJMACROS
+
+#include "config.h"
+#include "wine/port.h"
 #include "wine/unicode.h"
+#include "wine/debug.h"
 #include "explorer_private.h"
+#include "resource.h"
+
+#include <initguid.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <shobjidl.h>
+#include <shlobj.h>
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(explorer);
+
+#define EXPLORER_INFO_INDEX 0
+
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
+
+static const WCHAR ExplorerControlClassName[] = {'W','I','N','E','_','E','X','P','L','O','R','E','R','_','C','O','N','T','R','O','L','\0'};
+static const WCHAR ExplorerClassName[] = {'W','I','N','E','_','E','X','P','L','O','R','E','R','\0'};
+
+HINSTANCE explorer_hInstance;
  typedef struct parametersTAG {
     BOOL    explorer_mode;
@@ -30,6 +55,182 @@ typedef struct parametersTAG {
     WCHAR   selection[MAX_PATH];
 } parameters_struct;
 +typedef struct
+{
+    IExplorerBrowser *browser;
+} ExplorerInfo;
+
+static void MakeExplorerWindow(IShellFolder* startFolder, HINSTANCE hInstance)
+{
+    RECT explorerRect;
+    HWND window;
+    FOLDERSETTINGS fs;
+    ExplorerInfo *info;
+    HRESULT hres;
+    WCHAR explorerTitle[100];
+    LoadStringW(hInstance,IDS_EXPLORER_TITLE,explorerTitle,
+                sizeof(explorerTitle)/sizeof(WCHAR));
+    info = HeapAlloc(GetProcessHeap(),0,sizeof(ExplorerInfo));
+    if(!info)
+    {
+        WINE_ERR("Could not allocate a ExplorerInfo struct\n");
+        return;
+    }
+    hres = CoCreateInstance(&CLSID_ExplorerBrowser,NULL,CLSCTX_INPROC_SERVER,
+                            &IID_IExplorerBrowser,(LPVOID*)&info->browser);
+    if(!SUCCEEDED(hres))
+    {
+        WINE_ERR("Could not obtain an instance of IExplorerBrowser\n");
+        HeapFree(GetProcessHeap(),0,info);
+        return;
+    }
+
+    window = CreateWindowW(ExplorerClassName,explorerTitle,WS_OVERLAPPEDWINDOW,
+                           CW_USEDEFAULT,CW_USEDEFAULT,DEFAULT_WIDTH,
+                           DEFAULT_HEIGHT,NULL,NULL,hInstance,NULL);
+    fs.ViewMode = FVM_DETAILS;
+    fs.fFlags = FWF_AUTOARRANGE;
+    explorerRect.left = 0;
+    explorerRect.top = 0;
+    explorerRect.right = DEFAULT_WIDTH;
+    explorerRect.bottom = DEFAULT_HEIGHT;
+
+    IExplorerBrowser_Initialize(info->browser,window,&explorerRect,&fs);
+    IExplorerBrowser_SetOptions(info->browser,EBO_SHOWFRAMES);
+    SetWindowLongPtrW(window,EXPLORER_INFO_INDEX,(LONG)info);
+    IExplorerBrowser_BrowseToObject(info->browser,(IUnknown*)startFolder,
+                                    SBSP_ABSOLUTE);
+    ShowWindow(window,SW_SHOWDEFAULT);
+    UpdateWindow(window);
+}
+
+static void UpdateWindowSize(ExplorerInfo *info, int height, int width)
+{
+    RECT newRect;
+    int pathBoxWidth = width;
+    newRect.left = 0;
+    newRect.top = 0;
+    newRect.right = width;
+    newRect.bottom = height;
+    IExplorerBrowser_SetRect(info->browser,NULL,newRect);
+}
+
+static void DoExit(int code)
+{
+    CoUninitialize();
+    ExitProcess(code);
+}
+
+/*
+ * The WindowProc for the control window
+ */
+LRESULT CALLBACK ExplorerControl_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    static HINSTANCE hInstance;
+    switch(uMsg)
+    {
+    case WM_CREATE:
+        {
+            LPCREATESTRUCTW create_info = (LPCREATESTRUCTW)lParam;
+            hInstance = create_info->hInstance;
+            break;
+        }
+    case WM_NOTIFY:
+        break;
+    case WM_COPYDATA:
+        {
+            PCOPYDATASTRUCT data = (PCOPYDATASTRUCT)lParam;
+            parameters_struct* params= data->lpData;
+            IShellFolder* desktop,*folder;
+            LPITEMIDLIST rootPidl;
+            HRESULT hres;
+            SHGetDesktopFolder(&desktop);
+            if(!params || !params->root)
+            {
+                MakeExplorerWindow(desktop,hInstance);
+                IShellFolder_Release(desktop);
+                break;
+            }
+            hres = IShellFolder_ParseDisplayName(desktop,NULL,NULL,params->root,
+                                                 NULL,&rootPidl,NULL);
+            if(FAILED(hres))
+            {
+                MakeExplorerWindow(desktop,hInstance);
+                IShellFolder_Release(desktop);
+                break;
+            }
+            hres = IShellFolder_BindToObject(desktop,rootPidl,NULL,
+                                             &IID_IShellFolder,(void**)&folder);
+            if(FAILED(hres))
+            {
+                MakeExplorerWindow(desktop,hInstance);
+                IShellFolder_Release(desktop);
+                break;
+            }
+            MakeExplorerWindow(folder,hInstance);
+            IShellFolder_Release(folder);
+            IShellFolder_Release(desktop);
+            break;
+        }
+    case WM_QUIT:
+        DoExit(wParam);
+    default:
+        return DefWindowProcW(hwnd,uMsg,wParam,lParam);
+    }
+    return 0;
+}
+
+
+
+LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    ExplorerInfo *info
+        = (ExplorerInfo*)GetWindowLongPtrW(hwnd,EXPLORER_INFO_INDEX);
+    IExplorerBrowser *browser = NULL;
+
+    if(info)
+        browser = info->browser;
+    switch(uMsg)
+    {
+    case WM_CREATE:
+        break;
+    case WM_NOTIFY:
+        break;
+    case WM_DESTROY:
+        IExplorerBrowser_Release(browser);
+        HeapFree(GetProcessHeap(),0,info);
+        break;
+    case WM_SIZE:
+        UpdateWindowSize(info,HIWORD(lParam),LOWORD(lParam));
+        break;
+    default:
+        return DefWindowProcW(hwnd,uMsg,wParam,lParam);
+    }
+    return 0;
+}
+
+static HWND MakeControlWindow(HINSTANCE hInstance)
+{
+    WNDCLASSEXW windowClass;
+    windowClass.cbSize = sizeof(WNDCLASSEXW);
+    windowClass.style = 0;
+    windowClass.cbClsExtra = 0;
+    windowClass.cbWndExtra = 0;
+    windowClass.lpfnWndProc = ExplorerControl_WindowProc;
+    windowClass.hInstance = hInstance;
+    windowClass.hIcon = NULL;
+    windowClass.hCursor = NULL;
+    windowClass.hbrBackground = NULL;
+    windowClass.lpszMenuName = NULL;
+    windowClass.lpszClassName = ExplorerControlClassName;
+    windowClass.hIconSm = NULL;
+    RegisterClassExW(&windowClass);
+
+    return CreateWindowW(ExplorerControlClassName,ExplorerControlClassName,
+                         0,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
+                         CW_USEDEFAULT,HWND_MESSAGE,NULL,hInstance,NULL);
+}
+
  static int CopyPathString(LPWSTR target, LPWSTR source)
 {
@@ -145,56 +346,72 @@ int WINAPI wWinMain(HINSTANCE hinstance,
                     LPWSTR cmdline,
                     int cmdshow)
 {
-    STARTUPINFOW si;
-    PROCESS_INFORMATION info;
+
     parameters_struct   parameters;
-    BOOL rc;
-    static const WCHAR winefile[] = {'\\','w','i','n','e','f','i','l','e','.','e','x','e',0};
-    static const WCHAR space[] = {' ',0};
-    WCHAR app[MAX_PATH];
-    LPWSTR winefile_commandline = NULL;
-    DWORD len = 0;
+    HRESULT hres;
+    MSG msg;
+    WNDCLASSEXW windowClass;
+    HWND control;
+    COPYDATASTRUCT data;
+    HANDLE mutex;
      memset(&parameters,0,sizeof(parameters));
-    memset(&si,0,sizeof(STARTUPINFOW));
-
+    memset(&data,0,sizeof(data));
     ParseCommandLine(cmdline,&parameters);
-    len = GetSystemDirectoryW( NULL, 0 ) + sizeof(winefile)/sizeof(WCHAR);
-
-    if (parameters.selection[0]) len += lstrlenW(parameters.selection) + 2;
-    else if (parameters.root[0]) len += lstrlenW(parameters.root) + 3;
-
-    winefile_commandline = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
-    GetSystemDirectoryW( app, MAX_PATH - sizeof(winefile)/sizeof(WCHAR) );
-    strcatW( app, winefile );
-    strcpyW( winefile_commandline, app );
-
-    if (parameters.selection[0])
+    data.lpData = &parameters;
+    data.cbData = sizeof(parameters);
+    /*Take a named mutex*/
+    mutex = CreateMutexW(NULL,TRUE,ExplorerClassName);
+    if(!mutex)
     {
-        lstrcatW(winefile_commandline,space);
-        lstrcatW(winefile_commandline,parameters.selection);
+        WINE_WARN("Could not create a mutex\n");
     }
-    else if (parameters.root[0])
+    else if(GetLastError()==ERROR_ALREADY_EXISTS)
     {
-        lstrcatW(winefile_commandline,space);
-        lstrcatW(winefile_commandline,parameters.root);
-        if (winefile_commandline[lstrlenW(winefile_commandline)-1]!='\\')
+        WaitForSingleObject(mutex,INFINITE);
+        control = FindWindowExW(HWND_MESSAGE,NULL,NULL,ExplorerControlClassName);
+        ReleaseMutex(mutex);
+        if(control)
+        {
+            SendMessageW(control,WM_COPYDATA,0,(LPARAM)&data);
+            ExitProcess(EXIT_SUCCESS);
+        }
+        else
         {
-            static const WCHAR slash[] = {'\\',0};
-            lstrcatW(winefile_commandline,slash);
+            WINE_ERR("Previous Explorer process did not shutdown properly\n");
+            ExitProcess(EXIT_FAILURE);
         }
     }
-
-    rc = CreateProcessW(app, winefile_commandline, NULL, NULL, FALSE, 0, NULL,
-                        parameters.root[0] ? parameters.root:NULL, &si, &info);
-
-    HeapFree(GetProcessHeap(),0,winefile_commandline);
-
-    if (!rc)
-        return 0;
-
-    CloseHandle(info.hThread);
-    WaitForSingleObject(info.hProcess,INFINITE);
-    CloseHandle(info.hProcess);
+    explorer_hInstance = hinstance;
+    hres = CoInitialize(NULL);
+    if(!SUCCEEDED(hres))
+    {
+        WINE_ERR("Could not initialize COM\n");
+        if(mutex)
+            ReleaseMutex(mutex);
+        ExitProcess(EXIT_FAILURE);
+    }
+    windowClass.cbSize = sizeof(WNDCLASSEXW);
+    windowClass.style = 0;
+    windowClass.cbClsExtra = 0;
+    windowClass.cbWndExtra = sizeof(LONG_PTR);
+    windowClass.lpfnWndProc = WindowProc;
+    windowClass.hInstance = hinstance;
+    windowClass.hIcon = NULL;
+    windowClass.hCursor = NULL;
+    windowClass.hbrBackground = NULL;
+    windowClass.lpszMenuName = NULL;
+    windowClass.lpszClassName = ExplorerClassName;
+    windowClass.hIconSm = NULL;
+    RegisterClassExW(&windowClass);
+    control = MakeControlWindow(hinstance);
+    if(mutex)
+        ReleaseMutex(mutex);
+    SendMessageW(control,WM_COPYDATA,0,(LPARAM)&data);
+    while(GetMessageW( &msg, NULL, 0, 0 ) != 0)
+    {
+	    TranslateMessage(&msg);
+	    DispatchMessageW(&msg);
+    }
     return 0;
 }
diff --git a/programs/explorer/explorer.rc b/programs/explorer/explorer.rc
new file mode 100644
index 0000000..8fa81c6
--- /dev/null
+++ b/programs/explorer/explorer.rc
@@ -0,0 +1,26 @@
+/*
+ * Explorer resources
+ *
+ * Copyright 2011 Jay Yang
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "resource.h"
+
+STRINGTABLE
+{
+	IDS_EXPLORER_TITLE	"Wine Explorer"
+}
diff --git a/programs/explorer/resource.h b/programs/explorer/resource.h
new file mode 100644
index 0000000..f3813b0
--- /dev/null
+++ b/programs/explorer/resource.h
@@ -0,0 +1,26 @@
+/*
+ * Explorer resource definitions
+ *
+ * Copyright 2011 Jay Yang
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_EXPLORER_RESOURCE_H
+#define __WINE_EXPLORER_RESOURCE_H
+
+#define IDS_EXPLORER_TITLE 1
+
+#endif
-- 
1.7.5.2





More information about the wine-patches mailing list