Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Zip API in WindowsXP

283 views
Skip to first unread message

AGP

unread,
Mar 14, 2006, 1:49:46 PM3/14/06
to
In WindowsXP when I hover over a zip file a yellow help-style box will
pop-up displaying the first 10 or so entries in the zip file. There has
got to be a way to tap into the API that XP uses to enumerate the
contents. I dont need to compress or decompress, I just need to see
what the contents are and list them to a file.

Rgds,
AGP

Ken Halter

unread,
Mar 14, 2006, 2:01:29 PM3/14/06
to
"AGP" <warpe...@gmail.com> wrote in message
news:1142362186.3...@j33g2000cwa.googlegroups.com...

I'm not sure what XP does with zips. All I know is I turn XPs Zip File
support off and install Winzip as soon as possible after installing XP
anywhere. There may be some code in this sample that'll help with your
project. If you build something that doesn't rely on XPs APIs, it'll work on
any (modern) OS and will still work after the users turn XP Zip support off.

Advanced Programmatic Zipfile functionality
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=52005&lngWId=1

--
Ken Halter - MS-MVP-VB - Please keep all discussions in the groups..
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm


mr_unreliable

unread,
Mar 14, 2006, 4:35:36 PM3/14/06
to
Also, check out "Introduction to the freeware Info-ZIP libraries"

found here,

http://www.vbaccelerator.com/home/vb/code/libraries/Compression/Introduction_to_the_Info-ZIP_Libraries/article.asp

cheers, jw

AGP

unread,
Mar 14, 2006, 7:37:12 PM3/14/06
to
thanx for all the help. i appreciate it.
ive tried every possible piece of code from PSC and vbAccelerator and
CodeGuru and Codehound but all bomb on my issue, which has to deal with
enumerating the
contents of large files. all code i have tried from PSC has bombed on
large files. So I thought I would interafce with the XP API to see if I
can do it that way since it does enumerate it properly. DynaZip offers
an expensive control (in my view) that works perfectly but again its a
bit expensive for me and it works in VB6. I've searched and searched
and just cannot find a cost-effective way to do this. So my last resort
was to tap into the XP API.

AGP

AGP

unread,
Mar 14, 2006, 8:24:45 PM3/14/06
to

Thorsten Albers

unread,
Mar 14, 2006, 9:11:14 PM3/14/06
to
AGP <warpe...@gmail.com> schrieb im Beitrag
<1142362186.3...@j33g2000cwa.googlegroups.com>...

AFAIK there are 3 files responsible for the zip support of Windows XP:
DZIP32.DLL
DUNZIP32.DLL
ZIPFLDR.DLL

ZIPFLDR.DLL seems to provide only the explorer context menue functions, so
the base functions presumably are in DZIP32.DLL and DUNZIP32.DLL.
So, what I would do is searching the exports of these 2 DLLs with the
Dependency Walker, take some of the functions which have a characteristic
name, and google for a documentation of the them.

I don't, if this will lead to any results, but may be you should give it a
try...

--
----------------------------------------------------------------------
THORSTEN ALBERS Universität Freiburg
albers@
uni-freiburg.de
----------------------------------------------------------------------

Michael C

unread,
Mar 14, 2006, 9:35:19 PM3/14/06
to
"Thorsten Albers" <albe...@MOVEuni-freiburg.de> wrote in message
news:01c647d5$9c78b3c0$314ef8d9@thaldesk...

> AGP <warpe...@gmail.com> schrieb im Beitrag
> <1142362186.3...@j33g2000cwa.googlegroups.com>...
>> In WindowsXP when I hover over a zip file a yellow help-style box will
>> pop-up displaying the first 10 or so entries in the zip file. There has
>> got to be a way to tap into the API that XP uses to enumerate the
>> contents. I dont need to compress or decompress, I just need to see
>> what the contents are and list them to a file.
>
> AFAIK there are 3 files responsible for the zip support of Windows XP:
> DZIP32.DLL
> DUNZIP32.DLL
> ZIPFLDR.DLL

The only one of those files i've got on my system is zipfldr.dll which is a
com dll but not the type supported by vb6.

There was someone on one of these groups with a product that did support
large files but I can't rememeber what product it was.

Michael


AGP

unread,
Mar 15, 2006, 1:15:09 AM3/15/06
to
the only one that i have seen that interfaces well with vb6 is DynaZip
and its a bit expensive for my needs. and i have looked and looked
and cant find much.

ill check those DLLs only they might not be present in other OS's like
NT4 but something is better than nothing.

AGP

"Michael C" <nos...@nospam.com> wrote in message
news:uvvMPh9R...@TK2MSFTNGP12.phx.gbl...

Michael C

unread,
Mar 15, 2006, 1:28:59 AM3/15/06
to
"AGP" <sindiz...@softhome.net> wrote in message
news:NhORf.54033$H71....@newssvr13.news.prodigy.com...

> the only one that i have seen that interfaces well with vb6 is DynaZip
> and its a bit expensive for my needs. and i have looked and looked
> and cant find much.
>
> ill check those DLLs only they might not be present in other OS's like
> NT4 but something is better than nothing.

Search the microsoft.public.vb.* groups in the last couple of weeks as
someone mentioned this very topic.

Michael


Mike D Sutton

unread,
Mar 15, 2006, 4:49:05 AM3/15/06
to

See if this works for you, it simply enumerates the header of the .ZIP file without going deeper into the file and
doesn't require any third party libraries:
http://groups.google.co.uk/group/microsoft.public.vb.general.discussion/msg/af374a38d8cfe0fb
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ED...@mvps.org
WWW: Http://EDais.mvps.org/


Thorsten Albers

unread,
Mar 15, 2006, 4:48:56 AM3/15/06
to
Michael C <nos...@nospam.com> schrieb im Beitrag
<uvvMPh9R...@TK2MSFTNGP12.phx.gbl>...

> The only one of those files i've got on my system is zipfldr.dll which is
a
> com dll but not the type supported by vb6.

Then could you check the exports and imports of the DLL with Dependency
Walker? Either on XP(?) this file already holds all exported function, or
Dependency Walker will list the respective DLLs as dependencies of
ZIPFLDR.DLL.

Dave

unread,
Mar 15, 2006, 10:03:06 AM3/15/06
to
Not needed, this is the same poster as the thread you are thinking of, AGPs
problem is that all the methods he as tried so far bomb on files in excess
of 2Gig.

I suppose I better see if the code I use is OK on such files (I have to make
one first, that'll be fun!).

Dave O.


"Michael C" <nos...@nospam.com> wrote in message

news:%23%23v$yj$RGHA...@TK2MSFTNGP14.phx.gbl...

AGP

unread,
Mar 15, 2006, 10:16:04 AM3/15/06
to
yes that was me and i received many responses but none panned out so im
now trying to use the built-in XP libabries.

AGP

Thorsten Albers

unread,
Mar 15, 2006, 10:25:07 AM3/15/06
to
Thorsten Albers <albe...@MOVEuni-freiburg.de> schrieb im Beitrag
<01c64815$92399c40$2248f8d9@thaldesk>...

> Then could you check the exports and imports of the DLL with Dependency
> Walker? Either on XP(?) this file already holds all exported function, or
> Dependency Walker will list the respective DLLs as dependencies of
> ZIPFLDR.DLL.

I checked the ZIPFLDR.DLL now myself and came to the following conclusion:
Indeed ZIPFLDR.DLL seems to be the only DLL involved in ZIP compression
support of Windows XP. But it doesn't export functions usable for your
problem. It is a COM-DLL, so its functions should be available to VB if
there is a reference set to the DLL (I can't test it myself since XP isn't
available to me).
From the resources of the DLL it seems to be obvious that ZIPFLDR.DLL
heavily relies on the SETUPAPI.DLL, i.e. the presence of the SETUPAPI.DLL
is a necessary precondition for ZIPFLDR.DLL to work. Looking into
SETUPAPI.DLL shows some functions that somehow are dealing with
compression/decompression, e.g. SetupGetFileCompressionInfo()/
SetupGetFileCompressionInfoEx(). The functions of the SETUPAPI.DLL are
documented in the MSDN. So it should be possible to work out how to use
this functions to get information about a ZIP file.
The only thing that is irritating is that SetupGetFileCompressionInfo()
seems to support only two compression formats: LZ (the old windows LZ
compression format) and MSZIP. I don't know wether 'MSZIP' is the
description of a ZIP compatible compression or if it means the CAB file
compression.

In addition: There seems to be a command line tool COMPACT.EXE shipped with
XP which is able to compress/decompress files - but I don't know which
compression format it uses.

AGP

unread,
Mar 15, 2006, 10:29:18 AM3/15/06
to
Thanx so much for the leads. This piece of code halfway works but in
the end still bombs. The culprit is the Seek filenum, pos function. VB
expects a long for pos so when the seek position gets past 2.1G then an
overflow occurs. Files up to that point are enumerated but then it
bombs at the 2.1G mark. Is there an API version of that code?

AGP

Mike D Sutton

unread,
Mar 15, 2006, 11:14:51 AM3/15/06
to

I don't have an API version written, but it shouldn't be too difficult to
convert it - you have all of the file constructs and file structure logic
there, all that's involved is replacing VB's file reading calls with API
calls instead:
Open = CreateFile()
Get = ReadFile()
Seek = SetFilePointer()

Karl E. Peterson

unread,
Mar 15, 2006, 5:02:38 PM3/15/06
to

Have you tried ignoring the sign-bit and just treating Longs as unsigned
DWORDs? (I haven't seen the code, so...)
--
Working without a .NET?
http://classicvb.org/


Dave

unread,
Mar 16, 2006, 4:32:21 AM3/16/06
to
I tried to make a zip >2Gig using XP native zip handling, but it didn't want
to play. To save me duplicating effort does anybody know which zip handlers
will definately create files >2Gig.

Another thought I had about how to attack this problem was that some zip
handlers take command line parameters, so it may be possible to get one to
dump a listing of a files content to a text file which the OPs program can
then parse.

Dave O.

"Dave" <nob...@nowhere.com> wrote in message
news:eTBnRGES...@TK2MSFTNGP12.phx.gbl...

NickHK

unread,
Mar 16, 2006, 6:34:55 AM3/16/06
to

Don't know if it's of use to, but did you see the CAKE here:
http://www.quickzip.org/othersoftware/
Apparently there's a Delphi DLL available that exposes "property
Archive_Contents".
Can't say if it works for your 2.1G + files, but the QuickZip app from that
site does.

NickHK

"AGP" <warpe...@gmail.com> wrote in message
news:1142362186.3...@j33g2000cwa.googlegroups.com...

Mike D Sutton

unread,
Mar 16, 2006, 7:33:02 AM3/16/06
to
> I don't have an API version written, but it shouldn't be too difficult to
> convert it - you have all of the file constructs and file structure logic
> there, all that's involved is replacing VB's file reading calls with API
> calls instead:
> Open = CreateFile()
> Get = ReadFile()
> Seek = SetFilePointer()

Here's the code converted to API calls since on closer inspection there were a couple of nasties in doing so (namely
coping with padding bytes within VB structs and conversion of decimals to high/low unsigned DWord pair.)
This should support .ZIP files over 2GB and also files within .ZIP files of over 2GB since the seek distance is now
calculated as a decimal. It is however untested since I don't have any >2GB .zip files hanging around:

'***
Private Declare Function CreateFile Lib "Kernel32.dll" Alias "CreateFileA" ( _
ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, ByRef lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function SetFilePointer Lib "Kernel32.dll" ( _
ByVal hFile As Long, ByVal lDistanceToMove As Long, _
ByRef lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "Kernel32.dll" (ByVal hFile As Long, _
ByRef lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
ByRef lpNumberOfBytesRead As Long, ByRef lpOverlapped As Any) As Long

Private Type typZipLocalFileHead ' 30 bytes
zlfhSignature As Long ' 0x04034B50
zlfhVersion As Integer
zlfhBitFlag As Integer
zlfhCompression As Integer
zlfhModFileTime As Integer
zlfhModFileData As Integer
zlfhCRC As Long
zlfhCompressedSize As Long
zlfhUncompressedSize As Long
zlfhFileNameLength As Integer
zlfhExtraFieldLength As Integer
End Type

Private Const GENERIC_READ As Long = &H80000000
Private Const FILE_SHARE_READ As Long = &H1
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Private Const OPEN_EXISTING As Long = 3
Private Const FILE_CURRENT As Long = 1
Private Const Bit31 As Currency = 2147483648@ ' 0x80000000
Private Const Bit32 As Currency = 4294967296@ ' 0x100000000

Private Sub Form_Load()
SET THE ZIP PATH HERE THEN KILL THIS LINE
Const FileName As String = "X:\Path\File.zip"
Debug.Print "Found " & TestZip(FileName) & " files in zip"
End Sub

Private Function TestZip(ByRef inFile As String) As Long
Dim FileName As String
Dim ReadHead As typZipLocalFileHead
Dim FileString As String
Dim SeekSize As Variant
Dim hFile As Long
Dim ReadLen As Long
Dim SeekHigh As Long, SeekLow As Long

Const ZipLocalFileHeadSig As Long = &H4034B50

' Make sure file exists
If (Not FileExist(inFile)) Then Exit Function

' Get a free file handle and open the file
hFile = CreateFile(inFile, GENERIC_READ, FILE_SHARE_READ, _
ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0&)
If (hFile) Then
Do ' Read a chunk signature
Call ReadFile(hFile, ReadHead.zlfhSignature, _
Len(ReadHead.zlfhSignature), ReadLen, ByVal 0&)

' Check for a local file header signatrue
If (ReadHead.zlfhSignature = ZipLocalFileHeadSig) Then
' Ok, read the full structure
Call SetFilePointer(hFile, -4, ByVal 0&, FILE_CURRENT)
ReadHead = ReadZipLocalFileHeadFromFile(hFile)

With ReadHead
' Get the file name
If (.zlfhFileNameLength) Then
FileString = Space(.zlfhFileNameLength)
Call ReadFile(hFile, ByVal FileString, _
.zlfhFileNameLength, ReadLen, ByVal 0&)
Debug.Print "Got file: """ & FileString & """";
Else ' No filename?
Debug.Print "Got file: [No name]";
End If

' Print the compression percentage
Debug.Print " -- " & Format(1 - (.zlfhCompressedSize / _
.zlfhUncompressedSize), "0.0%")

' Work out how much extra data to skip over
SeekSize = CDec(.zlfhCompressedSize)
If (.zlfhExtraFieldLength) Then _
SeekSize = SeekSize + CDec(.zlfhExtraFieldLength)
If (.zlfhBitFlag And &H4) Then _
SeekSize = SeekSize + CDec(12)

' Convert seek to low and high DWords and seek to next record
SeekLow = DecToDWords(SeekSize, SeekHigh)
Call SetFilePointer(hFile, SeekLow, SeekHigh, FILE_CURRENT)
End With

' Increment file count
TestZip = TestZip + 1
Else
Exit Do
End If
Loop

Call CloseHandle(hFile)
End If
End Function

Private Function FileExist(ByVal inFile As String) As Boolean
On Error Resume Next
FileExist = FileLen(inFile) + 1
End Function

Private Function ReadZipLocalFileHeadFromFile( _
ByVal inFile As Long) As typZipLocalFileHead
Dim ReadLen As Long

' Read structure from file, taking into account padding bytes before CRC
With ReadZipLocalFileHeadFromFile
Call ReadFile(inFile, .zlfhSignature, 14, ReadLen, ByVal 0&)
Call ReadFile(inFile, .zlfhCRC, 16, ReadLen, ByVal 0&)
End With
End Function

' It gets nasty after this point, be warned..

Private Function DecToDWords( _
ByVal inDec As Variant, ByRef outHigh As Long) As Long
If (inDec >= Bit32) Then outHigh = UDWordToSDWord(Int(inDec / Bit32))
DecToDWords = UDWordToSDWord(inDec)
End Function

Private Function UDWordToSDWord(ByVal inUDWord As Currency) As Long
Dim TempVal As Currency ' Unsigned to signed DWord

TempVal = inUDWord - (Int(inUDWord / Bit32) * Bit32) ' Trim overflow
UDWordToSDWord = TempVal - (Int(TempVal / Bit31) * Bit31)
If (TempVal >= Bit31) Then _
UDWordToSDWord = UDWordToSDWord Or &H80000000
End Function
'***

AGP

unread,
Mar 16, 2006, 1:17:19 PM3/16/06
to
The latest WinZip defintely does and 7-zip can read them so Im assuminf it
can create them.

AGP

"Dave" <nob...@nowhere.com> wrote in message

news:%23esZJyN...@TK2MSFTNGP12.phx.gbl...

AGP

unread,
Mar 16, 2006, 2:01:54 PM3/16/06
to
omg. believe it or not that seems to work! many...many thanks!
I will more fullly test the code later tonite and post my results but
at work it enumerated a 2.4GB zip file and the contents seemed to match
those that WinZip9 reports.

Question...is there a reason for using the Dec variable rather than say
the Currency type? Although i consider myself an advanced VB6
programmer I don't generally get this deep into API's.

AGP

AGP

unread,
Mar 16, 2006, 4:24:42 PM3/16/06
to
CAKE seems to be geared towards the Delphi crowd. It also seems to be
unsupported or worked on for several years. im not even sure that the
component is self-contained. it seems to wrap around exisiting DLLs
like the 7zip, unrar, and other DLLs. Thanx for the lead though. ive
followed up with the devloper and will see what he says.

AGP

Mike D Sutton

unread,
Mar 16, 2006, 4:43:29 PM3/16/06
to

A currency data type is a 64-bit integer divided by 10,000 to give a fixed-point data type with 4 figures after the
decimal place, as such it does not cover the full 64-bit range available with the high/low DWord combination. Although
you're most likely not going to need to deal with files larger than 1.6 PetaBytes, it should mean I don't need to update
it again for a while (at least until we hit the 16 ExaByte mark!)
Generally though I prefer to work with Currency data types when using large numbers, since they're integer based and not
so susceptible to rounding errors as with the Double and Decimal types.
Cheers,

AGP

unread,
Mar 16, 2006, 6:50:39 PM3/16/06
to
Le me follow up with an additional question as Im absorbing this like a
sponge. before this issue with enumerating the contents of large files
i had problems with getting the size of any file larger than 2.1GB. The
VB function as well as the API if used as in examples will all give
negative numbers. From the help of this group i settled on:

unction MyFileSize(strFileName As String) As Variant
Dim WFD As WIN32_FIND_DATA
Dim hFindFirst As Long
Dim Hi As Currency, Lo As Currency

hFindFirst = FindFirstFile(strFileName, WFD)

If hFindFirst > 0 Then
FindClose hFindFirst
Hi = WFD.nFileSizeHigh
Lo = WFD.nFileSizeLow
If Hi < 0 Then Hi = Hi + (2 ^ 32)
If Lo < 0 Then Lo = Lo + (2 ^ 32)

MyFileSize = (Hi * (2 ^ 32)) + Lo
Else
MyFileSize = 0
End If
End Function

Do you see any problems with my code as it stands. i tested on files
greater than 2.1Gb and 4GB and it seemed to work ok. any ways to
optimize the snippet.

AGP

Mike D Sutton

unread,
Mar 16, 2006, 8:34:05 PM3/16/06
to

FindFirstFile() returns a handle which could use the high bit of the returned DWord value, so your test for a valid
handle should really be (hFindFirst <> 0) but other than that it looks fine. You may want to watch out using doubles
for your calculations since they're not as accurate as currency data types due to the way they're stored.
Also, personally I'd use the GetFileSize() API call rather than having to find the file:

'***
Private Declare Function CreateFile Lib "Kernel32.dll" Alias "CreateFileA" ( _
ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, ByRef lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long

Private Declare Function GetFileSize Lib "Kernel32.dll" ( _
ByVal hFile As Long, ByRef lpFileSizeHigh As Long) As Long

Private Const FILE_READ_ATTRIBUTES As Long = &H80


Private Const FILE_SHARE_READ As Long = &H1

Private Const FILE_SHARE_WRITE As Long = &H2


Private Const OPEN_EXISTING As Long = 3

Private Const Bit31 As Currency = 2147483648@ ' 0x80000000
Private Const Bit32 As Currency = 4294967296@ ' 0x100000000

Private Function FileLen(ByRef inFile As String) As Variant ' Decimal
Dim hFile As Long
Dim SizeLow As Long, SizeHigh As Long

' Get an API file handle to read the file's attributes
hFile = CreateFile(inFile, FILE_READ_ATTRIBUTES, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
ByVal 0&, OPEN_EXISTING, 0&, 0&)
If (hFile) Then ' Grab the file size and close the handle
SizeLow = GetFileSize(hFile, SizeHigh)
Call CloseHandle(hFile)

' Pack the file size into a single return value
FileLen = CDec(SDWordToUDWord(SizeLow)) + _
(CDec(Bit32) * SDWordToUDWord(SizeHigh))
End If
End Function

Private Function SDWordToUDWord(ByVal inLong As Long) As Currency
SDWordToUDWord = CCur(inLong And &H7FFFFFFF)
If (inLong < 0) Then SDWordToUDWord = SDWordToUDWord + Bit31
End Function
'***

Hope this helps,

Mike

Thorsten Albers

unread,
Mar 16, 2006, 10:26:36 PM3/16/06
to
Mike D Sutton <ED...@mvps.org> schrieb im Beitrag
<OEM7iLWS...@TK2MSFTNGP09.phx.gbl>...

> so your test for a valid
> handle should really be (hFindFirst <> 0)

It should be "hFindFirst <> INVALID_HANDLE_VALUE" with
"INVALID_HANDLE_VALUE = -1" because this is what FindFirstFile() and other
file related API functions (e.g. CreateFile()) will return in case of
error.
I don't know why MS set INVALID_HANDLE_VALUE to "-1" (FFFFFFFFh) instead of
"0". Presumably there is a reason for this, but I wouldn't ask MS because
from THGG I know all the nasty things about "reasons".

AGP

unread,
Mar 17, 2006, 1:14:27 AM3/17/06
to
i tried it ahome and it works on a 3.9GB file so i decided to go extreme and
tried it on a 10.7GB file and it works about half way i'd say.it gets to of
1095 of 2260 files
and then starts returning gibberish which i would assume is the actual
binary data.

AGP

"AGP" <warpe...@gmail.com> wrote in message

news:1142535713.9...@j52g2000cwj.googlegroups.com...

Mike D Sutton

unread,
Mar 17, 2006, 9:33:02 AM3/17/06
to
> It should be "hFindFirst <> INVALID_HANDLE_VALUE" with
> "INVALID_HANDLE_VALUE = -1" because this is what FindFirstFile() and other
> file related API functions (e.g. CreateFile()) will return in case of error.

Whoops, yes, well spotted! Glad someone's paying attention ;)

Mike D Sutton

unread,
Mar 17, 2006, 9:40:18 AM3/17/06
to
> i tried it ahome and it works on a 3.9GB file so i decided to go extreme and
> tried it on a 10.7GB file and it works about half way i'd say.it gets to of
> 1095 of 2260 files
> and then starts returning gibberish which i would assume is the actual
> binary data.

Hmm, I would guess then that it's getting confused at some point and seeking into binary data rather than to the next
header. I'm in the process of reclaiming some disk space at the moment to create some test files and I'll take a look
at it as soon as I get some data to work on.
If possible, it would be great to find out the exact situation in which it falls over since I'm guessing it's down to
the numeric conversion routines, but can't seem to find a situation where they return an incorrect value.
If you could find out the current file position and the typZipLocalFileHead structure that seeks it into binary data,
then I could hopefully reproduce the problem here and get a fix done.
Cheers,

AGP

unread,
Mar 17, 2006, 1:35:22 PM3/17/06
to

"Mike D Sutton" <ED...@mvps.org> wrote in message
news:%23Gka3Cd...@TK2MSFTNGP09.phx.gbl...

ok on the really big file I set up some debug statements like so:

' Work out how much extra data to skip over
SeekSize = CDec(.zlfhCompressedSize)

If (.zlfhExtraFieldLength) Then SeekSize = SeekSize +
CDec(.zlfhExtraFieldLength)
If (.zlfhBitFlag And &H4) Then SeekSize = SeekSize +
CDec(12)
Debug.Print .zlfhBitFlag
Debug.Print .zlfhCompressedSize
Debug.Print .zlfhCompression
Debug.Print .zlfhCRC
Debug.Print .zlfhExtraFieldLength
Debug.Print .zlfhFileNameLength
Debug.Print .zlfhModFileData
Debug.Print .zlfhModFileTime
Debug.Print .zlfhSignature
Debug.Print .zlfhUncompressedSize
Debug.Print .zlfhVersion
Debug.Print "FILE POS: " & SeekSize

and here is the result"


Got file: "1094 MP3z/(Battlestar Galactica) - 2x01 -
Scattered.dsr-loki.avi" -- 1.2%
0
362394396
8
-1313652064
0
59
13044
-19189
67324752
366778368
20
FILE POS: 362394396
Got file: "1095 /[PV] HIGH and MIGHTY COLOR - PRIDE(704x480
MPEG2)(2005.01.26).mpgμό.WTαχ7<bunch of binary data>-- -249203471.4%
-26570
174442500
13058
170405686
31283
20557
-20681
15736
45
70
8
FILE POS: 174473795

AGP


Mike D Sutton

unread,
Mar 17, 2006, 2:19:04 PM3/17/06
to
> ok on the really big file I set up some debug statements like so:
<snip>

Ah ok, I see the problem. Try replacing this:

'***
SeekSize = CDec(.zlfhCompressedSize)
If (.zlfhExtraFieldLength) Then _


SeekSize = SeekSize + CDec(.zlfhExtraFieldLength)

If (.zlfhBitFlag And &H4) Then _


SeekSize = SeekSize + CDec(12)

'***

With this:

'***
SeekSize = CDec(SDWordToUDWord(.zlfhCompressedSize))
If (.zlfhExtraFieldLength) Then _
SeekSize = SeekSize + SDWordToUDWord(.zlfhExtraFieldLength)
If (.zlfhBitFlag And &H4) Then _
SeekSize = SeekSize + 12

...

Private Function SDWordToUDWord(ByVal inLong As Long) As Currency
SDWordToUDWord = CCur(inLong And &H7FFFFFFF)
If (inLong < 0) Then SDWordToUDWord = SDWordToUDWord + Bit31
End Function
'***

This treats the data and extra field lengths as unsigned DWords. Currently it's (incorrectly) treating the compressed
length as signed on the AVI file which seeks it way back towards the start of the file into random data.
So many hoops to jump through in VB..
Hope this helps,

DIOS

unread,
Mar 17, 2006, 4:40:07 PM3/17/06
to
As i wrote that meesage this afternoon I was wondering what it would do
if there was a large file compressed in the zip file. in other words if
i had a 2.4GB file and then added a bunch of smaller files what would
it do and i think it just so happened that my test file probably and
one of those in there. i will test again tonite.

AGP

AGP

unread,
Mar 17, 2006, 9:29:30 PM3/17/06
to

"Mike D Sutton" <ED...@mvps.org> wrote in message
news:ez%23UpefS...@TK2MSFTNGP12.phx.gbl...

ok here is what I have after the code changes, looks like no change:

Got file: "1094 MP3z/(Battlestar Galactica) - 2x01 -
Scattered.dsr-loki.avi" -- 1.2%
0
362394396
8
-1313652064
0
59
13044
-19189
67324752
366778368
20
FILE POS: 362394396
Got file: "1095 /[PV] HIGH and MIGHTY COLOR - PRIDE(704x480

MPEG2)(2005.01.26).mpgμό.WTαχ7" --249203471.4%

Mike D Sutton

unread,
Mar 19, 2006, 2:28:34 PM3/19/06
to
> ok here is what I have after the code changes, looks like no change:
<snip>

I can see one potential bug when dealing with a file after a >2GB file, try
this fix:

'***


Private Function DecToDWords( _
ByVal inDec As Variant, ByRef outHigh As Long) As Long
If (inDec >= Bit32) Then outHigh = UDWordToSDWord(Int(inDec / Bit32))
DecToDWords = UDWordToSDWord(inDec)
End Function

'***

To:

'***
Private Function DecToDWords(ByVal inDec As Variant, ByRef outHigh As Long)

As Long
If (inDec >= Bit32) Then outHigh = UDWordToSDWord(Int(inDec / Bit32))

Else outHigh = 0&
DecToDWords = UDWordToSDWord(inDec) ' Handles positive values only!
End Function
'***

This may fix your bug, alternatively it'll need to wait until I get back to
the office on Tuesday and have a sizable chunk of disk space to play with.

AGP

unread,
Mar 19, 2006, 2:57:57 PM3/19/06
to

"Mike D Sutton" <ED...@mvps.org> wrote in message
news:OIRaUt4S...@TK2MSFTNGP09.phx.gbl...

> > ok here is what I have after the code changes, looks like no change:
> <snip>
>
> I can see one potential bug when dealing with a file after a >2GB file,
try
> this fix:
>
<snip>

>
> This may fix your bug, alternatively it'll need to wait until I get back
to
> the office on Tuesday and have a sizable chunk of disk space to play with.
>
> Mike


no change. i spent many hours yeterday trying to combine two pieces of code
that i have and the one you have posted
but to no avail. the other piece of code that i have looks a little bit
different than the one you tweaked. it appears that
the developer i got it from already knows where to look for the info and
instead skips ahead to that section and then
starts from there. here is what that code looks like and in fact works
great..except when you get to the large file sizes.
by using another function for GetFileSize() i can get the actual size for
values greater than 2.1GB and then i can see that
it works up to line 122. from there i just cannot seem to parse out the
logic for the lo and hi bytes since the API
takes longs and i am using the length and position as Currency values.

Private Type ZipFileCentralHeader
VersionMadeBy As Integer
VersionNeededToExtract As Integer
Flag As Integer
CompressionMethod As Integer
Time As Integer
Date As Integer
CRC32 As Long
CompressedSize As Long
UncompressedSize As Long
FileNameLength As Integer
ExtraFieldLength As Integer
FileCommentLength As Integer
DiskNumberStart As Integer
InternalAttr As Integer
ExternalAttr As Long
RelOffsetLocHdr As Long
Filename As String
ExtraField As String
FileComment As String
End Type
Private Type ZipFileEndCentralHeader
DiskNumberThis As Integer
DiskNumberCentralDir As Integer
CentralDirEntriesThisDisk As Integer
CentralDirEntriesTotal As Integer
SizeCentralDir As Long
CentralDirOffset As Long
FileCommentLength As Integer
FileComment As String
End Type

Dim Sig As Long
Dim LenFile As Long
Dim Index As Long
Dim sPath As String
Dim Filename As String
Dim Temp As String * 4096
Dim MyDate As Date
Dim hFile As Long
'Dim bBuffer(10) As Byte
'Dim lResult As Long
Dim lowbyte As Long 'low dword of file pointer position
Dim highbyte As Long 'high dword of file pointer position
Dim Ret As Long
Dim MyPos As Long
'-------------------------------------------------
'Dim zFile As ZipFileLocalHeader
Dim zCentral As ZipFileCentralHeader
Dim zEndCentral As ZipFileEndCentralHeader
'Dim zSignature As ZipDigitalSignature
'-------------------------------------------------
'Zip Signatures 'a.k.a.
'Const LocalFileHeaderSig = &H4034B50 'PK 03 04
'Const CentralFileHeaderSig = &H2014B50 'PK 01 02
'Const EndCentralHeaderSig = &H6054B50 'PK 05 06
'Const DigitalSig = &H5054B50 'PK 05 05
'Const SpanSig = &H8074B50 'PK 07 08
Const Offset As Long = 4096

100 hFile = CreateFile(ArchiveName, GENERIC_READ, FILE_SHARE_READ Or
FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0&)
102 If hFile = INVALID_HANDLE_VALUE Then Exit Sub
104 LenFile = GetFileSize(hFile, 0)
If LenFile = 0 Then Exit Sub

110 If LenFile > Offset Then
114 MyPos = LenFile - Offset
Else
118 MyPos = 1
End If
lowbyte = MyPos
highbyte = 0
lowbyte = SetFilePointer(hFile, lowbyte, highbyte, FILE_BEGIN)
ReadFile hFile, ByVal Temp, Offset, Ret, ByVal 0&
122 Sig = InStrRev(Temp, "PK" & Chr$(5) & Chr$(6))
124 If Sig Then
128 lowbyte = MyPos + Sig + 3
130 highbyte = 0
132 lowbyte = SetFilePointer(hFile, lowbyte, highbyte, FILE_BEGIN)
134 With zEndCentral
138 ReadFile hFile, .DiskNumberThis, 2, Ret, ByVal 0&
142 ReadFile hFile, .DiskNumberCentralDir, 2, Ret, ByVal 0&
146 ReadFile hFile, .CentralDirEntriesThisDisk, 2, Ret, ByVal 0&
150 ReadFile hFile, .CentralDirEntriesTotal, 2, Ret, ByVal 0&
154 ReadFile hFile, .SizeCentralDir, 4, Ret, ByVal 0&
158 ReadFile hFile, .CentralDirOffset, 4, Ret, ByVal 0&
' Get ZipStream, , .FileCommentLength 'Integer
' .FileComment = String$(.FileCommentLength, vbKeySpace)
' Get ZipStream, , .FileComment 'String
160 ' Seek ZipStream, .CentralDirOffset + 1
162 lowbyte = .CentralDirOffset '+ 1
164 highbyte = 0
166 lowbyte = SetFilePointer(hFile, lowbyte, highbyte, FILE_BEGIN)
168 FileCount = .CentralDirEntriesThisDisk
End With
170 For Index = 1 To FileCount
172 With zCentral 'This has all the goodies
174 ReadFile hFile, Sig, 4, Ret, ByVal 0&
176 ReadFile hFile, .VersionMadeBy, 2, Ret, ByVal 0&
178 ReadFile hFile, .VersionNeededToExtract, 2, Ret, ByVal 0&
180 ReadFile hFile, .Flag, 2, Ret, ByVal 0&
182 ReadFile hFile, .CompressionMethod, 2, Ret, ByVal 0&
184 ReadFile hFile, .Time, 2, Ret, ByVal 0&
186 ReadFile hFile, .Date, 2, Ret, ByVal 0&
188 ReadFile hFile, .CRC32, 4, Ret, ByVal 0&
190 ReadFile hFile, .CompressedSize, 4, Ret, ByVal 0&
192 ReadFile hFile, .UncompressedSize, 4, Ret, ByVal 0&
194 ReadFile hFile, .FileNameLength, 2, Ret, ByVal 0&
196 ReadFile hFile, .ExtraFieldLength, 2, Ret, ByVal 0&
198 ReadFile hFile, .FileCommentLength, 2, Ret, ByVal 0&
200 ReadFile hFile, .DiskNumberStart, 2, Ret, ByVal 0&
202 ReadFile hFile, .InternalAttr, 2, Ret, ByVal 0&
204 ReadFile hFile, .ExternalAttr, 4, Ret, ByVal 0&
206 ReadFile hFile, .RelOffsetLocHdr, 4, Ret, ByVal 0&
208 .Filename = String$(.FileNameLength, vbKeySpace)
210 ReadFile hFile, ByVal .Filename, Len(.Filename), Ret, ByVal 0&
212 If .ExtraFieldLength Then
214 .ExtraField = String$(.ExtraFieldLength, vbKeySpace)
216 ReadFile hFile, ByVal .ExtraField, Len(.ExtraField), Ret,
ByVal 0&
End If
218 If .FileCommentLength Then
220 .FileComment = String$(.FileCommentLength, vbKeySpace)
222 ReadFile hFile, ByVal .FileComment, Len(.FileComment), Ret,
ByVal 0&
End If
End With
224 ParseFullPath zCentral.Filename, sPath, Filename
226 With zCentral
228 MyDate = GetMyDate(.Date, .Time)
End With
Next
End If

234 CloseHandle (hFile)

AGP


DIOS

unread,
Mar 20, 2006, 2:02:31 PM3/20/06
to
I think i have tried this but let me give that another shot.

AGP

Karl E. Peterson

unread,
Mar 20, 2006, 2:17:18 PM3/20/06
to
DIOS wrote:
> I think i have tried this but let me give that another shot.

I shoulda followed up. I was curious enough to try it myself. VB tosses a
"Bad record number" if you give it a "negative" value in Seek.

Sorry...

Michael C

unread,
Mar 20, 2006, 5:02:11 PM3/20/06
to
"Karl E. Peterson" <ka...@mvps.org> wrote in message
news:uMS0oLFT...@tk2msftngp13.phx.gbl...

> DIOS wrote:
>> I think i have tried this but let me give that another shot.
>
> I shoulda followed up. I was curious enough to try it myself. VB tosses
> a
> "Bad record number" if you give it a "negative" value in Seek.
>
> Sorry...

And here was me thinking the file io in vb6 didn't need replacing :-)

Michael


Mike D Sutton

unread,
Mar 20, 2006, 5:52:46 PM3/20/06
to
Got it; the SetFilePointer() call 0f -4 called after the signature was read was failing in large files since I was
passing in NULL for the high DWord as I didn't require it, but and it's actually an in/out rather than optional
parameter. When the file size got large enough to require using the high DWord, it choked because it couldn't write the
value and so didn't perform the seek operation, which subsequently meant the ZipLocalFileHead structure was 4 bytes off.
In Win2K+ there is a SetFilePointerEx() API call which makes all these problems go away, but in order to keep this code
compatible with previous OS' I've stuck with the original method here.

Since we really didn't need to re-read the signature again (it was really just for convenience from the original code),
I've changed the ReadZipLocalFileHeadFromFile() function to optionally skip the signature so the seek back is no longer
required.
I've also changed the main function to return an array of UDTs describing the file's contents, mostly just for VB's
convenience when dealing with large numbers so SDWordToUDWord() can be tucked away and forgotten in some library
somewhere rather than having to be littered through your code.
Here's the new version of the function, I've tested it on a 12GB file with a 5GB file within it and it copes with both:

'***
Private Declare Function CreateFile Lib "Kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByRef lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long


Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long

Private Declare Function SetFilePointer Lib "Kernel32.dll" (ByVal hFile As Long, _
ByVal lDistanceToMove As Long, ByRef lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "Kernel32.dll" (ByVal hFile As Long, ByRef lpBuffer As Any, _
ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByRef lpOverlapped As Any) As Long

Private Type typZipLocalFileHead ' 30 bytes
zlfhSignature As Long ' 0x04034B50
zlfhVersion As Integer
zlfhBitFlag As Integer
zlfhCompression As Integer
zlfhModFileTime As Integer
zlfhModFileData As Integer
zlfhCRC As Long
zlfhCompressedSize As Long
zlfhUncompressedSize As Long
zlfhFileNameLength As Integer
zlfhExtraFieldLength As Integer
End Type

Private Type typZipFileInf
zfiName As String
zfiCompressedSize As Currency
zfiUncompressedSize As Currency
zfiDataOffset As Currency
End Type

Private Const GENERIC_READ As Long = &H80000000
Private Const FILE_SHARE_READ As Long = &H1
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80

Private Const OPEN_EXISTING As Long = &H3
Private Const FILE_CURRENT As Long = &H1


Private Const Bit31 As Currency = 2147483648@ ' 0x80000000
Private Const Bit32 As Currency = 4294967296@ ' 0x100000000

Private Sub Form_Load()
Dim Files() As typZipFileInf, NumFiles As Long, LoopFiles As Long

SET THE ZIP PATH HERE THEN KILL THIS LINE
Const FileName As String = "X:\Path\File.zip"

' Grab file list from .ZIP file
NumFiles = GetZipFileList(FileName, Files())

' Print file list to debug window
Debug.Print "Found " & CStr(NumFiles) & " file" & _
IIf(NumFiles = 1, "", "s") & " in .ZIP:"

For LoopFiles = 0 To NumFiles - 1
With Files(LoopFiles)
Debug.Print vbTab & """" & .zfiName & """";

If (.zfiCompressedSize) Then
Debug.Print " (" & Format(1 - ( _
.zfiCompressedSize / .zfiUncompressedSize), "0.0%") & ")";
Else
If (Right$(.zfiName, 1) = "/") Then
Debug.Print " (Folder)";
Else
Debug.Print " (Empty)";
End If
End If

Debug.Print " @ " & CStr(.zfiDataOffset)
End With
Next LoopFiles
End Sub

Private Function GetZipFileList(ByRef inFile As String, ByRef outFiles() As typZipFileInf) As Long


Dim ReadHead As typZipLocalFileHead
Dim FileString As String
Dim SeekSize As Variant
Dim hFile As Long
Dim ReadLen As Long
Dim SeekHigh As Long, SeekLow As Long

Dim RetArr() As typZipFileInf, ArrLen As Long
Dim NumRet As Long

Const ZipLocalFileHeadSig As Long = &H4034B50

Const ReDimStep As Long = 100

' Make sure file exists
If (Not FileExist(inFile)) Then Exit Function

' Get a free file handle and open the file
hFile = CreateFile(inFile, GENERIC_READ, FILE_SHARE_READ, _
ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0&)
If (hFile) Then
Do ' Read a chunk signature
Call ReadFile(hFile, ReadHead.zlfhSignature, _
Len(ReadHead.zlfhSignature), ReadLen, ByVal 0&)

' Check for a local file header signature


If (ReadHead.zlfhSignature = ZipLocalFileHeadSig) Then
' Ok, read the full structure

ReadHead = ReadZipLocalFileHeadFromFile(hFile, False)

If (NumRet >= ArrLen) Then
' Re-allocate return array in chunks for speed
ArrLen = ArrLen + ReDimStep
ReDim Preserve RetArr(0 To ArrLen - 1) As typZipFileInf
End If

With ReadHead ' Get the file name
If (.zlfhFileNameLength) Then
FileString = Space(.zlfhFileNameLength)
Call ReadFile(hFile, ByVal FileString, _
.zlfhFileNameLength, ReadLen, ByVal 0&)

RetArr(NumRet).zfiName = FileString
End If

' Fill rest of structure for this file
RetArr(NumRet).zfiCompressedSize = SDWordToUDWord(.zlfhCompressedSize)
RetArr(NumRet).zfiUncompressedSize = SDWordToUDWord(.zlfhUncompressedSize)
RetArr(NumRet).zfiDataOffset = GetFilePointer(hFile)

' Work out how much extra data to skip over

SeekSize = CDec(SDWordToUDWord(.zlfhCompressedSize))
If (.zlfhExtraFieldLength) Then _
SeekSize = SeekSize + SDWordToUDWord(.zlfhExtraFieldLength)

If (.zlfhBitFlag And &H4) Then

SeekSize = SeekSize + 12

RetArr(NumRet).zfiDataOffset = RetArr(NumRet).zfiDataOffset + 12
End If

' Convert seek to low and high DWords and seek to next record
SeekLow = DecToDWords(SeekSize, SeekHigh)
Call SetFilePointer(hFile, SeekLow, SeekHigh, FILE_CURRENT)
End With

' Increment file count
NumRet = NumRet + 1


Else
Exit Do
End If
Loop

' Close the file
Call CloseHandle(hFile)

' Trim junk off end of array and return
ReDim Preserve RetArr(0 To NumRet - 1) As typZipFileInf
GetZipFileList = NumRet
outFiles = RetArr
End If
End Function

Private Function GetFilePointer(ByVal inhFile As Long) As Variant ' Decimal
Dim FileHigh As Long
GetFilePointer = CDec(SDWordToUDWord(SetFilePointer(inhFile, 0, FileHigh, FILE_CURRENT)))
If (FileHigh) Then GetFilePointer = GetFilePointer + (CDec(FileHigh) * Bit32)
End Function

Private Function FileExist(ByVal inFile As String) As Boolean
On Error Resume Next
FileExist = FileLen(inFile) + 1
End Function

Private Function ReadZipLocalFileHeadFromFile(ByVal inFile As Long, _
Optional ByVal inReadSig As Boolean = True) As typZipLocalFileHead
Dim ReadLen As Long

' Read structure from file, taking into account padding bytes before CRC
With ReadZipLocalFileHeadFromFile

If (inReadSig) Then ' Read signature bytes


Call ReadFile(inFile, .zlfhSignature, 14, ReadLen, ByVal 0&)

Else ' Don't read signature bytes (already read for validation)
Call ReadFile(inFile, .zlfhVersion, 10, ReadLen, ByVal 0&)
End If

Call ReadFile(inFile, .zlfhCRC, 16, ReadLen, ByVal 0&)
End With
End Function

Private Function DecToDWords(ByVal inDec As Variant, ByRef outHigh As Long) As Long


If (inDec >= Bit32) Then outHigh = UDWordToSDWord(Int(inDec / Bit32)) Else outHigh = 0&
DecToDWords = UDWordToSDWord(inDec)

End Function

Private Function UDWordToSDWord(ByVal inUDWord As Currency) As Long
Dim TempVal As Currency ' Unsigned to signed DWord

TempVal = inUDWord - (Int(inUDWord / Bit32) * Bit32) ' Trim overflow
UDWordToSDWord = TempVal - (Int(TempVal / Bit31) * Bit31)

If (TempVal >= Bit31) Then UDWordToSDWord = UDWordToSDWord Or &H80000000
End Function

Private Function SDWordToUDWord(ByVal inLong As Long) As Currency


SDWordToUDWord = CCur(inLong And &H7FFFFFFF)
If (inLong < 0) Then SDWordToUDWord = SDWordToUDWord + Bit31
End Function
'***

Hope this helps,

DIOS

unread,
Mar 20, 2006, 6:51:06 PM3/20/06
to
ive tested on my 2.6GB file and it works ok. ill test on my big-o
10.2GB file at home and report the findings. i have an API book that i
completely forgot about so i think im gonna read that a bit to better
understand the hi and lo bytes and how the API calls work with them as
thats where im getting stuck. i have VB Developers guide to the Win32
API by Steve brown (Sybex) but it doesnt look like it covers the API
discussed here.

AGP

Schmidt

unread,
Mar 20, 2006, 6:42:10 PM3/20/06
to

"Mike D Sutton" <ED...@mvps.org> schrieb im Newsbeitrag
news:uJViCEHT...@TK2MSFTNGP14.phx.gbl...

> Here's the new version of the function, ...
Works nice here. :-)
(But tested only with Zips < 2GB)

> I've tested it on a 12GB file with a 5GB file within it and it copes with
both:

Just to make sure:
.zlfhUncompressedSize is a 32Bit-Value
What's the Max-Size for a single (uncompr.) ZipFile-Member..., 4GB?
What size is reported for .zfiUncompressedSize for your 5GB-File?
Are there (backward-compatible) 64Bit-Extensions for the Zip-Header defined
somewhere?

Olaf

AGP

unread,
Mar 21, 2006, 1:09:06 AM3/21/06
to

"DIOS" <sind...@gmail.com> wrote in message
news:1142898666.5...@g10g2000cwb.googlegroups.com...

wow that is amazing. i think its working!
on my tests:
3.92GB zip file with many small files - ok
10.7GB zip file with many small files - ok
16GB zip file with many small files and two large files(3.92Gb and 10.7GB)
- not fully enumerated but i may be pushing the limits here.

im going to do further tests as far as detailed comparisons with what
WinZip9 reports.
Also I will probably tweak the code a bit to gather some other information.
i will post
the results hopefuly within a couple days.

AGP

AGP

unread,
Mar 23, 2006, 2:15:31 AM3/23/06
to
> wow that is amazing. i think its working!
> on my tests:
> 3.92GB zip file with many small files - ok
> 10.7GB zip file with many small files - ok
> 16GB zip file with many small files and two large files(3.92Gb and 10.7GB)
> - not fully enumerated but i may be pushing the limits here.
>
> im going to do further tests as far as detailed comparisons with what
> WinZip9 reports.
> Also I will probably tweak the code a bit to gather some other
information.
> i will post
> the results hopefuly within a couple days.


ok ive done some tweaking on my own code and it works just like yours does
after implementation of some of your logic. now the code breaks both on
yours
and mines and i think i have narrowed it down to the following:

37 ReadFile hFile, .CompressedSize, 4, Ret, ByVal 0&
38 ReadFile hFile, .UncompressedSize, 4, Ret, ByVal 0&
39 ReadFile hFile, .FileNameLength, 2, Ret, ByVal 0&
40 ReadFile hFile, .ExtraFieldLength, 2, Ret, ByVal 0&
41 ReadFile hFile, .FileCommentLength, 2, Ret, ByVal 0&
42 ReadFile hFile, .DiskNumberStart, 2, Ret, ByVal 0&
43 ReadFile hFile, .InternalAttr, 2, Ret, ByVal 0&
44 ReadFile hFile, .ExternalAttr, 4, Ret, ByVal 0&
45 ReadFile hFile, .RelOffsetLocHdr, 4, Ret, ByVal 0&
46 .Filename = String$(.FileNameLength, vbKeySpace)
47 ReadFile hFile, ByVal .Filename, Len(.Filename), Ret,
ByVal 0&
48 If .ExtraFieldLength Then
49 .ExtraField = String$(.ExtraFieldLength, vbKeySpace)
50 ReadFile hFile, ByVal .ExtraField, Len(.ExtraField),


Ret, ByVal 0&
End If

the debug response for each line is as follows:
37 307021362
38 -1268774302
39 -4113
40 32109
41 -18703
42 23879
43 22629
44 0
45 -913938846
46 bombs due to negative .FileNameLength

should i assume those negative values are actual large numbers outside the
realm of a Long and
then convert them somehow to say a currency value?

Rgds,
AGP


Mike D Sutton

unread,
Mar 23, 2006, 11:46:37 AM3/23/06
to
> wow that is amazing. i think its working!
> on my tests:
> 3.92GB zip file with many small files - ok
> 10.7GB zip file with many small files - ok
> 16GB zip file with many small files and two large files(3.92Gb and 10.7GB)
> - not fully enumerated but i may be pushing the limits here.
>
> im going to do further tests as far as detailed comparisons with what
> WinZip9 reports.
> Also I will probably tweak the code a bit to gather some other
> information.
> i will post
> the results hopefuly within a couple days.

I should have a new version available tonight with a completely rewritten
parser including Zip64 support.
I'll post back here when it's available.
Cheers,

DIOS

unread,
Mar 23, 2006, 3:59:00 PM3/23/06
to
cool. i can probably user your results to tweak my code. the code that
i use has additional detail in the header as such:

Private Type ZipFileCentralHeader
VersionMadeBy As Integer
VersionNeededToExtract As Integer
Flag As Integer
CompressionMethod As Integer

time As Integer
date As Integer


CRC32 As Long
CompressedSize As Long
UncompressedSize As Long
FileNameLength As Integer
ExtraFieldLength As Integer
FileCommentLength As Integer
DiskNumberStart As Integer
InternalAttr As Integer
ExternalAttr As Long
RelOffsetLocHdr As Long

FileName As String


ExtraField As String
FileComment As String
End Type
Private Type ZipFileEndCentralHeader
DiskNumberThis As Integer
DiskNumberCentralDir As Integer
CentralDirEntriesThisDisk As Integer
CentralDirEntriesTotal As Integer
SizeCentralDir As Long
CentralDirOffset As Long
FileCommentLength As Integer
FileComment As String
End Type

The ZipFileEndCentralHeader structure tells you how many items there
are so that you can use this in a progress report. Once you have that
then you can go into the ZipFileCentralHeader to get the details for
each item. I have it working well and it matches WinZip and another
app, except for the file comments and large files. On some large zip
files it works ok but once you zip up several large files into one zip
then it breaks. I can send you what I have if you want to take a look
at it. I spent the better part of yesterday tweaking it and it seems to
work except for what i posted before this post.

AGP

Mike D Sutton

unread,
Mar 24, 2006, 5:21:29 PM3/24/06
to
> cool. i can probably user your results to tweak my code. the code that
> i use has additional detail in the header as such:
<code snipped>

> The ZipFileEndCentralHeader structure tells you how many items there
> are so that you can use this in a progress report. Once you have that
> then you can go into the ZipFileCentralHeader to get the details for
> each item. I have it working well and it matches WinZip and another
> app, except for the file comments and large files. On some large zip
> files it works ok but once you zip up several large files into one zip
> then it breaks. I can send you what I have if you want to take a look
> at it. I spent the better part of yesterday tweaking it and it seems to
> work except for what i posted before this post.

Ok, here we go; grab my ZIPInfo class from here:
Http://EDais.mvps.org/Code/Libraries/ZIPInfo/clsZIPInfo.cls
The file enumeration is all event based, so here's a quick example of how to
use it:

'***
Private WithEvents MyZIP As clsZIPInfo

Private Sub Form_Load()


Const FileName As String = "X:\Path\File.zip

Set MyZIP = New clsZIPInfo
Call MyZIP.ReadFile(FileName)
Set MyZIP = Nothing
End Sub

' Monster event declaration with all details about this file
' Oh how I wish we could pass structs through a class' public interface in
VB..
Private Sub MyZIP_OnFile(ByVal inVersionMadeBy As enZipInfVersion, _
ByVal inVersionNeededToExtract As enZipInfVersion, _
ByVal inGeneralPurposeBitFlag As Integer, _
ByVal inCompressionMethod As enZipInfCompressionMethod, _
ByVal inLastModified As Date, ByVal inCrc32 As Long, _
ByVal inCompressedSize As Variant, ByVal inUncompressedSize As Variant,
_
ByVal inDiskStartNumber As Currency, ByVal inInternalFileAttributes As
Integer, _
ByVal inExternalFileAttributes As Long, ByVal inOffsetToLocalHeader As
Variant, _
ByRef inFileName As String, ByRef inFileComment As String, ByRef
outCancel As Boolean)
Debug.Print "File: """ & inFileName & """"
End Sub

Private Sub MyZIP_ReadError(ByRef inError As enZipReadError)
Call MsgBox(MyZIP.ZipReadErrorToString(inError), vbCritical, "ZIPInfo")
End Sub
'***

This uses the central directory located at the end of the file, and also
properly interprets zip comments and Zip64 structures. If you want to
cancel enumeration at any point during a file parse then set the outCancel
parameter of the OnFile() event handler to true. This one should be a lot
more robust than the previous ones *knock on wood* but let me know if you
have any problems with it.
I'll be writing docs and a demo app for the page soon, but for now if you
have any questions about it then just post back here or e-mail me.
Hope this helps,

Mike

P.s. Remind me next time to avoid posts about large file support in VB.. ;)

AGP

unread,
Mar 25, 2006, 1:34:07 AM3/25/06
to

"Mike D Sutton" <ED...@mvps.org> wrote in message
news:%23fpsOF5...@TK2MSFTNGP09.phx.gbl...

>
> Ok, here we go; grab my ZIPInfo class from here:
> Http://EDais.mvps.org/Code/Libraries/ZIPInfo/clsZIPInfo.cls
> The file enumeration is all event based, so here's a quick example of how
to
> use it:
>
>
> Mike
>
> P.s. Remind me next time to avoid posts about large file support in VB..
;)
>

whew!! man that is some heavy conversions. what was your approach? im
looking through
the code and im getting a bit lost to tell you the truth but i can make sens
of it once I know
the general logic.

Also, I ws testing and all the files ive tested process no problem so it
looks to me like its working.
the only thing is that the attributes (external and internal) seem to result
in just some wierd numbers.
i should get like 32 or 35 but the results im getting are rather large. also
the offsets are often repeated.
i would say that the offsets should be different for each file. i'm looking
at it and i cant see where you extract
the attributes.

Rgds,
AGP


Schmidt

unread,
Mar 25, 2006, 12:57:11 PM3/25/06
to

"Mike D Sutton" <ED...@mvps.org> schrieb im Newsbeitrag
news:%23fpsOF5...@TK2MSFTNGP09.phx.gbl...

> Ok, here we go; grab my ZIPInfo class from here:

Whow, a lot of work - and it works great (tested with 5 different
zips, some with deep SubFolder-structures and many small files).

Not tested yet with Zips>4GB containing Files>4GB.
Waiting for the results of the guys with the "big ones".
;-)

> P.s. Remind me next time to avoid posts about large
> file support in VB.. ;)

<g>

Olaf


Mike D Sutton

unread,
Mar 25, 2006, 4:27:36 PM3/25/06
to
> Whow, a lot of work - and it works great (tested with 5 different
> zips, some with deep SubFolder-structures and many small files).

Thanks for the feedback.

> Not tested yet with Zips>4GB containing Files>4GB.
> Waiting for the results of the guys with the "big ones".

The base parser was tested on a 12GB .ZIP file, then after changing to event
model and adding properties etc it was tested on a 6GB file. Both of these
had a >4GB file internally to test large file support and everything so far
has come back positive. Theoretically it should support anything up to
0.8PB before running into problems but there may potentially be some obscure
ZIP nuances that I've overlooked.

Mike

AGP

unread,
Mar 25, 2006, 11:36:25 PM3/25/06
to
"Mike D Sutton" <ED...@mvps.org> wrote in message
news:%23ERcxLF...@tk2msftngp13.phx.gbl...

> > Whow, a lot of work - and it works great (tested with 5 different
> > zips, some with deep SubFolder-structures and many small files).
>
> Thanks for the feedback.
>
> > Not tested yet with Zips>4GB containing Files>4GB.
> > Waiting for the results of the guys with the "big ones".
>
> The base parser was tested on a 12GB .ZIP file, then after changing to
event
> model and adding properties etc it was tested on a 6GB file. Both of
these
> had a >4GB file internally to test large file support and everything so
far
> has come back positive. Theoretically it should support anything up to
> 0.8PB before running into problems but there may potentially be some
obscure
> ZIP nuances that I've overlooked.
>
> Mike

i guess my earlier post didnt come through with attachement.
but i tested several large zips...4, 10, 14 and 16GB zip files
some with large files in the contents and all were processed.
actually the code is alot faster than the OCX I was testing.
only thing i saw was that the attributes and offsets dont seem
right. even when i translate the attributes to string they dont
seem right. in the screenshot:
www.warpengine.com/files/ziptest1.gif
the top is the third party OCX, the middle is WinZip9, and
the bottom is Mike's code. You can see the attributes should be
something like 30 or 35 but come across as really large numbers
and the offsets should be large and non-repeating. it looks almost
like they are reversed.

AGP


AGP

unread,
Mar 27, 2006, 7:02:02 PM3/27/06
to

"AGP" <sindiz...@softhome.net> wrote in message
news:dToVf.60246$Jd.1...@newssvr25.news.prodigy.net...

> "Mike D Sutton" <ED...@mvps.org> wrote in message
> news:%23ERcxLF...@tk2msftngp13.phx.gbl...

> > > Whow, a lot of work - and it works great (tested with 5 different
> > > zips, some with deep SubFolder-structures and many small files).
> >
> > Thanks for the feedback.
> >
> > > Not tested yet with Zips>4GB containing Files>4GB.
> > > Waiting for the results of the guys with the "big ones".
> >
> > The base parser was tested on a 12GB .ZIP file, then after changing to
> event
> > model and adding properties etc it was tested on a 6GB file. Both of
> these
> > had a >4GB file internally to test large file support and everything so
> far
> > has come back positive. Theoretically it should support anything up to
> > 0.8PB before running into problems but there may potentially be some
> obscure
> > ZIP nuances that I've overlooked.
> >
> > Mike
>
> i guess my earlier post didnt come through with attachement.
> but i tested several large zips...4, 10, 14 and 16GB zip files
> some with large files in the contents and all were processed.
> actually the code is alot faster than the OCX I was testing.
> only thing i saw was that the attributes and offsets dont seem
> right. even when i translate the attributes to string they dont
> seem right. in the screenshot:
> www.warpengine.com/files/ziptest1.gif
> the top is the third party OCX, the middle is WinZip9, and
> the bottom is Mike's code. You can see the attributes should be
> something like 30 or 35 but come across as really large numbers
> and the offsets should be large and non-repeating. it looks almost
> like they are reversed.
>
> AGP

also, on your ReadFile() routine I can pass the current entry number and the
total
number of entries to the DoFile() routine so that it can be used for a
progression bar.
That would probably be the best way sine every thing eventually ends up in
DoFile().

AGP

DIOS

unread,
Mar 31, 2006, 3:37:15 PM3/31/06
to
Anyone still following this thread??

AGP

Mike D Sutton

unread,
Apr 3, 2006, 6:02:09 PM4/3/06
to
For anyone still following the thread, here's a new version (1.1) with a couple of minor bugs fixed:
Http://EDais.mvps.org/Code/Libraries/ZIPInfo/clsZIPInfo.cls
I'll put up a page for it in the libraries section of the site shortly.
Cheers,

DIOS

unread,
Apr 3, 2006, 9:14:59 PM4/3/06
to
ill check out the revised code tonite if i dont fall asleep on the
keyboard....(one of those days.)

AGP

0 new messages