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
;
37 #include "if_ole.h" // Interface definitions
38 #include "iid_ole.c" // UUID definitions (compile here)
40 /* Supply function prototype to work around bug in Mingw oleauto.h header */
42 WINOLEAUTAPI
UnRegisterTypeLib(REFGUID libID
, WORD wVerMajor
,
43 WORD wVerMinor
, LCID lcid
, SYSKIND syskind
);
46 /*****************************************************************************
47 1. Internal definitions for this file
48 *****************************************************************************/
54 // The identifier of the registered class factory
55 static unsigned long cf_id
= 0;
57 // The identifier of the running application object
58 static unsigned long app_id
= 0;
60 // The single global instance of the class factory
61 static CVimCF
*cf
= 0;
63 // The single global instance of the application object
66 /* GUIDs, versions and type library information */
67 #define MYCLSID CLSID_Vim
68 #define MYLIBID LIBID_Vim
69 #define MYIID IID_IVim
76 #define MYPROGID "Vim.Application.1"
77 #define MYVIPROGID "Vim.Application"
79 #define MAX_CLSID_LEN 100
81 /*****************************************************************************
82 2. The application object
83 *****************************************************************************/
89 class CVim
: public IVim
93 static CVim
*Create(int *pbDoRestart
);
96 STDMETHOD(QueryInterface
)(REFIID riid
, void ** ppv
);
97 STDMETHOD_(unsigned long, AddRef
)(void);
98 STDMETHOD_(unsigned long, Release
)(void);
101 STDMETHOD(GetTypeInfoCount
)(UINT
*pCount
);
102 STDMETHOD(GetTypeInfo
)(UINT iTypeInfo
, LCID
, ITypeInfo
**ppITypeInfo
);
103 STDMETHOD(GetIDsOfNames
)(const IID
&iid
, OLECHAR
**names
, UINT n
, LCID
, DISPID
*dispids
);
104 STDMETHOD(Invoke
)(DISPID member
, const IID
&iid
, LCID
, WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
);
107 STDMETHOD(SendKeys
)(BSTR keys
);
108 STDMETHOD(Eval
)(BSTR expr
, BSTR
*result
);
109 STDMETHOD(SetForeground
)(void);
110 STDMETHOD(GetHwnd
)(UINT
*result
);
113 // Constructor is private - create using CVim::Create()
114 CVim() : ref(0), typeinfo(0) {};
119 // The object's TypeInfo
127 CVim
*CVim::Create(int *pbDoRestart
)
131 ITypeLib
*typelib
= 0;
132 ITypeInfo
*typeinfo
= 0;
134 *pbDoRestart
= FALSE
;
140 MessageBox(0, "Cannot create application object", "Vim Initialisation", 0);
144 // Load the type library from the registry
145 hr
= LoadRegTypeLib(MYLIBID
, 1, 0, 0x00, &typelib
);
150 // Check we can write to the registry.
151 // RegCreateKeyEx succeeds even if key exists. W.Briscoe W2K 20021011
152 if (RegCreateKeyEx(HKEY_CLASSES_ROOT
, MYVIPROGID
, 0, NULL
,
153 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
))
156 return NULL
; // Unable to write to registry. Quietly fail.
160 if (MessageBox(0, "Cannot load registered type library.\nDo you want to register Vim now?",
161 "Vim Initialisation", MB_YESNO
| MB_ICONQUESTION
) != IDYES
)
169 // Load the type library from the registry
170 hr
= LoadRegTypeLib(MYLIBID
, 1, 0, 0x00, &typelib
);
173 MessageBox(0, "You must restart Vim in order for the registration to take effect.",
174 "Vim Initialisation", 0);
181 // Get the type info of the vtable interface
182 hr
= typelib
->GetTypeInfoOfGuid(MYIID
, &typeinfo
);
187 MessageBox(0, "Cannot get interface type information",
188 "Vim Initialisation", 0);
193 // Save the type information
194 me
->typeinfo
= typeinfo
;
200 if (typeinfo
&& vim_parent_hwnd
== NULL
)
206 CVim::QueryInterface(REFIID riid
, void **ppv
)
208 if (IsEqualIID(riid
, IID_IUnknown
) || IsEqualIID(riid
, IID_IDispatch
) || IsEqualIID(riid
, MYIID
))
216 return E_NOINTERFACE
;
228 // Don't delete the object when the reference count reaches zero, as there
229 // is only a single application object, and its lifetime is controlled by
230 // the running instance, not by its reference count.
237 CVim::GetTypeInfoCount(UINT
*pCount
)
244 CVim::GetTypeInfo(UINT iTypeInfo
, LCID
, ITypeInfo
**ppITypeInfo
)
249 return DISP_E_BADINDEX
;
252 *ppITypeInfo
= typeinfo
;
265 return DISP_E_UNKNOWNINTERFACE
;
267 return typeinfo
->GetIDsOfNames(names
, n
, dispids
);
276 DISPPARAMS
*dispparams
,
278 EXCEPINFO
*excepinfo
,
282 return DISP_E_UNKNOWNINTERFACE
;
284 ::SetErrorInfo(0, NULL
);
285 return typeinfo
->Invoke(static_cast<IDispatch
*>(this),
286 member
, flags
, dispparams
,
287 result
, excepinfo
, argerr
);
291 CVim::GetHwnd(UINT
*result
)
293 *result
= (UINT
) s_hwnd
;
298 CVim::SetForeground(void)
300 /* Make the Vim window come to the foreground */
301 gui_mch_set_foreground();
306 CVim::SendKeys(BSTR keys
)
313 /* Get a suitable buffer */
314 len
= WideCharToMultiByte(CP_ACP
, 0, keys
, -1, 0, 0, 0, 0);
315 buffer
= (char *)alloc(len
+1);
318 return E_OUTOFMEMORY
;
320 len
= WideCharToMultiByte(CP_ACP
, 0, keys
, -1, buffer
, len
, 0, 0);
328 /* Translate key codes like <Esc> */
329 str
= replace_termcodes((char_u
*)buffer
, &ptr
, FALSE
, TRUE
, FALSE
);
331 /* If ptr was set, then a new buffer was allocated,
332 * so we can free the old one.
335 vim_free((char_u
*)(buffer
));
337 /* Reject strings too long to fit in the input buffer. Allow 10 bytes
338 * space to cover for the (remote) possibility that characters may enter
339 * the input buffer between now and when the WM_OLE message is actually
340 * processed. If more that 10 characters enter the input buffer in that
341 * time, the WM_OLE processing will simply fail to insert the characters.
343 if ((int)(STRLEN(str
)) > (vim_free_in_input_buf() - 10))
349 /* Pass the string to the main input loop. The memory will be freed when
350 * the message is processed.
352 PostMessage(NULL
, WM_OLE
, 0, (LPARAM
)str
);
358 CVim::Eval(BSTR expr
, BSTR
*result
)
366 /* Get a suitable buffer */
367 len
= WideCharToMultiByte(CP_ACP
, 0, expr
, -1, 0, 0, 0, 0);
371 buffer
= (char *)alloc((unsigned)len
);
374 return E_OUTOFMEMORY
;
376 /* Convert the (wide character) expression to an ASCII string */
377 len
= WideCharToMultiByte(CP_ACP
, 0, expr
, -1, buffer
, len
, 0, 0);
381 /* Evaluate the expression */
383 str
= (char *)eval_to_string((char_u
*)buffer
, NULL
, TRUE
);
389 /* Convert the result to wide characters */
390 MultiByteToWideChar_alloc(CP_ACP
, 0, str
, -1, &w_buffer
, &len
);
392 if (w_buffer
== NULL
)
393 return E_OUTOFMEMORY
;
401 /* Store the result */
402 *result
= SysAllocString(w_buffer
);
411 /*****************************************************************************
413 *****************************************************************************/
419 class CVimCF
: public IClassFactory
422 static CVimCF
*Create();
424 STDMETHOD(QueryInterface
)(REFIID riid
, void ** ppv
);
425 STDMETHOD_(unsigned long, AddRef
)(void);
426 STDMETHOD_(unsigned long, Release
)(void);
427 STDMETHOD(CreateInstance
)(IUnknown
*punkOuter
, REFIID riid
, void ** ppv
);
428 STDMETHOD(LockServer
)(BOOL lock
);
431 // Constructor is private - create via Create()
432 CVimCF() : ref(0) {};
442 CVimCF
*CVimCF::Create()
444 CVimCF
*me
= new CVimCF();
447 MessageBox(0, "Cannot create class factory", "Vim Initialisation", 0);
453 CVimCF::QueryInterface(REFIID riid
, void **ppv
)
455 if (IsEqualIID(riid
, IID_IUnknown
) || IsEqualIID(riid
, IID_IClassFactory
))
463 return E_NOINTERFACE
;
475 // Don't delete the object when the reference count reaches zero, as there
476 // is only a single application object, and its lifetime is controlled by
477 // the running instance, not by its reference count.
485 CVimCF::CreateInstance(IUnknown
*punkOuter
, REFIID riid
, void **ppv
)
487 return app
->QueryInterface(riid
, ppv
);
492 CVimCF::LockServer(BOOL lock
)
497 /*****************************************************************************
498 4. Registry manipulation code
499 *****************************************************************************/
502 static void SetKeyAndValue(const char *path
, const char *subkey
, const char *value
);
503 static void GUIDtochar(const GUID
&guid
, char *GUID
, int length
);
504 static void RecursiveDeleteKey(HKEY hKeyParent
, const char *child
);
505 static const int GUID_STRING_SIZE
= 39;
507 // Register the component in the registry
508 // When "silent" is TRUE don't give any messages.
510 extern "C" void RegisterMe(int silent
)
514 // Get the application startup command
515 char module
[MAX_PATH
];
517 ::GetModuleFileName(NULL
, module
, MAX_PATH
);
519 // Unregister first (quietly)
522 // Convert the CLSID into a char
523 char clsid
[GUID_STRING_SIZE
];
524 GUIDtochar(MYCLSID
, clsid
, sizeof(clsid
));
526 // Convert the LIBID into a char
527 char libid
[GUID_STRING_SIZE
];
528 GUIDtochar(MYLIBID
, libid
, sizeof(libid
));
530 // Build the key CLSID\\{...}
531 char Key
[MAX_CLSID_LEN
];
532 strcpy(Key
, "CLSID\\");
535 // Add the CLSID to the registry
536 SetKeyAndValue(Key
, NULL
, MYNAME
);
537 SetKeyAndValue(Key
, "LocalServer32", module
);
538 SetKeyAndValue(Key
, "ProgID", MYPROGID
);
539 SetKeyAndValue(Key
, "VersionIndependentProgID", MYVIPROGID
);
540 SetKeyAndValue(Key
, "TypeLib", libid
);
542 // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT
543 SetKeyAndValue(MYVIPROGID
, NULL
, MYNAME
);
544 SetKeyAndValue(MYVIPROGID
, "CLSID", clsid
);
545 SetKeyAndValue(MYVIPROGID
, "CurVer", MYPROGID
);
547 // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
548 SetKeyAndValue(MYPROGID
, NULL
, MYNAME
);
549 SetKeyAndValue(MYPROGID
, "CLSID", clsid
);
551 wchar_t w_module
[MAX_PATH
];
552 MultiByteToWideChar(CP_ACP
, 0, module
, -1, w_module
, MAX_PATH
);
554 ITypeLib
*typelib
= NULL
;
555 if (LoadTypeLib(w_module
, &typelib
) != S_OK
)
558 MessageBox(0, "Cannot load type library to register",
559 "Vim Registration", 0);
564 if (RegisterTypeLib(typelib
, w_module
, NULL
) != S_OK
)
567 MessageBox(0, "Cannot register type library",
568 "Vim Registration", 0);
575 MessageBox(0, "Registered successfully", "Vim", 0);
578 // Remove the component from the registry
580 // Note: There is little error checking in this code, to allow incomplete
581 // or failed registrations to be undone.
582 extern "C" void UnregisterMe(int bNotifyUser
)
584 // Unregister the type library
586 if (SUCCEEDED(LoadRegTypeLib(MYLIBID
, MAJORVER
, MINORVER
, LOCALE
, &typelib
)))
589 if (SUCCEEDED(typelib
->GetLibAttr(&tla
)))
591 UnRegisterTypeLib(tla
->guid
, tla
->wMajorVerNum
, tla
->wMinorVerNum
,
592 tla
->lcid
, tla
->syskind
);
593 typelib
->ReleaseTLibAttr(tla
);
598 // Convert the CLSID into a char
599 char clsid
[GUID_STRING_SIZE
];
600 GUIDtochar(MYCLSID
, clsid
, sizeof(clsid
));
602 // Build the key CLSID\\{...}
603 char Key
[MAX_CLSID_LEN
];
604 strcpy(Key
, "CLSID\\");
607 // Delete the CLSID Key - CLSID\{...}
608 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, Key
);
610 // Delete the version-independent ProgID Key
611 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, MYVIPROGID
);
613 // Delete the ProgID key
614 RecursiveDeleteKey(HKEY_CLASSES_ROOT
, MYPROGID
);
617 MessageBox(0, "Unregistered successfully", "Vim", 0);
620 /****************************************************************************/
622 // Convert a GUID to a char string
623 static void GUIDtochar(const GUID
&guid
, char *GUID
, int length
)
625 // Get wide string version
626 LPOLESTR wGUID
= NULL
;
627 StringFromCLSID(guid
, &wGUID
);
629 // Covert from wide characters to non-wide
630 wcstombs(GUID
, wGUID
, length
);
633 CoTaskMemFree(wGUID
);
636 // Delete a key and all of its descendents
637 static void RecursiveDeleteKey(HKEY hKeyParent
, const char *child
)
641 LONG result
= RegOpenKeyEx(hKeyParent
, child
, 0, KEY_ALL_ACCESS
, &hKeyChild
);
642 if (result
!= ERROR_SUCCESS
)
645 // Enumerate all of the decendents of this child
650 while (RegEnumKeyEx(hKeyChild
, 0, buffer
, &size
, NULL
,
651 NULL
, NULL
, &time
) == S_OK
)
653 // Delete the decendents of this child
654 RecursiveDeleteKey(hKeyChild
, buffer
);
659 RegCloseKey(hKeyChild
);
662 RegDeleteKey(hKeyParent
, child
);
665 // Create a key and set its value
666 static void SetKeyAndValue(const char *key
, const char *subkey
, const char *value
)
673 // Add subkey name to buffer.
676 strcat(buffer
, "\\");
677 strcat(buffer
, subkey
);
680 // Create and open key and subkey.
681 long result
= RegCreateKeyEx(HKEY_CLASSES_ROOT
,
683 0, NULL
, REG_OPTION_NON_VOLATILE
,
684 KEY_ALL_ACCESS
, NULL
,
686 if (result
!= ERROR_SUCCESS
)
691 RegSetValueEx(hKey
, NULL
, 0, REG_SZ
, (BYTE
*)value
,
692 (DWORD
)STRLEN(value
)+1);
697 /*****************************************************************************
698 5. OLE Initialisation and shutdown processing
699 *****************************************************************************/
700 extern "C" void InitOLE(int *pbDoRestart
)
704 *pbDoRestart
= FALSE
;
706 // Initialize the OLE libraries
707 hr
= OleInitialize(NULL
);
710 MessageBox(0, "Cannot initialise OLE", "Vim Initialisation", 0);
714 // Create the application object
715 app
= CVim::Create(pbDoRestart
);
719 // Create the class factory
720 cf
= CVimCF::Create();
724 // Register the class factory
725 hr
= CoRegisterClassObject(
734 MessageBox(0, "Cannot register class factory", "Vim Initialisation", 0);
738 // Register the application object as active
739 hr
= RegisterActiveObject(
747 MessageBox(0, "Cannot register application object", "Vim Initialisation", 0);
753 // Errors: tidy up as much as needed and return
760 extern "C" void UninitOLE()
762 // Unregister the application object
765 RevokeActiveObject(app_id
, NULL
);
769 // Unregister the class factory
772 CoRevokeClassObject(cf_id
);
776 // Shut down the OLE libraries
779 // Delete the application object
786 // Delete the class factory
793 #endif /* FEAT_OLE */