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