1 // LoadCodecs.h 2 3 #ifndef __LOAD_CODECS_H 4 #define __LOAD_CODECS_H 5 6 /* 7 Client application uses LoadCodecs.* to load plugins to 8 CCodecs object, that contains 3 lists of plugins: 9 1) Formats - internal and external archive handlers 10 2) Codecs - external codecs 11 3) Hashers - external hashers 12 13 EXTERNAL_CODECS 14 --------------- 15 16 if EXTERNAL_CODECS is defined, then the code tries to load external 17 plugins from DLL files (shared libraries). 18 19 There are two types of executables in 7-Zip: 20 21 1) Executable that uses external plugins must be compiled 22 with EXTERNAL_CODECS defined: 23 - 7z.exe, 7zG.exe, 7zFM.exe 24 25 Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h 26 that code is used in plugin module (7z.dll). 27 28 2) Standalone modules are compiled without EXTERNAL_CODECS: 29 - SFX modules: 7z.sfx, 7zCon.sfx 30 - standalone versions of console 7-Zip: 7za.exe, 7zr.exe 31 32 if EXTERNAL_CODECS is defined, CCodecs class implements interfaces: 33 - ICompressCodecsInfo : for Codecs 34 - IHashers : for Hashers 35 36 The client application can send CCodecs object to each plugin module. 37 And plugin module can use ICompressCodecsInfo or IHashers interface to access 38 another plugins. 39 40 There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin 41 1) for old versions: 42 a) request ISetCompressCodecsInfo from created archive handler. 43 b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo) 44 2) for new versions: 45 a) request "SetCodecs" function from DLL file 46 b) call SetCodecs(compressCodecsInfo) function from DLL file 47 */ 48 49 #include "../../../Common/MyBuffer.h" 50 #include "../../../Common/MyCom.h" 51 #include "../../../Common/MyString.h" 52 #include "../../../Common/ComTry.h" 53 54 #ifdef EXTERNAL_CODECS 55 #include "../../../Windows/DLL.h" 56 #endif 57 58 #include "../../ICoder.h" 59 60 #include "../../Archive/IArchive.h" 61 62 63 #ifdef EXTERNAL_CODECS 64 65 struct CDllCodecInfo 66 { 67 unsigned LibIndex; 68 UInt32 CodecIndex; 69 bool EncoderIsAssigned; 70 bool DecoderIsAssigned; 71 CLSID Encoder; 72 CLSID Decoder; 73 }; 74 75 struct CDllHasherInfo 76 { 77 unsigned LibIndex; 78 UInt32 HasherIndex; 79 }; 80 81 #endif 82 83 struct CArcExtInfo 84 { 85 UString Ext; 86 UString AddExt; 87 88 CArcExtInfo() {} 89 CArcExtInfo(const UString &ext): Ext(ext) {} 90 CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} 91 }; 92 93 94 struct CArcInfoEx 95 { 96 UInt32 Flags; 97 98 Func_CreateInArchive CreateInArchive; 99 Func_IsArc IsArcFunc; 100 101 UString Name; 102 CObjectVector<CArcExtInfo> Exts; 103 104 #ifndef _SFX 105 Func_CreateOutArchive CreateOutArchive; 106 bool UpdateEnabled; 107 bool NewInterface; 108 // UInt32 Version; 109 UInt32 SignatureOffset; 110 CObjectVector<CByteBuffer> Signatures; 111 #ifdef NEW_FOLDER_INTERFACE 112 UStringVector AssociateExts; 113 #endif 114 #endif 115 116 #ifdef EXTERNAL_CODECS 117 int LibIndex; 118 UInt32 FormatIndex; 119 CLSID ClassID; 120 #endif 121 122 bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } 123 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } 124 125 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } 126 bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } 127 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } 128 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } 129 130 bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } 131 bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } 132 bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } 133 bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } 134 bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } 135 136 UString GetMainExt() const 137 { 138 if (Exts.IsEmpty()) 139 return UString(); 140 return Exts[0].Ext; 141 } 142 int FindExtension(const UString &ext) const; 143 144 /* 145 UString GetAllExtensions() const 146 { 147 UString s; 148 for (int i = 0; i < Exts.Size(); i++) 149 { 150 if (i > 0) 151 s += ' '; 152 s += Exts[i].Ext; 153 } 154 return s; 155 } 156 */ 157 158 void AddExts(const UString &ext, const UString &addExt); 159 160 bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); } 161 // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); } 162 163 CArcInfoEx(): 164 Flags(0), 165 CreateInArchive(NULL), 166 IsArcFunc(NULL) 167 #ifndef _SFX 168 , CreateOutArchive(NULL) 169 , UpdateEnabled(false) 170 , NewInterface(false) 171 // , Version(0) 172 , SignatureOffset(0) 173 #endif 174 #ifdef EXTERNAL_CODECS 175 , LibIndex(-1) 176 #endif 177 {} 178 }; 179 180 #ifdef NEW_FOLDER_INTERFACE 181 182 struct CCodecIcons 183 { 184 struct CIconPair 185 { 186 UString Ext; 187 int IconIndex; 188 }; 189 CObjectVector<CIconPair> IconPairs; 190 191 void LoadIcons(HMODULE m); 192 bool FindIconIndex(const UString &ext, int &iconIndex) const; 193 }; 194 195 #endif 196 197 #ifdef EXTERNAL_CODECS 198 199 struct CCodecLib 200 #ifdef NEW_FOLDER_INTERFACE 201 : public CCodecIcons 202 #endif 203 { 204 NWindows::NDLL::CLibrary Lib; 205 FString Path; 206 207 Func_CreateObject CreateObject; 208 Func_GetMethodProperty GetMethodProperty; 209 Func_CreateDecoder CreateDecoder; 210 Func_CreateEncoder CreateEncoder; 211 Func_SetCodecs SetCodecs; 212 213 CMyComPtr<IHashers> ComHashers; 214 215 #ifdef NEW_FOLDER_INTERFACE 216 void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } 217 #endif 218 219 CCodecLib(): 220 CreateObject(NULL), 221 GetMethodProperty(NULL), 222 CreateDecoder(NULL), 223 CreateEncoder(NULL), 224 SetCodecs(NULL) 225 {} 226 }; 227 228 #endif 229 230 231 class CCodecs: 232 #ifdef EXTERNAL_CODECS 233 public ICompressCodecsInfo, 234 public IHashers, 235 #else 236 public IUnknown, 237 #endif 238 public CMyUnknownImp 239 { 240 CLASS_NO_COPY(CCodecs); 241 public: 242 #ifdef EXTERNAL_CODECS 243 244 CObjectVector<CCodecLib> Libs; 245 FString MainDll_ErrorPath; 246 247 void CloseLibs(); 248 249 class CReleaser 250 { 251 CLASS_NO_COPY(CReleaser); 252 253 /* CCodecsReleaser object releases CCodecs links. 254 1) CCodecs is COM object that is deleted when all links to that object will be released/ 255 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. 256 To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ 257 258 CCodecs *_codecs; 259 260 public: 261 CReleaser(): _codecs(NULL) {} 262 void Set(CCodecs *codecs) { _codecs = codecs; } 263 ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } 264 }; 265 266 bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo 267 268 HRESULT LoadCodecs(); 269 HRESULT LoadFormats(); 270 HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); 271 HRESULT LoadDllsFromFolder(const FString &folderPrefix); 272 273 HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const 274 { 275 return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); 276 } 277 278 #endif 279 280 #ifdef NEW_FOLDER_INTERFACE 281 CCodecIcons InternalIcons; 282 #endif 283 284 CObjectVector<CArcInfoEx> Formats; 285 286 #ifdef EXTERNAL_CODECS 287 CRecordVector<CDllCodecInfo> Codecs; 288 CRecordVector<CDllHasherInfo> Hashers; 289 #endif 290 291 bool CaseSensitiveChange; 292 bool CaseSensitive; 293 294 CCodecs(): 295 #ifdef EXTERNAL_CODECS 296 NeedSetLibCodecs(true), 297 #endif 298 CaseSensitiveChange(false), 299 CaseSensitive(false) 300 {} 301 302 ~CCodecs() 303 { 304 // OutputDebugStringA("~CCodecs"); 305 } 306 307 const wchar_t *GetFormatNamePtr(int formatIndex) const 308 { 309 return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name; 310 } 311 312 HRESULT Load(); 313 314 #ifndef _SFX 315 int FindFormatForArchiveName(const UString &arcPath) const; 316 int FindFormatForExtension(const UString &ext) const; 317 int FindFormatForArchiveType(const UString &arcType) const; 318 bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; 319 #endif 320 321 #ifdef EXTERNAL_CODECS 322 323 MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) 324 325 STDMETHOD(GetNumMethods)(UInt32 *numMethods); 326 STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); 327 STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder); 328 STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder); 329 330 STDMETHOD_(UInt32, GetNumHashers)(); 331 STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); 332 STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); 333 334 #else 335 336 MY_UNKNOWN_IMP 337 338 #endif // EXTERNAL_CODECS 339 340 341 #ifdef EXTERNAL_CODECS 342 343 int GetCodec_LibIndex(UInt32 index) const; 344 bool GetCodec_DecoderIsAssigned(UInt32 index) const; 345 bool GetCodec_EncoderIsAssigned(UInt32 index) const; 346 UInt32 GetCodec_NumStreams(UInt32 index); 347 HRESULT GetCodec_Id(UInt32 index, UInt64 &id); 348 AString GetCodec_Name(UInt32 index); 349 350 int GetHasherLibIndex(UInt32 index); 351 UInt64 GetHasherId(UInt32 index); 352 AString GetHasherName(UInt32 index); 353 UInt32 GetHasherDigestSize(UInt32 index); 354 355 #endif 356 357 HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const 358 { 359 const CArcInfoEx &ai = Formats[formatIndex]; 360 #ifdef EXTERNAL_CODECS 361 if (ai.LibIndex < 0) 362 #endif 363 { 364 COM_TRY_BEGIN 365 archive = ai.CreateInArchive(); 366 return S_OK; 367 COM_TRY_END 368 } 369 #ifdef EXTERNAL_CODECS 370 return CreateArchiveHandler(ai, false, (void **)&archive); 371 #endif 372 } 373 374 #ifndef _SFX 375 376 HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const 377 { 378 const CArcInfoEx &ai = Formats[formatIndex]; 379 #ifdef EXTERNAL_CODECS 380 if (ai.LibIndex < 0) 381 #endif 382 { 383 COM_TRY_BEGIN 384 archive = ai.CreateOutArchive(); 385 return S_OK; 386 COM_TRY_END 387 } 388 389 #ifdef EXTERNAL_CODECS 390 return CreateArchiveHandler(ai, true, (void **)&archive); 391 #endif 392 } 393 394 int FindOutFormatFromName(const UString &name) const 395 { 396 FOR_VECTOR (i, Formats) 397 { 398 const CArcInfoEx &arc = Formats[i]; 399 if (!arc.UpdateEnabled) 400 continue; 401 if (arc.Name.IsEqualTo_NoCase(name)) 402 return i; 403 } 404 return -1; 405 } 406 407 #endif // _SFX 408 }; 409 410 #ifdef EXTERNAL_CODECS 411 #define CREATE_CODECS_OBJECT \ 412 CCodecs *codecs = new CCodecs; \ 413 CExternalCodecs __externalCodecs; \ 414 __externalCodecs.GetCodecs = codecs; \ 415 __externalCodecs.GetHashers = codecs; \ 416 CCodecs::CReleaser codecsReleaser; \ 417 codecsReleaser.Set(codecs); 418 #else 419 #define CREATE_CODECS_OBJECT \ 420 CCodecs *codecs = new CCodecs; \ 421 CMyComPtr<IUnknown> __codecsRef = codecs; 422 #endif 423 424 #endif 425