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 }

Generated on Mon Mar 20 22:00:10 2006 for GT2005 by doxygen 1.3.6