October 09, 2024, 04:03:04 PM

News:

IWBasic runs in Windows 11!


An easy zip extraction on XP

Started by sapero, June 18, 2009, 01:45:28 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

June 18, 2009, 01:45:28 PM Last Edit: June 18, 2009, 02:31:57 PM by sapero
This is a console example of how to read data from z zip storage using zipfldr.dll.// ZIP extraction using zipfldr.dll from Windows XP
// compile for console

#include "shlwapi.inc"
#include "shlobj.inc"
#include "stdio.inc"
#include "stierr.inc" // just for STIERR_OBJECTNOTFOUND

#define ZIP_PATH  "D:\\download\\myzip.zip"
//#define UNPACK_TO "D:\\download\\myzip"

sub ExtractFiles(IStorage *storage, string *pszTargetDir, IMalloc *memory)
{
   if (!memory)
   {
      if (CoGetMalloc(1, &memory)) return;
   }
   else
   {
      memory->AddRef();
   }

   if (!CreateDirectory(pszTargetDir, NULL))
   {
      DWORD dwError = GetLastError();
      if (dwError != ERROR_ALREADY_EXISTS)
      {
         printf("Failed (%d) to create directory %s\n", dwError, pszTargetDir);
         return;
      }
   }

   IEnumSTATSTG *enumerator;
   if (!storage->EnumElements(0,0,0,&enumerator))
   {
      ULONG celtFetched;
      STATSTG stat;
      while (!enumerator->Next(1, &stat, &celtFetched) && celtFetched)
      {
         if (stat.pwcsName)
         {
            string *pszPath = new(byte, lstrlen(pszTargetDir) + wcslen(stat.pwcsName) + 2);
            if (pszPath)
            {
               wsprintf(pszPath, "%s\\%S", pszTargetDir, stat.pwcsName);

               if (stat.type == STGTY_STORAGE) // directory
               {
                  IStorage *subfolder;
                  if (!storage->OpenStorage(stat.pwcsName, 0, STGM_READ, 0, 0, &subfolder))
                  {
                     ExtractFiles(subfolder, pszPath, memory);
                     subfolder->Release();
                  }
               }
               else if (stat.type == STGTY_STREAM) // file
               {
                  printf("processing %s ", pszPath);

                  if (stat.cbSize.QuadPart < 1024q)
                     printf("(%d bytes)\n", stat.cbSize.LowPart)
                  else if (stat.cbSize.QuadPart < 1048576q)
                     printf("(%.2f KB)\n", stat.cbSize.LowPart/1024.0)
                  else
                     printf("(%.2f MB)\n", stat.cbSize.QuadPart/1048576.0);

                  IStream *stream;
                  if (!storage->OpenStream(stat.pwcsName, 0, STGM_READ, 0, &stream))
                  {
                     IStream *file;
                     // check if the file exists
                     dwError = SHCreateStreamOnFile(pszPath, STGM_FAILIFTHERE, &file);
                     if (dwError == STG_E_FILEALREADYEXISTS)
                     {
                        BOOL fOverwrite = FALSE;
                        if (fOverwrite)
                        {
                           dwError = SHCreateStreamOnFile(pszPath, STGM_WRITE | STGM_CREATE, &file);
                        }
                     }
                     else if (dwError == STIERR_OBJECTNOTFOUND)
                     {
                        dwError = SHCreateStreamOnFile(pszPath, STGM_WRITE | STGM_CREATE, &file);
                     }

                     if (dwError && (dwError != STG_E_FILEALREADYEXISTS))
                     {
                        printf("Failed to create '%s' (%x)\n", pszPath, dwError);
                     }
                     else if (!dwError)
                     {
                        ULARGE_INTEGER cbSize;
                        dwError = stream->CopyTo(file, stat.cbSize, NULL, &cbSize);
                        file->Release();

                        //if (dwError || (stat.cbSize.QuadPart != cbSize.QuadPart))
                        //{
                        //    todo
                        //}
                     }
                     stream->Release();
                  }
               }
               delete pszPath;
            }
            memory->Free(stat.pwcsName);
         }
      }
      enumerator->Release();
   }
   memory->Release();
}


sub OpenZip(string *pszZip, string *pszTargetDir)
{
   dstring szDir[MAX_PATH];
   if (!pszTargetDir)
   {
      byte *pName = PathFindFileName(pszZip);
      if (!pName) return;
      pName--;
      int size = pName - pszZip;
      sprintf(szDir, "%.*s", size, pszZip);
      pszTargetDir = szDir;
   }

   ITEMIDLIST *pidl = ILCreateFromPath(pszZip);
   if (pidl)
   {
      IShellFolder *psfParent;
      ITEMIDLIST   *pidlChild;
      if (!SHBindToParent(pidl, _IID_IShellFolder, &psfParent, &pidlChild))
      {
         // open the virtual zip root directory as a storage
         IStorage *storage;
         if (!psfParent->BindToObject(pidlChild, NULL, _IID_IStorage, &storage))
         {
            ExtractFiles(storage, pszTargetDir, NULL);
            storage->Release();
         }
         psfParent->Release();
      }
      ILFree(pidl);
   }
}


sub main()
{
   CoInitialize(0);
#ifdef UNPACK_TO
   OpenZip(ZIP_PATH, UNPACK_TO);
#else
   OpenZip(ZIP_PATH, NULL);
#endif
   CoUninitialize();
   return 0;
}


EDIT: added file overwrite check, but didn't checked if it is working without extracted files :)

Haim

Sapero,
I get errors trying to compile and link the program.
This is what I get:

Compiling...
Zip_read.src
No Errors

Linking...
Aurora Linker v1.0 Copyright ÂÃ,©2005,2006 Ionic Wind Software
Unresolved external __imp_ILCreateFromPathA
Error: Unresolved extern __imp_ILCreateFromPathA
Error: Unresolved extern __imp_ILFree
Error(s) in linking C:\Program Files\Aurora\examples\sapero\Zip_read.exe

I am using your headers of June 2009.
Any ideas?

Haim

sapero

Haim,
just re-create import library for shell32.dll overwriting the existing. I think the "original" shell32.lib comes from OS older than Windows 2000.

Haim

Sapero,
That did it.
Thank you for the program and for the tip on Shell32.

Haim

LarryMc

Sapero,
Almost ashamed to ask.
Do you have an EB version of this?
Do you know if Vista machines have the zipfldr.dll ?

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

June 27, 2009, 02:20:51 AM #5 Last Edit: June 27, 2009, 08:17:22 AM by sapero
Hi Larry, click here for Emergence version
I have checked the zipfldr.dll, it is available on Windows7, thus on Vista should be no problem.

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library