1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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.
9 #if defined(FEAT_OLE) && defined(FEAT_GUI_W32)
11 * OLE server implementation.
13 * See os_mswin.c for the client side.
17 * We have some trouble with order of includes here. For Borland it needs to
18 * be different from MSVC...
34 extern HWND vim_parent_hwnd
;
38 /* Work around old versions of basetsd.h which wrongly declares
39 * UINT_PTR as unsigned long */
40 # define UINT_PTR UINT
43 #include "if_ole.h" // Interface definitions
44 #include "iid_ole.c" // UUID definitions (compile here)
46 /* Supply function prototype to work around bug in Mingw oleauto.h header */
48 WINOLEAUTAPI
UnRegisterTypeLib(REFGUID libID
, WORD wVerMajor
,
49 WORD wVerMinor
, LCID lcid
, SYSKIND syskind
);
52 /*****************************************************************************
53 1. Internal definitions for this file
54 *****************************************************************************/
60 // The identifier of the registered class factory
61 static unsigned long cf_id
= 0;
63 // The identifier of the running application object
64 static unsigned long app_id
= 0;
66 // The single global instance of the class factory
67 static CVimCF
*cf
= 0;
69 // The single global instance of the application object
72 /* GUIDs, versions and type library information */
73 #define MYCLSID CLSID_Vim
74 #define MYLIBID LIBID_Vim
75 #define MYIID IID_IVim
82 #define MYPROGID "Vim.Application.1"
83 #define MYVIPROGID "Vim.Application"
85 #define MAX_CLSID_LEN 100
87 /*****************************************************************************
88 2. The application object
89 *****************************************************************************/
95 class CVim
: public IVim
99 static CVim
*Create(int *pbDoRestart
);
102 STDMETHOD(QueryInterface
)(REFIID riid
, void ** ppv
);
103 STDMETHOD_(unsigned long, AddRef
)(void);
104 STDMETHOD_(unsigned long, Release
)(void);
107 STDMETHOD(GetTypeInfoCount
)(UINT
*pCount
);
108 STDMETHOD(GetTypeInfo
)(UINT iTypeInfo
, LCID
, ITypeInfo
**ppITypeInfo
);
109 STDMETHOD(GetIDsOfNames
)(const IID
&iid
, OLECHAR
**names
, UINT n
, LCID
, DISPID
*dispids
);
110 STDMETHOD(Invoke
)(DISPID member
, const IID
&iid
, LCID
, WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
);
113 STDMETHOD(SendKeys
)(BSTR keys
);
114 STDMETHOD(Eval
)(BSTR expr
, BSTR
*result
);
115 STDMETHOD(SetForeground
)(void);
116 STDMETHOD(GetHwnd
)(UINT_PTR
*result
);
119 // Constructor is private - create using CVim::Create()
120 CVim() : ref(0), typeinfo(0) {};
125 // The object's TypeInfo
133 CVim
*CVim::Create(int *pbDoRestart
)
137 ITypeLib
*typelib
= 0;
138 ITypeInfo
*typeinfo
= 0;
140 *pbDoRestart
= FALSE
;
146 MessageBox(0, "Cannot create application object", "Vim Initialisation", 0);
150 // Load the type library from the registry
151 hr
= LoadRegTypeLib(MYLIBID
, 1, 0, 0x00, &typelib
);
156 // Check we can write to the registry.
157 // RegCreateKeyEx succeeds even if key exists. W.Briscoe W2K 20021011
158 if (RegCreateKeyEx(HKEY_CLASSES_ROOT
, MYVIPROGID
, 0, NULL
,
159 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
))
162 return NULL
; // Unable to write to registry. Quietly fail.
166 if (MessageBox(0, "Cannot load registered type library.\nDo you want to register Vim now?",
167 "Vim Initialisation", MB_YESNO
| MB_ICONQUESTION
) != IDYES
)
175 // Load the type library from the registry
176 hr
= LoadRegTypeLib(MYLIBID
, 1, 0, 0x00, &typelib
);
179 MessageBox(0, "You must restart Vim in order for the registration to take effect.",
180 "Vim Initialisation", 0);
187 // Get the type info of the vtable interface
188 hr
= typelib
->GetTypeInfoOfGuid(MYIID
, &typeinfo
);
193 MessageBox(0, "Cannot get interface type information",
194 "Vim Initialisation", 0);
199 // Save the type information
200 me
->typeinfo
= typeinfo
;
206 if (typeinfo
&& vim_parent_hwnd
== NULL
)
212 CVim::QueryInterface(REFIID riid
, void **ppv
)
214 if (IsEqualIID(riid
, IID_IUnknown
) || IsEqualIID(riid
, IID_IDispatch
) || IsEqualIID(riid
, MYIID
))
222 return E_NOINTERFACE
;
234 // Don't delete the object when the reference count reaches zero, as there
235 // is only a single application object, and its lifetime is controlled by
236 // the running instance, not by its reference count.
243 CVim::GetTypeInfoCount(UINT
*pCount
)
250 CVim::GetTypeInfo(UINT iTypeInfo
, LCID
, ITypeInfo
**ppITypeInfo
)
255 return DISP_E_BADINDEX
;
258 *ppITypeInfo
= typeinfo
;
271 return DISP_E_UNKNOWNINTERFACE
;
273 return typeinfo
->GetIDsOfNames(names
, n
, dispids
);
282 DISPPARAMS
*dispparams
,
284 EXCEPINFO
*excepinfo
,
288 return DISP_E_UNKNOWNINTERFACE
;
290 ::SetErrorInfo(0, NULL
);
291 return typeinfo
->Invoke(static_cast<IDispatch
*>(this),
292 member
, flags
, dispparams
,
293 result
, excepinfo
, argerr
);
297 CVim::GetHwnd(UINT_PTR
*result
)
299 *result
= (UINT_PTR
)s_hwnd
;
304 CVim::SetForeground(void)
306 /* Make the Vim window come to the foreground */
307 gui_mch_set_foreground();
312 CVim::SendKeys(BSTR keys
)
319 /* Get a suitable buffer */
320 len
= WideCharToMultiByte(CP_ACP
, 0, keys
, -1, 0, 0, 0, 0);
321 buffer
= (char *)alloc(len
+1);
324 return E_OUTOFMEMORY
;
326 len
= WideCharToMultiByte(CP_ACP
, 0, keys
, -1, buffer
, len
, 0, 0);
334 /* Translate key codes like <Esc> */
335 str
= replace_termcodes((char_u
*)buffer
, &ptr
, FALSE
, TRUE
, FALSE
);
337 /* If ptr was set, then a new buffer was allocated,
338 * so we can free the old one.
341 vim_free((char_u
*)(buffer
));
343 /* Reject strings too long to fit in the input buffer. Allow 10 bytes
344 * space to cover for the (remote) possibility that characters may enter
345 * the input buffer between now and when the WM_OLE message is actually
346 * processed. If more that 10 characters enter the input buffer in that
347 * time, the WM_OLE processing will simply fail to insert the characters.
349 if ((int)(STRLEN(str
)) > (vim_free_in_input_buf() - 10))
355 /* Pass the string to the main input loop. The memory will be freed when
356 * the message is processed.
358 PostMessage(NULL
, WM_OLE
, 0, (LPARAM
)str
);
364 CVim::Eval(BSTR expr
, BSTR
*result
)
372 /* Get a suitable buffer */
373 len
= WideCharToMultiByte(CP_ACP
, 0, expr
, -1, 0, 0, 0, 0);
377 buffer
= (char *)alloc((unsigned)len
);
380 return E_OUTOFMEMORY
;
382 /* Convert the (wide character) expression to an ASCII string */
383 len
= WideCharToMultiByte(CP_ACP
, 0, expr
, -1, buffer
, len
, 0, 0);
387 /* Evaluate the expression */
389 str
= (char *)eval_to_string((char_u
*)buffer
, NULL
, TRUE
);
395 /* Convert the result to wide characters */
396 MultiByteToWideChar_alloc(CP_ACP
, 0, str
, -1, &w_buffer
, &len
);
398 if (w_buffer
== NULL
)
399 return E_OUTOFMEMORY
;
407 /* Store the result */
408 *result
= SysAllocString(w_buffer
);
417 /*****************************************************************************
419 *****************************************************************************/
425 class CVimCF
: public IClassFactory
428 static CVimCF
*Create();
430 STDMETHOD(QueryInterface
)(REFIID riid
, void ** ppv
);
431 STDMETHOD_(unsigned long, AddRef
)(void);
432 STDMETHOD_(unsigned long, Release
)(void);
433 STDMETHOD(CreateInstance
)(IUnknown
*punkOuter
, REFIID riid
, void ** ppv
);
434 STDMETHOD(LockServer
)(BOOL lock
);
437 // Constructor is private - create via Create()
438 CVimCF() : ref(0) {};
448 CVimCF
*CVimCF::Create()
450 CVimCF
*me
= new CVimCF();
453 MessageBox(0, "Cannot create class factory", "Vim Initialisation", 0);
459 CVimCF::QueryInterface(REFIID riid
, void **ppv
)
461 if (IsEqualIID(riid
, IID_IUnknown
) || IsEqualIID(riid
, IID_IClassFactory
))
469 return E_NOINTERFACE
;
481 // Don't delete the object when the reference count reaches zero, as there
482 // is only a single application object, and its lifetime is controlled by
483 // the running instance, not by its reference count.
491 CVimCF::CreateInstance(IUnknown
*punkOuter
, REFIID riid
, void **ppv
)
493 return app
->QueryInterface(riid
, ppv
);
498 CVimCF::LockServer(BOOL lock
)
503 /*****************************************************************************
504 4. Registry manipulation code
505 *****************************************************************************/
508 static void SetKeyAndValue(const char *path
, const char *subkey
, const char *value
);
509 static void GUIDtochar(const GUID
&guid
, char *GUID
, int length
);
510 static void RecursiveDeleteKey(HKEY hKeyParent
, const char *child
);
511 static const int GUID_STRING_SIZE
= 39;
513 // Register the component in the registry
514 // When "silent" is TRUE don't give any messages.
516 extern "C" void RegisterMe(int silent
)
520 // Get the application startup command
521 char module
[MAX_PATH
];
523 ::GetModuleFileName(NULL
, module
, MAX_PATH
);
525 // Unregister first (quietly)
528 // Convert the CLSID into a char
529 char clsid
[GUID_STRING_SIZE
];
530 GUIDtochar(MYCLSID
, clsid
, sizeof(clsid
));
532 // Convert the LIBID into a char
533 char libid
[GUID_STRING_SIZE
];
534 GUIDtochar(MYLIBID
, libid
, sizeof(libid
));
536 // Build the key CLSID\\{...}
537 char Key
[MAX_CLSID_LEN
];
538 strcpy(Key
, "CLSID\\");
541 // Add the CLSID to the registry
542 SetKeyAndValue(Key
, NULL
, MYNAME
);
543 SetKeyAndValue(Key
, "LocalServer32", module
);
544 SetKeyAndValue(Key
, "ProgID", MYPROGID
);
545 SetKeyAndValue(Key
, "VersionIndependentProgID", MYVIPROGID
);
546 SetKeyAndValue(Key
, "TypeLib", libid
);
548 // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT
549 SetKeyAndValue(MYVIPROGID
, NULL
, MYNAME
);
550 SetKeyAndValue(MYVIPROGID
, "CLSID", clsid
);
551 SetKeyAndValue(MYVIPROGID
, "CurVer", MYPROGID
);
553 // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
554 SetKeyAndValue(MYPROGID
, NULL
, MYNAME
);
555 SetKeyAndValue(MYPROGID
, "CLSID", clsid
);
557 wchar_t w_module
[MAX_PATH
];
558 MultiByteToWideChar(CP_ACP
, 0, module
, -1, w_module
, MAX_PATH
);
560 ITypeLib
*typelib
= NULL
;
561 if (LoadTypeLib(w_module
, &typelib
) != S_OK
)
564 MessageBox(0, "Cannot load type library to register",
565 "Vim Registration", 0);
570 if (RegisterTypeLib(typelib
, w_module
, NULL
) != S_OK
)
573 MessageBox(0, "Cannot register type library",
574 "Vim Registration", 0);
581 MessageBox(0, "Registered successfully", "Vim", 0);
584 // Remove the component from the registry
586 // Note: There is little error checking in this code, to allow incomplete
587 // or failed registrations to be undone.
588 extern "C" void UnregisterMe(int bNotifyUser
)
590 // Unregister the type library
592 if (SUCCEEDED(LoadRegTypeLib(MYLIBID
, MAJORVER
, MINORVER
, LOCALE
, &typelib
)))
595 if (SUCCEEDED(typelib
->GetLibAttr(&tla
)))
597 UnRegisterTypeLib(tla
->guid
, tla
->wMajorVerNum
, tla
->wMinorVerNum
,
598 tla
->lcid
, tla
->syskind
);
599 typelib
->ReleaseTLibAttr(tla
);
604 // Convert the CLSID into a char
605 char clsid
[GUID_STRING_SIZE
];
606 GUIDtochar(MYCLSID
, clsid
, sizeof(clsid
));
608 // Build the key CLSID\\{...}
609 char Key
[MAX_CLSID_LEN
];
610 strcpy(Key
, "CLSID\\");
613 // Delete the CLSID Key - CLSID\{...}
614 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, Key
);
616 // Delete the version-independent ProgID Key
617 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, MYVIPROGID
);
619 // Delete the ProgID key
620 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, MYPROGID
);
623 MessageBox(0, "Unregistered successfully", "Vim", 0);
626 /****************************************************************************/
628 // Convert a GUID to a char string
629 static void GUIDtochar(const GUID
&guid
, char *GUID
, int length
)
631 // Get wide string version
632 LPOLESTR wGUID
= NULL
;
633 StringFromCLSID(guid
, &wGUID
);
635 // Covert from wide characters to non-wide
636 wcstombs(GUID
, wGUID
, length
);
639 CoTaskMemFree(wGUID
);
642 // Delete a key and all of its descendents
643 static void RecursiveDeleteKey(HKEY hKeyParent
, const char *child
)
647 LONG result
= RegOpenKeyEx(hKeyParent
, child
, 0, KEY_ALL_ACCESS
, &hKeyChild
);
648 if (result
!= ERROR_SUCCESS
)
651 // Enumerate all of the decendents of this child
656 while (RegEnumKeyEx(hKeyChild
, 0, buffer
, &size
, NULL
,
657 NULL
, NULL
, &time
) == S_OK
)
659 // Delete the decendents of this child
660 RecursiveDeleteKey(hKeyChild
, buffer
);
665 RegCloseKey(hKeyChild
);
668 RegDeleteKey(hKeyParent
, child
);
671 // Create a key and set its value
672 static void SetKeyAndValue(const char *key
, const char *subkey
, const char *value
)
679 // Add subkey name to buffer.
682 strcat(buffer
, "\\");
683 strcat(buffer
, subkey
);
686 // Create and open key and subkey.
687 long result
= RegCreateKeyEx(HKEY_CLASSES_ROOT
,
689 0, NULL
, REG_OPTION_NON_VOLATILE
,
690 KEY_ALL_ACCESS
, NULL
,
692 if (result
!= ERROR_SUCCESS
)
697 RegSetValueEx(hKey
, NULL
, 0, REG_SZ
, (BYTE
*)value
,
698 (DWORD
)STRLEN(value
)+1);
703 /*****************************************************************************
704 5. OLE Initialisation and shutdown processing
705 *****************************************************************************/
706 extern "C" void InitOLE(int *pbDoRestart
)
710 *pbDoRestart
= FALSE
;
712 // Initialize the OLE libraries
713 hr
= OleInitialize(NULL
);
716 MessageBox(0, "Cannot initialise OLE", "Vim Initialisation", 0);
720 // Create the application object
721 app
= CVim::Create(pbDoRestart
);
725 // Create the class factory
726 cf
= CVimCF::Create();
730 // Register the class factory
731 hr
= CoRegisterClassObject(
740 MessageBox(0, "Cannot register class factory", "Vim Initialisation", 0);
744 // Register the application object as active
745 hr
= RegisterActiveObject(
753 MessageBox(0, "Cannot register application object", "Vim Initialisation", 0);
759 // Errors: tidy up as much as needed and return
766 extern "C" void UninitOLE()
768 // Unregister the application object
771 RevokeActiveObject(app_id
, NULL
);
775 // Unregister the class factory
778 CoRevokeClassObject(cf_id
);
782 // Shut down the OLE libraries
785 // Delete the application object
792 // Delete the class factory
799 #endif /* FEAT_OLE */