The following code works just fine when extracting anything from starcraft maps, but SFileOpenArchive seems to fail when trying to extract anything else (for example, ExtraWork dlls, unless they don't have (listfile)s) and files within internal directories. Can anyone see what seems to be the problem?
void ExtractMPQ(char *filename, char *toget) {
HMODULE hLibStorm = LoadLibrary("Storm.dll");
FILE *file;
char *asdf;
unsigned long hMPQ, hMPQFile, filesize, highdword;
unsigned long SFileDestroy = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(262));
unsigned long SFileSetLocale = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(272));
unsigned long SFileOpenArchive = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(266));
unsigned long SFileOpenFileEx = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(268));
unsigned long SFileGetFileSize = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(265));
unsigned long SFileReadFile = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(269));
unsigned long SFileCloseFile = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(253));
unsigned long SFileCloseArchive = (unsigned long)GetProcAddress(hLibStorm, MAKEINTRESOURCE(252));
__asm {
push 'enUS'
call SFileSetLocale
test eax, eax
jz errored
call SFileDestroy
test eax, eax
jz errored
lea eax, [hMPQ]
push eax
push 0
push 0
mov eax, filename
push eax
call SFileOpenArchive
test eax, eax
jz errored
lea eax, [hMPQFile]
push eax
push 0
push toget
push hMPQ
call SFileOpenFileEx
test eax, eax
jz errored
lea eax, [highdword]
push eax
push hMPQFile
call SFileGetFileSize
mov filesize, eax
cmp eax, -1
je errored
push eax
call malloc
pop ecx
mov asdf, eax
push 0
push 0
push filesize
push eax
push hMPQFile
call SFileReadFile
test eax, eax
jz errored
push '\\'
push toget
call strchr
add esp, 8
mov ecx, toget
test eax, eax
jz over
mov ecx, eax
inc ecx
over:
mov highdword, 'bw'
lea eax, [highdword]
push eax
push ecx
call fopen
mov file, eax
add esp, 8
push eax
push filesize
push 1
push asdf
call fwrite
add esp, 10h
push file
call fclose
pop ecx
push asdf
call free
pop ecx
push hMPQFile
call SFileCloseFile
test eax, eax
jz errored
push hMPQ
call SFileCloseArchive
test eax, eax
jz errored
push hLibStorm
call dword ptr [FreeLibrary]
}
return;
errored:
AddChat(vbRed, "ExtractMPQ Failed!");
return;
}
...
ExtractMPQ("C:\\Documents and Settings\\Owner\\Desktop\\IX86Mindsight.mpq", "(listfile)");
If it's any help, here's my VB code which seems to work just fine:
Option Explicit
Private Declare Function SFileCloseArchive Lib "Storm.dll" Alias "#252" (ByVal hMPQ As Long) As Boolean
Private Declare Function SFileCloseFile Lib "Storm.dll" Alias "#253" (ByVal hFile As Long) As Boolean
Private Declare Function SFileDestroy Lib "Storm.dll" Alias "#262" () As Boolean
Private Declare Function SFileGetFileSize Lib "Storm.dll" Alias "#265" (ByVal hFile As Long, ByRef lpFileSizeHigh As Long) As Long
Private Declare Function SFileOpenArchive Lib "Storm.dll" Alias "#266" (ByVal lpFileName As String, ByVal dwPriority As Long, ByVal dwFlags As Long, ByRef hMPQ As Long) As Boolean
Private Declare Function SFileOpenFileEx Lib "Storm.dll" Alias "#268" (ByVal hMPQ As Long, ByVal lpFileName As String, ByVal dwSearchScope As Long, ByRef hFile As Long) As Boolean
Private Declare Function SFileReadFile Lib "Storm.dll" Alias "#269" (ByVal hFile As Long, lpBuffer As Byte, ByVal nNumberOfBYTEsToRead As Long, ByRef lpNumberOfBYTEsRead As Long, lpOverlapped As Long) As Boolean
Private Declare Function SFileAuthenticateArchive Lib "Storm.dll" Alias "#251" (ByVal hMPQ As Long, ByRef dwAuthenticationStatus As Long) As Boolean
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long
Public Function ExtractFromMPQ(ByVal strArchive As String, ByVal strFile As String) As String
Dim hMPQ As Long
Dim hFile As Long
Dim hOutput As Long
Dim lngSize As Long
Dim dwBytes As Long
Dim szBuffer() As Byte
Dim Status As Long
On Error GoTo Erred
SFileDestroy
SFileOpenArchive SettingsFolder & "\Tmp\MPQs\" & strArchive, 0, 0, hMPQ
SFileOpenFileEx hMPQ, strFile, 0, hFile
If hFile <> 0 Then
SFileAuthenticateArchive hMPQ, Status
If Status = &H0 Or Status = &H1 Or Status = &H5 Then
lngSize = SFileGetFileSize(hFile, 0)
ReDim szBuffer(0 To lngSize)
SFileReadFile hFile, szBuffer(0), lngSize, dwBytes, ByVal &H0
If dwBytes <> lngSize Then
ExtractFromMPQ = "MPQ Corrupt (" & dwBytes & " / " & lngSize & ")"
GoTo Failed
End If
If LenB(Dir$(SettingsFolder & "\Tmp\MPQs\" & strFile)) > 0 Then Kill SettingsFolder & "\Tmp\MPQs\" & strFile
hOutput = CreateFileA(SettingsFolder & "\Tmp\MPQs\" & strFile, &H40000000, &H2, ByVal 0&, &H2, ByVal 0&, ByVal 0&)
WriteFile hOutput, szBuffer(0), lngSize, dwBytes, ByVal &H0
CloseHandle hOutput
If dwBytes <> lngSize Then
ExtractFromMPQ = "DLL Corrupt (" & dwBytes & " / " & lngSize & ")"
GoTo Failed
End If
SFileCloseFile hFile
SFileCloseArchive hMPQ
SetFileTimeInfo SettingsFolder & "\Tmp\MPQs\" & strFile, GetFileTimeInfo(SettingsFolder & "\Tmp\MPQs\" & strArchive), GetFileTimeInfo(SettingsFolder & "\Tmp\MPQs\" & strArchive), GetFileTimeInfo(SettingsFolder & "\Tmp\MPQs\" & strArchive)
ExtractFromMPQ = "OK"
Else
ExtractFromMPQ = "MPQ not authentic"
End If
Else
ExtractFromMPQ = "Could not find " & strFile & " in " & strArchive
End If
SFileDestroy
Exit Function
Failed:
If hFile <> 0 Then SFileCloseFile hFile
If hMPQ <> 0 Then SFileCloseArchive hMPQ
Exit Function
Erred:
ExtractFromMPQ = Err.Description
GoTo Failed
End Function
Actually, now that I look at it today, my own works just fine as well... mmm, idk.
So, better question: How would I get at those files inside of an internal directory? Would I have to call another storm function to change the current directory or something? Passing the raw filename and path to the lib doesn't seem to work.
I... never got that far. But if I had to guess, I'd say SFileSetBasePath.
Hm, I wonder what the params are for that?
I guess i'll check what battle.snp does...
EDIT**
Oops! I just realized, since when would battle.snp need that functionality? Hmm, i guess i'll check starcraft.exe.
EDIT***
Well, starcraft.exe doesn't call it either.
Apparently it passes the filename just like that?
.text:004CC3A4 loc_4CC3A4: ; CODE XREF: sub_4CC320+5A
.text:004CC3A4 push 104h
.text:004CC3A9 push offset aStareditScenar ; "staredit\\scenario.chk"
.text:004CC3AE lea ecx, [ebp+var_20C]
.text:004CC3B4 push ecx
.text:004CC3B5 call SStrNCpy
.text:004CC3BA
.text:004CC3BA loc_4CC3BA: ; CODE XREF: sub_4CC320+82
.text:004CC3BA push 88Bh
.text:004CC3BF push offset aStarcraftSw_66 ; "Starcraft\\SWAR\\lang\\maphdr.cpp"
.text:004CC3C4 push 1
.text:004CC3C6 push 0
.text:004CC3C8 lea edx, [ebp+var_20C]
.text:004CC3CE push edx ; effectively contains staredit\scenario.chk
.text:004CC3CF xor ecx, ecx
.text:004CC3D1 lea eax, [ebp+var_4]
.text:004CC3D4 call loc_4D2940
.text:004D2940 push ebp
.text:004D2941 mov ebp, esp
.text:004D2943 push ecx
.text:004D2944 push ebx
.text:004D2945 push esi
.text:004D2946 mov esi, [ebp+8]
.text:004D2949 mov ebx, eax
.text:004D294B lea eax, [ebp-4]
.text:004D294E push eax ; phFile
.text:004D294F push ecx ; "int"
.text:004D2950 push esi ; filename
.text:004D2951 push 0 ; hArchive
.text:004D2953 call SFileOpenFileEx
...and look at that. all of my mpq archive extracting woes are gone.
double backslash ftw. I'll have to make a note of that, just in case...
Quote from: Andy on March 25, 2008, 08:51 PM
double backslash ftw. I'll have to make a note of that, just in case...
AFAIK the double backslash is a language specific rule; you don't need to worry about it with VB.
Quote from: brew on March 25, 2008, 02:56 PM
Actually, now that I look at it today, my own works just fine as well... mmm, idk.
So, better question: How would I get at those files inside of an internal directory? Would I have to call another storm function to change the current directory or something? Passing the raw filename and path to the lib doesn't seem to work.
keep in mind your project in whatever IDE you're using might not have the same running location ('current directory') as your files so you have to include the whole path (or a part of it)
this program uses Storm Library and SFMPQ Library.
Programmed in VC++ 6.0
Unused Unprotector 2 Source code.
Link: http://sunrub.dothome.co.kr/Unused_Unprotector_2_source.zip