|
|
#include <windows.h>
#include <winerror.h>
#include <ole2.h>
#include "cpldebug.h"
#include "cab_dll.h"
//typedef HRESULT (WINAPI *EXTRACT) (PSESSION psess, LPCSTR lpCabName);
VOID FreeFileList(PSESSION psess); VOID FreeFileNode(PFNAME pfname); BOOL IsFileInList(LPSTR pszFile, LPSTR pszFileList); int PrepareFileList(LPSTR pszOutFileList, LPCSTR pszInFileList);
// BUGBUG: Minimum version of Cabinet DLL that supports the new Extract API
// the one that was formerly in URLMON.DLL.
//
#define MIN_CABINETDLL_MSVER 0
#define MIN_CABINETDLL_LSVER 0
//=--------------------------------------------------------------------------=
// ExtractFiles
//=--------------------------------------------------------------------------=
//
// Parameters:
// LPCSTR pszCabName - [in] full qualified filename to the .CAB file
// LPCSTR pszExpandDir- [in] full qualified path to where to extract the file(s)
// DWORD dwFlags - [in] Flags, currently not used
// LPCSTR pszFileList - [in] colon separated list of files to extract from pszCabName
// or NULL for all files
// LPVOID lpReserved - [in] currently not used
// DWORD dwReserved - [in] currently not used
//
// Return HRESULT:
// E_INVALIDARG - if pszCabName or pszExpandDir == NULL
// E_OUTOFMEMORY - if we could not allocate our memory
// E_FAIL - if no files in pszFileList and pszFileList!=NULL
// if not all files from pszFileList are in the .CAB file
// if Extract return S_FALSE
// any E_ code Extract returns
//
// Note: This function would not extract any file from the pszFileList, if not all
// of them are in the .CAB file. If one or more are not in the .CAB file
// the function does not extract any and returns E_FAIL
//
HRESULT WINAPI ExtractFiles( LPCSTR pszCabName, LPCSTR pszExpandDir, DWORD dwFlags, LPCSTR pszFileList, LPVOID lpReserved, DWORD dwReserved) { HINSTANCE hinst; PSESSION psess = NULL; PFNAME pf = NULL; PFNAME pfPriv = NULL; HRESULT hr = E_FAIL; // Return error
LPSTR pszMyFileList = NULL; PFN_EXTRACT fpExtract = NULL; PFN_DLLGETVERSION fpGetVer = NULL; int iFiles = 0; // number of files in list
CABINETDLLVERSIONINFO cabDllVer;
// Do checking for valid values??
if ((!pszCabName) || (!pszExpandDir)) return E_INVALIDARG;
hinst = LoadLibrary("CABINET.DLL"); if (hinst) { fpGetVer = (PFN_DLLGETVERSION)GetProcAddress(hinst, "DllGetVersion");
// Make sure this is the CABINET.DLL that supports the Extract API
//
if ( fpGetVer ) { cabDllVer.cbStruct = sizeof(cabDllVer); fpGetVer( &cabDllVer ); if ( (cabDllVer.dwFileVersionMS > MIN_CABINETDLL_MSVER) || (cabDllVer.dwFileVersionMS == MIN_CABINETDLL_MSVER) /* && (cabDllVer.dwFileVersionLS >= MIN_CABINETDLL_LSVER) */ ) { fpExtract = (PFN_EXTRACT)GetProcAddress(hinst, "Extract"); } }
if (!fpExtract) FreeLibrary(hinst); }
// If we did not get the Extract() API from cabinet.dll go for
// URLMON.DLL
//
if (!fpExtract) { hinst = LoadLibrary("URLMON.DLL"); if (hinst) fpExtract = (PFN_EXTRACT)GetProcAddress(hinst, "Extract"); }
if (fpExtract) { psess = (PSESSION)LocalAlloc(LPTR, sizeof(SESSION)); if (psess) { lstrcpy(psess->achLocation, pszExpandDir); // Initialize the structure
if (pszFileList == NULL) { // Extract all
psess->flags = SESSION_FLAG_EXTRACT_ALL|SESSION_FLAG_ENUMERATE; hr = fpExtract(psess, pszCabName); // BUGBUG: What if psess->erf reports an error??
} else { // I append a '/0' therefor +2
pszMyFileList = (LPSTR)LocalAlloc(LPTR, lstrlen(pszFileList)+2); if (pszMyFileList) { iFiles = PrepareFileList(pszMyFileList, pszFileList); psess->flags = SESSION_FLAG_ENUMERATE;
if ((iFiles > 0) && ( !FAILED(hr = fpExtract(psess, pszCabName)) )) // What if psess->erf reports an error??
{ // If there are files in the list and we enumarated files
// Got the list of files in the cab
pfPriv = NULL; pf = psess->pFileList; while (pf != NULL ) { if (!IsFileInList(pf->pszFilename, pszMyFileList)) { // Delete the node from the list
if (pfPriv == NULL) { // Delete the head
psess->pFileList = pf->pNextName; FreeFileNode(pf); pf = psess->pFileList; } else { pfPriv->pNextName = pf->pNextName; FreeFileNode(pf); pf = pfPriv->pNextName; } } else { // Just go to the next one
pfPriv = pf; pf = pf->pNextName; iFiles--; } }
if ((psess->pFileList) && (iFiles == 0)) { // Reset the error flag
psess->erf.fError = FALSE; psess->erf.erfOper = 0;
psess->pFilesToExtract = psess->pFileList; psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
hr = fpExtract(psess, pszCabName); // BUGBUG: What if psess->erf reports an error??
} else hr = E_FAIL; // File(s) is not in cab.
}
LocalFree(pszMyFileList); pszMyFileList = NULL;
} else hr = E_OUTOFMEMORY; } FreeFileList(psess); LocalFree(psess); psess = NULL; } else hr = E_OUTOFMEMORY; }
if (hinst) FreeLibrary(hinst);
// Extract may only return S_FALSE in a failure case.
if (!FAILED(hr) && (hr == S_FALSE)) hr = E_FAIL;
return (hr); }
VOID FreeFileList(PSESSION psess) { PFNAME rover = psess->pFileList; PFNAME roverprev;
while (rover != NULL) {
roverprev = rover; // save for free'ing current rover below
rover = rover->pNextName;
FreeFileNode(roverprev); }
psess->pFileList = NULL; // prevent use after deletion!
}
VOID FreeFileNode(PFNAME pfname) { CoTaskMemFree(pfname->pszFilename); CoTaskMemFree(pfname); }
BOOL IsFileInList(LPSTR pszFile, LPSTR pszFileList) { char *p; int iLenFile = lstrlen(pszFile); BOOL bFound = FALSE;
p = pszFileList; while ((*p != '\0') && (!bFound)) { if (lstrlen(p) == iLenFile) bFound = (lstrcmpi(p, pszFile) == 0); if (!bFound) p += lstrlen(p) + 1; } return (bFound); }
int PrepareFileList(LPSTR pszOutFileList, LPCSTR pszInFileList) { int iFiles = 0; // number of files in list
char *p; p = (LPSTR)pszInFileList; // p is used to point into both arrays
// trim leading spaces, tabs or :
while ((*p == ' ') || (*p == '\t') || (*p == ':')) p++; lstrcpy(pszOutFileList, p);
p = pszOutFileList; if (lstrlen(pszOutFileList) > 0) { // Only if we have atleast one character left.
// This cannot be a space of tab, because we
// would have removed this above.
p += (lstrlen(pszOutFileList) - 1);
// trim railing spaces, tabs or :
while ((*p == ' ') || (*p == '\t') || (*p == ':')) p--;
// Put a '\0' for the last space/tab
*(++p) = '\0'; }
if (*pszOutFileList) { iFiles++; // Now replace ':' with '\0'
p = pszOutFileList; while (*p != '\0') { if (*p == ':') { *p = '\0'; iFiles++; } p++; } // Make sure we have a double '\0' at the end.
*(++p) = '\0'; } return iFiles; }
|