Ошибка доступа для чтения
Основная проблема в том что при передаче файла .doc 97/2003, спустя несколько итераций, переменная 'ls' становится больше 0x10 вызывая прерывание выполнения и ошибку доступа.
#include "windows.h"
#include "ole2.h"
#include <iostream>
#define MAXBUF 0xFFFF
#define NAMELEN 256
#define _CRT_SECURE_NO_WARNINGS
char Buf[MAXBUF]; // поток
char SBuf[MAXBUF]; // распакованный текст
using namespace std;
ULONG search_chunk(char* Buf, ULONG streamlen)
{
ULONG ch_pos; // Позиция чунка внутри потока
if ((Buf[0] == 1) && (Buf[1] == 0x16) && (Buf[2] == 1))
{
ch_pos = streamlen / 2;
while ((ch_pos < (streamlen - 3)) && ((Buf[ch_pos] != 1) ||
((Buf[ch_pos + 2] & 0xF0) != 0xB0))) ch_pos++;
if (ch_pos < (streamlen - 3)) return ch_pos;
}
return 0;
}
typedef UINT(WINAPI* RTLD)(ULONG, PVOID, ULONG, PVOID, ULONG, PULONG);сюда код
void view_src(char* StreamName, char* Buf, ULONG ch_pos){
HMODULE h; // Хэндл библиотеки NTDLL.DLL
RTLD RtlDecompressBuffer; // Указатель на функцию
ULONG ulen; // Длина распакованного фрагмента
int i;
LoadLibrary("ntdll.dll");
h = GetModuleHandle("ntdll.dll");
RtlDecompressBuffer = (RTLD)GetProcAddress(h, "RtlDecompressBuffer");
if (RtlDecompressBuffer)
{
RtlDecompressBuffer(0x2, SBuf, MAXBUF, &(Buf[ch_pos + 1]), MAXBUF - ch_pos, &ulen);
cout << "-------------------" << StreamName << "-------------------" << endl;
i = 0; while (SBuf[i]) cout << SBuf[i++];
}
}
// Рекурсивный обход дерева потоков.
void walk(const char* s, LPSTORAGE ls){
OLECHAR FileName[NAMELEN]; // Unicode-имя для structured storage
char StreamName[NAMELEN]; // ASCII-имя потока
LPENUMSTATSTG lpEnum = NULL; // Интерфейс перечислителя
LPSTORAGE pIStorage = NULL; // Интерфейс структурированного хранилища
LPSTORAGE pIStorage2 = NULL; // Интерфейс хранилища нижнего уровня
LPSTREAM pIStream = NULL; // Интерфейс потока
STATSTG stat; // Очередная запись в каталоге
ULONG uCount; // Счетчик перечисления
ULONG streamlen; // Реальная длина потока
ULONG ch_pos; // Позиция чунка внутри потока
if (!ls) // Первый вызов
{
mbstowcs(FileName, s, 256);
StgOpenStorage(FileName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &
pIStorage);
walk("", pIStorage);
}
else // Повторный рекурсивный вызов
{
ls->EnumElements(0, NULL, 0, &lpEnum);
if (lpEnum)
while (lpEnum->Next(1, &stat, &uCount) == S_OK)
{
if (stat.type == STGTY_STORAGE) // Это хранилище
{
ls->OpenStorage(stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL, 0, &pIStorage2);
walk("", pIStorage2);
}
else // поток
{
ls->OpenStream(stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
&pIStream);
pIStream->Read(Buf, MAXBUF, &streamlen);
wcstombs(StreamName, stat.pwcsName, 256);
ch_pos = search_chunk(Buf, streamlen);
if (ch_pos) view_src(StreamName, Buf, ch_pos);
}
};
ls->Release();
}
}
int main(int argc, char* argv[]) {
if (argc > 1) walk(argv[1], NULL);
}