00001
00002
00003
00004
00005
00006
00007
00008 #include <malloc.h>
00009 #include "common.h"
00010 #include "dllmain.h"
00011 #include "languagedef.h"
00012
00013
00014
00015
00016 ITypeInfo* g_typeInfoBabelService = NULL;
00017
00018 static HINSTANCE g_instance = NULL;
00019 static ULONG g_dllRefCount = 0;
00020
00021
00022 static const CLSID babelPackageCLSID7 =
00023 { 0x221f0eb7, 0x30f7, 0x45ff, { 0xae, 0x73, 0x59, 0x68, 0xb1, 0x67, 0xcf, 0x9 } };
00024
00025
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
00036
00037 static HRESULT RegisterServer( in bool registerIt);
00038 static HRESULT GetRegistrationRoot(Str pszRegistrationRoot, ULONG cchBuffer = _MAX_PATH);
00039 static HRESULT LoadTypeInfo();
00040
00041
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
00049
00050 class BabelServiceFactory : IClassFactory
00051 {
00052 private:
00053 ULONG m_refCount;
00054
00055 public:
00056 BabelServiceFactory();
00057 ~BabelServiceFactory();
00058
00059
00060 STDMETHODIMP QueryInterface( REFIID iid, LPVOID* obj );
00061 STDMETHODIMP_(ULONG) AddRef();
00062 STDMETHODIMP_(ULONG) Release();
00063
00064
00065 STDMETHODIMP CreateInstance( IUnknown* outer, REFIID iid, LPVOID* obj );
00066 STDMETHODIMP LockServer( BOOL lockIt );
00067 };
00068
00069
00070
00071
00072
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
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
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
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
00218
00219 static HRESULT LoadTypeInfo()
00220 {
00221 HRESULT hr;
00222
00223
00224 if (g_typeInfoBabelService) return S_OK;
00225
00226
00227 ITypeLib* lib;
00228 hr = LoadRegTypeLib( LIBID_BabelServiceLib, 1, 0, LANG_NEUTRAL, &lib );
00229 if (FAILED(hr)) return hr;
00230
00231
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
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
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
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
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
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
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
00340 hr = RegCreateDwordValue( key, OLE("ThreadModel"), 1 );
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
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
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
00403 OleChar oleCLSID[128];
00404 if (StringFromGUID2(g_languageCLSID, oleCLSID, 127) == 0)
00405 { hr = E_FAIL; goto fail; }
00406
00407
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
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
00436 hr = RegDeleteRecursive( keyCLSID, Ole2CStr(oleCLSID) );
00437 if (FAILED(hr)) goto fail;
00438 }
00439 else
00440 {
00441
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
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
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 )
00532 {
00533 DWORD cchFreeBuffer = cchBuffer - 1;
00534 strCopy(pszRegistrationRoot, regPathVS7_NoVersion, -1);
00535
00536
00537
00538
00539 DWORD cchDefRegRoot = lstrlen(regPathVS7_NoVersion);
00540 cchFreeBuffer = cchFreeBuffer - cchDefRegRoot;
00541 DWORD cchEnvVarRead = GetEnvironmentVariable(
00542 TEXT("EnvSdk_RegKey"),
00543 &pszRegistrationRoot[cchDefRegRoot],
00544 cchFreeBuffer);
00545 cchEnvVarRead = 0;
00546 if (cchEnvVarRead >= cchFreeBuffer)
00547 return E_UNEXPECTED;
00548
00549
00550 if (0 == cchEnvVarRead)
00551 strCopy(pszRegistrationRoot, regPathVS7, -1);
00552
00553 return S_OK;
00554 }