// Fusion uses a context class to drive resolution of assemblies. // Each application has properties that can be pushed into the // fusion context (see fusionp.h). The public api is part of // application domains. HRESULT FusionBind::SetupFusionContext(LPCWSTR szAppBase, LPCWSTR szPrivateBin, IApplicationContext** ppFusionContext) { TIMELINE_START_SAFE(FUSIONBIND, ("SetupFusionContext %S", szAppBase)); HRESULT hr; _ASSERTE(ppFusionContext); LPCWSTR pBase; // if the appbase is null then use the current directory if (szAppBase == NULL) { pBase = (LPCWSTR) _alloca(_MAX_PATH * sizeof(WCHAR)); WszGetCurrentDirectory(_MAX_PATH, (LPWSTR) pBase); } else pBase = szAppBase; if (SUCCEEDED(hr = CreateFusionContext(pBase, ppFusionContext))) { (*ppFusionContext)->Set(ACTAG_APP_BASE_URL, (void*) pBase, (DWORD)(wcslen(pBase) + 1) * sizeof(WCHAR), 0); if (szPrivateBin) (*ppFusionContext)->Set(ACTAG_APP_PRIVATE_BINPATH, (void*) szPrivateBin, (DWORD)(wcslen(szPrivateBin) + 1) * sizeof(WCHAR), 0); else AddEnvironmentProperty(APPENV_RELATIVEPATH, ACTAG_APP_PRIVATE_BINPATH, *ppFusionContext); } TIMELINE_END(FUSIONBIND, ("SetupFusionContext %S", szAppBase)); return hr; }
//----------------------------------------------------------------------------- // Get the current directory. // On success, returns true and sets 'Value' to unicode version of cur dir. // Throws on all failures. This should mainly be oom. //----------------------------------------------------------------------------- void ClrGetCurrentDirectory(SString & value) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; // Get size needed DWORD len = WszGetCurrentDirectory(value); // An actual API failure in GetCurrentDirectory failure should be very rare, so we'll throw on those. if (len == 0) { value.CloseBuffer(0); ThrowLastError(); } value.CloseBuffer(); } // Nothrowing wrapper. bool ClrGetCurrentDirectoryNoThrow(SString & value) {
//***************************************************************************** // This is a routine to try to find a class implementation given its fully // qualified name by using the CORPATH environment variable. CORPATH is a list // of directories (like PATH). Before checking CORPATH, this checks the current // directory, then the directory that the exe lives in. The search is // performed by parsing off one element at a time from the class name, // appending it to the directory and looking for a subdirectory or image with // that name. If the subdirectory exists, it drills down into that subdirectory // and tries the next element of the class name. When it finally bottoms out // but can't find the image it takes the rest of the fully qualified class name // and appends them with intervening '.'s trying to find a matching DLL. // Example: // // CORPATH=c:\bin;c:\prog // classname = namespace.class // // checks the following things in order: // c:\bin\namespace, (if <-exists) c:\bin\namespace\class.dll, // c:\bin\namespace.dll, c:\bin\namespace.class.dll // c:\prog\namespace, (if <-exists) c:\prog\namespace\class.dll, // c:\prog\namespace.dll, c:\prog\namespace.class.dll //***************************************************************************** HRESULT CORPATHService::GetClassFromCORPath( __in __in_z LPWSTR wzClassname, // [IN] fully qualified class name mdTypeRef tr, // [IN] TypeRef to be resolved. IMetaModelCommon *pCommon, // [IN] Scope in which the TypeRef is defined. REFIID riid, // [IN] Interface type to be returned. IUnknown **ppIScope, // [OUT] Scope in which the TypeRef resolves. mdTypeDef *ptd) // [OUT] typedef corresponding the typeref { WCHAR rcCorPath[1024] = {W('\0')}; // The CORPATH environment variable. LPWSTR szCorPath = rcCorPath; // Used to parse CORPATH. int iLen; // Length of the directory. WCHAR rcCorDir[_MAX_PATH]; // Buffer for the directory. WCHAR *temp; // Used as a parsing temp. WCHAR *szSemiCol; // Get the CORPATH environment variable. if (WszGetEnvironmentVariable(W("CORPATH"), rcCorPath, sizeof(rcCorPath) / sizeof(WCHAR))) { // Force nul termination. rcCorPath[lengthof(rcCorPath)-1] = 0; // Try each directory in the path. for(;*szCorPath != W('\0');) { // Get the next directory off the path. if ((szSemiCol = wcschr(szCorPath, W(';')))) { temp = szCorPath; *szSemiCol = W('\0'); szCorPath = szSemiCol + 1; } else { temp = szCorPath; szCorPath += wcslen(temp); } if ((iLen = (int)wcslen(temp)) >= _MAX_PATH) continue; wcscpy_s(rcCorDir, COUNTOF(rcCorDir), temp); // Check if we can find the class in the directory. if (CORPATHService::GetClassFromDir(wzClassname, rcCorDir, iLen, tr, pCommon, riid, ppIScope, ptd) == S_OK) return S_OK; } } //<TODO>These should go before the path search, but it will cause test // some headaches right now, so we'll give them a little time to transition.</TODO> // Try the current directory first. if ((iLen = WszGetCurrentDirectory(_MAX_PATH, rcCorDir)) > 0 && CORPATHService::GetClassFromDir(wzClassname, rcCorDir, iLen, tr, pCommon, riid, ppIScope, ptd) == S_OK) { return S_OK; } // Try the app directory next. if ((iLen = WszGetModuleFileName(NULL, rcCorDir, _MAX_PATH)) > 0) { // Back up to the last path separator. while (--iLen >= 0 && rcCorDir[iLen] != W('\\') && rcCorDir[iLen] != W('/')) { } if (iLen > 0 && CORPATHService::GetClassFromDir( wzClassname, rcCorDir, iLen, tr, pCommon, riid, ppIScope, ptd) == S_OK) { return (S_OK); } } // Couldn't find the class. return S_FALSE; } // CORPATHService::GetClassFromCORPath
//***************************************************************************** // This is a routine to try to find a class implementation given its fully // qualified name by using the CORPATH environment variable. CORPATH is a list // of directories (like PATH). Before checking CORPATH, this checks the current // directory, then the directory that the exe lives in. The search is // performed by parsing off one element at a time from the class name, // appending it to the directory and looking for a subdirectory or image with // that name. If the subdirectory exists, it drills down into that subdirectory // and tries the next element of the class name. When it finally bottoms out // but can't find the image it takes the rest of the fully qualified class name // and appends them with intervening '.'s trying to find a matching DLL. // Example: // // CORPATH=c:\bin;c:\prog // classname = namespace.class // // checks the following things in order: // c:\bin\namespace, (if <-exists) c:\bin\namespace\class.dll, // c:\bin\namespace.dll, c:\bin\namespace.class.dll // c:\prog\namespace, (if <-exists) c:\prog\namespace\class.dll, // c:\prog\namespace.dll, c:\prog\namespace.class.dll //***************************************************************************** HRESULT CORPATHService::GetClassFromCORPath( __in __in_z LPWSTR wzClassname, // [IN] fully qualified class name mdTypeRef tr, // [IN] TypeRef to be resolved. IMetaModelCommon *pCommon, // [IN] Scope in which the TypeRef is defined. REFIID riid, // [IN] Interface type to be returned. IUnknown **ppIScope, // [OUT] Scope in which the TypeRef resolves. mdTypeDef *ptd) // [OUT] typedef corresponding the typeref { PathString rcCorPath; // The CORPATH environment variable. LPWSTR szCorPath; // Used to parse CORPATH. int iLen; // Length of the directory. PathString rcCorDir; // Buffer for the directory. WCHAR *temp; // Used as a parsing temp. WCHAR *szSemiCol; // Get the CORPATH environment variable. if (WszGetEnvironmentVariable(W("CORPATH"), rcCorPath)) { NewArrayHolder<WCHAR> szCorPathHolder = rcCorPath.GetCopyOfUnicodeString(); szCorPath = szCorPathHolder.GetValue(); // Try each directory in the path. for(;*szCorPath != W('\0');) { // Get the next directory off the path. if ((szSemiCol = wcschr(szCorPath, W(';')))) { temp = szCorPath; *szSemiCol = W('\0'); szCorPath = szSemiCol + 1; } else { temp = szCorPath; szCorPath += wcslen(temp); } rcCorDir.Set(temp); // Check if we can find the class in the directory. if (CORPATHService::GetClassFromDir(wzClassname, rcCorDir, tr, pCommon, riid, ppIScope, ptd) == S_OK) return S_OK; } } //<TODO>These should go before the path search, but it will cause test // some headaches right now, so we'll give them a little time to transition.</TODO> // Try the current directory first. if ((iLen = WszGetCurrentDirectory( rcCorDir)) > 0 && CORPATHService::GetClassFromDir(wzClassname, rcCorDir, tr, pCommon, riid, ppIScope, ptd) == S_OK) { return S_OK; } // Try the app directory next. if ((iLen = WszGetModuleFileName(NULL, rcCorDir)) > 0) { if(SUCCEEDED(CopySystemDirectory(rcCorDir, rcCorDir)) && CORPATHService::GetClassFromDir( wzClassname, rcCorDir, tr, pCommon, riid, ppIScope, ptd) == S_OK) { return (S_OK); } } // Couldn't find the class. return S_FALSE; } // CORPATHService::GetClassFromCORPath