Using Zip Files In VB Part 1

Creating The VB Wrapper

The DLL that you created in the last step doesn't export any functions, so it's useless as a DLL.  There are a couple of different ways to export functions in a DLL, but in order for the functions to be compatible with VB we need to make sure they're exported in a specific way, otherwise we would get a "Bad DLL Calling Convention" error when using the DLL in VB.

C Functions
In C, a basic function has a return data type, a function name, and optionally a list of parameters. A basic function named "foo" in C could look like this

    int foo (int bar) { }

The VB equivalent would be

    Function foo(bar as long) As Long : : End Function

To make a function export in C so that it is compatible in VB, we need to add the following information,

    __declspec(dllexport) WINAPI

The compatible C function would look like

    int __declspec(dllexport) WINAPI foo (int bar) { }


Open (double click) the file vbgamerzip.cpp.  If you gave your project a different name, then this file will have that name.  You should see the following code in the file.

  1. // vbgamerzip.cpp : Defines the entry point for the DLL application.
  2. //
  3. #include "stdafx.h"
  4. BOOL APIENTRY DllMain( HANDLE hModule,
  5.                       DWORD ul_reason_for_call,
  6.                       LPVOIDlpReserved
  7.                      )
  8. {
  9.     return TRUE;
  10. }

This file will contain all the functions we are going to export. We aren't creating any new functions, we're simply creating wrapper functions for a small set of functions that we need for creating and viewing zip files.  Before we start creating our wrapper functions, we need to include zip.h and unzip.h in this file. 

Depending on where your zlib files are physically located on the harddrive, either in the same folder as your VC++ project files or in the zlib122 folder or elsewhere will determine how you need to include the two header files I mentioned.

Since I copied my minizip files to the zlib122 folder, I have the following two lines of code in my project directly under the #include "stdafx.h" line.

#include "..\zlib122\zip.h"
#include "..\zlib122\unzip.h"

If your zip.h and unzip.h files are in your project directory, then you'll only need

#include "zip.h"
#include "unzip.h"

After adding the include statements you should do a test build of your DLL to make sure your include paths are correct.  If you get errors then you'll need to correct the path or possibly move all the sourcefiles into the project folder.

Adding The Functions

The first function we're going to add is crc32. This function is the only function that's not defined in zip.h or unzip.h.  This function is defined in crc32.c.  In the Zlib Source section, open the crc32.c file.  At line 215 you'll find the function that we need.  The first 5 lines look like this:
unsigned long ZEXPORT crc32(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    unsigned len;
We're going to create a similar function in the vbgamerzip.cpp file.  However, our's will be exported and will have a slightly different return type.   VB doesn't have unsigned data types, but it doesn't really matter in this situation because an "unsignedlong" and a VB LONG are both 32 bits.  This means we can accept values from a C function, as long as it's 32 bits in size, and store it in a 32bit variable.  The main thing is the size of the variables, not what they represent.  As long as the size of the data isn't changed, we can store them with no problem.

Since an "unsigned long" is 32 bits and an "int" is 32 bits, we can safely cast the crc32 function to an "int" data type with no problem.   Here is the listing of the first function we're going to create.

  1. int __declspec(dllexport) WINAPI VBCRC32 (unsigned long crc,
  2.                                     constunsigned char FAR*buf,
  3.                                     unsigned len)
  4. {
  5.     return crc32(crc, buf, len);
  6. }  

The function looks a little different.  The data types of the paramters are written with the variable names instead of after the function.  This is simply a personal preference.

If you look at the function, you'll notice that the function name is "VBCRC32," its return type is "int" instead of "unsigned long." The parameter list is exactly the same as the crc32 function.  For most of the functions you can do a copy and paste of the paramter list. The function also has __declspec(dllexport) WINAPI in the function definition, which lets the compiler know that this function, VBCRC32, needs to be exported in a VB compatible format. 

On line 5 you can see why this is just a wrapper for another function.  All of the functions we're going to create will be like this.


The next set of functions are defined in zip.h.  We're only going to export 5 functions, here is the list:
  • zipOpen2
  • zipOpenNewFileInZip3
  • zipWriteInFileInZip
  • zipCloseFileInZip
  • zipClose
The only odd function in this list in terms of return type is zipOpen2.  It returns a void pointer, so we have to convert the void pointer to an int in two steps.  The other four functions in the list will all have an "int" return type.

You can open the zip.h file to find the function definitions.

Some of the functions we're exporting have extra paramters that we don't really need.  If you want a more flexible zip dll, then you'll want to read through the zlib and minizip source code. Otherwise you can follow my suggestions here by simplifying the functions.

The function zipOpen2 has a final paramter that is a pointer to a struct of type zlib_filefunc_def. Since it's not really needed, we're going to leave it out of our exported function and simply pass a NULL when calling the wrapped function.  Here is what the final function looks like.

  1. int __declspec(dllexport) WINAPI VBZipOpen (const char *pathname,
  2.                                   intappend,
  3.                                   zipcharpc*globalcomment)
  4. {
  5.     zipFile z = zipOpen2(pathname, append, globalcomment, NULL);
  6.     return (int)z;
  7. }  

As you can see, the VBZipOpen function has 3 parameters (pathname, append, globalcomment), while the zipOpen2 function requires 4 parameters.  If you want access to the 4th paramter, then you'll need to modify the exported function to include the 4th parameter.

The next function, zipOpenNewFileInZip3, has a lot of extra paramters that aren't needed.  This function will be simplified a lot. We're going to use some predefined constants for our function call, as well as pass a few NULL values for some structs that can complicate our VB code.

NULL Pointers
I'd like to point out that I'm not blindly passing a "NULL" value for paramters that I don't need.  I've actually read the source code to these functions, so I know that they can handle situations when a NULL value is passed intead of the required pointer.  These functions were written to allow these paramters to be optional.
If you're following along by reading the zip.h file, you'll see some comments in the file that mention the constants that you need to use for this function.  Other constants may be defined in some of the zlib files, such as zlib.h, zconf.h, and zutil.h.

The zip compression technique allows you to specify a compression level or possibly no compression at all.  For this DLL I'm going to usethe maximum compression level possible.  If you want, you can add a compression parameter to the VB export function, but I've found that I never use anything other than the maximum.

The final version of this function is listed below.  As you can see the VB export function has only 5 parameters instead of 16 parameters for the function it calls.

  1. int __declspec(dllexport) WINAPI VBZipOpenNewFileInZip(zipFile file,
  2.                                            constchar* filename,
  3.                                            constchar* comment,
  4.                                            constchar* password,
  5.                                            uLongcrcForCrypting)
  6. {
  7.     return zipOpenNewFileInZip3(file, filename,
  8.                            NULL, NULL, 0, NULL, 0,
  9.                            comment,
  10.                             Z_DEFLATED,Z_BEST_COMPRESSION, 0,
  11.                             -MAX_WBITS,DEF_MEM_LEVEL,Z_DEFAULT_STRATEGY,
  12.                            password, crcForCrypting);
  13. }  

The remaining 3 functions in zip.h are easy to convert so there is no need to discuss them.  The VB names that I used however are thefollowing: zipWriteInFileInZip becomes VBZipWriteFile, zipCloseFileInZip becomes VBZipCloseFile, zipClose becomes VBZipClose.


There are 11 functions in unzip.h that we need.  Here is the list of functions.
  • unzOpen
  • unzClose
  • unzGetGlobalInfo
  • unzGetGlobalComment
  • unzGoToFirstFile
  • unzGoToNextFile
  • unzGetCurrentFileInfo
  • unzOpenCurrentFile
  • unzOpenCurrentFilePassword
  • unzCloseCurrentFile
  • unzReadCurrentFile
Just as zipOpen returned a void pointer, so does unzOpen.  It'scast from a void pointer to an int and is done in a similar way.

None of these functions are simplified, and they're all fairly straight forward. 

Here is a complete listing of the vbgamerzip.cpp file.

Code Listing for vbgamerzip.cpp

Next: The Final Export | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8


Tutorial Console

Tutorial by:

Eric Coleman

Date: 2005 May 23



Latest comment

by: TiCL

Is it possible to get the code for the later parts of this article?

Post a Comment

Printer Friendly

Copyright © 2002 - 2004 Eric Coleman, Peter Kuchnio , et. al.
There have been 39 visitors within the last 20 minutes
RSS News Feed