123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- /*
- * wordole.c
- * Copyright (C) 1998-2004 A.J. van Os; Released under GPL
- *
- * Description:
- * Deal with the OLE internals of a MS Word file
- */
- #include <string.h>
- #include "antiword.h"
- /* Private type for Property Set Storage entries */
- typedef struct pps_entry_tag {
- ULONG ulNext;
- ULONG ulPrevious;
- ULONG ulDir;
- ULONG ulSB;
- ULONG ulSize;
- int iLevel;
- char szName[32];
- UCHAR ucType;
- } pps_entry_type;
- /* Show that a PPS number or index should not be used */
- #define PPS_NUMBER_INVALID 0xffffffffUL
- /* Macro to make sure all such statements will be identical */
- #define FREE_ALL() \
- do {\
- vDestroySmallBlockList();\
- aulRootList = xfree(aulRootList);\
- aulSbdList = xfree(aulSbdList);\
- aulBbdList = xfree(aulBbdList);\
- aulSBD = xfree(aulSBD);\
- aulBBD = xfree(aulBBD);\
- } while(0)
- /*
- * ulReadLong - read four bytes from the given file and offset
- */
- static ULONG
- ulReadLong(FILE *pFile, ULONG ulOffset)
- {
- UCHAR aucBytes[4];
- fail(pFile == NULL);
- if (!bReadBytes(aucBytes, 4, ulOffset, pFile)) {
- werr(1, "Read long 0x%lx not possible", ulOffset);
- }
- return ulGetLong(0, aucBytes);
- } /* end of ulReadLong */
- /*
- * vName2String - turn the name into a proper string.
- */
- static void
- vName2String(char *szName, const UCHAR *aucBytes, size_t tNameSize)
- {
- char *pcChar;
- size_t tIndex;
- fail(aucBytes == NULL || szName == NULL);
- if (tNameSize < 2) {
- szName[0] = '\0';
- return;
- }
- for (tIndex = 0, pcChar = szName;
- tIndex < 2 * tNameSize;
- tIndex += 2, pcChar++) {
- *pcChar = (char)aucBytes[tIndex];
- }
- szName[tNameSize - 1] = '\0';
- } /* end of vName2String */
- /*
- * tReadBlockIndices - read the Big/Small Block Depot indices
- *
- * Returns the number of indices read
- */
- static size_t
- tReadBlockIndices(FILE *pFile, ULONG *aulBlockDepot,
- size_t tMaxRec, ULONG ulOffset)
- {
- size_t tDone;
- int iIndex;
- UCHAR aucBytes[BIG_BLOCK_SIZE];
- fail(pFile == NULL || aulBlockDepot == NULL);
- fail(tMaxRec == 0);
- /* Read a big block with BBD or SBD indices */
- if (!bReadBytes(aucBytes, BIG_BLOCK_SIZE, ulOffset, pFile)) {
- werr(0, "Reading big block from 0x%lx is not possible",
- ulOffset);
- return 0;
- }
- /* Split the big block into indices, an index is four bytes */
- tDone = min(tMaxRec, (size_t)BIG_BLOCK_SIZE / 4);
- for (iIndex = 0; iIndex < (int)tDone; iIndex++) {
- aulBlockDepot[iIndex] = ulGetLong(4 * iIndex, aucBytes);
- NO_DBG_DEC(aulBlockDepot[iIndex]);
- }
- return tDone;
- } /* end of tReadBlockIndices */
- /*
- * bGetBBD - get the Big Block Depot indices from the index-blocks
- */
- static BOOL
- bGetBBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
- ULONG *aulBBD, size_t tBBDLen)
- {
- ULONG ulBegin;
- size_t tToGo, tDone;
- int iIndex;
- fail(pFile == NULL || aulDepot == NULL || aulBBD == NULL);
- DBG_MSG("bGetBBD");
- tToGo = tBBDLen;
- for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
- ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
- NO_DBG_HEX(ulBegin);
- tDone = tReadBlockIndices(pFile, aulBBD, tToGo, ulBegin);
- fail(tDone > tToGo);
- if (tDone == 0) {
- return FALSE;
- }
- aulBBD += tDone;
- tToGo -= tDone;
- }
- return tToGo == 0;
- } /* end of bGetBBD */
- /*
- * bGetSBD - get the Small Block Depot indices from the index-blocks
- */
- static BOOL
- bGetSBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
- ULONG *aulSBD, size_t tSBDLen)
- {
- ULONG ulBegin;
- size_t tToGo, tDone;
- int iIndex;
- fail(pFile == NULL || aulDepot == NULL || aulSBD == NULL);
- DBG_MSG("bGetSBD");
- tToGo = tSBDLen;
- for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
- fail(aulDepot[iIndex] >= ULONG_MAX / BIG_BLOCK_SIZE);
- ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
- NO_DBG_HEX(ulBegin);
- tDone = tReadBlockIndices(pFile, aulSBD, tToGo, ulBegin);
- fail(tDone > tToGo);
- if (tDone == 0) {
- return FALSE;
- }
- aulSBD += tDone;
- tToGo -= tDone;
- }
- return tToGo == 0;
- } /* end of bGetSBD */
- /*
- * vComputePPSlevels - compute the levels of the Property Set Storage entries
- */
- static void
- vComputePPSlevels(pps_entry_type *atPPSlist, pps_entry_type *pNode,
- int iLevel, int iRecursionLevel)
- {
- fail(atPPSlist == NULL || pNode == NULL);
- fail(iLevel < 0 || iRecursionLevel < 0);
- if (iRecursionLevel > 25) {
- /* This removes the possibility of an infinite recursion */
- DBG_DEC(iRecursionLevel);
- return;
- }
- if (pNode->iLevel <= iLevel) {
- /* Avoid entering a loop */
- DBG_DEC(iLevel);
- DBG_DEC(pNode->iLevel);
- return;
- }
- pNode->iLevel = iLevel;
- if (pNode->ulDir != PPS_NUMBER_INVALID) {
- vComputePPSlevels(atPPSlist,
- &atPPSlist[pNode->ulDir],
- iLevel + 1,
- iRecursionLevel + 1);
- }
- if (pNode->ulNext != PPS_NUMBER_INVALID) {
- vComputePPSlevels(atPPSlist,
- &atPPSlist[pNode->ulNext],
- iLevel,
- iRecursionLevel + 1);
- }
- if (pNode->ulPrevious != PPS_NUMBER_INVALID) {
- vComputePPSlevels(atPPSlist,
- &atPPSlist[pNode->ulPrevious],
- iLevel,
- iRecursionLevel + 1);
- }
- } /* end of vComputePPSlevels */
- /*
- * bGetPPS - search the Property Set Storage for three sets
- *
- * Return TRUE if the WordDocument PPS is found
- */
- static BOOL
- bGetPPS(FILE *pFile,
- const ULONG *aulRootList, size_t tRootListLen, pps_info_type *pPPS)
- {
- pps_entry_type *atPPSlist;
- ULONG ulBegin, ulOffset, ulTmp;
- size_t tNbrOfPPS, tNameSize;
- int iIndex, iStartBlock, iRootIndex;
- BOOL bWord, bExcel;
- UCHAR aucBytes[PROPERTY_SET_STORAGE_SIZE];
- fail(pFile == NULL || aulRootList == NULL || pPPS == NULL);
- DBG_MSG("bGetPPS");
- NO_DBG_DEC(tRootListLen);
- bWord = FALSE;
- bExcel = FALSE;
- (void)memset(pPPS, 0, sizeof(*pPPS));
- /* Read and store all the Property Set Storage entries */
- tNbrOfPPS = tRootListLen * BIG_BLOCK_SIZE / PROPERTY_SET_STORAGE_SIZE;
- atPPSlist = xcalloc(tNbrOfPPS, sizeof(pps_entry_type));
- iRootIndex = 0;
- for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
- ulTmp = (ULONG)iIndex * PROPERTY_SET_STORAGE_SIZE;
- iStartBlock = (int)(ulTmp / BIG_BLOCK_SIZE);
- ulOffset = ulTmp % BIG_BLOCK_SIZE;
- ulBegin = (aulRootList[iStartBlock] + 1) * BIG_BLOCK_SIZE +
- ulOffset;
- NO_DBG_HEX(ulBegin);
- if (!bReadBytes(aucBytes, PROPERTY_SET_STORAGE_SIZE,
- ulBegin, pFile)) {
- werr(0, "Reading PPS %d is not possible", iIndex);
- atPPSlist = xfree(atPPSlist);
- return FALSE;
- }
- tNameSize = (size_t)usGetWord(0x40, aucBytes);
- tNameSize = (tNameSize + 1) / 2;
- vName2String(atPPSlist[iIndex].szName, aucBytes, tNameSize);
- atPPSlist[iIndex].ucType = ucGetByte(0x42, aucBytes);
- if (atPPSlist[iIndex].ucType == 5) {
- iRootIndex = iIndex;
- }
- atPPSlist[iIndex].ulPrevious = ulGetLong(0x44, aucBytes);
- atPPSlist[iIndex].ulNext = ulGetLong(0x48, aucBytes);
- atPPSlist[iIndex].ulDir = ulGetLong(0x4c, aucBytes);
- atPPSlist[iIndex].ulSB = ulGetLong(0x74, aucBytes);
- atPPSlist[iIndex].ulSize = ulGetLong(0x78, aucBytes);
- atPPSlist[iIndex].iLevel = INT_MAX;
- if ((atPPSlist[iIndex].ulPrevious >= (ULONG)tNbrOfPPS &&
- atPPSlist[iIndex].ulPrevious != PPS_NUMBER_INVALID) ||
- (atPPSlist[iIndex].ulNext >= (ULONG)tNbrOfPPS &&
- atPPSlist[iIndex].ulNext != PPS_NUMBER_INVALID) ||
- (atPPSlist[iIndex].ulDir >= (ULONG)tNbrOfPPS &&
- atPPSlist[iIndex].ulDir != PPS_NUMBER_INVALID)) {
- DBG_DEC(iIndex);
- DBG_DEC(atPPSlist[iIndex].ulPrevious);
- DBG_DEC(atPPSlist[iIndex].ulNext);
- DBG_DEC(atPPSlist[iIndex].ulDir);
- DBG_DEC(tNbrOfPPS);
- werr(0, "The Property Set Storage is damaged");
- atPPSlist = xfree(atPPSlist);
- return FALSE;
- }
- }
- #if 0 /* defined(DEBUG) */
- DBG_MSG("Before");
- for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
- DBG_MSG(atPPSlist[iIndex].szName);
- DBG_HEX(atPPSlist[iIndex].ulDir);
- DBG_HEX(atPPSlist[iIndex].ulPrevious);
- DBG_HEX(atPPSlist[iIndex].ulNext);
- DBG_DEC(atPPSlist[iIndex].ulSB);
- DBG_HEX(atPPSlist[iIndex].ulSize);
- DBG_DEC(atPPSlist[iIndex].iLevel);
- }
- #endif /* DEBUG */
- /* Add level information to each entry */
- vComputePPSlevels(atPPSlist, &atPPSlist[iRootIndex], 0, 0);
- /* Check the entries on level 1 for the required information */
- NO_DBG_MSG("After");
- for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
- #if 0 /* defined(DEBUG) */
- DBG_MSG(atPPSlist[iIndex].szName);
- DBG_HEX(atPPSlist[iIndex].ulDir);
- DBG_HEX(atPPSlist[iIndex].ulPrevious);
- DBG_HEX(atPPSlist[iIndex].ulNext);
- DBG_DEC(atPPSlist[iIndex].ulSB);
- DBG_HEX(atPPSlist[iIndex].ulSize);
- DBG_DEC(atPPSlist[iIndex].iLevel);
- #endif /* DEBUG */
- if (atPPSlist[iIndex].iLevel != 1 ||
- atPPSlist[iIndex].ucType != 2 ||
- atPPSlist[iIndex].szName[0] == '\0' ||
- atPPSlist[iIndex].ulSize == 0) {
- /* This entry can be ignored */
- continue;
- }
- if (pPPS->tWordDocument.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName, "WordDocument")) {
- pPPS->tWordDocument.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->tWordDocument.ulSize = atPPSlist[iIndex].ulSize;
- bWord = TRUE;
- } else if (pPPS->tData.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName, "Data")) {
- pPPS->tData.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->tData.ulSize = atPPSlist[iIndex].ulSize;
- } else if (pPPS->t0Table.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName, "0Table")) {
- pPPS->t0Table.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->t0Table.ulSize = atPPSlist[iIndex].ulSize;
- } else if (pPPS->t1Table.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName, "1Table")) {
- pPPS->t1Table.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->t1Table.ulSize = atPPSlist[iIndex].ulSize;
- } else if (pPPS->tSummaryInfo.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName,
- "\005SummaryInformation")) {
- pPPS->tSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->tSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
- } else if (pPPS->tDocSummaryInfo.ulSize == 0 &&
- STREQ(atPPSlist[iIndex].szName,
- "\005DocumentSummaryInformation")) {
- pPPS->tDocSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
- pPPS->tDocSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
- } else if (STREQ(atPPSlist[iIndex].szName, "Book") ||
- STREQ(atPPSlist[iIndex].szName, "Workbook")) {
- bExcel = TRUE;
- }
- }
- /* Free the space for the Property Set Storage entries */
- atPPSlist = xfree(atPPSlist);
- /* Draw your conclusions */
- if (bWord) {
- return TRUE;
- }
- if (bExcel) {
- werr(0, "Sorry, but this is an Excel spreadsheet");
- } else {
- werr(0, "This OLE file does not contain a Word document");
- }
- return FALSE;
- } /* end of bGetPPS */
- /*
- * vGetBbdList - make a list of the places to find big blocks
- */
- static void
- vGetBbdList(FILE *pFile, int iNbr, ULONG *aulBbdList, ULONG ulOffset)
- {
- int iIndex;
- fail(pFile == NULL);
- fail(iNbr > 127);
- fail(aulBbdList == NULL);
- NO_DBG_DEC(iNbr);
- for (iIndex = 0; iIndex < iNbr; iIndex++) {
- aulBbdList[iIndex] =
- ulReadLong(pFile, ulOffset + 4 * (ULONG)iIndex);
- NO_DBG_DEC(iIndex);
- NO_DBG_HEX(aulBbdList[iIndex]);
- }
- } /* end of vGetBbdList */
- /*
- * bGetDocumentText - make a list of the text blocks of a Word document
- *
- * Return TRUE when succesful, otherwise FALSE
- */
- static BOOL
- bGetDocumentText(FILE *pFile, const pps_info_type *pPPS,
- const ULONG *aulBBD, size_t tBBDLen,
- const ULONG *aulSBD, size_t tSBDLen,
- const UCHAR *aucHeader, int iWordVersion)
- {
- ULONG ulBeginOfText;
- ULONG ulTextLen, ulFootnoteLen, ulEndnoteLen;
- ULONG ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
- ULONG ulTextBoxLen, ulHdrTextBoxLen;
- UINT uiQuickSaves;
- BOOL bFarEastWord, bTemplate, bFastSaved, bEncrypted, bSuccess;
- USHORT usIdent, usDocStatus;
- fail(pFile == NULL || pPPS == NULL);
- fail(aulBBD == NULL);
- fail(aulSBD == NULL);
- DBG_MSG("bGetDocumentText");
- /* Get the "magic number" from the header */
- usIdent = usGetWord(0x00, aucHeader);
- DBG_HEX(usIdent);
- bFarEastWord = usIdent == 0x8098 || usIdent == 0x8099 ||
- usIdent == 0xa697 || usIdent == 0xa699;
- /* Get the status flags from the header */
- usDocStatus = usGetWord(0x0a, aucHeader);
- DBG_HEX(usDocStatus);
- bTemplate = (usDocStatus & BIT(0)) != 0;
- DBG_MSG_C(bTemplate, "This document is a Template");
- bFastSaved = (usDocStatus & BIT(2)) != 0;
- uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
- DBG_MSG_C(bFastSaved, "This document is Fast Saved");
- DBG_DEC_C(bFastSaved, uiQuickSaves);
- bEncrypted = (usDocStatus & BIT(8)) != 0;
- if (bEncrypted) {
- werr(0, "Encrypted documents are not supported");
- return FALSE;
- }
- /* Get length information */
- ulBeginOfText = ulGetLong(0x18, aucHeader);
- DBG_HEX(ulBeginOfText);
- switch (iWordVersion) {
- case 6:
- case 7:
- ulTextLen = ulGetLong(0x34, aucHeader);
- ulFootnoteLen = ulGetLong(0x38, aucHeader);
- ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
- ulMacroLen = ulGetLong(0x40, aucHeader);
- ulAnnotationLen = ulGetLong(0x44, aucHeader);
- ulEndnoteLen = ulGetLong(0x48, aucHeader);
- ulTextBoxLen = ulGetLong(0x4c, aucHeader);
- ulHdrTextBoxLen = ulGetLong(0x50, aucHeader);
- break;
- case 8:
- ulTextLen = ulGetLong(0x4c, aucHeader);
- ulFootnoteLen = ulGetLong(0x50, aucHeader);
- ulHdrFtrLen = ulGetLong(0x54, aucHeader);
- ulMacroLen = ulGetLong(0x58, aucHeader);
- ulAnnotationLen = ulGetLong(0x5c, aucHeader);
- ulEndnoteLen = ulGetLong(0x60, aucHeader);
- ulTextBoxLen = ulGetLong(0x64, aucHeader);
- ulHdrTextBoxLen = ulGetLong(0x68, aucHeader);
- break;
- default:
- werr(0, "This version of Word is not supported");
- return FALSE;
- }
- DBG_DEC(ulTextLen);
- DBG_DEC(ulFootnoteLen);
- DBG_DEC(ulHdrFtrLen);
- DBG_DEC(ulMacroLen);
- DBG_DEC(ulAnnotationLen);
- DBG_DEC(ulEndnoteLen);
- DBG_DEC(ulTextBoxLen);
- DBG_DEC(ulHdrTextBoxLen);
- /* Make a list of the text blocks */
- switch (iWordVersion) {
- case 6:
- case 7:
- if (bFastSaved) {
- bSuccess = bGet6DocumentText(pFile,
- bFarEastWord,
- pPPS->tWordDocument.ulSB,
- aulBBD, tBBDLen,
- aucHeader);
- } else {
- bSuccess = bAddTextBlocks(ulBeginOfText,
- ulTextLen +
- ulFootnoteLen +
- ulHdrFtrLen +
- ulMacroLen + ulAnnotationLen +
- ulEndnoteLen +
- ulTextBoxLen + ulHdrTextBoxLen,
- bFarEastWord,
- IGNORE_PROPMOD,
- pPPS->tWordDocument.ulSB,
- aulBBD, tBBDLen);
- }
- break;
- case 8:
- bSuccess = bGet8DocumentText(pFile,
- pPPS,
- aulBBD, tBBDLen, aulSBD, tSBDLen,
- aucHeader);
- break;
- default:
- werr(0, "This version of Word is not supported");
- bSuccess = FALSE;
- break;
- }
- if (bSuccess) {
- vSplitBlockList(pFile,
- ulTextLen,
- ulFootnoteLen,
- ulHdrFtrLen,
- ulMacroLen,
- ulAnnotationLen,
- ulEndnoteLen,
- ulTextBoxLen,
- ulHdrTextBoxLen,
- !bFastSaved && iWordVersion == 8);
- } else {
- vDestroyTextBlockList();
- werr(0, "I can't find the text of this document");
- }
- return bSuccess;
- } /* end of bGetDocumentText */
- /*
- * vGetDocumentData - make a list of the data blocks of a Word document
- */
- static void
- vGetDocumentData(FILE *pFile, const pps_info_type *pPPS,
- const ULONG *aulBBD, size_t tBBDLen,
- const UCHAR *aucHeader, int iWordVersion)
- {
- options_type tOptions;
- ULONG ulBeginOfText;
- BOOL bFastSaved, bHasImages, bSuccess;
- USHORT usDocStatus;
- fail(pFile == NULL);
- fail(pPPS == NULL);
- fail(aulBBD == NULL);
- /* Get the options */
- vGetOptions(&tOptions);
- /* Get the status flags from the header */
- usDocStatus = usGetWord(0x0a, aucHeader);
- DBG_HEX(usDocStatus);
- bFastSaved = (usDocStatus & BIT(2)) != 0;
- bHasImages = (usDocStatus & BIT(3)) != 0;
- if (!bHasImages ||
- tOptions.eConversionType == conversion_text ||
- tOptions.eConversionType == conversion_fmt_text ||
- tOptions.eConversionType == conversion_xml ||
- tOptions.eImageLevel == level_no_images) {
- /*
- * No images in the document or text-only output or
- * no images wanted, so no data blocks will be needed
- */
- vDestroyDataBlockList();
- return;
- }
- /* Get length information */
- ulBeginOfText = ulGetLong(0x18, aucHeader);
- DBG_HEX(ulBeginOfText);
- /* Make a list of the data blocks */
- switch (iWordVersion) {
- case 6:
- case 7:
- /*
- * The data blocks are in the text stream. The text stream
- * is in "fast saved" format or "normal saved" format
- */
- if (bFastSaved) {
- bSuccess = bGet6DocumentData(pFile,
- pPPS->tWordDocument.ulSB,
- aulBBD, tBBDLen,
- aucHeader);
- } else {
- bSuccess = bAddDataBlocks(ulBeginOfText,
- (ULONG)LONG_MAX,
- pPPS->tWordDocument.ulSB,
- aulBBD, tBBDLen);
- }
- break;
- case 8:
- /*
- * The data blocks are in the data stream. The data stream
- * is always in "normal saved" format
- */
- bSuccess = bAddDataBlocks(0, (ULONG)LONG_MAX,
- pPPS->tData.ulSB, aulBBD, tBBDLen);
- break;
- default:
- werr(0, "This version of Word is not supported");
- bSuccess = FALSE;
- break;
- }
- if (!bSuccess) {
- vDestroyDataBlockList();
- werr(0, "I can't find the data of this document");
- }
- } /* end of vGetDocumentData */
- /*
- * iInitDocumentOLE - initialize an OLE document
- *
- * Returns the version of Word that made the document or -1
- */
- int
- iInitDocumentOLE(FILE *pFile, long lFilesize)
- {
- pps_info_type PPS_info;
- ULONG *aulBBD, *aulSBD;
- ULONG *aulRootList, *aulBbdList, *aulSbdList;
- ULONG ulBdbListStart, ulAdditionalBBDlist;
- ULONG ulRootStartblock, ulSbdStartblock, ulSBLstartblock;
- ULONG ulStart, ulTmp;
- long lMaxBlock;
- size_t tBBDLen, tSBDLen, tNumBbdBlocks, tRootListLen;
- int iWordVersion, iIndex, iToGo;
- BOOL bSuccess;
- USHORT usIdent, usDocStatus;
- UCHAR aucHeader[HEADER_SIZE];
- fail(pFile == NULL);
- lMaxBlock = lFilesize / BIG_BLOCK_SIZE - 2;
- DBG_DEC(lMaxBlock);
- if (lMaxBlock < 1) {
- return -1;
- }
- tBBDLen = (size_t)(lMaxBlock + 1);
- tNumBbdBlocks = (size_t)ulReadLong(pFile, 0x2c);
- DBG_DEC(tNumBbdBlocks);
- ulRootStartblock = ulReadLong(pFile, 0x30);
- DBG_DEC(ulRootStartblock);
- ulSbdStartblock = ulReadLong(pFile, 0x3c);
- DBG_DEC(ulSbdStartblock);
- ulAdditionalBBDlist = ulReadLong(pFile, 0x44);
- DBG_HEX(ulAdditionalBBDlist);
- ulSBLstartblock = ulReadLong(pFile,
- (ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x74);
- DBG_DEC(ulSBLstartblock);
- tSBDLen = (size_t)(ulReadLong(pFile,
- (ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x78) /
- SMALL_BLOCK_SIZE);
- /* All to be xcalloc-ed pointers to NULL */
- aulRootList = NULL;
- aulSbdList = NULL;
- aulBbdList = NULL;
- aulSBD = NULL;
- aulBBD = NULL;
- /* Big Block Depot */
- aulBbdList = xcalloc(tNumBbdBlocks, sizeof(ULONG));
- aulBBD = xcalloc(tBBDLen, sizeof(ULONG));
- iToGo = (int)tNumBbdBlocks;
- vGetBbdList(pFile, min(iToGo, 109), aulBbdList, 0x4c);
- ulStart = 109;
- iToGo -= 109;
- while (ulAdditionalBBDlist != END_OF_CHAIN && iToGo > 0) {
- ulBdbListStart = (ulAdditionalBBDlist + 1) * BIG_BLOCK_SIZE;
- vGetBbdList(pFile, min(iToGo, 127),
- aulBbdList + ulStart, ulBdbListStart);
- ulAdditionalBBDlist = ulReadLong(pFile,
- ulBdbListStart + 4 * 127);
- DBG_DEC(ulAdditionalBBDlist);
- DBG_HEX(ulAdditionalBBDlist);
- ulStart += 127;
- iToGo -= 127;
- }
- if (!bGetBBD(pFile, aulBbdList, tNumBbdBlocks, aulBBD, tBBDLen)) {
- FREE_ALL();
- return -1;
- }
- aulBbdList = xfree(aulBbdList);
- /* Small Block Depot */
- aulSbdList = xcalloc(tBBDLen, sizeof(ULONG));
- aulSBD = xcalloc(tSBDLen, sizeof(ULONG));
- for (iIndex = 0, ulTmp = ulSbdStartblock;
- iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
- iIndex++, ulTmp = aulBBD[ulTmp]) {
- if (ulTmp >= (ULONG)tBBDLen) {
- DBG_DEC(ulTmp);
- DBG_DEC(tBBDLen);
- werr(1, "The Big Block Depot is damaged");
- }
- aulSbdList[iIndex] = ulTmp;
- NO_DBG_HEX(aulSbdList[iIndex]);
- }
- if (!bGetSBD(pFile, aulSbdList, tBBDLen, aulSBD, tSBDLen)) {
- FREE_ALL();
- return -1;
- }
- aulSbdList = xfree(aulSbdList);
- /* Root list */
- for (tRootListLen = 0, ulTmp = ulRootStartblock;
- tRootListLen < tBBDLen && ulTmp != END_OF_CHAIN;
- tRootListLen++, ulTmp = aulBBD[ulTmp]) {
- if (ulTmp >= (ULONG)tBBDLen) {
- DBG_DEC(ulTmp);
- DBG_DEC(tBBDLen);
- werr(1, "The Big Block Depot is damaged");
- }
- }
- if (tRootListLen == 0) {
- werr(0, "No Rootlist found");
- FREE_ALL();
- return -1;
- }
- aulRootList = xcalloc(tRootListLen, sizeof(ULONG));
- for (iIndex = 0, ulTmp = ulRootStartblock;
- iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
- iIndex++, ulTmp = aulBBD[ulTmp]) {
- if (ulTmp >= (ULONG)tBBDLen) {
- DBG_DEC(ulTmp);
- DBG_DEC(tBBDLen);
- werr(1, "The Big Block Depot is damaged");
- }
- aulRootList[iIndex] = ulTmp;
- NO_DBG_DEC(aulRootList[iIndex]);
- }
- fail(tRootListLen != (size_t)iIndex);
- bSuccess = bGetPPS(pFile, aulRootList, tRootListLen, &PPS_info);
- aulRootList = xfree(aulRootList);
- if (!bSuccess) {
- FREE_ALL();
- return -1;
- }
- /* Small block list */
- if (!bCreateSmallBlockList(ulSBLstartblock, aulBBD, tBBDLen)) {
- FREE_ALL();
- return -1;
- }
- if (PPS_info.tWordDocument.ulSize < MIN_SIZE_FOR_BBD_USE) {
- DBG_DEC(PPS_info.tWordDocument.ulSize);
- FREE_ALL();
- werr(0, "I'm afraid the text stream of this file "
- "is too small to handle.");
- return -1;
- }
- /* Read the headerblock */
- if (!bReadBuffer(pFile, PPS_info.tWordDocument.ulSB,
- aulBBD, tBBDLen, BIG_BLOCK_SIZE,
- aucHeader, 0, HEADER_SIZE)) {
- FREE_ALL();
- return -1;
- }
- usIdent = usGetWord(0x00, aucHeader);
- DBG_HEX(usIdent);
- fail(usIdent != 0x8098 && /* Word 7 for oriental languages */
- usIdent != 0x8099 && /* Word 7 for oriental languages */
- usIdent != 0xa5dc && /* Word 6 & 7 */
- usIdent != 0xa5ec && /* Word 7 & 97 & 98 */
- usIdent != 0xa697 && /* Word 7 for oriental languages */
- usIdent != 0xa699); /* Word 7 for oriental languages */
- iWordVersion = iGetVersionNumber(aucHeader);
- if (iWordVersion < 6) {
- FREE_ALL();
- werr(0, "This file is from a version of Word before Word 6.");
- return -1;
- }
- /* Get the status flags from the header */
- usDocStatus = usGetWord(0x0a, aucHeader);
- if (usDocStatus & BIT(9)) {
- PPS_info.tTable = PPS_info.t1Table;
- } else {
- PPS_info.tTable = PPS_info.t0Table;
- }
- /* Clean the entries that should not be used */
- memset(&PPS_info.t0Table, 0, sizeof(PPS_info.t0Table));
- memset(&PPS_info.t1Table, 0, sizeof(PPS_info.t1Table));
- bSuccess = bGetDocumentText(pFile, &PPS_info,
- aulBBD, tBBDLen, aulSBD, tSBDLen,
- aucHeader, iWordVersion);
- if (bSuccess) {
- vGetDocumentData(pFile, &PPS_info,
- aulBBD, tBBDLen, aucHeader, iWordVersion);
- vGetPropertyInfo(pFile, &PPS_info,
- aulBBD, tBBDLen, aulSBD, tSBDLen,
- aucHeader, iWordVersion);
- vSetDefaultTabWidth(pFile, &PPS_info,
- aulBBD, tBBDLen, aulSBD, tSBDLen,
- aucHeader, iWordVersion);
- vGetNotesInfo(pFile, &PPS_info,
- aulBBD, tBBDLen, aulSBD, tSBDLen,
- aucHeader, iWordVersion);
- }
- FREE_ALL();
- return bSuccess ? iWordVersion : -1;
- } /* end of iInitDocumentOLE */
|