[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(¶meters,0,sizeof(parameters));
- memset(&si,0,sizeof(STARTUPINFOW));
-
+ memset(&data,0,sizeof(data));
ParseCommandLine(cmdline,¶meters);
- 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 = ¶meters;
+ 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