IonicWind Software

Aurora Compiler => Software Projects => Topic started by: sapero on June 18, 2009, 01:45:28 PM

Title: An easy zip extraction on XP
Post by: sapero on June 18, 2009, 01:45:28 PM
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 :)
Title: Re: An easy zip extraction on XP
Post by: Haim on June 19, 2009, 07:59:20 AM
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
Title: Re: An easy zip extraction on XP
Post by: sapero on June 19, 2009, 08:22:38 AM
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.
Title: Re: An easy zip extraction on XP
Post by: Haim on June 19, 2009, 08:32:09 AM
Sapero,
That did it.
Thank you for the program and for the tip on Shell32.

Haim
Title: Re: An easy zip extraction on XP
Post by: LarryMc on June 26, 2009, 06:42:47 PM
Sapero,
Almost ashamed to ask.
Do you have an EB version of this?
Do you know if Vista machines have the zipfldr.dll ?

Larry
Title: Re: An easy zip extraction on XP
Post by: sapero on June 27, 2009, 02:20:51 AM
Hi Larry, click here for Emergence version (http://www.ionicwind.com/forums/index.php/topic,3444.0.html)
I have checked the zipfldr.dll, it is available on Windows7, thus on Vista should be no problem.
Title: Re: An easy zip extraction on XP
Post by: LarryMc on June 27, 2009, 07:53:00 AM
Thanks, Sapero.

Larry