explorerframe: Implement expansion of nodes.
[wine] / dlls / explorerframe / explorerframe_main.c
1 /*
2  * ExplorerFrame main functions
3  *
4  * Copyright 2010 David Hedberg
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
33 #include "advpub.h"
34 #include "shobjidl.h"
35
36 #include "wine/debug.h"
37
38 #include "explorerframe_main.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(explorerframe);
41
42 HINSTANCE explorerframe_hinstance;
43 LONG EFRAME_refCount = 0;
44
45 /*************************************************************************
46  *              DllMain (ExplorerFrame.@)
47  */
48 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad)
49 {
50     TRACE("%p, 0x%x, %p\n", hinst, fdwReason, fImpLoad);
51     switch (fdwReason)
52     {
53     case DLL_PROCESS_ATTACH:
54         DisableThreadLibraryCalls(hinst);
55         explorerframe_hinstance = hinst;
56         break;
57     case DLL_PROCESS_DETACH:
58         break;
59     }
60     return TRUE;
61 }
62
63 /*************************************************************************
64  *              DllCanUnloadNow (ExplorerFrame.@)
65  */
66 HRESULT WINAPI DllCanUnloadNow(void)
67 {
68     TRACE("refCount is %d\n", EFRAME_refCount);
69     return EFRAME_refCount ? S_FALSE : S_OK;
70 }
71
72 /*************************************************************************
73  *              DllGetVersion (ExplorerFrame.@)
74  */
75 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *info)
76 {
77     TRACE("%p\n", info);
78     if(info->cbSize == sizeof(DLLVERSIONINFO) ||
79        info->cbSize == sizeof(DLLVERSIONINFO2))
80     {
81         /* Windows 7 */
82         info->dwMajorVersion = 6;
83         info->dwMinorVersion = 1;
84         info->dwBuildNumber = 7600;
85         info->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
86         if(info->cbSize == sizeof(DLLVERSIONINFO2))
87         {
88             DLLVERSIONINFO2 *info2 = (DLLVERSIONINFO2*)info;
89             info2->dwFlags = 0;
90             info2->ullVersion = MAKEDLLVERULL(info->dwMajorVersion,
91                                               info->dwMinorVersion,
92                                               info->dwBuildNumber,
93                                               16385); /* "hotfix number" */
94         }
95         return S_OK;
96     }
97
98     WARN("wrong DLLVERSIONINFO size from app.\n");
99     return E_INVALIDARG;
100 }
101
102 /*************************************************************************
103  * Implement the ExplorerFrame class factory
104  *
105  * (Taken from shdocvw/factory.c; based on implementation in
106  *  ddraw/main.c)
107  */
108
109 #define FACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
110
111 typedef struct
112 {
113     const IClassFactoryVtbl *lpClassFactoryVtbl;
114     HRESULT (*cf)(IUnknown*, REFIID, void**);
115     LONG ref;
116 } IClassFactoryImpl;
117
118 /*************************************************************************
119  * EFCF_QueryInterface (IUnknown)
120  */
121 static HRESULT WINAPI EFCF_QueryInterface(IClassFactory* iface,
122                                           REFIID riid, void **ppobj)
123 {
124     TRACE("%p (%s %p)\n", iface, debugstr_guid(riid), ppobj);
125
126     if(!ppobj)
127         return E_POINTER;
128
129     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid))
130     {
131         *ppobj = iface;
132         IClassFactory_AddRef(iface);
133         return S_OK;
134     }
135
136     WARN("Interface not supported.\n");
137
138     *ppobj = NULL;
139     return E_NOINTERFACE;
140 }
141
142 /*************************************************************************
143  * EFCF_AddRef (IUnknown)
144  */
145 static ULONG WINAPI EFCF_AddRef(IClassFactory *iface)
146 {
147     EFRAME_LockModule();
148
149     return 2; /* non-heap based object */
150 }
151
152 /*************************************************************************
153  * EFCF_Release (IUnknown)
154  */
155 static ULONG WINAPI EFCF_Release(IClassFactory *iface)
156 {
157     EFRAME_UnlockModule();
158
159     return 1; /* non-heap based object */
160 }
161
162 /*************************************************************************
163  * EFCF_CreateInstance (IClassFactory)
164  */
165 static HRESULT WINAPI EFCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
166                                           REFIID riid, void **ppobj)
167 {
168     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
169     return This->cf(pOuter, riid, ppobj);
170 }
171
172 /*************************************************************************
173  * EFCF_LockServer (IClassFactory)
174  */
175 static HRESULT WINAPI EFCF_LockServer(IClassFactory *iface, BOOL dolock)
176 {
177     TRACE("%p (%d)\n", iface, dolock);
178
179     if (dolock)
180         EFRAME_LockModule();
181     else
182         EFRAME_UnlockModule();
183
184     return S_OK;
185 }
186
187 static const IClassFactoryVtbl EFCF_Vtbl =
188 {
189     EFCF_QueryInterface,
190     EFCF_AddRef,
191     EFCF_Release,
192     EFCF_CreateInstance,
193     EFCF_LockServer
194 };
195
196 /*************************************************************************
197  *              DllGetClassObject (ExplorerFrame.@)
198  */
199 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
200 {
201     static IClassFactoryImpl NSTCClassFactory = {&EFCF_Vtbl, NamespaceTreeControl_Constructor};
202
203     TRACE("%s, %s, %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
204
205     if(IsEqualGUID(&CLSID_NamespaceTreeControl, rclsid))
206         return IClassFactory_QueryInterface(FACTORY(&NSTCClassFactory), riid, ppv);
207
208     return CLASS_E_CLASSNOTAVAILABLE;
209 }
210
211 /*************************************************************************
212  *          Register/Unregister DLL, based on shdocvw/factory.c
213  */
214 static HRESULT reg_install(LPCSTR section, STRTABLEA *strtable)
215 {
216     HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
217     HMODULE hadvpack;
218     HRESULT hres;
219
220     static const WCHAR advpackW[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
221
222     hadvpack = LoadLibraryW(advpackW);
223     pRegInstall = (void *)GetProcAddress(hadvpack, "RegInstall");
224
225     hres = pRegInstall(explorerframe_hinstance, section, strtable);
226
227     FreeLibrary(hadvpack);
228     return hres;
229 }
230
231 #define INF_SET_CLSID(clsid)                  \
232     do                                        \
233     {                                         \
234         static CHAR name[] = "CLSID_" #clsid; \
235                                               \
236         pse[i].pszName = name;                \
237         clsids[i++] = &CLSID_ ## clsid;       \
238     } while (0)
239
240 static HRESULT register_server(BOOL doregister)
241 {
242     STRTABLEA strtable;
243     STRENTRYA pse[1];
244     static CLSID const *clsids[1];
245     unsigned int i = 0;
246     HRESULT hres;
247
248     INF_SET_CLSID(NamespaceTreeControl);
249
250     for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++)
251     {
252         pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39);
253         sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
254                 clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
255                 clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
256                 clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
257     }
258
259     strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
260     strtable.pse = pse;
261
262     hres = reg_install(doregister ? "RegisterDll" : "UnregisterDll", &strtable);
263
264     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
265         HeapFree(GetProcessHeap(), 0, pse[i].pszValue);
266
267     return hres;
268 }
269
270 #undef INF_SET_CLSID
271
272 /*************************************************************************
273  *          DllRegisterServer (ExplorerFrame.@)
274  */
275 HRESULT WINAPI DllRegisterServer(void)
276 {
277     return register_server(TRUE);
278 }
279
280 /*************************************************************************
281  *          DllUnregisterServer (ExplorerFrame.@)
282  */
283 HRESULT WINAPI DllUnregisterServer(void)
284 {
285     return register_server(FALSE);
286 }