Click here to Skip to main content
15,894,825 members
Articles / Web Development / HTML

Cabinet File (*.CAB) Compression and Extraction

Rate me:
Please Sign up or sign in to vote.
4.93/5 (217 votes)
23 Mar 2012CPOL38 min read 3.2M   26.5K   573  
How to implement creation and extraction of Microsoft CAB files
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Author: Luuk Weltevreden
// Date: 23-07-2004
//
// Modified a lot by Elm� (http://kickme.to/elmue)
// Date: 01-08-2006
//
// Filename: ExtractResourceT.hpp
//
// - CExtractResourceT<T>
// - CExtractResource
//
// Purpose: This template extracts files from cabinet files stored as a Win32 Resource.
//

#pragma once

#include "ExtractMemoryT.hpp"

#pragma warning(disable: 4996)

template <class T> class CExtractResourceT : public CExtractMemoryT<T>
{
public:
	// Copy the content of the cabinet in the resources onto disk
	// You can set s8_Module = 0 if the cabinet is in the file which created the process
	// Otherwise s8_Module must be the filename (without path) of the DLL which contains the CAB resource
	// To test this function with the file Test.cab included in this project
	// set s8_Module = "Cablib.dll" and uResourceID = ID_CAB_TEST and s8_ResourceTypeName = "CABFILE"
	// because the file CabLib.rc contains:
	// ID_CAB_TEST        CABFILE         "Res\\Test.cab"
	BOOL ExtractResource(char* s8_Module, UINT uResourceID, UINT uResourceTypeID, LPCSTR szTarget, void * pParam = NULL)
		{ return ExtractResource(s8_Module, MAKEINTRESOURCEA(uResourceID), MAKEINTRESOURCEA(uResourceTypeID), szTarget, pParam); }

	BOOL ExtractResource(char* s8_Module, UINT uResourceID, LPCSTR s8_ResourceTypeName, LPCSTR szTarget, void * pParam = NULL)
		{ return ExtractResource(s8_Module, MAKEINTRESOURCEA(uResourceID), s8_ResourceTypeName, szTarget, pParam); }

	BOOL ExtractResource(char* s8_Module, LPCSTR s8_ResourceName, UINT uResourceTypeID, LPCSTR szTarget, void * pParam = NULL)
		{ return ExtractResource(s8_Module, s8_ResourceName, MAKEINTRESOURCEA(uResourceTypeID), szTarget, pParam); }

	BOOL ExtractResource(char* s8_Module, LPCSTR s8_ResourceName, LPCSTR s8_ResourceTypeName, LPCSTR szTarget, void * pParam = NULL)
	{
		GetModule() = GetModuleHandleA(s8_Module);

		char s8_Cabinet[2000];
		BuildFileName(s8_ResourceName, s8_ResourceTypeName, s8_Cabinet);

		// Pass it on to the base class
		return ExtractFile(s8_Cabinet, szTarget, pParam);
	}


	// Check if the cabinet in the resources is valid
	// You can set s8_Module = 0 if the cabinet is in the file which created the process
	// Otherwise s8_Module must be the filename (without path) of the DLL which contains the CAB resource
	// To test this function with the file Test.cab included in this project
	// set s8_Module = "Cablib.dll" and uResourceID = ID_CAB_TEST and s8_ResourceTypeName = "CABFILE"
	// because the file CabLib.rc contains:
	// ID_CAB_TEST        CABFILE         "Res\\Test.cab"
	BOOL IsResourceCabinet(char* s8_Module, UINT uResourceID, UINT uResourceType, PFDICABINETINFO pfdici = NULL)
		{ return IsResourceCabinet(s8_Module, MAKEINTRESOURCEA(uResourceID), MAKEINTRESOURCEA(uResourceTypeID), pfdici); }

	BOOL IsResourceCabinet(char* s8_Module, UINT uResourceID, LPCSTR s8_ResourceTypeName, PFDICABINETINFO pfdici = NULL)
		{ return IsResourceCabinet(s8_Module, MAKEINTRESOURCEA(uResourceID), s8_ResourceTypeName, pfdici); }

	BOOL IsResourceCabinet(char* s8_Module, LPCSTR s8_ResourceName, UINT uResourceTypeID, PFDICABINETINFO pfdici = NULL)
		{ return IsResourceCabinet(s8_Module, s8_ResourceName, MAKEINTRESOURCEA(uResourceTypeID), pfdici); }

	BOOL IsResourceCabinet(char* s8_Module, LPCSTR s8_ResourceName, LPCSTR s8_ResourceTypeName, PFDICABINETINFO pfdici = NULL)
	{
		GetModule() = GetModuleHandleA(s8_Module);

		char s8_Cabinet[2000];
		BuildFileName(s8_ResourceName, s8_ResourceTypeName, s8_Cabinet);

		// Pass it on to the base class
		return IsCabinet(s8_Cabinet, pfdici);
	}


protected:
	// Create a file name for the CAB file which contains the resource name and resource type 
	// in the form "RESOURCETYPE\\RESOURCENAME"
	void BuildFileName(LPCSTR s8_ResourceName, LPCSTR s8_ResourceTypeName, LPSTR lpszBuffer)
	{
		LPCSTR pszResName = s8_ResourceName;
		LPCSTR pszResType = s8_ResourceTypeName;
		char szTemp1[12]  = {0};
		char szTemp2[12]  = {0};

		if (IS_INTRESOURCE(s8_ResourceName))
		{
			itoa((int)(PtrToInt(s8_ResourceName)), szTemp1, 10);
			memmove(szTemp1 + 1, szTemp1, strlen(szTemp1));
			szTemp1[0] = '#';
			pszResName = szTemp1;
		}

		if (IS_INTRESOURCE(s8_ResourceTypeName))
		{
			itoa((int)(PtrToInt(s8_ResourceTypeName)), szTemp2, 10);
			memmove(szTemp2 + 1, szTemp2, strlen(szTemp2));
			szTemp2[0] = '#';
			pszResType = szTemp2;
		}

		sprintf(lpszBuffer, "%s\\%s", pszResType, pszResName);
	}

	static HMODULE& GetModule()
	{
		static HMODULE Mod = 0;
		return Mod;
	}

	// This function opens the specified resource from the current module
	// and returns a pointer to the resource memory block
	static kMemory* OpenMem(const char* s8_File, int, int)
	{
		char s8_ResourceName[2000];
		char s8_ResourceType[2000];

		// Split the filename
		char* s8_Slash = (char*) strrchr(s8_File, '\\');
		if  (!s8_Slash)
			return (kMemory*) -1;

		// Copy the resource name and type
		strcpy(s8_ResourceName, s8_Slash+1);
		strcpy(s8_ResourceType, s8_File);
		s8_ResourceType[(int)(s8_Slash-s8_File)] = 0;

		// Load the resource
		HRSRC hResource = FindResourceA(GetModule(), s8_ResourceName, s8_ResourceType);
		HGLOBAL hGlobal   = LoadResource (GetModule(), hResource);
		void* p_Addr      = LockResource (hGlobal);
		if  (!p_Addr)
			return (kMemory*) -1;

		UINT Size = (UINT)SizeofResource(GetModule(), hResource);

		return new kMemory(p_Addr, 0, Size);
	}


	// Copies a part of the CAB file's memory from the resource to the given buffer
	static int ReadMem(kMemory* pk_Mem, void* buffer, UINT count)
	{
		// Reached the end of the resource
		if (pk_Mem->s32_Pos >= pk_Mem->s32_Size)
			return 0;

		// Do not try to read behind the end of the resource
		count = min((long)count, pk_Mem->s32_Size - pk_Mem->s32_Pos);

		// Copy the memory in the buffer
		memcpy(buffer, (char*)(pk_Mem->p_Addr) + pk_Mem->s32_Pos, count);

		// Return the amount of bytes copied
		return count;
	}

	// Declare this class as a friend so it can access the protected members.
	friend class CExtractMemoryT<T>;
};

class CExtractResource : public CExtractResourceT<CExtractResource> { };

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) ElmüSoft
Chile Chile
Software Engineer since 40 years.

Comments and Discussions