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