blob: 1e5eee65a196cb980aaf60a9709480231d8b6378 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
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
9#if defined(FEAT_OLE) && defined(FEAT_GUI_W32)
10/*
11 * OLE server implementation.
12 *
13 * See os_mswin.c for the client side.
14 */
15
Bram Moolenaar1c892472006-08-16 15:34:57 +000016/*
17 * We have some trouble with order of includes here. For Borland it needs to
18 * be different from MSVC...
19 */
20#ifndef __BORLANDC__
Bram Moolenaar4666d502006-08-08 15:04:31 +000021extern "C" {
Bram Moolenaar1c892472006-08-16 15:34:57 +000022# include "vim.h"
Bram Moolenaar4666d502006-08-08 15:04:31 +000023}
Bram Moolenaar1c892472006-08-16 15:34:57 +000024#endif
Bram Moolenaar4666d502006-08-08 15:04:31 +000025
Bram Moolenaar071d4272004-06-13 20:20:40 +000026#include <windows.h>
27#include <oleauto.h>
28
29extern "C" {
Bram Moolenaar1c892472006-08-16 15:34:57 +000030#ifdef __BORLANDC__
31# include "vim.h"
32#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000033extern HWND s_hwnd;
34extern HWND vim_parent_hwnd;
35}
36
Bram Moolenaar167632f2010-05-26 21:42:54 +020037#if (defined(_MSC_VER) && _MSC_VER < 1300) || !defined(MAXULONG_PTR)
Bram Moolenaar0fde2902008-03-16 13:54:13 +000038/* Work around old versions of basetsd.h which wrongly declares
39 * UINT_PTR as unsigned long */
Bram Moolenaar167632f2010-05-26 21:42:54 +020040# undef UINT_PTR
Bram Moolenaar0fde2902008-03-16 13:54:13 +000041# define UINT_PTR UINT
42#endif
43
Bram Moolenaar071d4272004-06-13 20:20:40 +000044#include "if_ole.h" // Interface definitions
45#include "iid_ole.c" // UUID definitions (compile here)
46
47/* Supply function prototype to work around bug in Mingw oleauto.h header */
48#ifdef __MINGW32__
49WINOLEAUTAPI UnRegisterTypeLib(REFGUID libID, WORD wVerMajor,
50 WORD wVerMinor, LCID lcid, SYSKIND syskind);
51#endif
52
53/*****************************************************************************
54 1. Internal definitions for this file
55*****************************************************************************/
56
57class CVim;
58class CVimCF;
59
60/* Internal data */
61// The identifier of the registered class factory
62static unsigned long cf_id = 0;
63
64// The identifier of the running application object
65static unsigned long app_id = 0;
66
67// The single global instance of the class factory
68static CVimCF *cf = 0;
69
70// The single global instance of the application object
71static CVim *app = 0;
72
73/* GUIDs, versions and type library information */
74#define MYCLSID CLSID_Vim
75#define MYLIBID LIBID_Vim
76#define MYIID IID_IVim
77
78#define MAJORVER 1
79#define MINORVER 0
80#define LOCALE 0x0409
81
82#define MYNAME "Vim"
83#define MYPROGID "Vim.Application.1"
84#define MYVIPROGID "Vim.Application"
85
86#define MAX_CLSID_LEN 100
87
88/*****************************************************************************
89 2. The application object
90*****************************************************************************/
91
92/* Definition
93 * ----------
94 */
95
96class CVim : public IVim
97{
98public:
99 ~CVim();
Bram Moolenaar505e8282005-07-01 22:31:55 +0000100 static CVim *Create(int *pbDoRestart);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000101
102 // IUnknown members
103 STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
104 STDMETHOD_(unsigned long, AddRef)(void);
105 STDMETHOD_(unsigned long, Release)(void);
106
107 // IDispatch members
108 STDMETHOD(GetTypeInfoCount)(UINT *pCount);
109 STDMETHOD(GetTypeInfo)(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo);
Bram Moolenaar505e8282005-07-01 22:31:55 +0000110 STDMETHOD(GetIDsOfNames)(const IID &iid, OLECHAR **names, UINT n, LCID, DISPID *dispids);
111 STDMETHOD(Invoke)(DISPID member, const IID &iid, LCID, WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112
113 // IVim members
114 STDMETHOD(SendKeys)(BSTR keys);
115 STDMETHOD(Eval)(BSTR expr, BSTR *result);
116 STDMETHOD(SetForeground)(void);
Bram Moolenaar0fde2902008-03-16 13:54:13 +0000117 STDMETHOD(GetHwnd)(UINT_PTR *result);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000118
119private:
120 // Constructor is private - create using CVim::Create()
121 CVim() : ref(0), typeinfo(0) {};
122
123 // Reference count
124 unsigned long ref;
125
126 // The object's TypeInfo
127 ITypeInfo *typeinfo;
128};
129
130/* Implementation
131 * --------------
132 */
133
Bram Moolenaar505e8282005-07-01 22:31:55 +0000134CVim *CVim::Create(int *pbDoRestart)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000135{
136 HRESULT hr;
137 CVim *me = 0;
138 ITypeLib *typelib = 0;
139 ITypeInfo *typeinfo = 0;
140
141 *pbDoRestart = FALSE;
142
143 // Create the object
144 me = new CVim();
145 if (me == NULL)
146 {
147 MessageBox(0, "Cannot create application object", "Vim Initialisation", 0);
148 return NULL;
149 }
150
151 // Load the type library from the registry
152 hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib);
153 if (FAILED(hr))
154 {
155 HKEY hKey;
156
157 // Check we can write to the registry.
158 // RegCreateKeyEx succeeds even if key exists. W.Briscoe W2K 20021011
159 if (RegCreateKeyEx(HKEY_CLASSES_ROOT, MYVIPROGID, 0, NULL,
160 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
161 {
162 delete me;
163 return NULL; // Unable to write to registry. Quietly fail.
164 }
165 RegCloseKey(hKey);
166
167 if (MessageBox(0, "Cannot load registered type library.\nDo you want to register Vim now?",
168 "Vim Initialisation", MB_YESNO | MB_ICONQUESTION) != IDYES)
169 {
170 delete me;
171 return NULL;
172 }
173
174 RegisterMe(FALSE);
175
176 // Load the type library from the registry
177 hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib);
178 if (FAILED(hr))
179 {
180 MessageBox(0, "You must restart Vim in order for the registration to take effect.",
181 "Vim Initialisation", 0);
182 *pbDoRestart = TRUE;
183 delete me;
184 return NULL;
185 }
186 }
187
188 // Get the type info of the vtable interface
189 hr = typelib->GetTypeInfoOfGuid(MYIID, &typeinfo);
190 typelib->Release();
191
192 if (FAILED(hr))
193 {
194 MessageBox(0, "Cannot get interface type information",
195 "Vim Initialisation", 0);
196 delete me;
197 return NULL;
198 }
199
200 // Save the type information
201 me->typeinfo = typeinfo;
202 return me;
203}
204
205CVim::~CVim()
206{
207 if (typeinfo && vim_parent_hwnd == NULL)
208 typeinfo->Release();
Bram Moolenaar505e8282005-07-01 22:31:55 +0000209 typeinfo = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000210}
211
212STDMETHODIMP
213CVim::QueryInterface(REFIID riid, void **ppv)
214{
215 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, MYIID))
216 {
217 AddRef();
218 *ppv = this;
219 return S_OK;
220 }
221
222 *ppv = 0;
223 return E_NOINTERFACE;
224}
225
226STDMETHODIMP_(ULONG)
227CVim::AddRef()
228{
229 return ++ref;
230}
231
232STDMETHODIMP_(ULONG)
233CVim::Release()
234{
235 // Don't delete the object when the reference count reaches zero, as there
236 // is only a single application object, and its lifetime is controlled by
237 // the running instance, not by its reference count.
238 if (ref > 0)
239 --ref;
240 return ref;
241}
242
243STDMETHODIMP
244CVim::GetTypeInfoCount(UINT *pCount)
245{
246 *pCount = 1;
247 return S_OK;
248}
249
250STDMETHODIMP
251CVim::GetTypeInfo(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo)
252{
253 *ppITypeInfo = 0;
254
255 if (iTypeInfo != 0)
256 return DISP_E_BADINDEX;
257
258 typeinfo->AddRef();
259 *ppITypeInfo = typeinfo;
260 return S_OK;
261}
262
263STDMETHODIMP
264CVim::GetIDsOfNames(
Bram Moolenaar505e8282005-07-01 22:31:55 +0000265 const IID &iid,
266 OLECHAR **names,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000267 UINT n,
268 LCID,
269 DISPID *dispids)
270{
271 if (iid != IID_NULL)
272 return DISP_E_UNKNOWNINTERFACE;
273
274 return typeinfo->GetIDsOfNames(names, n, dispids);
275}
276
277STDMETHODIMP
278CVim::Invoke(
279 DISPID member,
Bram Moolenaar505e8282005-07-01 22:31:55 +0000280 const IID &iid,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000281 LCID,
282 WORD flags,
283 DISPPARAMS *dispparams,
284 VARIANT *result,
285 EXCEPINFO *excepinfo,
286 UINT *argerr)
287{
288 if (iid != IID_NULL)
289 return DISP_E_UNKNOWNINTERFACE;
290
291 ::SetErrorInfo(0, NULL);
292 return typeinfo->Invoke(static_cast<IDispatch*>(this),
293 member, flags, dispparams,
294 result, excepinfo, argerr);
295}
296
297STDMETHODIMP
Bram Moolenaar0fde2902008-03-16 13:54:13 +0000298CVim::GetHwnd(UINT_PTR *result)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000299{
Bram Moolenaar0fde2902008-03-16 13:54:13 +0000300 *result = (UINT_PTR)s_hwnd;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000301 return S_OK;
302}
303
304STDMETHODIMP
305CVim::SetForeground(void)
306{
307 /* Make the Vim window come to the foreground */
308 gui_mch_set_foreground();
309 return S_OK;
310}
311
312STDMETHODIMP
313CVim::SendKeys(BSTR keys)
314{
315 int len;
316 char *buffer;
317 char_u *str;
318 char_u *ptr;
319
320 /* Get a suitable buffer */
321 len = WideCharToMultiByte(CP_ACP, 0, keys, -1, 0, 0, 0, 0);
322 buffer = (char *)alloc(len+1);
323
324 if (buffer == NULL)
325 return E_OUTOFMEMORY;
326
327 len = WideCharToMultiByte(CP_ACP, 0, keys, -1, buffer, len, 0, 0);
328
329 if (len == 0)
330 {
331 vim_free(buffer);
332 return E_INVALIDARG;
333 }
334
335 /* Translate key codes like <Esc> */
Bram Moolenaar9c102382006-05-03 21:26:49 +0000336 str = replace_termcodes((char_u *)buffer, &ptr, FALSE, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337
338 /* If ptr was set, then a new buffer was allocated,
339 * so we can free the old one.
340 */
341 if (ptr)
342 vim_free((char_u *)(buffer));
343
344 /* Reject strings too long to fit in the input buffer. Allow 10 bytes
345 * space to cover for the (remote) possibility that characters may enter
346 * the input buffer between now and when the WM_OLE message is actually
347 * processed. If more that 10 characters enter the input buffer in that
348 * time, the WM_OLE processing will simply fail to insert the characters.
349 */
350 if ((int)(STRLEN(str)) > (vim_free_in_input_buf() - 10))
351 {
352 vim_free(str);
353 return E_INVALIDARG;
354 }
355
356 /* Pass the string to the main input loop. The memory will be freed when
Bram Moolenaar370feaf2009-01-28 13:18:26 +0000357 * the message is processed. Except for an empty message, we don't need
358 * to post it then.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000359 */
Bram Moolenaar370feaf2009-01-28 13:18:26 +0000360 if (*str == NUL)
361 vim_free(str);
362 else
363 PostMessage(NULL, WM_OLE, 0, (LPARAM)str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364
365 return S_OK;
366}
367
368STDMETHODIMP
369CVim::Eval(BSTR expr, BSTR *result)
370{
371#ifdef FEAT_EVAL
372 int len;
373 char *buffer;
374 char *str;
375 wchar_t *w_buffer;
376
377 /* Get a suitable buffer */
378 len = WideCharToMultiByte(CP_ACP, 0, expr, -1, 0, 0, 0, 0);
379 if (len == 0)
380 return E_INVALIDARG;
381
382 buffer = (char *)alloc((unsigned)len);
383
384 if (buffer == NULL)
385 return E_OUTOFMEMORY;
386
387 /* Convert the (wide character) expression to an ASCII string */
388 len = WideCharToMultiByte(CP_ACP, 0, expr, -1, buffer, len, 0, 0);
389 if (len == 0)
390 return E_INVALIDARG;
391
392 /* Evaluate the expression */
393 ++emsg_skip;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000394 str = (char *)eval_to_string((char_u *)buffer, NULL, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 --emsg_skip;
396 vim_free(buffer);
397 if (str == NULL)
398 return E_FAIL;
399
400 /* Convert the result to wide characters */
401 MultiByteToWideChar_alloc(CP_ACP, 0, str, -1, &w_buffer, &len);
402 vim_free(str);
403 if (w_buffer == NULL)
404 return E_OUTOFMEMORY;
405
406 if (len == 0)
407 {
408 vim_free(w_buffer);
409 return E_FAIL;
410 }
411
412 /* Store the result */
413 *result = SysAllocString(w_buffer);
414 vim_free(w_buffer);
415
416 return S_OK;
417#else
418 return E_NOTIMPL;
419#endif
420}
421
422/*****************************************************************************
423 3. The class factory
424*****************************************************************************/
425
426/* Definition
427 * ----------
428 */
429
430class CVimCF : public IClassFactory
431{
432public:
433 static CVimCF *Create();
434
435 STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
436 STDMETHOD_(unsigned long, AddRef)(void);
437 STDMETHOD_(unsigned long, Release)(void);
438 STDMETHOD(CreateInstance)(IUnknown *punkOuter, REFIID riid, void ** ppv);
439 STDMETHOD(LockServer)(BOOL lock);
440
441private:
442 // Constructor is private - create via Create()
443 CVimCF() : ref(0) {};
444
445 // Reference count
446 unsigned long ref;
447};
448
449/* Implementation
450 * --------------
451 */
452
453CVimCF *CVimCF::Create()
454{
455 CVimCF *me = new CVimCF();
456
457 if (me == NULL)
458 MessageBox(0, "Cannot create class factory", "Vim Initialisation", 0);
459
460 return me;
461}
462
463STDMETHODIMP
464CVimCF::QueryInterface(REFIID riid, void **ppv)
465{
466 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
467 {
468 AddRef();
469 *ppv = this;
470 return S_OK;
471 }
472
473 *ppv = 0;
474 return E_NOINTERFACE;
475}
476
477STDMETHODIMP_(ULONG)
478CVimCF::AddRef()
479{
480 return ++ref;
481}
482
483STDMETHODIMP_(ULONG)
484CVimCF::Release()
485{
486 // Don't delete the object when the reference count reaches zero, as there
487 // is only a single application object, and its lifetime is controlled by
488 // the running instance, not by its reference count.
489 if (ref > 0)
490 --ref;
491 return ref;
492}
493
Bram Moolenaarbac97eb2005-06-13 22:12:09 +0000494/*ARGSUSED*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495STDMETHODIMP
496CVimCF::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
497{
498 return app->QueryInterface(riid, ppv);
499}
500
Bram Moolenaarbac97eb2005-06-13 22:12:09 +0000501/*ARGSUSED*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502STDMETHODIMP
503CVimCF::LockServer(BOOL lock)
504{
505 return S_OK;
506}
507
508/*****************************************************************************
509 4. Registry manipulation code
510*****************************************************************************/
511
512// Internal use only
Bram Moolenaar505e8282005-07-01 22:31:55 +0000513static void SetKeyAndValue(const char *path, const char *subkey, const char *value);
514static void GUIDtochar(const GUID &guid, char *GUID, int length);
515static void RecursiveDeleteKey(HKEY hKeyParent, const char *child);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000516static const int GUID_STRING_SIZE = 39;
517
518// Register the component in the registry
519// When "silent" is TRUE don't give any messages.
520
521extern "C" void RegisterMe(int silent)
522{
523 BOOL ok = TRUE;
524
525 // Get the application startup command
526 char module[MAX_PATH];
527
528 ::GetModuleFileName(NULL, module, MAX_PATH);
529
530 // Unregister first (quietly)
531 UnregisterMe(FALSE);
532
533 // Convert the CLSID into a char
534 char clsid[GUID_STRING_SIZE];
535 GUIDtochar(MYCLSID, clsid, sizeof(clsid));
536
537 // Convert the LIBID into a char
538 char libid[GUID_STRING_SIZE];
539 GUIDtochar(MYLIBID, libid, sizeof(libid));
540
541 // Build the key CLSID\\{...}
542 char Key[MAX_CLSID_LEN];
543 strcpy(Key, "CLSID\\");
544 strcat(Key, clsid);
545
546 // Add the CLSID to the registry
547 SetKeyAndValue(Key, NULL, MYNAME);
548 SetKeyAndValue(Key, "LocalServer32", module);
549 SetKeyAndValue(Key, "ProgID", MYPROGID);
550 SetKeyAndValue(Key, "VersionIndependentProgID", MYVIPROGID);
551 SetKeyAndValue(Key, "TypeLib", libid);
552
553 // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT
554 SetKeyAndValue(MYVIPROGID, NULL, MYNAME);
555 SetKeyAndValue(MYVIPROGID, "CLSID", clsid);
556 SetKeyAndValue(MYVIPROGID, "CurVer", MYPROGID);
557
558 // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
559 SetKeyAndValue(MYPROGID, NULL, MYNAME);
560 SetKeyAndValue(MYPROGID, "CLSID", clsid);
561
562 wchar_t w_module[MAX_PATH];
563 MultiByteToWideChar(CP_ACP, 0, module, -1, w_module, MAX_PATH);
564
565 ITypeLib *typelib = NULL;
566 if (LoadTypeLib(w_module, &typelib) != S_OK)
567 {
568 if (!silent)
569 MessageBox(0, "Cannot load type library to register",
570 "Vim Registration", 0);
571 ok = FALSE;
572 }
573 else
574 {
575 if (RegisterTypeLib(typelib, w_module, NULL) != S_OK)
576 {
577 if (!silent)
578 MessageBox(0, "Cannot register type library",
579 "Vim Registration", 0);
580 ok = FALSE;
581 }
582 typelib->Release();
583 }
584
585 if (ok && !silent)
586 MessageBox(0, "Registered successfully", "Vim", 0);
587}
588
589// Remove the component from the registry
590//
591// Note: There is little error checking in this code, to allow incomplete
592// or failed registrations to be undone.
593extern "C" void UnregisterMe(int bNotifyUser)
594{
595 // Unregister the type library
596 ITypeLib *typelib;
597 if (SUCCEEDED(LoadRegTypeLib(MYLIBID, MAJORVER, MINORVER, LOCALE, &typelib)))
598 {
599 TLIBATTR *tla;
600 if (SUCCEEDED(typelib->GetLibAttr(&tla)))
601 {
602 UnRegisterTypeLib(tla->guid, tla->wMajorVerNum, tla->wMinorVerNum,
603 tla->lcid, tla->syskind);
604 typelib->ReleaseTLibAttr(tla);
605 }
606 typelib->Release();
607 }
608
609 // Convert the CLSID into a char
610 char clsid[GUID_STRING_SIZE];
611 GUIDtochar(MYCLSID, clsid, sizeof(clsid));
612
613 // Build the key CLSID\\{...}
614 char Key[MAX_CLSID_LEN];
615 strcpy(Key, "CLSID\\");
616 strcat(Key, clsid);
617
618 // Delete the CLSID Key - CLSID\{...}
619 RecursiveDeleteKey(HKEY_CLASSES_ROOT, Key);
620
621 // Delete the version-independent ProgID Key
622 RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYVIPROGID);
623
624 // Delete the ProgID key
625 RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYPROGID);
626
627 if (bNotifyUser)
628 MessageBox(0, "Unregistered successfully", "Vim", 0);
629}
630
631/****************************************************************************/
632
633// Convert a GUID to a char string
Bram Moolenaar505e8282005-07-01 22:31:55 +0000634static void GUIDtochar(const GUID &guid, char *GUID, int length)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000635{
636 // Get wide string version
637 LPOLESTR wGUID = NULL;
638 StringFromCLSID(guid, &wGUID);
639
640 // Covert from wide characters to non-wide
641 wcstombs(GUID, wGUID, length);
642
643 // Free memory
644 CoTaskMemFree(wGUID);
645}
646
647// Delete a key and all of its descendents
Bram Moolenaar505e8282005-07-01 22:31:55 +0000648static void RecursiveDeleteKey(HKEY hKeyParent, const char *child)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649{
650 // Open the child
651 HKEY hKeyChild;
652 LONG result = RegOpenKeyEx(hKeyParent, child, 0, KEY_ALL_ACCESS, &hKeyChild);
653 if (result != ERROR_SUCCESS)
654 return;
655
656 // Enumerate all of the decendents of this child
657 FILETIME time;
658 char buffer[1024];
659 DWORD size = 1024;
660
661 while (RegEnumKeyEx(hKeyChild, 0, buffer, &size, NULL,
662 NULL, NULL, &time) == S_OK)
663 {
664 // Delete the decendents of this child
665 RecursiveDeleteKey(hKeyChild, buffer);
666 size = 256;
667 }
668
669 // Close the child
670 RegCloseKey(hKeyChild);
671
672 // Delete this child
673 RegDeleteKey(hKeyParent, child);
674}
675
676// Create a key and set its value
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +0000677static void SetKeyAndValue(const char *key, const char *subkey, const char *value)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678{
679 HKEY hKey;
680 char buffer[1024];
681
682 strcpy(buffer, key);
683
684 // Add subkey name to buffer.
685 if (subkey)
686 {
687 strcat(buffer, "\\");
688 strcat(buffer, subkey);
689 }
690
691 // Create and open key and subkey.
692 long result = RegCreateKeyEx(HKEY_CLASSES_ROOT,
693 buffer,
694 0, NULL, REG_OPTION_NON_VOLATILE,
695 KEY_ALL_ACCESS, NULL,
696 &hKey, NULL);
697 if (result != ERROR_SUCCESS)
698 return;
699
700 // Set the value
701 if (value)
702 RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value,
703 (DWORD)STRLEN(value)+1);
704
705 RegCloseKey(hKey);
706}
707
708/*****************************************************************************
709 5. OLE Initialisation and shutdown processing
710*****************************************************************************/
Bram Moolenaar505e8282005-07-01 22:31:55 +0000711extern "C" void InitOLE(int *pbDoRestart)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000712{
713 HRESULT hr;
714
715 *pbDoRestart = FALSE;
716
717 // Initialize the OLE libraries
718 hr = OleInitialize(NULL);
719 if (FAILED(hr))
720 {
721 MessageBox(0, "Cannot initialise OLE", "Vim Initialisation", 0);
722 goto error0;
723 }
724
725 // Create the application object
726 app = CVim::Create(pbDoRestart);
727 if (app == NULL)
728 goto error1;
729
730 // Create the class factory
731 cf = CVimCF::Create();
732 if (cf == NULL)
733 goto error1;
734
735 // Register the class factory
736 hr = CoRegisterClassObject(
737 MYCLSID,
738 cf,
739 CLSCTX_LOCAL_SERVER,
740 REGCLS_MULTIPLEUSE,
741 &cf_id);
742
743 if (FAILED(hr))
744 {
745 MessageBox(0, "Cannot register class factory", "Vim Initialisation", 0);
746 goto error1;
747 }
748
749 // Register the application object as active
750 hr = RegisterActiveObject(
751 app,
752 MYCLSID,
753 NULL,
754 &app_id);
755
756 if (FAILED(hr))
757 {
758 MessageBox(0, "Cannot register application object", "Vim Initialisation", 0);
759 goto error1;
760 }
761
762 return;
763
764 // Errors: tidy up as much as needed and return
765error1:
766 UninitOLE();
767error0:
768 return;
769}
770
771extern "C" void UninitOLE()
772{
773 // Unregister the application object
774 if (app_id)
775 {
776 RevokeActiveObject(app_id, NULL);
777 app_id = 0;
778 }
779
780 // Unregister the class factory
781 if (cf_id)
782 {
783 CoRevokeClassObject(cf_id);
784 cf_id = 0;
785 }
786
787 // Shut down the OLE libraries
788 OleUninitialize();
789
790 // Delete the application object
791 if (app)
792 {
793 delete app;
794 app = NULL;
795 }
796
797 // Delete the class factory
798 if (cf)
799 {
800 delete cf;
801 cf = NULL;
802 }
803}
804#endif /* FEAT_OLE */