d93caaa4b68c1b21e4068f9d5ac36b7f5baac051
[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
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #undef THIS_FILE
28 static char THIS_FILE[] = __FILE__;
29 #endif
30
31 static const IID IID_IShellExt =
32 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
33
34 /////////////////////////////////////////////////////////////////////////////
35 // CAfsShlExt
36
37 BEGIN_MESSAGE_MAP(CAfsShlExt, CWinApp)
38         //{{AFX_MSG_MAP(CAfsShlExt)
39                 // NOTE - the ClassWizard will add and remove mapping macros here.
40                 //    DO NOT EDIT what you see in these blocks of generated code!
41         //}}AFX_MSG_MAP
42 END_MESSAGE_MAP()
43
44 /////////////////////////////////////////////////////////////////////////////
45 // CAfsShlExt construction
46
47 CAfsShlExt::CAfsShlExt()
48 {
49         /* Start up sockets */
50         WSADATA WSAjunk;
51         WSAStartup(0x0101, &WSAjunk);
52 }
53
54 /////////////////////////////////////////////////////////////////////////////
55 // The one and only CAfsShlExt object
56
57 CAfsShlExt theApp;
58
59 /////////////////////////////////////////////////////////////////////////////
60 // CAfsShlExt initialization
61 HINSTANCE g_hInstance;
62
63 BOOL CAfsShlExt::InitInstance()
64 {
65         // Load our translated resources
66         TaLocale_LoadCorrespondingModuleByName (m_hInstance, TEXT("afs_shl_ext.dll"));
67
68         // Register all OLE server (factories) as running.  This enables the
69         //  OLE libraries to create objects from other applications.
70         COleObjectFactory::RegisterAll();
71
72         SetHelpPath(m_pszHelpFilePath);
73
74         return TRUE;
75 }
76
77 /////////////////////////////////////////////////////////////////////////////
78 // Special entry points required for inproc servers
79
80 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
81 {
82         AFX_MANAGE_STATE(AfxGetStaticModuleState());
83         return AfxDllGetClassObject(rclsid, riid, ppv);
84 }
85
86 STDAPI DllCanUnloadNow(void)
87 {
88         AFX_MANAGE_STATE(AfxGetStaticModuleState());
89
90 #ifdef COMMENT
91     // This test is correct and we really do want to allow the extension to be loaded and 
92     // unloaded as needed.   Unfortunately, the extension is being unloaded and never loaded
93     // again which is disconcerting for many folks.  For now we will prevent the unloading 
94     // until someone has time to figure out how to debug this.   
95     // Jeffrey Altman - 2 Oct 2005
96
97         if (!nCMRefCount && !nSERefCount && !nICRefCount && !nTPRefCount && !nXPRefCount)
98                 return S_OK;
99 #endif
100         return S_FALSE;
101 }
102
103 int WideCharToLocal(LPTSTR pLocal, LPCWSTR pWide, DWORD dwChars)
104 {
105         *pLocal = 0;
106         WideCharToMultiByte( CP_ACP, 0, pWide, -1, pLocal, dwChars, NULL, NULL);
107         return lstrlen(pLocal);
108 }
109
110 LRESULT DoRegCLSID(HKEY hKey,PTCHAR szSubKey,PTCHAR szData,PTCHAR szValue=NULL)
111 {
112         DWORD    dwDisp;
113         LRESULT  lResult;
114         HKEY     thKey;
115         lResult = RegCreateKeyEx(hKey, szSubKey, 0, NULL,
116                                  REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
117                                  &thKey, &dwDisp);
118         if(NOERROR == lResult)
119         {
120                 lResult = RegSetValueEx(thKey, szValue, 0, REG_SZ,
121                                         (LPBYTE)szData, (lstrlen(szData) + 1) 
122                                         * sizeof(TCHAR));
123                 RegCloseKey(thKey);
124         }
125         RegCloseKey(hKey);
126         return lResult;
127 }
128
129 // by exporting DllRegisterServer, you can use regsvr.exe
130 STDAPI DllRegisterServer(void)
131 {
132         HKEY     hKey;
133         LRESULT  lResult;
134         DWORD    dwDisp;
135         TCHAR    szSubKey[MAX_PATH];
136         TCHAR    szCLSID[MAX_PATH];
137     TCHAR    szModule[MAX_PATH];
138     LPWSTR   pwsz;
139         AFX_MANAGE_STATE(AfxGetStaticModuleState());
140         COleObjectFactory::UpdateRegistryAll();
141
142         StringFromIID(IID_IShellExt, &pwsz);
143         if(pwsz)
144         {
145                 WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
146                 LPMALLOC pMalloc;
147                 CoGetMalloc(1, &pMalloc);
148                 if(pMalloc)
149                 {
150                         (pMalloc->Free)(pwsz);
151                         (pMalloc->Release)();
152                 }
153         } else {
154                 return E_FAIL;
155         }
156     
157     /*
158     [HKEY_CLASSES_ROOT\CLSID\{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}\InprocServer32]
159     @="Y:\\DEST\\root.client\\usr\\vice\\etc\\afs_shl_ext.dll"
160     "ThreadingModel"="Apartment"
161     */
162     HMODULE hModule=GetModuleHandle("afs_shl_ext.dll");
163         DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule));
164         wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
165         if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szModule))!=NOERROR)
166                 return lResult;
167
168         wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID);
169         if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,"Apartment","ThreadingModel"))!=NOERROR)
170                 return lResult;
171
172     /*
173     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\AFS Client Shell Extension]
174     @="{EA3775F2-28BE-11D3-9C8D-00105A24ED29}"
175     */
176
177         wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
178         if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,szCLSID))!=NOERROR)
179                 return lResult;
180         
181         //If running on NT, register the extension as approved.
182     /*
183     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved]
184     "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}"="AFS Client Shell Extension"
185
186     [HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\AFS Client Shell Extension]
187     @="{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}"
188     */
189
190     OSVERSIONINFO  osvi;
191     osvi.dwOSVersionInfoSize = sizeof(osvi);
192     GetVersionEx(&osvi);
193     if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
194     {
195         wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
196         if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,STR_EXT_TITLE,szCLSID))!=NOERROR)
197             return lResult;
198     }
199     wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
200     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
201         return lResult;
202     wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
203     if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
204         return lResult;
205
206     /*
207     Register InfoTip
208
209     [HKEY_CLASSES_ROOT\Folder\shellex\{00021500-0000-0000-C000-000000000046}]
210     @="{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}"
211     */
212
213         wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}"));
214         if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR)
215                 return lResult;
216
217         
218         /* Below needs to be merged with above */
219
220     wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
221         lResult = RegCreateKeyEx(  HKEY_LOCAL_MACHINE,
222                                                         szSubKey,
223                                                         0,
224                                                         NULL,
225                                                         REG_OPTION_NON_VOLATILE,
226                                                         KEY_WRITE,
227                                                         NULL,
228                                                         &hKey,
229                                                         &dwDisp);
230
231         if(NOERROR == lResult)
232         {
233         //Create the value string.
234                 lResult = RegSetValueEx(   hKey,
235                                                                 NULL,
236                                                                 0,
237                                                                 REG_SZ,
238                                                                 (LPBYTE)szCLSID,
239                                                                 (lstrlen(szCLSID) + 1) * sizeof(TCHAR));
240                 RegCloseKey(hKey);
241         }
242         else
243                 return SELFREG_E_CLASS;
244
245         //If running on NT, register the extension as approved.
246         osvi.dwOSVersionInfoSize = sizeof(osvi);
247         GetVersionEx(&osvi);
248         if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
249         {
250                 lstrcpy( szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
251
252                 lResult = RegCreateKeyEx(  HKEY_LOCAL_MACHINE,
253                                                                 szSubKey,
254                                                                 0,
255                                                                 NULL,
256                                                                 REG_OPTION_NON_VOLATILE,
257                                                                 KEY_WRITE,
258                                                                 NULL,
259                                                                 &hKey,
260                                                                 &dwDisp);
261
262                 if(NOERROR == lResult)
263                 {
264                         TCHAR szData[MAX_PATH];
265
266                 //Create the value string.
267                         lstrcpy(szData, STR_EXT_TITLE);
268
269                         lResult = RegSetValueEx(   hKey,
270                                                                         szCLSID,
271                                                                         0,
272                                                                         REG_SZ,
273                                                                         (LPBYTE)szData,
274                                                                         (lstrlen(szData) + 1) * sizeof(TCHAR));
275               
276                         RegCloseKey(hKey);
277                 } else
278                         return SELFREG_E_CLASS;
279         }
280         return S_OK;
281 }
282
283 //returnValue = RegOpenKeyEx (HKEY_CLASSES_ROOT, keyName, 0, KEY_ALL_ACCESS, &registryKey);
284
285 LRESULT DoValueDelete(HKEY hKey,PTCHAR pszSubKey,PTCHAR szValue=NULL)
286 {
287         LRESULT  lResult;
288         HKEY     thKey;
289         if (szValue==NULL) {
290                 lResult=RegDeleteKey(hKey, pszSubKey);
291                 return lResult;
292         }
293         lResult = RegOpenKeyEx( hKey,
294                                 pszSubKey,
295                                 0,
296                                 KEY_ALL_ACCESS,
297                                 &thKey);
298         if(NOERROR == lResult)
299         {
300                 lResult=RegDeleteValue(hKey, szValue);
301                 RegCloseKey(thKey);
302         }
303         return lResult;
304 }
305
306 STDAPI DllUnregisterServer(void)
307 {
308         TCHAR    szSubKey[MAX_PATH];
309         TCHAR    szCLSID[MAX_PATH];
310         LPWSTR   pwsz;
311         AFX_MANAGE_STATE(AfxGetStaticModuleState());
312         COleObjectFactory::UpdateRegistryAll(FALSE);
313         StringFromIID(IID_IShellExt, &pwsz);
314         if(pwsz)
315         {
316                 WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL);
317                 LPMALLOC pMalloc;
318                 CoGetMalloc(1, &pMalloc);
319                 if(pMalloc)
320                 {
321                         (pMalloc->Free)(pwsz);
322                         (pMalloc->Release)();
323                 }
324         } else {
325                 return E_FAIL;
326         }
327         wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
328         DoValueDelete(HKEY_LOCAL_MACHINE,szSubKey,szCLSID);
329         wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
330         DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
331         wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}"));
332         DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
333         wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE);
334         DoValueDelete(HKEY_CLASSES_ROOT, szSubKey);
335         wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE);
336         DoValueDelete(HKEY_LOCAL_MACHINE, szSubKey);
337         return S_OK;
338 }
339