Jonney thanx for the info on the 2 typos. I've updated the code in post #39.
To all. The code will correctly extract/uncompress files/folders dragged from within a compressed folder
Printable View
Jonney thanx for the info on the 2 typos. I've updated the code in post #39.
To all. The code will correctly extract/uncompress files/folders dragged from within a compressed folder
Jonney,
What utility/version did you use to Zip the folder/files?
With WinZip 14 I am not getting Unicode filenames with your ZippedUniFiles.zip.
If I Zip a folder here (WinZip 14) with Unicode filenames they are OK.
Also get Unicode filenames with WinRar and 7Zip.
From http://www.winzip.com/whatsnew112.htm :
WinZip prior to 11.2 does not support Unicode characters in filenames.
For Unicode support, the Zip file must be created and opened with a zip utility that supports the Unicode extensions to the Zip file format such as WinZip 11.2
What utility/version did you use to Zip the folder/files?
--- Winzip 9
With WinZip 14 I am not getting Unicode filenames with your ZippedUniFiles.zip.
If I Zip a folder here (WinZip 14) with Unicode filenames they are OK.
Also get Unicode filenames with WinRar and 7Zip.
-- I downloaded and installed Winzip 15 on my Win7. It still doesn't support.
a. Locale = 1033 (English)
Step 1: Compressed a folder with filename in Chinese Characters using Winzip V15
Step 2: I can see right filename in Winzip windows
Step 3: Run Lavolpe's project, Failed to show Original filename with weird characters
Step 4: Change locale = 2052 (Chinese PRC) and restart Win7
Step 4: Run Lavolpe's project, Failed to show Original filename with wrong characters mixed Chinese. But interestingly if the compressed zip file contained another zip file,that zip file show right chinese characters in Winzip window or unzipped without demage.
b. Locale = 2052 (Chinese,PRC)
Step 1: Compressed a folder with filename in Chinese Characters using Winzip V15
Step 2: I can see right filename in Winzip windows
Step 3: Run Lavolpe's project, show right filenames
Step 4: Change locale = 1033(English) and restart Win7
Step 4: Run Lavolpe's project, Failed to show Original filename with weird characters. But interestingly if the compressed zip file contained another zip file,that zip file show right chinese characters in Winzip window or unzipped without demage.
From http://www.winzip.com/whatsnew112.htm :
WinZip prior to 11.2 does not support Unicode characters in filenames.
For Unicode support, the Zip file must be created and opened with a zip utility that supports the Unicode extensions to the Zip file format such as WinZip 11.2
--- Winzip v15 seems not 100% unicode compatible even it can zip/unzip files with Unicode filenames.I am not clear why the treeview of windows explorer can show winzip compressed folder but why winRAR can't??? It is done by Windows Explorer or Winzip?
If it was done by Windows Explorer,it is explorer problem in unicode;If it was done by Winzip,it is Winzip problem in unicode. Just a GUESS.
Can you reupload ZippedUniFiles.zip using WinZip 15?
I think Explorer is showing MBCS Chinese characters when locale is 1033(English).
The correct folder name is ChrW$(&H4E2D) & ChrW$(&H6587)
Explorer (Locale 1033) shows this as Íð+-
So is Explorer just extracting the Zip filenames using legacy code and doesn't support "Unicode extensions to the Zip file format".
I see that Chilkat Zip C / C++ Library "Supports Unicode filename zip file format extensions".
http://www.chilkatsoft.com/zip-library.asp
Also Xceed Zip Compression Library "Stores and retrieves the latest zip file format extensions, allowing Unicode filenames and NT file attributes, extra time stamps, and security permissions to be stored in the zip file.".
http://xceed.com/Zip_ActiveX_Features.html
Thanks LaVolpe
That works great. Can happily copy files out of compressed folder with subfolders to my application. No longer have to worry about foreground windows and finding the source shell.
When copying like this do you think it should used the same creation time etc for the copied file as that of the original?
It's up to you. If you want to, that data is part of the file descriptor and you can use the API SetFileTime (example at bottom of that link).
Reference post #39 for the code being talked about.
Edited. As a matter of completeness, there are 2 holes in that code
1) I don't immediately know how to move, vs. copy, the file from a compressed folder during/after drag-drop. Knowing/fixing that would make the routine more complete. Prior to this thread, I never even used compressed folders. So all this was new to me.
2) It is possible to get data via IStorage vs IStream, though I haven't been able to test that as I'm always getting IStream even if I ask for IStorage. If someone knows how we can get Windows to give us IStorage, I can add appropriate code for that. Writing data to file with IStorage could be far simpler than using IStream. Additionally, if Windows adds IStorage vs. IStream, then code will just ignore it. Code would be more complete with IStorage handling.
Not a hole, but something each should do depending on their requirements. Several places in that code, I left comments/spots for error handling. Specific errors should be handled
a) Folder failed to be created with CreateDirectoryW. Possible reasons: already exists (ignore error), anything else: handle it & stop processing files
-- optional: test for folder's existance before calling CreateDirectoryW
b) Target file fails to be created. Possible reasons: no drive space, no permissions, existing file/folder to overwrite is read-only/locked. Handle it & stop processing files
c) Failed to create a mapped file or view of mapped file. Possible reasons: chunk size too big? Handle it & stop processing files
d) Failed to read stream. lRead <> [number of bytes attemped to read] or varRtn<>0. Possible reasons: unknown. Handle it & stop processing files
e) File contents not passed as IStream (files vs. directories). Possible reason: File placed in Data object as HGlobal or IStorage. Handle these with separate code, i.e.
Room for enhancement. There are 2 places in that code where one can create/call a Public Event if the code were added to a class. That public event could be used for progress. Just a suggestion/idea.Code:Select Case fMedium.TYMED
Case TYMED_ISTREAM
Case TYMED_HGLOBAL
Case TYMED_ISTORAGE ' value is 8
Case Else
' handle the exception
End Select
1) Within GetDroppedCompressedFiles routine's loop. You could forward which file number & total files being processed and current file name
2) Within the SaveSteamToFile. If chunking the stream, you could return percentage (bytesWritten/FileSize) of file being processed & file name
3) I'd suggest changing GetDroppedCompressedFiles to a function that returns true/false & test for the CF_FILECONTENTS & CF_FILEGROUPDESCRIPTORW in the OLEDragDrop before calling GetDroppedCompressedFiles. What's the point of calling it if those aren't in the Data object?
I chose to set the last write time (modified) time to that of the original file as this is what seems to happen on a normal cut and paste. creation and last accessed times are set to the current time.
Yes, not sure about the move versus copy. If its a normal file drop, then setting the copy of move effect flags causes the source to tidy up. i.e. only ever have to copy the file, setting only the move effect flag (and clearing the copy one) causes the source to delete the file after the drop. This is what the documentation suggests.
However, this does not seem to happen if the effect is set to move, the source does not delete the file. Although I one point during my testing I was sure it did.
For all. MSDN provides some conflicting information described below which may effect release of the IStream after transferring file data.
Souce page. Notice conflicting comments highlighted in blue below
Quote:
Originally Posted by MSDN TYMED_ISTREAM
And from MSDN's page for ReleaseStgMedium function, this.Quote:
Originally Posted by MSDN Remarks for post-drag/drop
Majority wins? If you agree, the code in post #39 should be modified as soQuote:
Originally Posted by MSDN
Routine: GetDroppedCompressedFiles
Change from: If fMedium.pUnkForRelease <> 0 Then ' are we to release the stream?
Change to: If fMedium.pUnkForRelease = 0 Then ' are we to release the stream?
Note: No issues noted and may be that Windows Explorer checks if the stream was released and releases it if not ??? But I wouldn't bet my career on it without knowing for sure.
The provider indicates that the receiver of the medium is responsible for freeing the medium by specifying NULL for the punkForRelease structure member. Then the receiver calls ReleaseStgMedium, which makes a call as described in the following table depending on the type of storage medium being freed.
So yes I believe you are right and if it is null, then we have to release it.
Although any vaguely similar code examples I find seem to release it regardless.
The issue with using OPC (other people's code). Many coders are lazy and don't want to research how something works; they just use it as is. I, personally, have no problem going to MSDN and researching. That's how I determined the inconsistencies with their statements above. I originally wrote the code based on the TYMED_ISTREAM statements which said to not release it if it is Null. What made me question it was that I was releasing TYMED_HGLOBAL if it was Null -- why the difference? That was enough to make me dig deeper.
I was thinking of posting it in the CodeBank, but am not satisfied yet. I wanted to do some more testing (XP & Vista) to see if Windows ever passes compressed file(s) by IStorage or HGlobal.
Oh, and regarding OPC... not many coders out there understand the core API I am using to access COM interface methods. If someone really wants to understand why the code works and how the API calls trigger the interface methods, they need to understand the API first of all. Then they need to understand how Interfaces are laid out in memory (their VTables specifically). And how inheritance of other interfaces affect the VTable offsets. Low-level stuff in that code. Understanding it may be a challenge at first. It was for me when I first started to mess with that core API a few years ago. And regarding VTables of COM Interfaces, MSDN changed their pages again and list interface methods alphabetically instead of VTable order. One will have to find a good trusted site to get quick lists of VTable orders now.
Edited. Or one could just rewrite the code using a TLB and supported interfaces. Then the low-level API approach would not be needed at all.