00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <string.h>
00010 #include "antiword.h"
00011
00012
00013 typedef struct pps_entry_tag {
00014 ULONG ulNext;
00015 ULONG ulPrevious;
00016 ULONG ulDir;
00017 ULONG ulSB;
00018 ULONG ulSize;
00019 int iLevel;
00020 char szName[32];
00021 UCHAR ucType;
00022 } pps_entry_type;
00023
00024
00025 #define PPS_NUMBER_INVALID 0xffffffffUL
00026
00027
00028
00029 #define FREE_ALL() \
00030 do {\
00031 vDestroySmallBlockList();\
00032 aulRootList = xfree(aulRootList);\
00033 aulSbdList = xfree(aulSbdList);\
00034 aulBbdList = xfree(aulBbdList);\
00035 aulSBD = xfree(aulSBD);\
00036 aulBBD = xfree(aulBBD);\
00037 } while(0)
00038
00039
00040
00041
00042
00043 static ULONG
00044 ulReadLong(FILE *pFile, ULONG ulOffset)
00045 {
00046 UCHAR aucBytes[4];
00047
00048 fail(pFile == NULL);
00049
00050 if (!bReadBytes(aucBytes, 4, ulOffset, pFile)) {
00051 werr(1, "Read long 0x%lx not possible", ulOffset);
00052 }
00053 return ulGetLong(0, aucBytes);
00054 }
00055
00056
00057
00058
00059 static void
00060 vName2String(char *szName, const UCHAR *aucBytes, size_t tNameSize)
00061 {
00062 char *pcChar;
00063 size_t tIndex;
00064
00065 fail(aucBytes == NULL || szName == NULL);
00066
00067 if (tNameSize < 2) {
00068 szName[0] = '\0';
00069 return;
00070 }
00071 for (tIndex = 0, pcChar = szName;
00072 tIndex < 2 * tNameSize;
00073 tIndex += 2, pcChar++) {
00074 *pcChar = (char)aucBytes[tIndex];
00075 }
00076 szName[tNameSize - 1] = '\0';
00077 }
00078
00079
00080
00081
00082
00083
00084 static size_t
00085 tReadBlockIndices(FILE *pFile, ULONG *aulBlockDepot,
00086 size_t tMaxRec, ULONG ulOffset)
00087 {
00088 size_t tDone;
00089 int iIndex;
00090 UCHAR aucBytes[BIG_BLOCK_SIZE];
00091
00092 fail(pFile == NULL || aulBlockDepot == NULL);
00093 fail(tMaxRec == 0);
00094
00095
00096 if (!bReadBytes(aucBytes, BIG_BLOCK_SIZE, ulOffset, pFile)) {
00097 werr(0, "Reading big block from 0x%lx is not possible",
00098 ulOffset);
00099 return 0;
00100 }
00101
00102 tDone = min(tMaxRec, (size_t)BIG_BLOCK_SIZE / 4);
00103 for (iIndex = 0; iIndex < (int)tDone; iIndex++) {
00104 aulBlockDepot[iIndex] = ulGetLong(4 * iIndex, aucBytes);
00105 NO_DBG_DEC(aulBlockDepot[iIndex]);
00106 }
00107 return tDone;
00108 }
00109
00110
00111
00112
00113 static BOOL
00114 bGetBBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
00115 ULONG *aulBBD, size_t tBBDLen)
00116 {
00117 ULONG ulBegin;
00118 size_t tToGo, tDone;
00119 int iIndex;
00120
00121 fail(pFile == NULL || aulDepot == NULL || aulBBD == NULL);
00122
00123 DBG_MSG("bGetBBD");
00124
00125 tToGo = tBBDLen;
00126 for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
00127 ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
00128 NO_DBG_HEX(ulBegin);
00129 tDone = tReadBlockIndices(pFile, aulBBD, tToGo, ulBegin);
00130 fail(tDone > tToGo);
00131 if (tDone == 0) {
00132 return FALSE;
00133 }
00134 aulBBD += tDone;
00135 tToGo -= tDone;
00136 }
00137 return tToGo == 0;
00138 }
00139
00140
00141
00142
00143 static BOOL
00144 bGetSBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
00145 ULONG *aulSBD, size_t tSBDLen)
00146 {
00147 ULONG ulBegin;
00148 size_t tToGo, tDone;
00149 int iIndex;
00150
00151 fail(pFile == NULL || aulDepot == NULL || aulSBD == NULL);
00152
00153 DBG_MSG("bGetSBD");
00154
00155 tToGo = tSBDLen;
00156 for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
00157 fail(aulDepot[iIndex] >= ULONG_MAX / BIG_BLOCK_SIZE);
00158 ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
00159 NO_DBG_HEX(ulBegin);
00160 tDone = tReadBlockIndices(pFile, aulSBD, tToGo, ulBegin);
00161 fail(tDone > tToGo);
00162 if (tDone == 0) {
00163 return FALSE;
00164 }
00165 aulSBD += tDone;
00166 tToGo -= tDone;
00167 }
00168 return tToGo == 0;
00169 }
00170
00171
00172
00173
00174 static void
00175 vComputePPSlevels(pps_entry_type *atPPSlist, pps_entry_type *pNode,
00176 int iLevel, int iRecursionLevel)
00177 {
00178 fail(atPPSlist == NULL || pNode == NULL);
00179 fail(iLevel < 0 || iRecursionLevel < 0);
00180
00181 if (iRecursionLevel > 25) {
00182
00183 DBG_DEC(iRecursionLevel);
00184 return;
00185 }
00186 if (pNode->iLevel <= iLevel) {
00187
00188 DBG_DEC(iLevel);
00189 DBG_DEC(pNode->iLevel);
00190 return;
00191 }
00192
00193 pNode->iLevel = iLevel;
00194
00195 if (pNode->ulDir != PPS_NUMBER_INVALID) {
00196 vComputePPSlevels(atPPSlist,
00197 &atPPSlist[pNode->ulDir],
00198 iLevel + 1,
00199 iRecursionLevel + 1);
00200 }
00201 if (pNode->ulNext != PPS_NUMBER_INVALID) {
00202 vComputePPSlevels(atPPSlist,
00203 &atPPSlist[pNode->ulNext],
00204 iLevel,
00205 iRecursionLevel + 1);
00206 }
00207 if (pNode->ulPrevious != PPS_NUMBER_INVALID) {
00208 vComputePPSlevels(atPPSlist,
00209 &atPPSlist[pNode->ulPrevious],
00210 iLevel,
00211 iRecursionLevel + 1);
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220 static BOOL
00221 bGetPPS(FILE *pFile,
00222 const ULONG *aulRootList, size_t tRootListLen, pps_info_type *pPPS)
00223 {
00224 pps_entry_type *atPPSlist;
00225 ULONG ulBegin, ulOffset, ulTmp;
00226 size_t tNbrOfPPS, tNameSize;
00227 int iIndex, iStartBlock, iRootIndex;
00228 BOOL bWord, bExcel;
00229 UCHAR aucBytes[PROPERTY_SET_STORAGE_SIZE];
00230
00231 fail(pFile == NULL || aulRootList == NULL || pPPS == NULL);
00232
00233 DBG_MSG("bGetPPS");
00234
00235 NO_DBG_DEC(tRootListLen);
00236
00237 bWord = FALSE;
00238 bExcel = FALSE;
00239 (void)memset(pPPS, 0, sizeof(*pPPS));
00240
00241
00242
00243 tNbrOfPPS = tRootListLen * BIG_BLOCK_SIZE / PROPERTY_SET_STORAGE_SIZE;
00244 atPPSlist = xcalloc(tNbrOfPPS, sizeof(pps_entry_type));
00245 iRootIndex = 0;
00246
00247 for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
00248 ulTmp = (ULONG)iIndex * PROPERTY_SET_STORAGE_SIZE;
00249 iStartBlock = (int)(ulTmp / BIG_BLOCK_SIZE);
00250 ulOffset = ulTmp % BIG_BLOCK_SIZE;
00251 ulBegin = (aulRootList[iStartBlock] + 1) * BIG_BLOCK_SIZE +
00252 ulOffset;
00253 NO_DBG_HEX(ulBegin);
00254 if (!bReadBytes(aucBytes, PROPERTY_SET_STORAGE_SIZE,
00255 ulBegin, pFile)) {
00256 werr(0, "Reading PPS %d is not possible", iIndex);
00257 atPPSlist = xfree(atPPSlist);
00258 return FALSE;
00259 }
00260 tNameSize = (size_t)usGetWord(0x40, aucBytes);
00261 tNameSize = (tNameSize + 1) / 2;
00262 vName2String(atPPSlist[iIndex].szName, aucBytes, tNameSize);
00263 atPPSlist[iIndex].ucType = ucGetByte(0x42, aucBytes);
00264 if (atPPSlist[iIndex].ucType == 5) {
00265 iRootIndex = iIndex;
00266 }
00267 atPPSlist[iIndex].ulPrevious = ulGetLong(0x44, aucBytes);
00268 atPPSlist[iIndex].ulNext = ulGetLong(0x48, aucBytes);
00269 atPPSlist[iIndex].ulDir = ulGetLong(0x4c, aucBytes);
00270 atPPSlist[iIndex].ulSB = ulGetLong(0x74, aucBytes);
00271 atPPSlist[iIndex].ulSize = ulGetLong(0x78, aucBytes);
00272 atPPSlist[iIndex].iLevel = INT_MAX;
00273 if ((atPPSlist[iIndex].ulPrevious >= (ULONG)tNbrOfPPS &&
00274 atPPSlist[iIndex].ulPrevious != PPS_NUMBER_INVALID) ||
00275 (atPPSlist[iIndex].ulNext >= (ULONG)tNbrOfPPS &&
00276 atPPSlist[iIndex].ulNext != PPS_NUMBER_INVALID) ||
00277 (atPPSlist[iIndex].ulDir >= (ULONG)tNbrOfPPS &&
00278 atPPSlist[iIndex].ulDir != PPS_NUMBER_INVALID)) {
00279 DBG_DEC(iIndex);
00280 DBG_DEC(atPPSlist[iIndex].ulPrevious);
00281 DBG_DEC(atPPSlist[iIndex].ulNext);
00282 DBG_DEC(atPPSlist[iIndex].ulDir);
00283 DBG_DEC(tNbrOfPPS);
00284 werr(0, "The Property Set Storage is damaged");
00285 atPPSlist = xfree(atPPSlist);
00286 return FALSE;
00287 }
00288 }
00289
00290 #if 0
00291 DBG_MSG("Before");
00292 for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
00293 DBG_MSG(atPPSlist[iIndex].szName);
00294 DBG_HEX(atPPSlist[iIndex].ulDir);
00295 DBG_HEX(atPPSlist[iIndex].ulPrevious);
00296 DBG_HEX(atPPSlist[iIndex].ulNext);
00297 DBG_DEC(atPPSlist[iIndex].ulSB);
00298 DBG_HEX(atPPSlist[iIndex].ulSize);
00299 DBG_DEC(atPPSlist[iIndex].iLevel);
00300 }
00301 #endif
00302
00303
00304 vComputePPSlevels(atPPSlist, &atPPSlist[iRootIndex], 0, 0);
00305
00306
00307 NO_DBG_MSG("After");
00308 for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
00309 #if 0
00310 DBG_MSG(atPPSlist[iIndex].szName);
00311 DBG_HEX(atPPSlist[iIndex].ulDir);
00312 DBG_HEX(atPPSlist[iIndex].ulPrevious);
00313 DBG_HEX(atPPSlist[iIndex].ulNext);
00314 DBG_DEC(atPPSlist[iIndex].ulSB);
00315 DBG_HEX(atPPSlist[iIndex].ulSize);
00316 DBG_DEC(atPPSlist[iIndex].iLevel);
00317 #endif
00318 if (atPPSlist[iIndex].iLevel != 1 ||
00319 atPPSlist[iIndex].ucType != 2 ||
00320 atPPSlist[iIndex].szName[0] == '\0' ||
00321 atPPSlist[iIndex].ulSize == 0) {
00322
00323 continue;
00324 }
00325 if (pPPS->tWordDocument.ulSize == 0 &&
00326 STREQ(atPPSlist[iIndex].szName, "WordDocument")) {
00327 pPPS->tWordDocument.ulSB = atPPSlist[iIndex].ulSB;
00328 pPPS->tWordDocument.ulSize = atPPSlist[iIndex].ulSize;
00329 bWord = TRUE;
00330 } else if (pPPS->tData.ulSize == 0 &&
00331 STREQ(atPPSlist[iIndex].szName, "Data")) {
00332 pPPS->tData.ulSB = atPPSlist[iIndex].ulSB;
00333 pPPS->tData.ulSize = atPPSlist[iIndex].ulSize;
00334 } else if (pPPS->t0Table.ulSize == 0 &&
00335 STREQ(atPPSlist[iIndex].szName, "0Table")) {
00336 pPPS->t0Table.ulSB = atPPSlist[iIndex].ulSB;
00337 pPPS->t0Table.ulSize = atPPSlist[iIndex].ulSize;
00338 } else if (pPPS->t1Table.ulSize == 0 &&
00339 STREQ(atPPSlist[iIndex].szName, "1Table")) {
00340 pPPS->t1Table.ulSB = atPPSlist[iIndex].ulSB;
00341 pPPS->t1Table.ulSize = atPPSlist[iIndex].ulSize;
00342 } else if (pPPS->tSummaryInfo.ulSize == 0 &&
00343 STREQ(atPPSlist[iIndex].szName,
00344 "\005SummaryInformation")) {
00345 pPPS->tSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
00346 pPPS->tSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
00347 } else if (pPPS->tDocSummaryInfo.ulSize == 0 &&
00348 STREQ(atPPSlist[iIndex].szName,
00349 "\005DocumentSummaryInformation")) {
00350 pPPS->tDocSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
00351 pPPS->tDocSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
00352 } else if (STREQ(atPPSlist[iIndex].szName, "Book") ||
00353 STREQ(atPPSlist[iIndex].szName, "Workbook")) {
00354 bExcel = TRUE;
00355 }
00356 }
00357
00358
00359 atPPSlist = xfree(atPPSlist);
00360
00361
00362 if (bWord) {
00363 return TRUE;
00364 }
00365
00366 if (bExcel) {
00367 werr(0, "Sorry, but this is an Excel spreadsheet");
00368 } else {
00369 werr(0, "This OLE file does not contain a Word document");
00370 }
00371 return FALSE;
00372 }
00373
00374
00375
00376
00377 static void
00378 vGetBbdList(FILE *pFile, int iNbr, ULONG *aulBbdList, ULONG ulOffset)
00379 {
00380 int iIndex;
00381
00382 fail(pFile == NULL);
00383 fail(iNbr > 127);
00384 fail(aulBbdList == NULL);
00385
00386 NO_DBG_DEC(iNbr);
00387 for (iIndex = 0; iIndex < iNbr; iIndex++) {
00388 aulBbdList[iIndex] =
00389 ulReadLong(pFile, ulOffset + 4 * (ULONG)iIndex);
00390 NO_DBG_DEC(iIndex);
00391 NO_DBG_HEX(aulBbdList[iIndex]);
00392 }
00393 }
00394
00395
00396
00397
00398
00399
00400 static BOOL
00401 bGetDocumentText(FILE *pFile, const pps_info_type *pPPS,
00402 const ULONG *aulBBD, size_t tBBDLen,
00403 const ULONG *aulSBD, size_t tSBDLen,
00404 const UCHAR *aucHeader, int iWordVersion)
00405 {
00406 ULONG ulBeginOfText;
00407 ULONG ulTextLen, ulFootnoteLen, ulEndnoteLen;
00408 ULONG ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
00409 ULONG ulTextBoxLen, ulHdrTextBoxLen;
00410 UINT uiQuickSaves;
00411 BOOL bFarEastWord, bTemplate, bFastSaved, bEncrypted, bSuccess;
00412 USHORT usIdent, usDocStatus;
00413
00414 fail(pFile == NULL || pPPS == NULL);
00415 fail(aulBBD == NULL);
00416 fail(aulSBD == NULL);
00417
00418 DBG_MSG("bGetDocumentText");
00419
00420
00421 usIdent = usGetWord(0x00, aucHeader);
00422 DBG_HEX(usIdent);
00423 bFarEastWord = usIdent == 0x8098 || usIdent == 0x8099 ||
00424 usIdent == 0xa697 || usIdent == 0xa699;
00425
00426 usDocStatus = usGetWord(0x0a, aucHeader);
00427 DBG_HEX(usDocStatus);
00428 bTemplate = (usDocStatus & BIT(0)) != 0;
00429 DBG_MSG_C(bTemplate, "This document is a Template");
00430 bFastSaved = (usDocStatus & BIT(2)) != 0;
00431 uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
00432 DBG_MSG_C(bFastSaved, "This document is Fast Saved");
00433 DBG_DEC_C(bFastSaved, uiQuickSaves);
00434 bEncrypted = (usDocStatus & BIT(8)) != 0;
00435 if (bEncrypted) {
00436 werr(0, "Encrypted documents are not supported");
00437 return FALSE;
00438 }
00439
00440
00441 ulBeginOfText = ulGetLong(0x18, aucHeader);
00442 DBG_HEX(ulBeginOfText);
00443 switch (iWordVersion) {
00444 case 6:
00445 case 7:
00446 ulTextLen = ulGetLong(0x34, aucHeader);
00447 ulFootnoteLen = ulGetLong(0x38, aucHeader);
00448 ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
00449 ulMacroLen = ulGetLong(0x40, aucHeader);
00450 ulAnnotationLen = ulGetLong(0x44, aucHeader);
00451 ulEndnoteLen = ulGetLong(0x48, aucHeader);
00452 ulTextBoxLen = ulGetLong(0x4c, aucHeader);
00453 ulHdrTextBoxLen = ulGetLong(0x50, aucHeader);
00454 break;
00455 case 8:
00456 ulTextLen = ulGetLong(0x4c, aucHeader);
00457 ulFootnoteLen = ulGetLong(0x50, aucHeader);
00458 ulHdrFtrLen = ulGetLong(0x54, aucHeader);
00459 ulMacroLen = ulGetLong(0x58, aucHeader);
00460 ulAnnotationLen = ulGetLong(0x5c, aucHeader);
00461 ulEndnoteLen = ulGetLong(0x60, aucHeader);
00462 ulTextBoxLen = ulGetLong(0x64, aucHeader);
00463 ulHdrTextBoxLen = ulGetLong(0x68, aucHeader);
00464 break;
00465 default:
00466 werr(0, "This version of Word is not supported");
00467 return FALSE;
00468 }
00469 DBG_DEC(ulTextLen);
00470 DBG_DEC(ulFootnoteLen);
00471 DBG_DEC(ulHdrFtrLen);
00472 DBG_DEC(ulMacroLen);
00473 DBG_DEC(ulAnnotationLen);
00474 DBG_DEC(ulEndnoteLen);
00475 DBG_DEC(ulTextBoxLen);
00476 DBG_DEC(ulHdrTextBoxLen);
00477
00478
00479 switch (iWordVersion) {
00480 case 6:
00481 case 7:
00482 if (bFastSaved) {
00483 bSuccess = bGet6DocumentText(pFile,
00484 bFarEastWord,
00485 pPPS->tWordDocument.ulSB,
00486 aulBBD, tBBDLen,
00487 aucHeader);
00488 } else {
00489 bSuccess = bAddTextBlocks(ulBeginOfText,
00490 ulTextLen +
00491 ulFootnoteLen +
00492 ulHdrFtrLen +
00493 ulMacroLen + ulAnnotationLen +
00494 ulEndnoteLen +
00495 ulTextBoxLen + ulHdrTextBoxLen,
00496 bFarEastWord,
00497 IGNORE_PROPMOD,
00498 pPPS->tWordDocument.ulSB,
00499 aulBBD, tBBDLen);
00500 }
00501 break;
00502 case 8:
00503 bSuccess = bGet8DocumentText(pFile,
00504 pPPS,
00505 aulBBD, tBBDLen, aulSBD, tSBDLen,
00506 aucHeader);
00507 break;
00508 default:
00509 werr(0, "This version of Word is not supported");
00510 bSuccess = FALSE;
00511 break;
00512 }
00513
00514 if (bSuccess) {
00515 vSplitBlockList(pFile,
00516 ulTextLen,
00517 ulFootnoteLen,
00518 ulHdrFtrLen,
00519 ulMacroLen,
00520 ulAnnotationLen,
00521 ulEndnoteLen,
00522 ulTextBoxLen,
00523 ulHdrTextBoxLen,
00524 !bFastSaved && iWordVersion == 8);
00525 } else {
00526 vDestroyTextBlockList();
00527 werr(0, "I can't find the text of this document");
00528 }
00529 return bSuccess;
00530 }
00531
00532
00533
00534
00535 static void
00536 vGetDocumentData(FILE *pFile, const pps_info_type *pPPS,
00537 const ULONG *aulBBD, size_t tBBDLen,
00538 const UCHAR *aucHeader, int iWordVersion)
00539 {
00540 options_type tOptions;
00541 ULONG ulBeginOfText;
00542 BOOL bFastSaved, bHasImages, bSuccess;
00543 USHORT usDocStatus;
00544
00545 fail(pFile == NULL);
00546 fail(pPPS == NULL);
00547 fail(aulBBD == NULL);
00548
00549
00550 vGetOptions(&tOptions);
00551
00552
00553 usDocStatus = usGetWord(0x0a, aucHeader);
00554 DBG_HEX(usDocStatus);
00555 bFastSaved = (usDocStatus & BIT(2)) != 0;
00556 bHasImages = (usDocStatus & BIT(3)) != 0;
00557
00558 if (!bHasImages ||
00559 tOptions.eConversionType == conversion_text ||
00560 tOptions.eConversionType == conversion_fmt_text ||
00561 tOptions.eConversionType == conversion_xml ||
00562 tOptions.eImageLevel == level_no_images) {
00563
00564
00565
00566
00567 vDestroyDataBlockList();
00568 return;
00569 }
00570
00571
00572 ulBeginOfText = ulGetLong(0x18, aucHeader);
00573 DBG_HEX(ulBeginOfText);
00574
00575
00576 switch (iWordVersion) {
00577 case 6:
00578 case 7:
00579
00580
00581
00582
00583 if (bFastSaved) {
00584 bSuccess = bGet6DocumentData(pFile,
00585 pPPS->tWordDocument.ulSB,
00586 aulBBD, tBBDLen,
00587 aucHeader);
00588 } else {
00589 bSuccess = bAddDataBlocks(ulBeginOfText,
00590 (ULONG)LONG_MAX,
00591 pPPS->tWordDocument.ulSB,
00592 aulBBD, tBBDLen);
00593 }
00594 break;
00595 case 8:
00596
00597
00598
00599
00600 bSuccess = bAddDataBlocks(0, (ULONG)LONG_MAX,
00601 pPPS->tData.ulSB, aulBBD, tBBDLen);
00602 break;
00603 default:
00604 werr(0, "This version of Word is not supported");
00605 bSuccess = FALSE;
00606 break;
00607 }
00608
00609 if (!bSuccess) {
00610 vDestroyDataBlockList();
00611 werr(0, "I can't find the data of this document");
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 int
00621 iInitDocumentOLE(FILE *pFile, long lFilesize)
00622 {
00623 pps_info_type PPS_info;
00624 ULONG *aulBBD, *aulSBD;
00625 ULONG *aulRootList, *aulBbdList, *aulSbdList;
00626 ULONG ulBdbListStart, ulAdditionalBBDlist;
00627 ULONG ulRootStartblock, ulSbdStartblock, ulSBLstartblock;
00628 ULONG ulStart, ulTmp;
00629 long lMaxBlock;
00630 size_t tBBDLen, tSBDLen, tNumBbdBlocks, tRootListLen;
00631 int iWordVersion, iIndex, iToGo;
00632 BOOL bSuccess;
00633 USHORT usIdent, usDocStatus;
00634 UCHAR aucHeader[HEADER_SIZE];
00635
00636 fail(pFile == NULL);
00637
00638 lMaxBlock = lFilesize / BIG_BLOCK_SIZE - 2;
00639 DBG_DEC(lMaxBlock);
00640 if (lMaxBlock < 1) {
00641 return -1;
00642 }
00643 tBBDLen = (size_t)(lMaxBlock + 1);
00644 tNumBbdBlocks = (size_t)ulReadLong(pFile, 0x2c);
00645 DBG_DEC(tNumBbdBlocks);
00646 ulRootStartblock = ulReadLong(pFile, 0x30);
00647 DBG_DEC(ulRootStartblock);
00648 ulSbdStartblock = ulReadLong(pFile, 0x3c);
00649 DBG_DEC(ulSbdStartblock);
00650 ulAdditionalBBDlist = ulReadLong(pFile, 0x44);
00651 DBG_HEX(ulAdditionalBBDlist);
00652 ulSBLstartblock = ulReadLong(pFile,
00653 (ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x74);
00654 DBG_DEC(ulSBLstartblock);
00655 tSBDLen = (size_t)(ulReadLong(pFile,
00656 (ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x78) /
00657 SMALL_BLOCK_SIZE);
00658
00659 aulRootList = NULL;
00660 aulSbdList = NULL;
00661 aulBbdList = NULL;
00662 aulSBD = NULL;
00663 aulBBD = NULL;
00664
00665 aulBbdList = xcalloc(tNumBbdBlocks, sizeof(ULONG));
00666 aulBBD = xcalloc(tBBDLen, sizeof(ULONG));
00667 iToGo = (int)tNumBbdBlocks;
00668 vGetBbdList(pFile, min(iToGo, 109), aulBbdList, 0x4c);
00669 ulStart = 109;
00670 iToGo -= 109;
00671 while (ulAdditionalBBDlist != END_OF_CHAIN && iToGo > 0) {
00672 ulBdbListStart = (ulAdditionalBBDlist + 1) * BIG_BLOCK_SIZE;
00673 vGetBbdList(pFile, min(iToGo, 127),
00674 aulBbdList + ulStart, ulBdbListStart);
00675 ulAdditionalBBDlist = ulReadLong(pFile,
00676 ulBdbListStart + 4 * 127);
00677 DBG_DEC(ulAdditionalBBDlist);
00678 DBG_HEX(ulAdditionalBBDlist);
00679 ulStart += 127;
00680 iToGo -= 127;
00681 }
00682 if (!bGetBBD(pFile, aulBbdList, tNumBbdBlocks, aulBBD, tBBDLen)) {
00683 FREE_ALL();
00684 return -1;
00685 }
00686 aulBbdList = xfree(aulBbdList);
00687
00688 aulSbdList = xcalloc(tBBDLen, sizeof(ULONG));
00689 aulSBD = xcalloc(tSBDLen, sizeof(ULONG));
00690 for (iIndex = 0, ulTmp = ulSbdStartblock;
00691 iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
00692 iIndex++, ulTmp = aulBBD[ulTmp]) {
00693 if (ulTmp >= (ULONG)tBBDLen) {
00694 DBG_DEC(ulTmp);
00695 DBG_DEC(tBBDLen);
00696 werr(1, "The Big Block Depot is damaged");
00697 }
00698 aulSbdList[iIndex] = ulTmp;
00699 NO_DBG_HEX(aulSbdList[iIndex]);
00700 }
00701 if (!bGetSBD(pFile, aulSbdList, tBBDLen, aulSBD, tSBDLen)) {
00702 FREE_ALL();
00703 return -1;
00704 }
00705 aulSbdList = xfree(aulSbdList);
00706
00707 for (tRootListLen = 0, ulTmp = ulRootStartblock;
00708 tRootListLen < tBBDLen && ulTmp != END_OF_CHAIN;
00709 tRootListLen++, ulTmp = aulBBD[ulTmp]) {
00710 if (ulTmp >= (ULONG)tBBDLen) {
00711 DBG_DEC(ulTmp);
00712 DBG_DEC(tBBDLen);
00713 werr(1, "The Big Block Depot is damaged");
00714 }
00715 }
00716 if (tRootListLen == 0) {
00717 werr(0, "No Rootlist found");
00718 FREE_ALL();
00719 return -1;
00720 }
00721 aulRootList = xcalloc(tRootListLen, sizeof(ULONG));
00722 for (iIndex = 0, ulTmp = ulRootStartblock;
00723 iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
00724 iIndex++, ulTmp = aulBBD[ulTmp]) {
00725 if (ulTmp >= (ULONG)tBBDLen) {
00726 DBG_DEC(ulTmp);
00727 DBG_DEC(tBBDLen);
00728 werr(1, "The Big Block Depot is damaged");
00729 }
00730 aulRootList[iIndex] = ulTmp;
00731 NO_DBG_DEC(aulRootList[iIndex]);
00732 }
00733 fail(tRootListLen != (size_t)iIndex);
00734 bSuccess = bGetPPS(pFile, aulRootList, tRootListLen, &PPS_info);
00735 aulRootList = xfree(aulRootList);
00736 if (!bSuccess) {
00737 FREE_ALL();
00738 return -1;
00739 }
00740
00741 if (!bCreateSmallBlockList(ulSBLstartblock, aulBBD, tBBDLen)) {
00742 FREE_ALL();
00743 return -1;
00744 }
00745
00746 if (PPS_info.tWordDocument.ulSize < MIN_SIZE_FOR_BBD_USE) {
00747 DBG_DEC(PPS_info.tWordDocument.ulSize);
00748 FREE_ALL();
00749 werr(0, "I'm afraid the text stream of this file "
00750 "is too small to handle.");
00751 return -1;
00752 }
00753
00754 if (!bReadBuffer(pFile, PPS_info.tWordDocument.ulSB,
00755 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
00756 aucHeader, 0, HEADER_SIZE)) {
00757 FREE_ALL();
00758 return -1;
00759 }
00760 usIdent = usGetWord(0x00, aucHeader);
00761 DBG_HEX(usIdent);
00762 fail(usIdent != 0x8098 &&
00763 usIdent != 0x8099 &&
00764 usIdent != 0xa5dc &&
00765 usIdent != 0xa5ec &&
00766 usIdent != 0xa697 &&
00767 usIdent != 0xa699);
00768 iWordVersion = iGetVersionNumber(aucHeader);
00769 if (iWordVersion < 6) {
00770 FREE_ALL();
00771 werr(0, "This file is from a version of Word before Word 6.");
00772 return -1;
00773 }
00774
00775
00776 usDocStatus = usGetWord(0x0a, aucHeader);
00777 if (usDocStatus & BIT(9)) {
00778 PPS_info.tTable = PPS_info.t1Table;
00779 } else {
00780 PPS_info.tTable = PPS_info.t0Table;
00781 }
00782
00783 memset(&PPS_info.t0Table, 0, sizeof(PPS_info.t0Table));
00784 memset(&PPS_info.t1Table, 0, sizeof(PPS_info.t1Table));
00785
00786 bSuccess = bGetDocumentText(pFile, &PPS_info,
00787 aulBBD, tBBDLen, aulSBD, tSBDLen,
00788 aucHeader, iWordVersion);
00789 if (bSuccess) {
00790 vGetDocumentData(pFile, &PPS_info,
00791 aulBBD, tBBDLen, aucHeader, iWordVersion);
00792 vGetPropertyInfo(pFile, &PPS_info,
00793 aulBBD, tBBDLen, aulSBD, tSBDLen,
00794 aucHeader, iWordVersion);
00795 vSetDefaultTabWidth(pFile, &PPS_info,
00796 aulBBD, tBBDLen, aulSBD, tSBDLen,
00797 aucHeader, iWordVersion);
00798 vGetNotesInfo(pFile, &PPS_info,
00799 aulBBD, tBBDLen, aulSBD, tSBDLen,
00800 aucHeader, iWordVersion);
00801 }
00802 FREE_ALL();
00803 return bSuccess ? iWordVersion : -1;
00804 }