Windows: Build afs_shl_ext.dll with talocaleU.lib
[openafs.git] / src / WINNT / client_exp / afs_shl_ext.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include "stdafx.h"
11 #include <winsock2.h>
12 #include <ws2tcpip.h>
13
14 extern "C" {
15 #include <afs/param.h>
16 #include <afs/stds.h>
17 }
18
19 #include "afs_shl_ext.h"
20 #include <winsock2.h>
21 #include "help.h"
22 #include "shell_ext.h"
23 #include <winreg.h>
24 extern "C" {
25 #include "WINNT\afsreg.h"
26 }
27 #include "WINNT\talocale.h"
28 #define STRSAFE_NO_DEPRECATE
29 #include <strsafe.h>
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #undef THIS_FILE
34 static char THIS_FILE[] = __FILE__;
35 #endif
36
37 #ifndef _WIN64
38
39 // 32-bit
40 static const IID IID_IShellExt =
41     { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
42 static const IID IID_IShellExt2 =
43     { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd3 } };
44
45 #else
46
47 // 64-bit
48 static const IID IID_IShellExt =
49     { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb5} };
50 static const IID IID_IShellExt2 =
51     { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb6} };
52
53 #endif
54
55 /////////////////////////////////////////////////////////////////////////////
56 // CAfsShlExt
57
58 BEGIN_MESSAGE_MAP(CAfsShlExt, CWinApp)
59     //{{AFX_MSG_MAP(CAfsShlExt)
60     // NOTE - the ClassWizard will add and remove mapping macros here.
61     //    DO NOT EDIT what you see in these blocks of generated code!
62     //}}AFX_MSG_MAP
63 END_MESSAGE_MAP()
64
65 /////////////////////////////////////////////////////////////////////////////
66 // CAfsShlExt construction
67
68 CAfsShlExt::CAfsShlExt()
69 {
70     /* Start up sockets */
71     WSADATA WSAjunk;
72     WSAStartup(0x0101, &WSAjunk);
73 }
74
75 /////////////////////////////////////////////////////////////////////////////
76 // The one and only CAfsShlExt object
77
78 CAfsShlExt theApp;
79
80 /////////////////////////////////////////////////////////////////////////////
81 // CAfsShlExt initialization
82 HINSTANCE g_hInstance;
83
84 BOOL CAfsShlExt::InitInstance()
85 {
86     // Load our translated resources
87     TaLocale_LoadCorrespondingModuleByName (m_hInstance, TEXT("afs_shl_ext.dll"));
88
89     // Register all OLE server (factories) as running.  This enables the
90     //  OLE libraries to create objects from other applications.
91     COleObjectFactory::RegisterAll();
92
93     SetHelpPath(m_pszHelpFilePath);
94
95     return TRUE;
96 }
97
98 /////////////////////////////////////////////////////////////////////////////
99 // Special entry points required for inproc servers
100
101 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
102 {
103     AFX_MANAGE_STATE(AfxGetStaticModuleState());
104     return AfxDllGetClassObject(rclsid, riid, ppv);
105 }       
106
107 STDAPI DllCanUnloadNow(void)
108 {
109     AFX_MANAGE_STATE(AfxGetStaticModuleState());
110
111 #ifdef COMMENT
112     // This test is correct and we really do want to allow the extension to be loaded and 
113     // unloaded as needed.   Unfortunately, the extension is being unloaded and never loaded
114     // again which is disconcerting for many folks.  For now we will prevent the unloading 
115     // until someone has time to figure out how to debug this.   
116     // Jeffrey Altman - 2 Oct 2005
117
118     if (!nCMRefCount && !nSERefCount && !nICRefCount && !nTPRefCount && !nXPRefCount)
119         return S_OK;
120 #endif
121     return S_FALSE;
122 }
123
124 int WideCharToLocal(LPTSTR pLocal, LPCWSTR pWide, DWORD dwChars)
125 {
126 #ifdef UNICODE
127     StringCchCopy(pLocal, dwChars, pWide);
128 #else
129     *pLocal = 0;
130     WideCharToMultiByte( CP_ACP, 0, pWide, -1, pLocal, dwChars, NULL, NULL);
131 #endif
132     return lstrlen(pLocal);
133 }
134
135 LRESULT DoRegCLSID(HKEY hKey,PTCHAR szSubKey,PTCHAR szData,PTCHAR szValue=NULL)
136 {
137     DWORD    dwDisp;
138     LRESULT  lResult;
139     HKEY     thKey;
140     lResult = RegCreateKeyEx(hKey, szSubKey, 0, NULL,
141                               REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
142                               &thKey, &dwDisp);
143     if(NOERROR == lResult)
144     {
145         lResult = RegSetValueEx(thKey, szValue, 0, REG_SZ,
146                                  (LPBYTE)szData, (lstrlen(szData) + 1) 
147                                  * sizeof(TCHAR));
148         RegCloseKey(thKey);
149     }
150     RegCloseKey(hKey);
151     return lResult;
152 }
153
154 // by exporting DllRegisterServer, you can use regsvr.exe
155 STDAPI DllRegisterServer(void)
156 {
157     HKEY     hKey;
158     LRESULT  lResult;
159     DWORD    dwDisp;
160     TCHAR    szSubKey[MAX_PATH];
161     TCHAR    szCLSID[MAX_PATH];
162     TCHAR    szModule[MAX_PATH];
163     LPWSTR   pwsz;
164     AFX_MANAGE_STATE(AfxGetStaticModuleState());
165     COleObjectFactory::UpdateRegistryAll();
166
167     StringFromIID(IID_IShellExt, &pwsz);
168     if(pwsz)
169     {
170 #ifdef UNICODE
171         StringCbCopy(szCLSID, sizeof(szCLSID), pwsz);
172 #else
173         WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
174 #endif
175         CoTaskMemFree(pwsz);
176     } else {
177         return E_FAIL;
178     }
179     
180     /*
181     [HKEY_CLASSES_ROOT\CLSID\{$CLSID}\InprocServer32]
182     @="Y:\\DEST\\root.client\\usr\\vice\\etc\\afs_shl_ext.dll"
183     "ThreadingModel"="Apartment"
184     */
185     HMODULE hModule=GetModuleHandle(TEXT("afs_shl_ext.dll"));
186     DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule));
187     wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
188     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szModule))!=NOERROR)
189         return lResult;
190
191     wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
192     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,
193                             TEXT("Apartment"),TEXT("ThreadingModel")))!=NOERROR)
194         return lResult;
195
196     /*
197     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\AFS Client Shell Extension]
198     @="{EA3775F2-28BE-11D3-9C8D-00105A24ED29}"
199     */
200
201     wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
202     if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,szCLSID))!=NOERROR)
203         return lResult;
204         
205     //If running on NT, register the extension as approved.
206     /*
207     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved]
208     "{$(CLSID)}"="AFS Client Shell Extension"
209
210     [HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\AFS Client Shell Extension]
211     @="{$(CLSID)}"
212     */
213
214     OSVERSIONINFO  osvi;
215     osvi.dwOSVersionInfoSize = sizeof(osvi);
216     GetVersionEx(&osvi);
217     if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
218     {
219         wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
220         if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,STR_EXT_TITLE,szCLSID))!=NOERROR)
221             return lResult;
222     }
223     wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
224     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
225         return lResult;
226     wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
227     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
228         return lResult;
229     wsprintf(szSubKey, TEXT("Directory\\Background\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
230     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
231         return lResult;
232     wsprintf(szSubKey, TEXT("LibraryFolder\\background\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
233     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
234         return lResult;
235
236     /*
237     Register InfoTip
238
239     [HKEY_CLASSES_ROOT\Folder\shellex\{00021500-0000-0000-C000-000000000046}]
240     @="{$(CLSID)}"
241     */
242
243     wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}"));
244     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
245         return lResult;
246
247         
248     /* Below needs to be merged with above */
249     wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
250     lResult = RegCreateKeyEx(  HKEY_LOCAL_MACHINE,
251                               szSubKey,
252                               0,
253                               NULL,
254                               REG_OPTION_NON_VOLATILE,
255                               KEY_WRITE,
256                               NULL,
257                               &hKey,
258                               &dwDisp);
259
260     if(NOERROR == lResult)
261     {
262         //Create the value string.
263         lResult = RegSetValueEx( hKey,
264                                  NULL,
265                                  0,
266                                  REG_SZ,
267                                  (LPBYTE)szCLSID,
268                                  (lstrlen(szCLSID) + 1) * sizeof(TCHAR));
269         RegCloseKey(hKey);
270     }
271     else
272         return SELFREG_E_CLASS;
273
274     //If running on NT, register the extension as approved.
275     osvi.dwOSVersionInfoSize = sizeof(osvi);
276     GetVersionEx(&osvi);
277     if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
278     {
279         lstrcpy( szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
280
281         lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
282                                   szSubKey,
283                                   0,
284                                   NULL,
285                                   REG_OPTION_NON_VOLATILE,
286                                   KEY_WRITE,
287                                   NULL,
288                                   &hKey,
289                                   &dwDisp);
290
291         if(NOERROR == lResult)
292         {
293             TCHAR szData[MAX_PATH];
294
295             //Create the value string.
296             lstrcpy(szData, STR_EXT_TITLE);
297
298             lResult = RegSetValueEx( hKey,
299                                      szCLSID,
300                                      0,
301                                      REG_SZ,
302                                      (LPBYTE)szData,
303                                      (lstrlen(szData) + 1) * sizeof(TCHAR));
304
305             RegCloseKey(hKey);
306         } else
307             return SELFREG_E_CLASS;
308     }
309
310     StringFromIID(IID_IShellExt2, &pwsz);
311     if(pwsz)
312     {
313 #ifdef UNICODE
314         StringCbCopy(szCLSID, sizeof(szCLSID), pwsz);
315 #else
316         WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
317 #endif
318         CoTaskMemFree(pwsz);
319     } else {
320         return E_FAIL;
321     }
322
323     /*
324     [HKEY_CLASSES_ROOT\CLSID\{$CLSID}\InprocServer32]
325     @="Y:\\DEST\\root.client\\usr\\vice\\etc\\afs_shl_ext.dll"
326     "ThreadingModel"="Apartment"
327     */
328     hModule=GetModuleHandle(TEXT("afs_shl_ext.dll"));
329     z=GetModuleFileName(hModule,szModule,sizeof(szModule));
330     wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
331     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szModule))!=NOERROR)
332         return lResult;
333
334     wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
335     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,
336                             TEXT("Apartment"),TEXT("ThreadingModel")))!=NOERROR)
337         return lResult;
338
339     /*
340     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\AFS Client Shell Extension]
341     @="{EA3775F2-28BE-11D3-9C8D-00105A24ED29}"
342     */
343
344     wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE2);
345     if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,szCLSID))!=NOERROR)
346         return lResult;
347
348     //If running on NT, register the extension as approved.
349     /*
350     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved]
351     "{$(CLSID)}"="AFS Client Shell Extension"
352
353     [HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\AFS Client Shell Extension]
354     @="{$(CLSID)}"
355     */
356
357     osvi.dwOSVersionInfoSize = sizeof(osvi);
358     GetVersionEx(&osvi);
359     if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
360     {
361         wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
362         if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,STR_EXT_TITLE2,szCLSID))!=NOERROR)
363             return lResult;
364     }
365
366
367     return S_OK;
368 }
369
370 //returnValue = RegOpenKeyEx (HKEY_CLASSES_ROOT, keyName, 0, KEY_ALL_ACCESS, &registryKey);
371
372 LRESULT DoValueDelete(HKEY hKey,PTCHAR pszSubKey,PTCHAR szValue=NULL)
373 {
374     LRESULT  lResult;
375     HKEY     thKey;
376     if (szValue==NULL) {
377         lResult=RegDeleteKey(hKey, pszSubKey);
378         return lResult;
379     }
380     lResult = RegOpenKeyEx( hKey,
381                             pszSubKey,
382                             0,
383                             (IsWow64()?KEY_WOW64_64KEY:0)|KEY_ALL_ACCESS,
384                             &thKey);
385     if(NOERROR == lResult)
386     {
387         lResult=RegDeleteValue(hKey, szValue);
388         RegCloseKey(thKey);
389     }
390     return lResult;
391 }
392
393 STDAPI DllUnregisterServer(void)
394 {
395     TCHAR    szSubKey[MAX_PATH];
396     TCHAR    szCLSID[MAX_PATH];
397     LPWSTR   pwsz;
398     AFX_MANAGE_STATE(AfxGetStaticModuleState());
399     COleObjectFactory::UpdateRegistryAll(FALSE);
400     StringFromIID(IID_IShellExt, &pwsz);
401     if(pwsz)
402     {
403 #ifdef UNICODE
404         StringCbCopy(szCLSID, sizeof(szCLSID), pwsz);
405 #else
406         WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
407 #endif
408         CoTaskMemFree(pwsz);
409     } else {
410         return E_FAIL;
411     }
412     wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
413     DoValueDelete(HKEY_LOCAL_MACHINE,szSubKey,szCLSID);
414     wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
415     DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
416     wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}"));
417     DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
418     wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
419     DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
420     wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
421     DoValueDelete(HKEY_LOCAL_MACHINE, szSubKey);
422
423     StringFromIID(IID_IShellExt2, &pwsz);
424     if(pwsz)
425     {
426 #ifdef UNICODE
427         StringCbCopy(szCLSID, sizeof(szCLSID), pwsz);
428 #else
429         WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
430 #endif
431         CoTaskMemFree(pwsz);
432     } else {
433         return E_FAIL;
434     }
435     wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
436     DoValueDelete(HKEY_LOCAL_MACHINE,szSubKey,szCLSID);
437
438     return S_OK;
439 }       
440
441