📄 pehandler.cpp
字号:
kpidSubSystem,
kpidDllCharacts,
kpidStackReserve,
kpidStackCommit,
kpidHeapReserve,
kpidHeapCommit,
};
STATPROPSTG kArcProps[] =
{
{ NULL, kpidCpu, VT_BSTR},
{ NULL, kpidBit64, VT_BOOL},
{ NULL, kpidCharacts, VT_BSTR},
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidPhySize, VT_UI4},
{ NULL, kpidHeadersSize, VT_UI4},
{ NULL, kpidChecksum, VT_UI4},
{ L"Image Size", kpidImageSize, VT_UI4},
{ L"Section Alignment", kpidSectAlign, VT_UI4},
{ L"File Alignment", kpidFileAlign, VT_UI4},
{ L"Code Size", kpidCodeSize, VT_UI4},
{ L"Initialized Data Size", kpidInitDataSize, VT_UI4},
{ L"Uninitialized Data Size", kpidUnInitDataSize, VT_UI4},
{ L"Linker Version", kpidLinkerVer, VT_BSTR},
{ L"OS Version", kpidOsVer, VT_BSTR},
{ L"Image Version", kpidImageVer, VT_BSTR},
{ L"Subsystem Version", kpidSubsysVer, VT_BSTR},
{ L"Subsystem", kpidSubSystem, VT_BSTR},
{ L"DLL Characteristics", kpidDllCharacts, VT_BSTR},
{ L"Stack Reserve", kpidStackReserve, VT_UI8},
{ L"Stack Commit", kpidStackCommit, VT_UI8},
{ L"Heap Reserve", kpidHeapReserve, VT_UI8},
{ L"Heap Commit", kpidHeapCommit, VT_UI8},
};
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidCharacts, VT_BSTR},
{ NULL, kpidOffset, VT_UI8},
{ NULL, kpidVa, VT_UI8}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_WITH_NAME
static void VerToProp(const CVersion &v, NCOM::CPropVariant &prop)
{
StringToProp(v.GetString(), prop);
}
void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop)
{
if (unixTime != 0)
{
FILETIME ft;
NTime::UnixTimeToFileTime(unixTime, ft);
prop = ft;
}
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch(propID)
{
case kpidSectAlign: prop = _optHeader.SectAlign; break;
case kpidFileAlign: prop = _optHeader.FileAlign; break;
case kpidLinkerVer:
{
CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };
VerToProp(v, prop); break;
break;
}
case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break;
case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break;
case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break;
case kpidCodeSize: prop = _optHeader.CodeSize; break;
case kpidInitDataSize: prop = _optHeader.InitDataSize; break;
case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;
case kpidImageSize: prop = _optHeader.ImageSize; break;
case kpidPhySize: prop = _totalSize; break;
case kpidHeadersSize: prop = _optHeader.HeadersSize; break;
case kpidChecksum: prop = _optHeader.CheckSum; break;
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
case kpidMTime:
case kpidCTime: TimeToProp(_header.Time, prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;
case kpidStackReserve: prop = _optHeader.StackReserve; break;
case kpidStackCommit: prop = _optHeader.StackCommit; break;
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
/*
if (_optHeader.Is64Bit())
s += " 64-bit";
*/
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
const CSection &item = _sections[index];
switch(propID)
{
case kpidPath: StringToProp(item.Name, prop); break;
case kpidSize: prop = (UInt64)item.VSize; break;
case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
case kpidOffset: prop = item.Pa; break;
case kpidVa: if (item.IsRealSect) prop = item.Va; break;
case kpidMTime:
case kpidCTime:
TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;
case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
{
thereIsSection = false;
const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug];
if (debugLink.Size == 0)
return S_OK;
const unsigned kEntrySize = 28;
UInt32 numItems = debugLink.Size / kEntrySize;
if (numItems * kEntrySize != debugLink.Size || numItems > 16)
return S_FALSE;
UInt64 pa = 0;
int i;
for (i = 0; i < _sections.Size(); i++)
{
const CSection § = _sections[i];
if (sect.Va < debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize)
{
pa = sect.Pa + (debugLink.Va - sect.Va);
break;
}
}
if (i == _sections.Size())
return S_FALSE;
CByteBuffer buffer;
buffer.SetCapacity(debugLink.Size);
Byte *buf = buffer;
RINOK(stream->Seek(pa, STREAM_SEEK_SET, NULL));
RINOK(ReadStream_FALSE(stream, buf, debugLink.Size));
for (i = 0; i < (int)numItems; i++)
{
CDebugEntry de;
de.Parse(buf);
if (de.Size == 0)
continue;
CSection sect;
sect.Name = ".debug" + GetDecString(i);
sect.IsDebug = true;
sect.Time = de.Time;
sect.Va = de.Va;
sect.Pa = de.Pa;
sect.PSize = sect.VSize = de.Size;
UInt32 totalSize = sect.Pa + sect.PSize;
if (totalSize > _totalSize)
{
_totalSize = totalSize;
_sections.Add(sect);
thereIsSection = true;
}
buf += kEntrySize;
}
return S_OK;
}
HRESULT CHandler::Open2(IInStream *stream)
{
const UInt32 kBufSize = 1 << 18;
const UInt32 kSigSize = 2;
CByteBuffer buffer;
buffer.SetCapacity(kBufSize);
Byte *buf = buffer;
size_t processed = kSigSize;
RINOK(ReadStream_FALSE(stream, buf, processed));
if (buf[0] != 'M' || buf[1] != 'Z')
return S_FALSE;
processed = kBufSize - kSigSize;
RINOK(ReadStream(stream, buf + kSigSize, &processed));
processed += kSigSize;
if (!Parse(buf, (UInt32)processed))
return S_FALSE;
bool thereISDebug;
RINOK(LoadDebugSections(stream, thereISDebug));
const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];
if (certLink.Size != 0)
{
CSection sect;
sect.Name = "CERTIFICATE";
sect.Va = 0;
sect.Pa = certLink.Va;
sect.PSize = sect.VSize = certLink.Size;
sect.UpdateTotalSize(_totalSize);
_sections.Add(sect);
}
if (thereISDebug)
{
const UInt32 kAlign = 1 << 12;
UInt32 alignPos = _totalSize & (kAlign - 1);
if (alignPos != 0)
{
UInt32 size = kAlign - alignPos;
RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL));
buffer.Free();
buffer.SetCapacity(kAlign);
Byte *buf = buffer;
size_t processed = size;
RINOK(ReadStream(stream, buf, &processed));
size_t i;
for (i = 0; i < processed; i++)
{
if (buf[i] != 0)
break;
}
if (processed < size && processed < 100)
_totalSize += (UInt32)processed;
else if (((_totalSize + i) & 0x1FF) == 0 || processed < size)
_totalSize += (UInt32)i;
}
}
if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512)
{
if (_header.NumSymbols >= (1 << 24))
return S_FALSE;
CSection sect;
sect.Name = "COFF_SYMBOLS";
UInt32 size = _header.NumSymbols * 18;
RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_SET, NULL));
Byte buf[4];
RINOK(ReadStream_FALSE(stream, buf, 4));
UInt32 size2 = Get32(buf);
if (size2 >= (1 << 28))
return S_FALSE;
size += size2;
sect.Va = 0;
sect.Pa = _header.PointerToSymbolTable;
sect.PSize = sect.VSize = size;
sect.UpdateTotalSize(_totalSize);
_sections.Add(sect);
}
UInt64 fileSize;
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
if (fileSize > _totalSize)
return S_FALSE;
_totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize;
return S_OK;
}
HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
{
// size &= ~1;
const UInt32 kBufSize = 1 << 23;
CByteBuffer buffer;
buffer.SetCapacity(kBufSize);
Byte *buf = buffer;
UInt32 sum = 0;
UInt32 pos;
for(pos = 0;;)
{
UInt32 rem = size - pos;
if (rem > kBufSize)
rem = kBufSize;
if (rem == 0)
break;
size_t processed = rem;
RINOK(ReadStream(stream, buf, &processed));
/*
*/
/*
for (; processed < rem; processed++)
buf[processed] = 0;
*/
if ((processed & 1) != 0)
buf[processed] = 0;
for (int j = 0; j < 4; j++)
{
UInt32 p = excludePos + j;
if (pos <= p && p < pos + processed)
buf[p - pos] = 0;
}
for (size_t i = 0; i < processed; i += 2)
{
sum += Get16(buf + i);
sum = (sum + (sum >> 16)) & 0xFFFF;
}
pos += (UInt32)processed;
if (rem != processed)
break;
}
sum += pos;
res = sum;
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *inStream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
Close();
RINOK(Open2(inStream));
_inStream = inStream;
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_inStream.Release();
_sections.Clear();
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _sections.Size();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool testMode = (_aTestMode != 0);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode)
numItems = _sections.Size();
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize();
extractCallback->SetTotal(totalSize);
UInt64 currentTotalSize = 0;
UInt64 currentItemSize;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
bool checkSumOK = true;
if (_optHeader.CheckSum != 0 && (int)numItems == _sections.Size())
{
UInt32 checkSum = 0;
RINOK(_inStream->Seek(0, STREAM_SEEK_SET, NULL));
CalcCheckSum(_inStream, _totalSizeLimited, _peOffset + kHeaderSize + 64, checkSum);
checkSumOK = (checkSum == _optHeader.CheckSum);
}
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_inStream);
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
{
lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur());
Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CSection &item = _sections[index];
currentItemSize = item.GetPackSize();
{
CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && (!realOutStream))
continue;
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
}
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL));
streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ?
checkSumOK ?
NArchive::NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kCRCError:
NArchive::NExtract::NOperationResult::kDataError));
}
return S_OK;
COM_TRY_END
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"PE", L"", 0, 0xDD, { 0 }, 0, false, CreateArc, 0 };
REGISTER_ARC(Pe)
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -