joachim99@75
|
1 /*
|
joachim99@75
|
2 * Copyright (c) 2003-2005, Sergey Zorin. All rights reserved.
|
joachim99@75
|
3 *
|
joachim99@75
|
4 * This software is distributable under the BSD license. See the terms
|
joachim99@75
|
5 * of the BSD license in the LICENSE file provided with this software.
|
joachim99@75
|
6 *
|
joachim99@75
|
7 */
|
joachim99@75
|
8
|
joachim99@75
|
9 #define _CRT_NON_CONFORMING_SWPRINTFS
|
joachim99@75
|
10 #define _CRT_SECURE_NO_DEPRECATE
|
joachim99@75
|
11
|
joachim99@75
|
12 #include <stdio.h>
|
joachim99@75
|
13
|
joachim99@75
|
14 #include <windows.h>
|
joachim99@75
|
15 #include <tchar.h>
|
joachim99@75
|
16
|
joachim99@75
|
17 #include <shlguid.h>
|
joachim99@75
|
18 #include <olectl.h>
|
joachim99@75
|
19 #include <objidl.h>
|
joachim99@75
|
20
|
joachim99@75
|
21 #include <objbase.h>
|
joachim99@75
|
22 #include <initguid.h>
|
joachim99@75
|
23
|
joachim99@75
|
24 //#include <log/log.h>
|
joachim99@75
|
25 //#include <log/log_message.h>
|
joachim99@75
|
26 //#include <log/file_sink.h>
|
joachim99@75
|
27 //#include <debug/trace.h>
|
joachim99@75
|
28
|
joachim99@75
|
29 #include "server.h"
|
joachim99@75
|
30 #include "class_factory.h"
|
joachim99@75
|
31
|
joachim99@75
|
32 #define DllExport __declspec( dllexport )
|
joachim99@75
|
33
|
joachim99@75
|
34 // registry key util struct
|
joachim99@75
|
35 struct REGSTRUCT {
|
joachim99@94
|
36 LPCTSTR subkey;
|
joachim99@94
|
37 LPCTSTR name;
|
joachim99@94
|
38 LPCTSTR value;
|
joachim99@75
|
39 };
|
joachim99@75
|
40
|
joachim99@75
|
41 SERVER* SERVER::_instance = 0;
|
joachim99@75
|
42 static HINSTANCE server_instance; // Handle to this DLL itself.
|
joachim99@75
|
43
|
joachim99@75
|
44 //DEFINE_GUID(CLSID_DIFF_EXT, 0xA0482097, 0xC69D, 0x4DEC, 0x8A, 0xB6, 0xD3, 0xA2, 0x59, 0xAC, 0xC1, 0x51);
|
joachim99@75
|
45 // New class id for DIFF_EXT for KDiff3
|
joachim99@94
|
46 #ifdef _WIN64
|
joachim99@94
|
47 // {34471FFB-4002-438b-8952-E4588D0C0FE9}
|
joachim99@94
|
48 DEFINE_GUID( CLSID_DIFF_EXT, 0x34471FFB, 0x4002, 0x438b, 0x89, 0x52, 0xE4, 0x58, 0x8D, 0x0C, 0x0F, 0xE9 );
|
joachim99@94
|
49 #else
|
joachim99@75
|
50 DEFINE_GUID( CLSID_DIFF_EXT, 0x9f8528e4, 0xab20, 0x456e, 0x84, 0xe5, 0x3c, 0xe6, 0x9d, 0x87, 0x20, 0xf3 );
|
joachim99@94
|
51 #endif
|
joachim99@75
|
52
|
joachim99@75
|
53 tstring SERVER::getRegistryKeyString( const tstring& subKey, const tstring& value )
|
joachim99@75
|
54 {
|
joachim99@75
|
55 tstring keyName = m_registryBaseName;
|
joachim99@75
|
56 if (!subKey.empty())
|
joachim99@75
|
57 keyName += TEXT("\\")+subKey;
|
joachim99@75
|
58
|
joachim99@75
|
59 HKEY key;
|
joachim99@75
|
60 HKEY baseKey = HKEY_CURRENT_USER;
|
joachim99@75
|
61 tstring result;
|
joachim99@75
|
62 for(;;)
|
joachim99@75
|
63 {
|
joachim99@75
|
64 if( RegOpenKeyEx( baseKey, keyName.c_str(), 0, KEY_READ, &key ) == ERROR_SUCCESS )
|
joachim99@75
|
65 {
|
joachim99@75
|
66 DWORD neededSizeInBytes = 0;
|
joachim99@75
|
67 if (RegQueryValueEx(key, value.c_str(), 0, 0, 0, &neededSizeInBytes) == ERROR_SUCCESS)
|
joachim99@75
|
68 {
|
joachim99@75
|
69 DWORD length = neededSizeInBytes / sizeof( TCHAR );
|
joachim99@75
|
70 result.resize( length );
|
joachim99@75
|
71 if ( RegQueryValueEx( key, value.c_str(), 0, 0, (LPBYTE)&result[0], &neededSizeInBytes ) == ERROR_SUCCESS)
|
joachim99@75
|
72 {
|
joachim99@75
|
73 //Everything is ok, but we want to cut off the terminating 0-character
|
joachim99@75
|
74 result.resize( length - 1 );
|
joachim99@75
|
75 RegCloseKey(key);
|
joachim99@75
|
76 return result;
|
joachim99@75
|
77 }
|
joachim99@75
|
78 else
|
joachim99@75
|
79 {
|
joachim99@75
|
80 result.resize(0);
|
joachim99@75
|
81 }
|
joachim99@75
|
82 }
|
joachim99@75
|
83
|
joachim99@75
|
84 RegCloseKey(key);
|
joachim99@75
|
85 }
|
joachim99@75
|
86 if (baseKey==HKEY_LOCAL_MACHINE)
|
joachim99@75
|
87 break;
|
joachim99@75
|
88 baseKey = HKEY_LOCAL_MACHINE;
|
joachim99@75
|
89 }
|
joachim99@75
|
90
|
joachim99@75
|
91 // Error
|
joachim99@75
|
92 {
|
joachim99@75
|
93 LPTSTR message;
|
joachim99@75
|
94 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0,
|
joachim99@75
|
95 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &message, 0, 0);
|
joachim99@75
|
96 ERRORLOG( (tstring(TEXT("RegOpenKeyEx: ")+keyName+TEXT("->")+value) + TEXT(": ")) + message ); \
|
joachim99@75
|
97 LocalFree(message);
|
joachim99@75
|
98 }
|
joachim99@75
|
99 return result;
|
joachim99@75
|
100 }
|
joachim99@75
|
101
|
joachim99@75
|
102
|
joachim99@75
|
103 STDAPI
|
joachim99@75
|
104 DllCanUnloadNow(void) {
|
joachim99@75
|
105 HRESULT ret = S_FALSE;
|
joachim99@75
|
106
|
joachim99@75
|
107 if(SERVER::instance()->reference_count() == 0) {
|
joachim99@75
|
108 ret = S_OK;
|
joachim99@75
|
109 }
|
joachim99@75
|
110
|
joachim99@75
|
111 return ret;
|
joachim99@75
|
112 }
|
joachim99@75
|
113
|
joachim99@75
|
114 extern "C" int APIENTRY
|
joachim99@75
|
115 DllMain(HINSTANCE instance, DWORD reason, LPVOID /* reserved */) {
|
joachim99@75
|
116 // char str[1024];
|
joachim99@75
|
117 // char* reason_string[] = {"DLL_PROCESS_DETACH", "DLL_PROCESS_ATTACH", "DLL_THREAD_ATTACH", "DLL_THREAD_DETACH"};
|
joachim99@75
|
118 // sprintf(str, "instance: %x; reason: '%s'", instance, reason_string[reason]);
|
joachim99@75
|
119 // MessageBox(0, str, TEXT("Info"), MB_OK);
|
joachim99@75
|
120 switch (reason) {
|
joachim99@75
|
121 case DLL_PROCESS_ATTACH:
|
joachim99@75
|
122 server_instance = instance;
|
joachim99@75
|
123 SERVER::instance()->save_history();
|
joachim99@75
|
124 MESSAGELOG(TEXT("DLL_PROCESS_ATTACH"));
|
joachim99@75
|
125 break;
|
joachim99@75
|
126
|
joachim99@75
|
127 case DLL_PROCESS_DETACH:
|
joachim99@75
|
128 MESSAGELOG(TEXT("DLL_PROCESS_DETACH"));
|
joachim99@75
|
129 SERVER::instance()->save_history();
|
joachim99@75
|
130 break;
|
joachim99@75
|
131 }
|
joachim99@75
|
132
|
joachim99@75
|
133 return 1;
|
joachim99@75
|
134 }
|
joachim99@75
|
135
|
joachim99@75
|
136 STDAPI
|
joachim99@75
|
137 DllGetClassObject(REFCLSID rclsid, REFIID riid, void** class_object) {
|
joachim99@75
|
138 HRESULT ret = CLASS_E_CLASSNOTAVAILABLE;
|
joachim99@75
|
139 *class_object = 0;
|
joachim99@75
|
140
|
joachim99@75
|
141 if (IsEqualIID(rclsid, CLSID_DIFF_EXT)) {
|
joachim99@75
|
142 CLASS_FACTORY* pcf = new CLASS_FACTORY();
|
joachim99@75
|
143
|
joachim99@75
|
144 ret = pcf->QueryInterface(riid, class_object);
|
joachim99@75
|
145 }
|
joachim99@75
|
146
|
joachim99@75
|
147 return ret;
|
joachim99@75
|
148 }
|
joachim99@75
|
149
|
joachim99@75
|
150 /*extern "C" HRESULT STDAPICALLTYPE*/ STDAPI
|
joachim99@75
|
151 DllRegisterServer() {
|
joachim99@75
|
152 return SERVER::instance()->do_register();
|
joachim99@75
|
153 }
|
joachim99@75
|
154
|
joachim99@75
|
155 STDAPI
|
joachim99@75
|
156 DllUnregisterServer() {
|
joachim99@75
|
157 return SERVER::instance()->do_unregister();
|
joachim99@75
|
158 }
|
joachim99@75
|
159
|
joachim99@75
|
160 SERVER* SERVER::instance()
|
joachim99@75
|
161 {
|
joachim99@75
|
162 if(_instance == 0)
|
joachim99@75
|
163 {
|
joachim99@75
|
164 _instance = new SERVER();
|
joachim99@75
|
165 _instance->initLogging();
|
joachim99@75
|
166 MESSAGELOG(TEXT("New Server instance"));
|
joachim99@75
|
167 }
|
joachim99@75
|
168
|
joachim99@75
|
169 return _instance;
|
joachim99@75
|
170 }
|
joachim99@75
|
171
|
joachim99@75
|
172 SERVER::SERVER() : _reference_count(0)
|
joachim99@75
|
173 {
|
joachim99@75
|
174 m_registryBaseName = TEXT("Software\\KDiff3\\diff-ext");
|
joachim99@75
|
175 m_pRecentFiles = 0;
|
joachim99@75
|
176 m_pLogFile = 0;
|
joachim99@75
|
177 }
|
joachim99@75
|
178
|
joachim99@75
|
179 void SERVER::initLogging()
|
joachim99@75
|
180 {
|
joachim99@75
|
181 tstring logFileName = getRegistryKeyString( TEXT(""), TEXT("LogFile") );
|
joachim99@75
|
182 if ( !logFileName.empty() )
|
joachim99@75
|
183 {
|
joachim99@75
|
184 m_pLogFile = _tfopen( logFileName.c_str(), TEXT("a+, ccs=UTF-8") );
|
joachim99@75
|
185 if (m_pLogFile)
|
joachim99@75
|
186 {
|
joachim99@75
|
187 _ftprintf( m_pLogFile, TEXT("\nSERVER::SERVER()\n") );
|
joachim99@75
|
188 }
|
joachim99@75
|
189 }
|
joachim99@75
|
190 }
|
joachim99@75
|
191
|
joachim99@75
|
192 SERVER::~SERVER()
|
joachim99@75
|
193 {
|
joachim99@75
|
194 if ( m_pLogFile )
|
joachim99@75
|
195 {
|
joachim99@75
|
196 _ftprintf( m_pLogFile, TEXT("SERVER::~SERVER()\n\n") );
|
joachim99@75
|
197 fclose( m_pLogFile );
|
joachim99@75
|
198 }
|
joachim99@75
|
199
|
joachim99@75
|
200 delete m_pRecentFiles;
|
joachim99@75
|
201 }
|
joachim99@75
|
202
|
joachim99@75
|
203 HINSTANCE
|
joachim99@75
|
204 SERVER::handle() const
|
joachim99@75
|
205 {
|
joachim99@75
|
206 return server_instance;
|
joachim99@75
|
207 }
|
joachim99@75
|
208
|
joachim99@75
|
209 void
|
joachim99@75
|
210 SERVER::lock() {
|
joachim99@75
|
211 InterlockedIncrement(&_reference_count);
|
joachim99@75
|
212 }
|
joachim99@75
|
213
|
joachim99@75
|
214 void
|
joachim99@75
|
215 SERVER::release() {
|
joachim99@75
|
216 InterlockedDecrement(&_reference_count);
|
joachim99@75
|
217
|
joachim99@75
|
218 //if(InterlockedDecrement((LPLONG)&_reference_count) == 0)
|
joachim99@75
|
219 // delete this;
|
joachim99@75
|
220 }
|
joachim99@75
|
221
|
joachim99@75
|
222 void SERVER::logMessage( const char* function, const char* file, int line, const tstring& msg )
|
joachim99@75
|
223 {
|
joachim99@75
|
224 SERVER* pServer = SERVER::instance();
|
joachim99@75
|
225 if ( pServer && pServer->m_pLogFile )
|
joachim99@75
|
226 {
|
joachim99@75
|
227 SYSTEMTIME st;
|
joachim99@75
|
228 GetSystemTime( &st );
|
joachim99@75
|
229 _ftprintf( pServer->m_pLogFile, TEXT("%04d/%02d/%02d %02d:%02d:%02d ")
|
joachim99@75
|
230 #ifdef UNICODE
|
joachim99@75
|
231 TEXT("%S (%S:%d) %s\n"), // integrate char-string into wchar_t string
|
joachim99@75
|
232 #else
|
joachim99@75
|
233 TEXT("%s (%s:%d) %s\n"),
|
joachim99@75
|
234 #endif
|
joachim99@75
|
235 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, function, file, line, msg.c_str() );
|
joachim99@75
|
236 fflush(pServer->m_pLogFile);
|
joachim99@75
|
237 }
|
joachim99@75
|
238 }
|
joachim99@75
|
239
|
joachim99@75
|
240 std::list<tstring>&
|
joachim99@75
|
241 SERVER::recent_files()
|
joachim99@75
|
242 {
|
joachim99@75
|
243 LOG();
|
joachim99@75
|
244 if ( m_pRecentFiles==0 )
|
joachim99@75
|
245 {
|
joachim99@75
|
246 MESSAGELOG(TEXT("Reading history from registry..."));
|
joachim99@75
|
247 m_pRecentFiles = new std::list<tstring>;
|
joachim99@75
|
248 for( int i=0; i<32; ++i ) // Max history size
|
joachim99@75
|
249 {
|
joachim99@75
|
250 TCHAR numAsString[10];
|
joachim99@75
|
251 _sntprintf( numAsString, 10, TEXT("%d"), i );
|
joachim99@75
|
252 tstring historyItem = getRegistryKeyString( TEXT("history"), numAsString );
|
joachim99@75
|
253 if ( ! historyItem.empty() )
|
joachim99@75
|
254 m_pRecentFiles->push_back( historyItem );
|
joachim99@75
|
255 }
|
joachim99@75
|
256 }
|
joachim99@75
|
257 return *m_pRecentFiles;
|
joachim99@75
|
258 }
|
joachim99@75
|
259
|
joachim99@75
|
260 void
|
joachim99@75
|
261 SERVER::save_history() const
|
joachim99@75
|
262 {
|
joachim99@75
|
263 if( m_pRecentFiles && !m_pRecentFiles->empty() )
|
joachim99@75
|
264 {
|
joachim99@75
|
265 HKEY key;
|
joachim99@75
|
266 if( RegCreateKeyEx(HKEY_CURRENT_USER, (m_registryBaseName + TEXT("\\history")).c_str(), 0, 0,
|
joachim99@75
|
267 REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) == ERROR_SUCCESS )
|
joachim99@75
|
268 {
|
joachim99@75
|
269 LOG();
|
joachim99@75
|
270 //DWORD len = MAX_PATH;
|
joachim99@75
|
271 int n = 0;
|
joachim99@75
|
272
|
joachim99@75
|
273 std::list<tstring>::const_iterator i;
|
joachim99@75
|
274
|
joachim99@75
|
275 for(i = m_pRecentFiles->begin(); i!=m_pRecentFiles->end(); ++i, ++n )
|
joachim99@75
|
276 {
|
joachim99@75
|
277 tstring str = *i;
|
joachim99@75
|
278 TCHAR numAsString[10];
|
joachim99@75
|
279 _sntprintf( numAsString, 10, TEXT("%d"), n );
|
joachim99@75
|
280 if(RegSetValueEx(key, numAsString, 0, REG_SZ, (const BYTE*)str.c_str(), (DWORD)(str.size()+1)*sizeof(TCHAR) ) != ERROR_SUCCESS)
|
joachim99@75
|
281 {
|
joachim99@75
|
282 LPTSTR message;
|
joachim99@75
|
283 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0,
|
joachim99@75
|
284 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
joachim99@75
|
285 (LPTSTR) &message, 0, 0);
|
joachim99@75
|
286 MessageBox(0, message, TEXT("Save history failed"), MB_OK | MB_ICONINFORMATION);
|
joachim99@75
|
287 LocalFree(message);
|
joachim99@75
|
288 }
|
joachim99@75
|
289 }
|
joachim99@75
|
290
|
joachim99@75
|
291 RegCloseKey(key);
|
joachim99@75
|
292 }
|
joachim99@75
|
293 else
|
joachim99@75
|
294 {
|
joachim99@75
|
295 SYSERRORLOG(TEXT("RegOpenKeyEx"));
|
joachim99@75
|
296 }
|
joachim99@75
|
297 }
|
joachim99@75
|
298 }
|
joachim99@75
|
299
|
joachim99@75
|
300 HRESULT
|
joachim99@75
|
301 SERVER::do_register() {
|
joachim99@75
|
302 LOG();
|
joachim99@75
|
303 TCHAR class_id[MAX_PATH];
|
joachim99@75
|
304 LPWSTR tmp_guid;
|
joachim99@75
|
305 HRESULT ret = SELFREG_E_CLASS;
|
joachim99@75
|
306
|
joachim99@75
|
307 if (StringFromIID(CLSID_DIFF_EXT, &tmp_guid) == S_OK) {
|
joachim99@75
|
308 #ifdef UNICODE
|
joachim99@75
|
309 _tcsncpy(class_id, tmp_guid, MAX_PATH);
|
joachim99@75
|
310 #else
|
joachim99@75
|
311 wcstombs(class_id, tmp_guid, MAX_PATH);
|
joachim99@75
|
312 #endif
|
joachim99@75
|
313 CoTaskMemFree((void*)tmp_guid);
|
joachim99@75
|
314
|
joachim99@75
|
315 TCHAR subkey[MAX_PATH];
|
joachim99@75
|
316 TCHAR server_path[MAX_PATH];
|
joachim99@75
|
317 HKEY key;
|
joachim99@75
|
318 LRESULT result = NOERROR;
|
joachim99@75
|
319 DWORD dwDisp;
|
joachim99@75
|
320
|
joachim99@75
|
321 GetModuleFileName(SERVER::instance()->handle(), server_path, MAX_PATH);
|
joachim99@75
|
322
|
joachim99@75
|
323 REGSTRUCT entry[] = {
|
joachim99@75
|
324 {TEXT("Software\\Classes\\CLSID\\%s"), 0, TEXT("diff-ext-for-kdiff3")},
|
joachim99@75
|
325 {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), 0, TEXT("%s")},
|
joachim99@75
|
326 {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), TEXT("ThreadingModel"), TEXT("Apartment")}
|
joachim99@75
|
327 };
|
joachim99@75
|
328
|
joachim99@75
|
329 for(unsigned int i = 0; (i < sizeof(entry)/sizeof(entry[0])) && (result == NOERROR); i++) {
|
joachim99@75
|
330 _sntprintf(subkey, MAX_PATH, entry[i].subkey, class_id);
|
joachim99@75
|
331 result = RegCreateKeyEx(HKEY_CURRENT_USER, subkey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp);
|
joachim99@75
|
332
|
joachim99@75
|
333 if(result == NOERROR) {
|
joachim99@75
|
334 TCHAR szData[MAX_PATH];
|
joachim99@75
|
335
|
joachim99@75
|
336 _sntprintf(szData, MAX_PATH, entry[i].value, server_path);
|
joachim99@75
|
337 szData[MAX_PATH-1]=0;
|
joachim99@75
|
338
|
joachim99@75
|
339 result = RegSetValueEx(key, entry[i].name, 0, REG_SZ, (LPBYTE)szData, DWORD(_tcslen(szData)*sizeof(TCHAR)));
|
joachim99@75
|
340 }
|
joachim99@75
|
341
|
joachim99@75
|
342 RegCloseKey(key);
|
joachim99@75
|
343 }
|
joachim99@75
|
344
|
joachim99@75
|
345 if(result == NOERROR) {
|
joachim99@75
|
346 result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Classes\\*\\shellex\\ContextMenuHandlers\\diff-ext-for-kdiff3"), 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp);
|
joachim99@75
|
347
|
joachim99@75
|
348 if(result == NOERROR) {
|
joachim99@75
|
349
|
joachim99@75
|
350 result = RegSetValueEx(key, 0, 0, REG_SZ, (LPBYTE)class_id, DWORD(_tcslen(class_id)*sizeof(TCHAR)));
|
joachim99@75
|
351
|
joachim99@75
|
352 RegCloseKey(key);
|
joachim99@75
|
353
|
joachim99@75
|
354 //If running on NT, register the extension as approved.
|
joachim99@75
|
355 OSVERSIONINFO osvi;
|
joachim99@75
|
356
|
joachim99@75
|
357 osvi.dwOSVersionInfoSize = sizeof(osvi);
|
joachim99@75
|
358 GetVersionEx(&osvi);
|
joachim99@75
|
359
|
joachim99@75
|
360 // NT needs to have shell extensions "approved".
|
joachim99@75
|
361 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
joachim99@75
|
362 result = RegCreateKeyEx(HKEY_CURRENT_USER,
|
joachim99@75
|
363 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),
|
joachim99@75
|
364 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp);
|
joachim99@75
|
365
|
joachim99@75
|
366 if(result == NOERROR) {
|
joachim99@75
|
367 TCHAR szData[MAX_PATH];
|
joachim99@75
|
368
|
joachim99@75
|
369 lstrcpy(szData, TEXT("diff-ext"));
|
joachim99@75
|
370
|
joachim99@75
|
371 result = RegSetValueEx(key, class_id, 0, REG_SZ, (LPBYTE)szData, DWORD(_tcslen(szData)*sizeof(TCHAR)));
|
joachim99@75
|
372
|
joachim99@75
|
373 RegCloseKey(key);
|
joachim99@75
|
374
|
joachim99@75
|
375 ret = S_OK;
|
joachim99@75
|
376 } else if (result == ERROR_ACCESS_DENIED) {
|
joachim99@75
|
377 TCHAR msg[] = TEXT("Warning! You have unsufficient rights to write to a specific registry key.\n")
|
joachim99@75
|
378 TEXT("The application may work anyway, but it is advised to register this module ")
|
joachim99@75
|
379 TEXT("again while having administrator rights.");
|
joachim99@75
|
380
|
joachim99@75
|
381 MessageBox(0, msg, TEXT("Warning"), MB_ICONEXCLAMATION);
|
joachim99@75
|
382
|
joachim99@75
|
383 ret = S_OK;
|
joachim99@75
|
384 }
|
joachim99@75
|
385 }
|
joachim99@75
|
386 else {
|
joachim99@75
|
387 ret = S_OK;
|
joachim99@75
|
388 }
|
joachim99@75
|
389 }
|
joachim99@75
|
390 }
|
joachim99@75
|
391 }
|
joachim99@75
|
392
|
joachim99@75
|
393 return ret;
|
joachim99@75
|
394 }
|
joachim99@75
|
395
|
joachim99@75
|
396 HRESULT
|
joachim99@75
|
397 SERVER::do_unregister() {
|
joachim99@75
|
398 LOG();
|
joachim99@75
|
399 TCHAR class_id[MAX_PATH];
|
joachim99@75
|
400 LPWSTR tmp_guid;
|
joachim99@75
|
401 HRESULT ret = SELFREG_E_CLASS;
|
joachim99@75
|
402
|
joachim99@75
|
403 if (StringFromIID(CLSID_DIFF_EXT, &tmp_guid) == S_OK) {
|
joachim99@75
|
404 #ifdef UNICODE
|
joachim99@75
|
405 _tcsncpy(class_id, tmp_guid, MAX_PATH);
|
joachim99@75
|
406 #else
|
joachim99@75
|
407 wcstombs(class_id, tmp_guid, MAX_PATH);
|
joachim99@75
|
408 #endif
|
joachim99@75
|
409 CoTaskMemFree((void*)tmp_guid);
|
joachim99@75
|
410
|
joachim99@75
|
411 LRESULT result = NOERROR;
|
joachim99@75
|
412 TCHAR subkey[MAX_PATH];
|
joachim99@75
|
413
|
joachim99@75
|
414 REGSTRUCT entry[] = {
|
joachim99@75
|
415 {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), 0, 0},
|
joachim99@75
|
416 {TEXT("Software\\Classes\\CLSID\\%s"), 0, 0}
|
joachim99@75
|
417 };
|
joachim99@75
|
418
|
joachim99@75
|
419 for(unsigned int i = 0; (i < sizeof(entry)/sizeof(entry[0])) && (result == NOERROR); i++) {
|
joachim99@75
|
420 _stprintf(subkey, entry[i].subkey, class_id);
|
joachim99@75
|
421 result = RegDeleteKey(HKEY_CURRENT_USER, subkey);
|
joachim99@75
|
422 }
|
joachim99@75
|
423
|
joachim99@75
|
424 if(result == NOERROR) {
|
joachim99@75
|
425 result = RegDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Classes\\*\\shellex\\ContextMenuHandlers\\diff-ext-for-kdiff3"));
|
joachim99@75
|
426
|
joachim99@75
|
427 if(result == NOERROR) {
|
joachim99@75
|
428 //If running on NT, register the extension as approved.
|
joachim99@75
|
429 OSVERSIONINFO osvi;
|
joachim99@75
|
430
|
joachim99@75
|
431 osvi.dwOSVersionInfoSize = sizeof(osvi);
|
joachim99@75
|
432 GetVersionEx(&osvi);
|
joachim99@75
|
433
|
joachim99@75
|
434 // NT needs to have shell extensions "approved".
|
joachim99@75
|
435 if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
joachim99@75
|
436 HKEY key;
|
joachim99@75
|
437
|
joachim99@75
|
438 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), 0, KEY_ALL_ACCESS, &key);
|
joachim99@75
|
439
|
joachim99@75
|
440 result = RegDeleteValue(key, class_id);
|
joachim99@75
|
441
|
joachim99@75
|
442 RegCloseKey(key);
|
joachim99@75
|
443
|
joachim99@75
|
444 if(result == ERROR_SUCCESS) {
|
joachim99@75
|
445 ret = S_OK;
|
joachim99@75
|
446 }
|
joachim99@75
|
447 }
|
joachim99@75
|
448 else {
|
joachim99@75
|
449 ret = S_OK;
|
joachim99@75
|
450 }
|
joachim99@75
|
451 }
|
joachim99@75
|
452 }
|
joachim99@75
|
453 }
|
joachim99@75
|
454
|
joachim99@75
|
455 return ret;
|
joachim99@75
|
456 }
|