Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

# Tools/Xabsl2/yabsl/vsyabsl/dllmain.cpp

Go to the documentation of this file.

    00001
    00002 /***************************************************************************
    00003          Copyright (c) Microsoft Corporation, All rights reserved.
    00004     This code sample is provided "AS IS" without warranty of any kind,
    00005     it is not recommended for use in a production environment.
    00006 ***************************************************************************/
    00007
    00008 #include <malloc.h>
    00009 #include "common.h"
    00010 #include "dllmain.h"
    00011 #include "languagedef.h"
    00012
    00013 /*---------------------------------------------------------
    00014   globals
    00015 -----------------------------------------------------------*/
    00016 ITypeInfo* g_typeInfoBabelService     = NULL;
    00017
    00018 static HINSTANCE  g_instance          = NULL;
    00019 static ULONG      g_dllRefCount       = 0;
    00020
    00021 //babel package clsid's
    00022 static const CLSID babelPackageCLSID7 =
    00023   { 0x221f0eb7, 0x30f7, 0x45ff, { 0xae, 0x73, 0x59, 0x68, 0xb1, 0x67, 0xcf, 0x9 } };
    00024
    00025 //registry paths
    00026 static CStr regPathVS7                  = STR("Software\\Microsoft\\VisualStudio\\7.1");
    00027 static CStr regPathVS7_NoVersion        = STR("Software\\Microsoft\\VisualStudio\\");
    00028
    00029 static CStr regPathFileExts  = STR("Languages\\File Extensions");
    00030 static CStr regPathLServices = STR("Languages\\Language Services");
    00031 static CStr regPathServices  = STR("Services");
    00032
    00033
    00034 /*---------------------------------------------------------
    00035   Prototypes
    00036 -----------------------------------------------------------*/
    00037 static HRESULT RegisterServer( in bool registerIt);
    00038 static HRESULT GetRegistrationRoot(Str pszRegistrationRoot, ULONG cchBuffer = _MAX_PATH);
    00039 static HRESULT LoadTypeInfo();
    00040
    00041 //registry helpers
    00042 static HRESULT RegCreateValue( in HKEY key, in CStr name, in CStr value );
    00043 static HRESULT RegCreateDwordValue( in HKEY key, in CStr name, in DWORD value );
    00044 static HRESULT RegDeleteRecursive( in HKEY keyRoot, in CStr path );
    00045
    00046
    00047 /*---------------------------------------------------------
    00048   Class Factory
    00049 -----------------------------------------------------------*/
    00050 class BabelServiceFactory : IClassFactory
    00051 {
    00052 private:
    00053   ULONG   m_refCount;
    00054
    00055 public:
    00056   BabelServiceFactory();
    00057   ~BabelServiceFactory();
    00058
    00059   //IUnknown
    00060   STDMETHODIMP QueryInterface( REFIID iid, LPVOID* obj );
    00061   STDMETHODIMP_(ULONG) AddRef();
    00062   STDMETHODIMP_(ULONG) Release();
    00063
    00064   //IClassFactory
    00065   STDMETHODIMP CreateInstance( IUnknown* outer, REFIID iid, LPVOID* obj );
    00066   STDMETHODIMP LockServer( BOOL lockIt );
    00067 };
    00068
    00069
    00070
    00071 /*---------------------------------------------------------
    00072   Dll entry points
    00073 -----------------------------------------------------------*/
    00074 BOOL APIENTRY DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved )
    00075 {
    00076   switch (reason)
    00077   {
    00078   case DLL_PROCESS_ATTACH:
    00079     TRACE_INIT( g_languageName );
    00080     TRACE( "load dll" );
    00081     g_instance    = instance;
    00082     g_dllRefCount = 0;
    00083     LoadTypeInfo();
    00084     break;
    00085   case DLL_PROCESS_DETACH:
    00086     TRACE("unload dll");
    00087     RELEASE(g_typeInfoBabelService);
    00088     TRACE_DONE;
    00089     break;
    00090   case DLL_THREAD_ATTACH:
    00091     TRACE("dll attach thread");
    00092     break;
    00093   case DLL_THREAD_DETACH:
    00094     TRACE("dll detach thread");
    00095     break;
    00096   }
    00097
    00098   return TRUE;
    00099 }
    00100
    00101 STDAPI DllCanUnloadNow()
    00102 {
    00103   return (g_dllRefCount == 0);
    00104 }
    00105
    00106
    00107 STDAPI DllGetClassObject( REFCLSID clsid, REFIID iid, LPVOID* obj )
    00108 {
    00109   OUTARG(obj);
    00110
    00111   if (clsid == g_languageCLSID)
    00112   {
    00113     BabelServiceFactory* factory  = new BabelServiceFactory();
    00114     if (!factory) return E_OUTOFMEMORY;
    00115
    00116     HRESULT hr = factory->QueryInterface(iid,obj);
    00117     RELEASE(factory);
    00118     return hr;
    00119   }
    00120   else
    00121     return CLASS_E_CLASSNOTAVAILABLE;
    00122 }
    00123
    00124
    00125 STDAPI DllRegisterServer()
    00126 {
    00127   return RegisterServer(true);
    00128 }
    00129
    00130
    00131 STDAPI DllUnregisterServer()
    00132 {
    00133   return RegisterServer(false);
    00134 }
    00135
    00136
    00137 /*---------------------------------------------------------
    00138   Class Factory
    00139 -----------------------------------------------------------*/
    00140 BabelServiceFactory::BabelServiceFactory()
    00141 {
    00142   TRACE_CREATE("BabelServiceFactory", this );
    00143   m_refCount = 1;
    00144 }
    00145
    00146 BabelServiceFactory::~BabelServiceFactory()
    00147 {
    00148   TRACE_DESTROY(this);
    00149 }
    00150
    00151 //IUnknown
    00152 STDMETHODIMP BabelServiceFactory::QueryInterface( REFIID iid, LPVOID* obj )
    00153 {
    00154   OUTARG(obj);
    00155
    00156   if (iid == IID_IUnknown || iid == IID_IClassFactory)
    00157   {
    00158     *obj = static_cast<IClassFactory*>(this);
    00159   }
    00160   else
    00161     return E_NOINTERFACE;
    00162
    00163   AddRef();
    00164   return S_OK;
    00165 }
    00166
    00167 STDMETHODIMP_(ULONG) BabelServiceFactory::AddRef()
    00168 {
    00169   return IncRefCount(&m_refCount);
    00170 }
    00171
    00172 STDMETHODIMP_(ULONG) BabelServiceFactory::Release()
    00173 {
    00174   if (DecRefCount(&m_refCount) == 0)
    00175   {
    00176     delete this;
    00177     return 0;
    00178   }
    00179   else
    00180     return m_refCount;
    00181 }
    00182
    00183 //IClassFactory
    00184 STDMETHODIMP BabelServiceFactory::CreateInstance( IUnknown* outer, REFIID iid, LPVOID* obj )
    00185 {
    00186   TRACE("BabelServiceFactory::CreateInstance");
    00187   OUTARG(obj);
    00188   HRESULT hr;
    00189
    00190   if (outer) return CLASS_E_NOAGGREGATION;
    00191
    00192   IBabelService* babelService;
    00193   hr = CreateBabelService( &babelService );
    00194   if (FAILED(hr)) return hr;
    00195
    00196   hr = babelService->QueryInterface( iid, obj );
    00197   RELEASE(babelService);
    00198
    00199   return hr;
    00200 }
    00201
    00202 STDMETHODIMP BabelServiceFactory::LockServer( BOOL lockIt )
    00203 {
    00204   if (lockIt)
    00205   {
    00206     IncRefCount( &g_dllRefCount );
    00207   }
    00208   else
    00209   {
    00210     DecRefCount( &g_dllRefCount );
    00211   }
    00212
    00213   return S_OK;
    00214 }
    00215
    00216 /*---------------------------------------------------------
    00217   Load the BabelService type library
    00218 -----------------------------------------------------------*/
    00219 static HRESULT LoadTypeInfo()
    00220 {
    00221   HRESULT hr;
    00222
    00223   //load it only once
    00224   if (g_typeInfoBabelService) return S_OK;
    00225
    00226   //load the library
    00227   ITypeLib* lib;
    00228   hr = LoadRegTypeLib( LIBID_BabelServiceLib, 1, 0, LANG_NEUTRAL, &lib );
    00229   if (FAILED(hr)) return hr;
    00230
    00231   //get the typeinfo
    00232   hr = lib->GetTypeInfoOfGuid( IID_IBabelService, &g_typeInfoBabelService );
    00233   RELEASE(lib);
    00234   if (FAILED(hr)) return hr;
    00235
    00236   return S_OK;
    00237 }
    00238
    00239 /*---------------------------------------------------------
    00240   Registration
    00241 -----------------------------------------------------------*/
    00242 static HRESULT RegisterService( in CStr         regPathVS,
    00243                                 in const CLSID& packageCLSID,
    00244                                 in bool         registerIt )
    00245 {
    00246   USECONV;
    00247   HRESULT hr;
    00248
    00249   //get clsid's as string
    00250   OleChar oleLanguageCLSID[128];
    00251   if (StringFromGUID2(g_languageCLSID, oleLanguageCLSID, 127) == 0)
    00252   { return E_FAIL; }
    00253
    00254   OleChar olePackageCLSID[128];
    00255   if (StringFromGUID2(packageCLSID, olePackageCLSID, 127) == 0)
    00256   { return E_FAIL; }
    00257
    00258   //open root key
    00259   HKEY    keyVS   = 0;
    00260   HKEY    keySub  = 0;
    00261   HKEY    key     = 0;
    00262
    00263   hr = RegOpenKey( HKEY_LOCAL_MACHINE, regPathVS, &keyVS );
    00264   if (FAILED(hr)) return hr;
    00265
    00266   //file extensions
    00267   hr = RegOpenKey( keyVS, regPathFileExts, &keySub );
    00268   if (FAILED(hr)) goto fail;
    00269
    00270   int idx;
    00271   for (idx = 0; g_languageFileExtensions[idx] != NULL; idx++)
    00272   {
    00273     const char* fileExt;
    00274
    00275     fileExt = g_languageFileExtensions[idx];
    00276
    00277     if (!registerIt)
    00278     {
    00279       RegDeleteRecursive( keySub, Ansi2CStr(fileExt) );
    00280     }
    00281     else
    00282     {
    00283       hr = RegCreateKey( keySub, Ansi2CStr(fileExt), &key );
    00284       if (FAILED(hr)) goto fail;
    00285
    00286       hr = RegCreateValue( key, NULL, Ole2CStr(oleLanguageCLSID) );
    00287       if (FAILED(hr)) goto fail;
    00288
    00289       hr = RegCreateValue( key, STR("Name"), Ansi2CStr(g_languageName) );
    00290       if (FAILED(hr)) goto fail;
    00291
    00292       RegCloseKey(key); key = 0;
    00293     }
    00294   }
    00295   RegCloseKey(keySub); keySub = 0;
    00296
    00297
    00298   //Create an extensions string
    00299   Char fileExtensions[MAXPATH+1];
    00300   fileExtensions[0] = 0;
    00301   for (idx = 0; g_languageFileExtensions[idx] != NULL; idx++)
    00302   {
    00303     ansiToStrCat( fileExtensions, g_languageFileExtensions[idx], MAXPATH );
    00304     strCat( fileExtensions, STR(";"), MAXPATH );
    00305   }
    00306
    00307   //language service
    00308   hr = RegOpenKey( keyVS, regPathLServices, &keySub );
    00309   if (FAILED(hr)) goto fail;
    00310
    00311   if (!registerIt)
    00312   {
    00313     RegDeleteRecursive( keySub, Ansi2CStr(g_languageName) );
    00314   }
    00315   else
    00316   {
    00317     hr = RegCreateKey( keySub, Ansi2CStr(g_languageName), &key );
    00318     if (FAILED(hr)) goto fail;
    00319
    00320     hr = RegCreateValue( key, NULL, Ole2CStr(oleLanguageCLSID) );
    00321     if (FAILED(hr)) goto fail;
    00322
    00323     hr = RegCreateValue( key, STR("Package"), Ole2CStr(olePackageCLSID) );
    00324     if (FAILED(hr)) goto fail;
    00325
    00326     hr = RegCreateValue( key, STR("Extensions"), fileExtensions );
    00327     if (FAILED(hr)) goto fail;
    00328
    00329     hr = RegCreateDwordValue( key, STR("LangResId"), 0 );
    00330     if (FAILED(hr)) goto fail;
    00331
    00332     hr = RegCreateDwordValue( key, STR("RequestStockColors"), 1 );
    00333     if (FAILED(hr)) goto fail;
    00334
    00335     hr = RegCreateDwordValue( key, STR("ShowCompletion"), 0 );
    00336     if (FAILED(hr)) goto fail;
    00337
    00338
    00339     //babel specific entries
    00340     hr = RegCreateDwordValue( key, OLE("ThreadModel"), 1 ); //colorizer/parser can be called from two different threads
    00341     if (FAILED(hr)) goto fail;
    00342
    00343     hr = RegCreateDwordValue( key, OLE("MatchBraces"), 1 );
    00344     if (FAILED(hr)) goto fail;
    00345
    00346     hr = RegCreateDwordValue( key, OLE("QuickInfo"), 1 );
    00347     if (FAILED(hr)) goto fail;
    00348
    00349     const LanguageProperty* property;
    00350     for (property = g_languageProperties; property->name; property++)
    00351     {
    00352       hr = RegCreateDwordValue( key, Ansi2CStr(property->name), property->value );
    00353       if (FAILED(hr)) goto fail;
    00354     }
    00355
    00356     RegCloseKey( key ); key = 0;
    00357   }
    00358   RegCloseKey( keySub ); keySub = 0;
    00359
    00360   //services
    00361   hr = RegOpenKey( keyVS, regPathServices, &keySub );
    00362   if (FAILED(hr)) goto fail;
    00363
    00364   if (!registerIt)
    00365   {
    00366     RegDeleteRecursive( keySub, Ole2CStr(oleLanguageCLSID) );
    00367   }
    00368   else
    00369   {
    00370     hr = RegCreateKey( keySub, Ole2CStr(oleLanguageCLSID), &key );
    00371     if (FAILED(hr)) goto fail;
    00372
    00373     hr = RegCreateValue( key, NULL, Ole2CStr(olePackageCLSID) );
    00374     if (FAILED(hr)) goto fail;
    00375
    00376     hr = RegCreateValue( key, STR("Name"), Ansi2CStr(g_languageName) );
    00377     if (FAILED(hr)) goto fail;
    00378
    00379     RegCloseKey( key ); key = 0;
    00380   }
    00381   RegCloseKey( keySub ); keySub = 0;
    00382
    00383   //release resources
    00384 fail:
    00385   if (key)    RegCloseKey(key);
    00386   if (keySub) RegCloseKey(keySub);
    00387   if (keyVS)  RegCloseKey(keyVS);
    00388   if (FAILED(hr)) return hr;
    00389
    00390   return S_OK;
    00391 }
    00392
    00393 static HRESULT RegisterServer( in bool registerIt)
    00394 {
    00395   USECONV;
    00396   HRESULT hr = S_OK;
    00397
    00398   HKEY    keyCLSID  = 0;
    00399   HKEY    keyClass  = 0;
    00400   HKEY    keyInProc = 0;
    00401
    00402   //get clsid as string
    00403   OleChar oleCLSID[128];
    00404   if (StringFromGUID2(g_languageCLSID, oleCLSID, 127) == 0)
    00405   { hr = E_FAIL; goto fail; }
    00406
    00407   //get dll path
    00408   Char dllPath[MAX_PATH+1];
    00409   DWORD dwLen = ::GetModuleFileName(g_instance, dllPath, MAX_PATH);
    00410   if (dwLen == 0)
    00411   {
    00412     hr = HRESULT_FROM_WIN32(::GetLastError());
    00413     goto fail;
    00414   }
    00415   if (dwLen == MAX_PATH)
    00416   {
    00417     hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
    00418     goto fail;
    00419   }
    00420
    00421   //open CLSID key
    00422   Char szRegistrationRoot[_MAX_PATH + 1];
    00423   hr = GetRegistrationRoot(szRegistrationRoot, _MAX_PATH);
    00424   if (FAILED(hr)) goto fail;
    00425
    00426   Char szClsidRoot[_MAX_PATH + 11];
    00427   strCopy(szClsidRoot, szRegistrationRoot, _MAX_PATH);
    00428   strCat(szClsidRoot, STR("\\CLSID"), _MAX_PATH + 10);
    00429
    00430   hr = RegOpenKey( HKEY_LOCAL_MACHINE, szClsidRoot, &keyCLSID );
    00431   if (FAILED(hr)) goto fail;
    00432
    00433   if (!registerIt)
    00434   {
    00435     //delete it
    00436     hr = RegDeleteRecursive( keyCLSID, Ole2CStr(oleCLSID) );
    00437     if (FAILED(hr)) goto fail;
    00438   }
    00439   else
    00440   {
    00441     //create it
    00442     hr = RegCreateKey( keyCLSID, Ole2CStr(oleCLSID), &keyClass );
    00443     if (FAILED(hr)) goto fail;
    00444
    00445     RegCreateValue( keyClass, NULL, Ansi2CStr(g_languageName));
    00446
    00447     RegCreateValue( keyClass, STR("InprocServer32"), dllPath );
    00448   }
    00449
    00450
    00451 fail:
    00452   if (keyInProc) RegCloseKey(keyInProc);
    00453   if (keyClass)  RegCloseKey(keyClass);
    00454   if (keyCLSID)  RegCloseKey(keyCLSID);
    00455
    00456   //register language service with VS.NET
    00457   if (SUCCEEDED(hr) || (registerIt == false))
    00458   {
    00459      hr = RegisterService(szRegistrationRoot, babelPackageCLSID7, registerIt );
    00460   }
    00461
    00462   if (FAILED(hr)) return hr;
    00463
    00464   return S_OK;
    00465 }
    00466
    00467
    00468 /*---------------------------------------------------------
    00469   Registry helpers
    00470 -----------------------------------------------------------*/
    00471 static HRESULT RegCreateValue( in HKEY key, in CStr name, in CStr value )
    00472 {
    00473   return RegSetValueEx( key, name, 0, REG_SZ,
    00474                         reinterpret_cast<const BYTE*>(value),
    00475                         sizeof(Char) * (strLen(value)+1) );
    00476 }
    00477
    00478 static HRESULT RegCreateDwordValue( in HKEY key, in CStr name, in DWORD value )
    00479 {
    00480   return RegSetValueEx( key, name, 0, REG_DWORD,
    00481                         reinterpret_cast<const BYTE*>(&value), sizeof(value) );
    00482 }
    00483
    00484 static HRESULT RegDeleteRecursive( in HKEY keyRoot, in CStr path )
    00485 {
    00486   HRESULT hr;
    00487   HKEY    key       = 0;
    00488   ULONG   subKeys   = 0;
    00489   ULONG   maxKeyLen = 0;
    00490
    00491   ULONG   currentKey= 0;
    00492   Str     keyName   = NULL;
    00493
    00494   hr = WINERROR(RegOpenKeyEx( keyRoot, path, 0, KEY_ALL_ACCESS, &key ));
    00495   if (FAILED(hr)) goto fail;
    00496
    00497   hr = WINERROR(RegQueryInfoKey( key, NULL, NULL, NULL,
    00498                                 &subKeys, &maxKeyLen,
    00499                                 NULL, NULL, NULL, NULL, NULL, NULL ));
    00500   if (FAILED(hr))   goto fail;
    00501   if (subKeys == 0) goto fail;
    00502
    00503   keyName = (Str) malloc(sizeof(Char) * (maxKeyLen+1) );
    00504   if (keyName == NULL)
    00505   {
    00506     hr = E_OUTOFMEMORY;
    00507     goto fail;
    00508   }
    00509
    00510   for (currentKey = 0; currentKey < subKeys; currentKey++)
    00511   {
    00512     ULONG keyLen;
    00513
    00514     keyLen = maxKeyLen+1;
    00515     hr = WINERROR( RegEnumKeyEx( key, currentKey, keyName, &keyLen, NULL, NULL, NULL, NULL ));
    00516     if (SUCCEEDED(hr))
    00517     {
    00518       RegDeleteRecursive(key,keyName);
    00519     }
    00520     else ASSERT(0);
    00521   }
    00522
    00523 fail:
    00524   hr = WINERROR(RegDeleteKey( keyRoot, path ));
    00525   if (key) RegCloseKey(key);
    00526   if (keyName) free(keyName);
    00527   return hr;
    00528 }
    00529
    00530
    00531 static HRESULT GetRegistrationRoot(Str pszRegistrationRoot, ULONG cchBuffer /* = _MAX_PATH*/)
    00532 {
    00533   DWORD cchFreeBuffer = cchBuffer - 1;
    00534   strCopy(pszRegistrationRoot, regPathVS7_NoVersion, -1);
    00535
    00536   // this is Environment SDK specific
    00537   // we check for  EnvSdk_RegKey environment variable to
    00538   // determine where to register
    00539   DWORD cchDefRegRoot = lstrlen(regPathVS7_NoVersion);
    00540   cchFreeBuffer = cchFreeBuffer - cchDefRegRoot;
    00541   DWORD cchEnvVarRead = GetEnvironmentVariable(
    00542     /* LPCTSTR */ TEXT("EnvSdk_RegKey"),               // environment variable name
    00543     /* LPTSTR  */ &pszRegistrationRoot[cchDefRegRoot],// buffer for variable value
    00544     /* DWORD   */ cchFreeBuffer);// size of buffer
    00545   cchEnvVarRead = 0; //use always 7.1
    00546   if (cchEnvVarRead >= cchFreeBuffer)
    00547     return E_UNEXPECTED;
    00548   // If the environment variable does not exist then we must use
    00549   // regPathVS7 which has the version number.
    00550   if (0 == cchEnvVarRead)
    00551     strCopy(pszRegistrationRoot, regPathVS7, -1);
    00552
    00553   return S_OK;
    00554 }