How to zip/unzip files

28 10 2013

If we search ‘How to zip/unzip files’ in any search engines, we will get lots of links to Open Source Softwares(OSS) to do it. But once you use OSS in your application, then definitely you should have to take care of OSS clearnce before you make Product release to the market. So how we can do it our own without any dependecy with OSS components?

Windows Shell library do it for free of cost.

Step 1 : Create an empty zip file

Step 2 : Add files to it using shell32 CopyHere method.


ZIP File

void CreateEmptyZipFile(CString strPath)
{
	BYTE startBuffer[] = {80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	FILE *f = _wfopen(strPath.GetBuffer(strPath.GetLength()), _T("wb"));
	strPath.ReleaseBuffer();
	fwrite(startBuffer,sizeof(startBuffer),1,f);
	fclose(f); 
}

void ZipFile(CString strSrc, CString strDest)
{
	//Create an empty zip file
	CreateEmptyZipFile(strDest);

	BSTR bstrSource = strSrc.AllocSysString();
	BSTR bstrDest = strDest.AllocSysString();

	HRESULT hResult = S_FALSE;
	IShellDispatch *pIShellDispatch = NULL;
	Folder *pToFolder = NULL;		
	VARIANT variantDir, variantFile, variantOpt;

	CoInitialize(NULL);

	hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, 
		IID_IShellDispatch, (void **)&pIShellDispatch);

	if (SUCCEEDED(hResult))
	{
		VariantInit(&variantDir);
		variantDir.vt = VT_BSTR;
		variantDir.bstrVal = bstrDest;
		hResult = pIShellDispatch->NameSpace(variantDir, &pToFolder);

		if (SUCCEEDED(hResult))
		{
			VariantInit(&variantFile);
			variantFile.vt = VT_BSTR;
			variantFile.bstrVal = bstrSource;

			VariantInit(&variantOpt);
			variantOpt.vt = VT_I4;
			variantOpt.lVal = FOF_NO_UI;

			hResult = pToFolder->CopyHere(variantFile, variantOpt);
			Sleep(1000);
			pToFolder->Release();
		}

		pIShellDispatch->Release();
	}

	CoUninitialize();
}

UNZIP File

void UnZipFile(CString strSrc, CString strDest)
{
	BSTR source = strSrc.AllocSysString();
	BSTR dest = strDest.AllocSysString();

	HRESULT hResult = S_FALSE;
	IShellDispatch *pIShellDispatch = NULL;
	Folder *pToFolder = NULL;		
	VARIANT variantDir, variantFile, variantOpt;

	CoInitialize(NULL);

	hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, 
		IID_IShellDispatch, (void **)&pIShellDispatch);
	if (SUCCEEDED(hResult))
	{
		VariantInit(&variantDir);
		variantDir.vt = VT_BSTR;
		variantDir.bstrVal = dest;
		hResult = pIShellDispatch->NameSpace(variantDir, &pToFolder);

		if  (SUCCEEDED(hResult))
		{
			Folder *pFromFolder = NULL;
			VariantInit(&variantFile);
            variantFile.vt = VT_BSTR;
            variantFile.bstrVal = source;
			pIShellDispatch->NameSpace(variantFile, &pFromFolder);

			FolderItems *fi = NULL;
			pFromFolder->Items(&fi);

			VariantInit(&variantOpt);
            variantOpt.vt = VT_I4;
            variantOpt.lVal = FOF_NO_UI;			

			VARIANT newV;
			VariantInit(&newV);
			newV.vt = VT_DISPATCH;
			newV.pdispVal = fi;
			hResult = pToFolder->CopyHere(newV, variantOpt);
			Sleep(1000);
			pFromFolder->Release();
            pToFolder->Release();
		}
		pIShellDispatch->Release();
	}

	CoUninitialize();
}


It has been used a Folder object also in the program. Please refer MSDN for more information. Please don’t forget to include shell32.lib and Shellapi.h to your project.