Mercurial > vim
annotate src/if_ole.cpp @ 34219:a0a4a774117b v9.1.0058
patch 9.1.0058: Cannot map Super Keys in GTK UI
Commit: https://github.com/vim/vim/commit/92e90a1e102825aa9149262cacfc991264db05df
Author: Casey Tucker <dctucker@hotmail.com>
Date: Thu Jan 25 22:44:00 2024 +0100
patch 9.1.0058: Cannot map Super Keys in GTK UI
Problem: Cannot map Super Keys in GTK UI
(Casey Tucker)
Solution: Enable Super Key mappings in GTK using <D-Key>
(Casey Tucker)
As a developer who works in both Mac and Linux using the same keyboard,
it can be frustrating having to remember different key combinations or
having to rely on system utilities to remap keys.
This change allows `<D-z>` `<D-x>` `<D-c>` `<D-v>` etc. to be recognized
by the `map` commands, along with the `<D-S-...>` shifted variants.
```vimrc
if has('gui_gtk')
nnoremap <D-z> u
nnoremap <D-S-Z> <C-r>
vnoremap <D-x> "+d
vnoremap <D-c> "+y
cnoremap <D-v> <C-R>+
inoremap <D-v> <C-o>"+gP
nnoremap <D-v> "+P
vnoremap <D-v> "-d"+P
nnoremap <D-s> :w<CR>
inoremap <D-s> <C-o>:w<CR>
nnoremap <D-w> :q<CR>
nnoremap <D-q> :qa<CR>
nnoremap <D-t> :tabe<CR>
nnoremap <D-S-T> :vs#<CR><C-w>T
nnoremap <D-a> ggVG
vnoremap <D-a> <ESC>ggVG
inoremap <D-a> <ESC>ggVG
nnoremap <D-f> /
nnoremap <D-g> n
nnoremap <D-S-G> N
vnoremap <D-x> "+x
endif
```
closes: #12698
Signed-off-by: Casey Tucker <dctucker@hotmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 25 Jan 2024 23:00:03 +0100 |
parents | 161ae1985d81 |
children |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
8641
diff
changeset
|
1 /* vi:set ts=8 sts=4 sw=4 noet: |
7 | 2 * |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 */ | |
8 | |
15886
cdb9cbe731b3
patch 8.1.0949: MS-windows defines GUI macros different than other systems
Bram Moolenaar <Bram@vim.org>
parents:
15868
diff
changeset
|
9 #if defined(FEAT_OLE) && defined(FEAT_GUI_MSWIN) |
7 | 10 /* |
11 * OLE server implementation. | |
12 * | |
13 * See os_mswin.c for the client side. | |
14 */ | |
919 | 15 extern "C" { |
931 | 16 # include "vim.h" |
919 | 17 } |
18 | |
7 | 19 #include <windows.h> |
20 #include <oleauto.h> | |
21 | |
22 extern "C" { | |
23 extern HWND s_hwnd; | |
24 extern HWND vim_parent_hwnd; | |
25 } | |
26 | |
8641
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
27 #if (defined(_MSC_VER) && (_MSC_VER >= 1700)) || (__cplusplus >= 201103L) |
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
28 # define FINAL final |
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
29 #else |
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
30 # define FINAL |
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
31 #endif |
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
32 |
7 | 33 #include "if_ole.h" // Interface definitions |
34 #include "iid_ole.c" // UUID definitions (compile here) | |
35 | |
36 /* Supply function prototype to work around bug in Mingw oleauto.h header */ | |
37 #ifdef __MINGW32__ | |
38 WINOLEAUTAPI UnRegisterTypeLib(REFGUID libID, WORD wVerMajor, | |
39 WORD wVerMinor, LCID lcid, SYSKIND syskind); | |
40 #endif | |
41 | |
42 /***************************************************************************** | |
43 1. Internal definitions for this file | |
44 *****************************************************************************/ | |
45 | |
46 class CVim; | |
47 class CVimCF; | |
48 | |
49 /* Internal data */ | |
50 // The identifier of the registered class factory | |
51 static unsigned long cf_id = 0; | |
52 | |
53 // The identifier of the running application object | |
54 static unsigned long app_id = 0; | |
55 | |
56 // The single global instance of the class factory | |
57 static CVimCF *cf = 0; | |
58 | |
59 // The single global instance of the application object | |
60 static CVim *app = 0; | |
61 | |
62 /* GUIDs, versions and type library information */ | |
63 #define MYCLSID CLSID_Vim | |
64 #define MYLIBID LIBID_Vim | |
65 #define MYIID IID_IVim | |
66 | |
67 #define MAJORVER 1 | |
68 #define MINORVER 0 | |
69 #define LOCALE 0x0409 | |
70 | |
71 #define MYNAME "Vim" | |
72 #define MYPROGID "Vim.Application.1" | |
73 #define MYVIPROGID "Vim.Application" | |
74 | |
75 #define MAX_CLSID_LEN 100 | |
76 | |
77 /***************************************************************************** | |
78 2. The application object | |
79 *****************************************************************************/ | |
80 | |
81 /* Definition | |
82 * ---------- | |
83 */ | |
84 | |
8641
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
85 class CVim FINAL : public IVim |
7 | 86 { |
87 public: | |
8299
d2a215e8d5b4
commit https://github.com/vim/vim/commit/e0fd2aa8f6544f9cf8286c707be3fb1c66c609e6
Christian Brabandt <cb@256bit.org>
parents:
4352
diff
changeset
|
88 virtual ~CVim(); |
380 | 89 static CVim *Create(int *pbDoRestart); |
7 | 90 |
91 // IUnknown members | |
92 STDMETHOD(QueryInterface)(REFIID riid, void ** ppv); | |
93 STDMETHOD_(unsigned long, AddRef)(void); | |
94 STDMETHOD_(unsigned long, Release)(void); | |
95 | |
96 // IDispatch members | |
97 STDMETHOD(GetTypeInfoCount)(UINT *pCount); | |
98 STDMETHOD(GetTypeInfo)(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo); | |
380 | 99 STDMETHOD(GetIDsOfNames)(const IID &iid, OLECHAR **names, UINT n, LCID, DISPID *dispids); |
100 STDMETHOD(Invoke)(DISPID member, const IID &iid, LCID, WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr); | |
7 | 101 |
102 // IVim members | |
103 STDMETHOD(SendKeys)(BSTR keys); | |
104 STDMETHOD(Eval)(BSTR expr, BSTR *result); | |
105 STDMETHOD(SetForeground)(void); | |
1569 | 106 STDMETHOD(GetHwnd)(UINT_PTR *result); |
7 | 107 |
108 private: | |
109 // Constructor is private - create using CVim::Create() | |
110 CVim() : ref(0), typeinfo(0) {}; | |
111 | |
112 // Reference count | |
113 unsigned long ref; | |
114 | |
115 // The object's TypeInfo | |
116 ITypeInfo *typeinfo; | |
117 }; | |
118 | |
119 /* Implementation | |
120 * -------------- | |
121 */ | |
122 | |
380 | 123 CVim *CVim::Create(int *pbDoRestart) |
7 | 124 { |
125 HRESULT hr; | |
126 CVim *me = 0; | |
127 ITypeLib *typelib = 0; | |
128 ITypeInfo *typeinfo = 0; | |
129 | |
130 *pbDoRestart = FALSE; | |
131 | |
132 // Create the object | |
133 me = new CVim(); | |
134 if (me == NULL) | |
135 { | |
136 MessageBox(0, "Cannot create application object", "Vim Initialisation", 0); | |
137 return NULL; | |
138 } | |
139 | |
140 // Load the type library from the registry | |
141 hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib); | |
142 if (FAILED(hr)) | |
143 { | |
144 HKEY hKey; | |
145 | |
146 // Check we can write to the registry. | |
147 // RegCreateKeyEx succeeds even if key exists. W.Briscoe W2K 20021011 | |
148 if (RegCreateKeyEx(HKEY_CLASSES_ROOT, MYVIPROGID, 0, NULL, | |
2443
499bff609a86
Possibly make OLE work on Windows 64 bit. (untested)
Bram Moolenaar <bram@vim.org>
parents:
2224
diff
changeset
|
149 REG_OPTION_NON_VOLATILE, |
2474
a29301e7c05f
Take OLE registration back to 32 bit registry, the unregister wasn't working
Bram Moolenaar <bram@vim.org>
parents:
2469
diff
changeset
|
150 KEY_ALL_ACCESS, NULL, &hKey, NULL)) |
7 | 151 { |
152 delete me; | |
153 return NULL; // Unable to write to registry. Quietly fail. | |
154 } | |
155 RegCloseKey(hKey); | |
156 | |
157 if (MessageBox(0, "Cannot load registered type library.\nDo you want to register Vim now?", | |
158 "Vim Initialisation", MB_YESNO | MB_ICONQUESTION) != IDYES) | |
159 { | |
160 delete me; | |
161 return NULL; | |
162 } | |
163 | |
164 RegisterMe(FALSE); | |
165 | |
166 // Load the type library from the registry | |
167 hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib); | |
168 if (FAILED(hr)) | |
169 { | |
170 MessageBox(0, "You must restart Vim in order for the registration to take effect.", | |
171 "Vim Initialisation", 0); | |
172 *pbDoRestart = TRUE; | |
173 delete me; | |
174 return NULL; | |
175 } | |
176 } | |
177 | |
178 // Get the type info of the vtable interface | |
179 hr = typelib->GetTypeInfoOfGuid(MYIID, &typeinfo); | |
180 typelib->Release(); | |
181 | |
182 if (FAILED(hr)) | |
183 { | |
184 MessageBox(0, "Cannot get interface type information", | |
185 "Vim Initialisation", 0); | |
186 delete me; | |
187 return NULL; | |
188 } | |
189 | |
190 // Save the type information | |
191 me->typeinfo = typeinfo; | |
192 return me; | |
193 } | |
194 | |
195 CVim::~CVim() | |
196 { | |
197 if (typeinfo && vim_parent_hwnd == NULL) | |
198 typeinfo->Release(); | |
380 | 199 typeinfo = 0; |
7 | 200 } |
201 | |
202 STDMETHODIMP | |
203 CVim::QueryInterface(REFIID riid, void **ppv) | |
204 { | |
205 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, MYIID)) | |
206 { | |
207 AddRef(); | |
208 *ppv = this; | |
209 return S_OK; | |
210 } | |
211 | |
212 *ppv = 0; | |
213 return E_NOINTERFACE; | |
214 } | |
215 | |
216 STDMETHODIMP_(ULONG) | |
217 CVim::AddRef() | |
218 { | |
219 return ++ref; | |
220 } | |
221 | |
222 STDMETHODIMP_(ULONG) | |
223 CVim::Release() | |
224 { | |
225 // Don't delete the object when the reference count reaches zero, as there | |
226 // is only a single application object, and its lifetime is controlled by | |
227 // the running instance, not by its reference count. | |
228 if (ref > 0) | |
229 --ref; | |
230 return ref; | |
231 } | |
232 | |
233 STDMETHODIMP | |
234 CVim::GetTypeInfoCount(UINT *pCount) | |
235 { | |
236 *pCount = 1; | |
237 return S_OK; | |
238 } | |
239 | |
240 STDMETHODIMP | |
241 CVim::GetTypeInfo(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo) | |
242 { | |
243 *ppITypeInfo = 0; | |
244 | |
245 if (iTypeInfo != 0) | |
246 return DISP_E_BADINDEX; | |
247 | |
248 typeinfo->AddRef(); | |
249 *ppITypeInfo = typeinfo; | |
250 return S_OK; | |
251 } | |
252 | |
253 STDMETHODIMP | |
254 CVim::GetIDsOfNames( | |
380 | 255 const IID &iid, |
256 OLECHAR **names, | |
7 | 257 UINT n, |
258 LCID, | |
259 DISPID *dispids) | |
260 { | |
261 if (iid != IID_NULL) | |
262 return DISP_E_UNKNOWNINTERFACE; | |
263 | |
264 return typeinfo->GetIDsOfNames(names, n, dispids); | |
265 } | |
266 | |
267 STDMETHODIMP | |
268 CVim::Invoke( | |
269 DISPID member, | |
380 | 270 const IID &iid, |
7 | 271 LCID, |
272 WORD flags, | |
273 DISPPARAMS *dispparams, | |
274 VARIANT *result, | |
275 EXCEPINFO *excepinfo, | |
276 UINT *argerr) | |
277 { | |
278 if (iid != IID_NULL) | |
279 return DISP_E_UNKNOWNINTERFACE; | |
280 | |
281 ::SetErrorInfo(0, NULL); | |
282 return typeinfo->Invoke(static_cast<IDispatch*>(this), | |
283 member, flags, dispparams, | |
284 result, excepinfo, argerr); | |
285 } | |
286 | |
287 STDMETHODIMP | |
1569 | 288 CVim::GetHwnd(UINT_PTR *result) |
7 | 289 { |
1569 | 290 *result = (UINT_PTR)s_hwnd; |
7 | 291 return S_OK; |
292 } | |
293 | |
294 STDMETHODIMP | |
295 CVim::SetForeground(void) | |
296 { | |
297 /* Make the Vim window come to the foreground */ | |
298 gui_mch_set_foreground(); | |
299 return S_OK; | |
300 } | |
301 | |
302 STDMETHODIMP | |
303 CVim::SendKeys(BSTR keys) | |
304 { | |
305 int len; | |
306 char *buffer; | |
307 char_u *str; | |
308 char_u *ptr; | |
309 | |
310 /* Get a suitable buffer */ | |
311 len = WideCharToMultiByte(CP_ACP, 0, keys, -1, 0, 0, 0, 0); | |
312 buffer = (char *)alloc(len+1); | |
313 | |
314 if (buffer == NULL) | |
315 return E_OUTOFMEMORY; | |
316 | |
317 len = WideCharToMultiByte(CP_ACP, 0, keys, -1, buffer, len, 0, 0); | |
318 | |
319 if (len == 0) | |
320 { | |
321 vim_free(buffer); | |
322 return E_INVALIDARG; | |
323 } | |
324 | |
325 /* Translate key codes like <Esc> */ | |
32736
161ae1985d81
patch 9.0.1687: mapset() not properly handling script ID
Christian Brabandt <cb@256bit.org>
parents:
32244
diff
changeset
|
326 str = replace_termcodes((char_u *)buffer, &ptr, 0, REPTERM_DO_LT, NULL); |
7 | 327 |
328 /* If ptr was set, then a new buffer was allocated, | |
329 * so we can free the old one. | |
330 */ | |
331 if (ptr) | |
332 vim_free((char_u *)(buffer)); | |
333 | |
334 /* Reject strings too long to fit in the input buffer. Allow 10 bytes | |
335 * space to cover for the (remote) possibility that characters may enter | |
336 * the input buffer between now and when the WM_OLE message is actually | |
32244
533e36e02a68
patch 9.0.1453: typos in source code and tests
Bram Moolenaar <Bram@vim.org>
parents:
30598
diff
changeset
|
337 * processed. If more than 10 characters enter the input buffer in that |
7 | 338 * time, the WM_OLE processing will simply fail to insert the characters. |
339 */ | |
340 if ((int)(STRLEN(str)) > (vim_free_in_input_buf() - 10)) | |
341 { | |
342 vim_free(str); | |
343 return E_INVALIDARG; | |
344 } | |
345 | |
346 /* Pass the string to the main input loop. The memory will be freed when | |
1791 | 347 * the message is processed. Except for an empty message, we don't need |
348 * to post it then. | |
7 | 349 */ |
1791 | 350 if (*str == NUL) |
351 vim_free(str); | |
352 else | |
353 PostMessage(NULL, WM_OLE, 0, (LPARAM)str); | |
7 | 354 |
355 return S_OK; | |
356 } | |
357 | |
358 STDMETHODIMP | |
359 CVim::Eval(BSTR expr, BSTR *result) | |
360 { | |
361 #ifdef FEAT_EVAL | |
362 int len; | |
363 char *buffer; | |
364 char *str; | |
365 wchar_t *w_buffer; | |
366 | |
367 /* Get a suitable buffer */ | |
368 len = WideCharToMultiByte(CP_ACP, 0, expr, -1, 0, 0, 0, 0); | |
369 if (len == 0) | |
370 return E_INVALIDARG; | |
371 | |
16782
fc58fee685e2
patch 8.1.1393: unnecessary type casts
Bram Moolenaar <Bram@vim.org>
parents:
16606
diff
changeset
|
372 buffer = (char *)alloc(len); |
7 | 373 |
374 if (buffer == NULL) | |
375 return E_OUTOFMEMORY; | |
376 | |
377 /* Convert the (wide character) expression to an ASCII string */ | |
378 len = WideCharToMultiByte(CP_ACP, 0, expr, -1, buffer, len, 0, 0); | |
379 if (len == 0) | |
380 return E_INVALIDARG; | |
381 | |
382 /* Evaluate the expression */ | |
383 ++emsg_skip; | |
30598
37aa9fd2ed72
patch 9.0.0634: evaluating "expr" options has more overhead than needed
Bram Moolenaar <Bram@vim.org>
parents:
27342
diff
changeset
|
384 str = (char *)eval_to_string((char_u *)buffer, TRUE, FALSE); |
7 | 385 --emsg_skip; |
386 vim_free(buffer); | |
387 if (str == NULL) | |
388 return E_FAIL; | |
389 | |
390 /* Convert the result to wide characters */ | |
391 MultiByteToWideChar_alloc(CP_ACP, 0, str, -1, &w_buffer, &len); | |
392 vim_free(str); | |
393 if (w_buffer == NULL) | |
394 return E_OUTOFMEMORY; | |
395 | |
396 if (len == 0) | |
397 { | |
398 vim_free(w_buffer); | |
399 return E_FAIL; | |
400 } | |
401 | |
402 /* Store the result */ | |
403 *result = SysAllocString(w_buffer); | |
404 vim_free(w_buffer); | |
405 | |
406 return S_OK; | |
407 #else | |
408 return E_NOTIMPL; | |
409 #endif | |
410 } | |
411 | |
412 /***************************************************************************** | |
413 3. The class factory | |
414 *****************************************************************************/ | |
415 | |
416 /* Definition | |
417 * ---------- | |
418 */ | |
419 | |
8641
0af716a4f5d2
commit https://github.com/vim/vim/commit/cc6cf9b9f9045a7d8b5923ea0c556e9a4c2567d3
Christian Brabandt <cb@256bit.org>
parents:
8299
diff
changeset
|
420 class CVimCF FINAL : public IClassFactory |
7 | 421 { |
422 public: | |
423 static CVimCF *Create(); | |
8299
d2a215e8d5b4
commit https://github.com/vim/vim/commit/e0fd2aa8f6544f9cf8286c707be3fb1c66c609e6
Christian Brabandt <cb@256bit.org>
parents:
4352
diff
changeset
|
424 virtual ~CVimCF() {}; |
7 | 425 |
426 STDMETHOD(QueryInterface)(REFIID riid, void ** ppv); | |
427 STDMETHOD_(unsigned long, AddRef)(void); | |
428 STDMETHOD_(unsigned long, Release)(void); | |
429 STDMETHOD(CreateInstance)(IUnknown *punkOuter, REFIID riid, void ** ppv); | |
430 STDMETHOD(LockServer)(BOOL lock); | |
431 | |
432 private: | |
433 // Constructor is private - create via Create() | |
434 CVimCF() : ref(0) {}; | |
435 | |
436 // Reference count | |
437 unsigned long ref; | |
438 }; | |
439 | |
440 /* Implementation | |
441 * -------------- | |
442 */ | |
443 | |
444 CVimCF *CVimCF::Create() | |
445 { | |
446 CVimCF *me = new CVimCF(); | |
447 | |
448 if (me == NULL) | |
449 MessageBox(0, "Cannot create class factory", "Vim Initialisation", 0); | |
450 | |
451 return me; | |
452 } | |
453 | |
454 STDMETHODIMP | |
455 CVimCF::QueryInterface(REFIID riid, void **ppv) | |
456 { | |
457 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) | |
458 { | |
459 AddRef(); | |
460 *ppv = this; | |
461 return S_OK; | |
462 } | |
463 | |
464 *ppv = 0; | |
465 return E_NOINTERFACE; | |
466 } | |
467 | |
468 STDMETHODIMP_(ULONG) | |
469 CVimCF::AddRef() | |
470 { | |
471 return ++ref; | |
472 } | |
473 | |
474 STDMETHODIMP_(ULONG) | |
475 CVimCF::Release() | |
476 { | |
477 // Don't delete the object when the reference count reaches zero, as there | |
478 // is only a single application object, and its lifetime is controlled by | |
479 // the running instance, not by its reference count. | |
480 if (ref > 0) | |
481 --ref; | |
482 return ref; | |
483 } | |
484 | |
322 | 485 /*ARGSUSED*/ |
7 | 486 STDMETHODIMP |
487 CVimCF::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv) | |
488 { | |
489 return app->QueryInterface(riid, ppv); | |
490 } | |
491 | |
322 | 492 /*ARGSUSED*/ |
7 | 493 STDMETHODIMP |
494 CVimCF::LockServer(BOOL lock) | |
495 { | |
496 return S_OK; | |
497 } | |
498 | |
499 /***************************************************************************** | |
500 4. Registry manipulation code | |
501 *****************************************************************************/ | |
502 | |
503 // Internal use only | |
380 | 504 static void SetKeyAndValue(const char *path, const char *subkey, const char *value); |
505 static void GUIDtochar(const GUID &guid, char *GUID, int length); | |
506 static void RecursiveDeleteKey(HKEY hKeyParent, const char *child); | |
7 | 507 static const int GUID_STRING_SIZE = 39; |
508 | |
509 // Register the component in the registry | |
510 // When "silent" is TRUE don't give any messages. | |
511 | |
512 extern "C" void RegisterMe(int silent) | |
513 { | |
514 BOOL ok = TRUE; | |
515 | |
516 // Get the application startup command | |
517 char module[MAX_PATH]; | |
518 | |
519 ::GetModuleFileName(NULL, module, MAX_PATH); | |
520 | |
521 // Unregister first (quietly) | |
522 UnregisterMe(FALSE); | |
523 | |
524 // Convert the CLSID into a char | |
525 char clsid[GUID_STRING_SIZE]; | |
526 GUIDtochar(MYCLSID, clsid, sizeof(clsid)); | |
527 | |
528 // Convert the LIBID into a char | |
529 char libid[GUID_STRING_SIZE]; | |
530 GUIDtochar(MYLIBID, libid, sizeof(libid)); | |
531 | |
532 // Build the key CLSID\\{...} | |
533 char Key[MAX_CLSID_LEN]; | |
534 strcpy(Key, "CLSID\\"); | |
535 strcat(Key, clsid); | |
536 | |
537 // Add the CLSID to the registry | |
538 SetKeyAndValue(Key, NULL, MYNAME); | |
539 SetKeyAndValue(Key, "LocalServer32", module); | |
540 SetKeyAndValue(Key, "ProgID", MYPROGID); | |
541 SetKeyAndValue(Key, "VersionIndependentProgID", MYVIPROGID); | |
542 SetKeyAndValue(Key, "TypeLib", libid); | |
543 | |
544 // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT | |
545 SetKeyAndValue(MYVIPROGID, NULL, MYNAME); | |
546 SetKeyAndValue(MYVIPROGID, "CLSID", clsid); | |
547 SetKeyAndValue(MYVIPROGID, "CurVer", MYPROGID); | |
548 | |
549 // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT | |
550 SetKeyAndValue(MYPROGID, NULL, MYNAME); | |
551 SetKeyAndValue(MYPROGID, "CLSID", clsid); | |
552 | |
553 wchar_t w_module[MAX_PATH]; | |
554 MultiByteToWideChar(CP_ACP, 0, module, -1, w_module, MAX_PATH); | |
555 | |
556 ITypeLib *typelib = NULL; | |
557 if (LoadTypeLib(w_module, &typelib) != S_OK) | |
558 { | |
559 if (!silent) | |
560 MessageBox(0, "Cannot load type library to register", | |
561 "Vim Registration", 0); | |
562 ok = FALSE; | |
563 } | |
564 else | |
565 { | |
566 if (RegisterTypeLib(typelib, w_module, NULL) != S_OK) | |
567 { | |
568 if (!silent) | |
569 MessageBox(0, "Cannot register type library", | |
570 "Vim Registration", 0); | |
571 ok = FALSE; | |
572 } | |
573 typelib->Release(); | |
574 } | |
575 | |
576 if (ok && !silent) | |
577 MessageBox(0, "Registered successfully", "Vim", 0); | |
578 } | |
579 | |
580 // Remove the component from the registry | |
581 // | |
582 // Note: There is little error checking in this code, to allow incomplete | |
583 // or failed registrations to be undone. | |
584 extern "C" void UnregisterMe(int bNotifyUser) | |
585 { | |
586 // Unregister the type library | |
587 ITypeLib *typelib; | |
588 if (SUCCEEDED(LoadRegTypeLib(MYLIBID, MAJORVER, MINORVER, LOCALE, &typelib))) | |
589 { | |
590 TLIBATTR *tla; | |
591 if (SUCCEEDED(typelib->GetLibAttr(&tla))) | |
592 { | |
593 UnRegisterTypeLib(tla->guid, tla->wMajorVerNum, tla->wMinorVerNum, | |
594 tla->lcid, tla->syskind); | |
595 typelib->ReleaseTLibAttr(tla); | |
596 } | |
597 typelib->Release(); | |
598 } | |
599 | |
600 // Convert the CLSID into a char | |
601 char clsid[GUID_STRING_SIZE]; | |
602 GUIDtochar(MYCLSID, clsid, sizeof(clsid)); | |
603 | |
604 // Build the key CLSID\\{...} | |
605 char Key[MAX_CLSID_LEN]; | |
606 strcpy(Key, "CLSID\\"); | |
607 strcat(Key, clsid); | |
608 | |
609 // Delete the CLSID Key - CLSID\{...} | |
610 RecursiveDeleteKey(HKEY_CLASSES_ROOT, Key); | |
611 | |
612 // Delete the version-independent ProgID Key | |
613 RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYVIPROGID); | |
614 | |
615 // Delete the ProgID key | |
616 RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYPROGID); | |
617 | |
618 if (bNotifyUser) | |
619 MessageBox(0, "Unregistered successfully", "Vim", 0); | |
620 } | |
621 | |
622 /****************************************************************************/ | |
623 | |
624 // Convert a GUID to a char string | |
380 | 625 static void GUIDtochar(const GUID &guid, char *GUID, int length) |
7 | 626 { |
627 // Get wide string version | |
628 LPOLESTR wGUID = NULL; | |
629 StringFromCLSID(guid, &wGUID); | |
630 | |
23229
b545334ae654
patch 8.2.2160: various typos
Bram Moolenaar <Bram@vim.org>
parents:
20996
diff
changeset
|
631 // Convert from wide characters to non-wide |
7 | 632 wcstombs(GUID, wGUID, length); |
633 | |
634 // Free memory | |
635 CoTaskMemFree(wGUID); | |
636 } | |
637 | |
4352 | 638 // Delete a key and all of its descendants |
380 | 639 static void RecursiveDeleteKey(HKEY hKeyParent, const char *child) |
7 | 640 { |
641 // Open the child | |
642 HKEY hKeyChild; | |
2449
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2443
diff
changeset
|
643 LONG result = RegOpenKeyEx(hKeyParent, child, 0, |
2474
a29301e7c05f
Take OLE registration back to 32 bit registry, the unregister wasn't working
Bram Moolenaar <bram@vim.org>
parents:
2469
diff
changeset
|
644 KEY_ALL_ACCESS, &hKeyChild); |
7 | 645 if (result != ERROR_SUCCESS) |
646 return; | |
647 | |
4352 | 648 // Enumerate all of the descendants of this child |
7 | 649 FILETIME time; |
650 char buffer[1024]; | |
651 DWORD size = 1024; | |
652 | |
653 while (RegEnumKeyEx(hKeyChild, 0, buffer, &size, NULL, | |
654 NULL, NULL, &time) == S_OK) | |
655 { | |
4352 | 656 // Delete the descendants of this child |
7 | 657 RecursiveDeleteKey(hKeyChild, buffer); |
658 size = 256; | |
659 } | |
660 | |
661 // Close the child | |
662 RegCloseKey(hKeyChild); | |
663 | |
664 // Delete this child | |
665 RegDeleteKey(hKeyParent, child); | |
666 } | |
667 | |
668 // Create a key and set its value | |
388 | 669 static void SetKeyAndValue(const char *key, const char *subkey, const char *value) |
7 | 670 { |
671 HKEY hKey; | |
672 char buffer[1024]; | |
673 | |
674 strcpy(buffer, key); | |
675 | |
676 // Add subkey name to buffer. | |
677 if (subkey) | |
678 { | |
679 strcat(buffer, "\\"); | |
680 strcat(buffer, subkey); | |
681 } | |
682 | |
683 // Create and open key and subkey. | |
684 long result = RegCreateKeyEx(HKEY_CLASSES_ROOT, | |
685 buffer, | |
686 0, NULL, REG_OPTION_NON_VOLATILE, | |
2474
a29301e7c05f
Take OLE registration back to 32 bit registry, the unregister wasn't working
Bram Moolenaar <bram@vim.org>
parents:
2469
diff
changeset
|
687 KEY_ALL_ACCESS, NULL, |
7 | 688 &hKey, NULL); |
689 if (result != ERROR_SUCCESS) | |
690 return; | |
691 | |
692 // Set the value | |
693 if (value) | |
694 RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, | |
695 (DWORD)STRLEN(value)+1); | |
696 | |
697 RegCloseKey(hKey); | |
698 } | |
699 | |
700 /***************************************************************************** | |
701 5. OLE Initialisation and shutdown processing | |
702 *****************************************************************************/ | |
380 | 703 extern "C" void InitOLE(int *pbDoRestart) |
7 | 704 { |
705 HRESULT hr; | |
706 | |
707 *pbDoRestart = FALSE; | |
708 | |
709 // Initialize the OLE libraries | |
710 hr = OleInitialize(NULL); | |
711 if (FAILED(hr)) | |
712 { | |
713 MessageBox(0, "Cannot initialise OLE", "Vim Initialisation", 0); | |
714 goto error0; | |
715 } | |
716 | |
717 // Create the application object | |
718 app = CVim::Create(pbDoRestart); | |
719 if (app == NULL) | |
720 goto error1; | |
721 | |
722 // Create the class factory | |
723 cf = CVimCF::Create(); | |
724 if (cf == NULL) | |
725 goto error1; | |
726 | |
727 // Register the class factory | |
728 hr = CoRegisterClassObject( | |
729 MYCLSID, | |
730 cf, | |
731 CLSCTX_LOCAL_SERVER, | |
732 REGCLS_MULTIPLEUSE, | |
733 &cf_id); | |
734 | |
735 if (FAILED(hr)) | |
736 { | |
737 MessageBox(0, "Cannot register class factory", "Vim Initialisation", 0); | |
738 goto error1; | |
739 } | |
740 | |
741 // Register the application object as active | |
742 hr = RegisterActiveObject( | |
743 app, | |
744 MYCLSID, | |
14325
89dd0ad361fb
patch 8.1.0178: warning for passing pointer to non-pointer argument
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
745 0, |
7 | 746 &app_id); |
747 | |
748 if (FAILED(hr)) | |
749 { | |
750 MessageBox(0, "Cannot register application object", "Vim Initialisation", 0); | |
751 goto error1; | |
752 } | |
753 | |
754 return; | |
755 | |
756 // Errors: tidy up as much as needed and return | |
757 error1: | |
758 UninitOLE(); | |
759 error0: | |
760 return; | |
761 } | |
762 | |
763 extern "C" void UninitOLE() | |
764 { | |
765 // Unregister the application object | |
766 if (app_id) | |
767 { | |
768 RevokeActiveObject(app_id, NULL); | |
769 app_id = 0; | |
770 } | |
771 | |
772 // Unregister the class factory | |
773 if (cf_id) | |
774 { | |
775 CoRevokeClassObject(cf_id); | |
776 cf_id = 0; | |
777 } | |
778 | |
779 // Shut down the OLE libraries | |
780 OleUninitialize(); | |
781 | |
782 // Delete the application object | |
783 if (app) | |
784 { | |
785 delete app; | |
786 app = NULL; | |
787 } | |
788 | |
789 // Delete the class factory | |
790 if (cf) | |
791 { | |
792 delete cf; | |
793 cf = NULL; | |
794 } | |
795 } | |
796 #endif /* FEAT_OLE */ |