michael@0: // 7zMethods.cpp michael@0: michael@0: #include "StdAfx.h" michael@0: michael@0: #include "7zMethods.h" michael@0: michael@0: #include "../../../Windows/FileFind.h" michael@0: #include "../../../Windows/DLL.h" michael@0: #include "../../../Windows/PropVariant.h" michael@0: #include "../../../Windows/Synchronization.h" michael@0: michael@0: #include "../../ICoder.h" michael@0: #include "../Common/CodecsPath.h" michael@0: michael@0: using namespace NWindows; michael@0: michael@0: namespace NArchive { michael@0: namespace N7z { michael@0: michael@0: static CObjectVector g_Methods; michael@0: static bool g_Loaded = false; michael@0: michael@0: typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); michael@0: michael@0: typedef UInt32 (WINAPI *GetMethodPropertyFunc)( michael@0: UInt32 index, PROPID propID, PROPVARIANT *value); michael@0: michael@0: static void Load(const CSysString &folderPrefix) michael@0: { michael@0: NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); michael@0: NFile::NFind::CFileInfo fileInfo; michael@0: while (enumerator.Next(fileInfo)) michael@0: { michael@0: if (fileInfo.IsDirectory()) michael@0: continue; michael@0: CSysString filePath = folderPrefix + fileInfo.Name; michael@0: { michael@0: NDLL::CLibrary library; michael@0: if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE)) michael@0: continue; michael@0: } michael@0: NDLL::CLibrary library; michael@0: if (!library.Load(filePath)) michael@0: continue; michael@0: GetMethodPropertyFunc getMethodProperty = (GetMethodPropertyFunc) michael@0: library.GetProcAddress("GetMethodProperty"); michael@0: if (getMethodProperty == NULL) michael@0: continue; michael@0: michael@0: UInt32 numMethods = 1; michael@0: GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc) michael@0: library.GetProcAddress("GetNumberOfMethods"); michael@0: if (getNumberOfMethodsFunc != NULL) michael@0: if (getNumberOfMethodsFunc(&numMethods) != S_OK) michael@0: continue; michael@0: michael@0: for(UInt32 i = 0; i < numMethods; i++) michael@0: { michael@0: CMethodInfo2 info; michael@0: info.FilePath = filePath; michael@0: michael@0: NWindows::NCOM::CPropVariant propVariant; michael@0: if (getMethodProperty(i, NMethodPropID::kID, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt != VT_BSTR) michael@0: continue; michael@0: info.MethodID.IDSize = SysStringByteLen(propVariant.bstrVal); michael@0: memmove(info.MethodID.ID, propVariant.bstrVal, info.MethodID.IDSize); michael@0: propVariant.Clear(); michael@0: michael@0: if (getMethodProperty(i, NMethodPropID::kName, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt == VT_EMPTY) michael@0: { michael@0: } michael@0: else if (propVariant.vt == VT_BSTR) michael@0: info.Name = propVariant.bstrVal; michael@0: else michael@0: continue; michael@0: propVariant.Clear(); michael@0: michael@0: if (getMethodProperty (i, NMethodPropID::kEncoder, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt == VT_EMPTY) michael@0: info.EncoderIsAssigned = false; michael@0: else if (propVariant.vt == VT_BSTR) michael@0: { michael@0: info.EncoderIsAssigned = true; michael@0: info.Encoder = *(const GUID *)propVariant.bstrVal; michael@0: } michael@0: else michael@0: continue; michael@0: propVariant.Clear(); michael@0: michael@0: if (getMethodProperty (i, NMethodPropID::kDecoder, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt == VT_EMPTY) michael@0: info.DecoderIsAssigned = false; michael@0: else if (propVariant.vt == VT_BSTR) michael@0: { michael@0: info.DecoderIsAssigned = true; michael@0: info.Decoder = *(const GUID *)propVariant.bstrVal; michael@0: } michael@0: else michael@0: continue; michael@0: propVariant.Clear(); michael@0: michael@0: if (getMethodProperty (i, NMethodPropID::kInStreams, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt == VT_EMPTY) michael@0: info.NumInStreams = 1; michael@0: else if (propVariant.vt == VT_UI4) michael@0: info.NumInStreams = propVariant.ulVal; michael@0: else michael@0: continue; michael@0: propVariant.Clear(); michael@0: michael@0: if (getMethodProperty (i, NMethodPropID::kOutStreams, &propVariant) != S_OK) michael@0: continue; michael@0: if (propVariant.vt == VT_EMPTY) michael@0: info.NumOutStreams = 1; michael@0: else if (propVariant.vt == VT_UI4) michael@0: info.NumOutStreams = propVariant.ulVal; michael@0: else michael@0: continue; michael@0: propVariant.Clear(); michael@0: michael@0: g_Methods.Add(info); michael@0: } michael@0: } michael@0: } michael@0: michael@0: static NSynchronization::CCriticalSection g_CriticalSection; michael@0: michael@0: void LoadMethodMap() michael@0: { michael@0: NSynchronization::CCriticalSectionLock lock(g_CriticalSection); michael@0: if (g_Loaded) michael@0: return; michael@0: g_Loaded = true; michael@0: Load(GetCodecsFolderPrefix()); michael@0: } michael@0: michael@0: bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo) michael@0: { michael@0: for(int i = 0; i < g_Methods.Size(); i++) michael@0: { michael@0: const CMethodInfo2 &method = g_Methods[i]; michael@0: if (method.MethodID == methodID) michael@0: { michael@0: methodInfo = (CMethodInfo)method; michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo) michael@0: { michael@0: for(int i = 0; i < g_Methods.Size(); i++) michael@0: { michael@0: const CMethodInfo2 &method = g_Methods[i]; michael@0: if (method.Name.CompareNoCase(name) == 0) michael@0: { michael@0: methodInfo = method; michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: }} michael@0: michael@0: