//***************************************************************************** // This is used in conjunction with GetClassFromCORPath. See it for details // of the algorithm. //***************************************************************************** HRESULT CORPATHService::GetClassFromDir( __in __in_z LPWSTR wzClassname, // Fully qualified class name. __in SString& directory, // Directory to try. at most appended with a '\\' mdTypeRef tr, // TypeRef to resolve. IMetaModelCommon *pCommon, // Scope in which the TypeRef is defined. REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) // [OUT] typedef { WCHAR *temp; // Used as a parsing temp. int iTmp; bool bContinue; // Flag to check if the for loop should end. LPWSTR wzSaveClassname = NULL; // Saved offset into the class name string. // Process the class name appending each segment of the name to the // directory until we find a DLL. PathString dir; if (!directory.EndsWith(DIRECTORY_SEPARATOR_CHAR_W)) { directory.Append(DIRECTORY_SEPARATOR_CHAR_W); } for(;;) { bContinue = false; dir.Set(directory); if ((temp = wcschr(wzClassname, NAMESPACE_SEPARATOR_WCHAR)) != NULL) { *temp = W('\0'); //terminate with null so that it can be appended dir.Append(wzClassname); *temp = NAMESPACE_SEPARATOR_WCHAR; //recover the '.' wzClassname = temp+1; // Check if a directory by this name exists. DWORD iAttrs = WszGetFileAttributes(dir); if (iAttrs != 0xffffffff && (iAttrs & FILE_ATTRIBUTE_DIRECTORY)) { // Next element in the class spec. bContinue = true; wzSaveClassname = wzClassname; } } else { dir.Append(wzClassname); // Advance past the class name. iTmp = (int)wcslen(wzClassname); wzClassname += iTmp; } // Try to load the image. dir.Append(W(".dll")); // OpenScope given the dll name and make sure that the class is defined in the module. if ( SUCCEEDED( CORPATHService::FindTypeDef(dir, tr, pCommon, riid, ppIScope, ptd) ) ) { return (S_OK); } // If we didn't find the dll, try some more. while (*wzClassname != W('\0')) { // Find the length of the next class name element. if ((temp = wcschr(wzClassname, NAMESPACE_SEPARATOR_WCHAR)) == NULL) { temp = wzClassname + wcslen(wzClassname); } // Tack on ".element.dll" SString::Iterator iter = dir.End(); BOOL findperiod = dir.FindBack(iter, NAMESPACE_SEPARATOR_WCHAR); _ASSERTE(findperiod); iter++; dir.Truncate(iter); WCHAR save = *temp; *temp = W('\0'); dir.Append(wzClassname); //element *temp = save; // Try to load the image. dir.Append(W(".dll")); // OpenScope given the dll name and make sure that the class is defined in the module. if ( SUCCEEDED( CORPATHService::FindTypeDef(dir, tr, pCommon, riid, ppIScope, ptd) ) ) { return (S_OK); } // Advance to the next class name element. wzClassname = temp; if (*wzClassname != '\0') ++wzClassname; } if (bContinue) { wzClassname = wzSaveClassname; } else { break; } } return S_FALSE; } // CORPATHService::GetClassFromDir
//***************************************************************************** // 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