172 lines
3.2 KiB
C++
172 lines
3.2 KiB
C++
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// CAB file manipulation for extracting dump files
|
||
|
// from dump CABs.
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 2001.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include "pch.hpp"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <io.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys\stat.h>
|
||
|
#include <share.h>
|
||
|
|
||
|
#include <fdi.h>
|
||
|
|
||
|
#include "cmnutil.hpp"
|
||
|
|
||
|
#define FDI_HR(Code) MAKE_HRESULT(SEVERITY_ERROR, 0xfd1, ((Code) & 0xffff))
|
||
|
|
||
|
struct FDI_CB_STATE
|
||
|
{
|
||
|
PSTR DmpFile;
|
||
|
PSTR DstDir;
|
||
|
ULONG FileFlags;
|
||
|
INT_PTR DmpFh;
|
||
|
};
|
||
|
|
||
|
PSTR
|
||
|
FdiPathTail(PSTR Path)
|
||
|
{
|
||
|
PSTR Tail = strrchr(Path, '\\');
|
||
|
if (Tail == NULL)
|
||
|
{
|
||
|
Tail = strrchr(Path, '/');
|
||
|
if (Tail == NULL)
|
||
|
{
|
||
|
Tail = strrchr(Path, ':');
|
||
|
}
|
||
|
}
|
||
|
return Tail ? Tail + 1 : Path;
|
||
|
}
|
||
|
|
||
|
FNALLOC(FdiAlloc)
|
||
|
{
|
||
|
return malloc(cb);
|
||
|
}
|
||
|
|
||
|
FNFREE(FdiFree)
|
||
|
{
|
||
|
free(pv);
|
||
|
}
|
||
|
|
||
|
FNOPEN(FdiOpen)
|
||
|
{
|
||
|
return _open(pszFile, oflag, pmode);
|
||
|
}
|
||
|
|
||
|
FNREAD(FdiRead)
|
||
|
{
|
||
|
return _read((int)hf, pv, cb);
|
||
|
}
|
||
|
|
||
|
FNWRITE(FdiWrite)
|
||
|
{
|
||
|
return _write((int)hf, pv, cb);
|
||
|
}
|
||
|
|
||
|
FNCLOSE(FdiClose)
|
||
|
{
|
||
|
return _close((int)hf);
|
||
|
}
|
||
|
|
||
|
FNSEEK(FdiSeek)
|
||
|
{
|
||
|
return _lseek((int)hf, dist, seektype);
|
||
|
}
|
||
|
|
||
|
FNFDINOTIFY(FdiNotify)
|
||
|
{
|
||
|
FDI_CB_STATE* CbState = (FDI_CB_STATE*)pfdin->pv;
|
||
|
PSTR Scan;
|
||
|
|
||
|
switch(fdint)
|
||
|
{
|
||
|
case fdintCOPY_FILE:
|
||
|
if (CbState->DmpFh >= 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Scan = strrchr(pfdin->psz1, '.');
|
||
|
if (Scan == NULL ||
|
||
|
(_stricmp(Scan, ".dmp") != 0 &&
|
||
|
_stricmp(Scan, ".mdmp") != 0))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Scan = FdiPathTail(pfdin->psz1);
|
||
|
if (*CbState->DstDir)
|
||
|
{
|
||
|
sprintf(CbState->DmpFile, "%s\\%s", CbState->DstDir, Scan);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strcpy(CbState->DmpFile, Scan);
|
||
|
}
|
||
|
|
||
|
CbState->DmpFh = FdiOpen(CbState->DmpFile,
|
||
|
_O_BINARY | _O_WRONLY | CbState->FileFlags,
|
||
|
_S_IREAD | _S_IWRITE);
|
||
|
return CbState->DmpFh;
|
||
|
|
||
|
case fdintCLOSE_FILE_INFO:
|
||
|
// Leave the file open.
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
ExpandDumpCab(PCSTR CabFile, ULONG FileFlags,
|
||
|
PSTR DmpFile, INT_PTR* DmpFh)
|
||
|
{
|
||
|
FDI_CB_STATE CbState;
|
||
|
HFDI Context;
|
||
|
ERF Err;
|
||
|
BOOL Status;
|
||
|
PSTR Env;
|
||
|
|
||
|
Env = getenv("TMP");
|
||
|
if (Env == NULL)
|
||
|
{
|
||
|
Env = getenv("TEMP");
|
||
|
if (Env == NULL)
|
||
|
{
|
||
|
Env = "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CbState.DmpFile = DmpFile;
|
||
|
CbState.DstDir = Env;
|
||
|
CbState.FileFlags = FileFlags;
|
||
|
CbState.DmpFh = -1;
|
||
|
|
||
|
Context = FDICreate(FdiAlloc, FdiFree,
|
||
|
FdiOpen, FdiRead, FdiWrite, FdiClose, FdiSeek,
|
||
|
cpuUNKNOWN, &Err);
|
||
|
if (Context == NULL)
|
||
|
{
|
||
|
return FDI_HR(Err.erfOper);
|
||
|
}
|
||
|
|
||
|
Status = FDICopy(Context, "", (PSTR)CabFile, 0,
|
||
|
FdiNotify, NULL, &CbState);
|
||
|
|
||
|
FDIDestroy(Context);
|
||
|
|
||
|
if (!Status)
|
||
|
{
|
||
|
return FDI_HR(Err.erfOper);
|
||
|
}
|
||
|
|
||
|
*DmpFh = CbState.DmpFh;
|
||
|
return (CbState.DmpFh >= 0) ? S_OK : E_NOINTERFACE;
|
||
|
}
|