PDBFile.cpp
上传用户:hmc_gdtv
上传日期:2013-08-04
资源大小:798k
文件大小:7k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001,2002,2003 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    this list of conditions, and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: PDBFile.cpp,v 1.13.2.5 2004/09/29 08:27:12 mike Exp $
  29.  * 
  30.  */
  31. #include <afxwin.h>
  32. #include "ptr.h"
  33. #include "PDBFile.h"
  34. #include "TextViewNG.h"
  35. #include <string.h>
  36. // pdb header
  37. struct PDBHdr {
  38.   char   name[32];
  39.   WORD   attr;
  40.   WORD   ver;
  41.   DWORD   ctime;
  42.   DWORD   mtime;
  43.   DWORD   btime;
  44.   DWORD   mnum;
  45.   DWORD   appinfoid;
  46.   DWORD   aortinfoid;
  47.   char   type[4];
  48.   char   creator[4];
  49.   DWORD   idseed;
  50.   DWORD   nextreclist;
  51.   WORD   numrec;
  52. };
  53. #define PDBHDRSIZE  78
  54. // record 0
  55. struct PDBRec0 {
  56.   WORD   ver;
  57.   WORD   res1;
  58.   DWORD   usize;
  59.   WORD   nrec;
  60.   WORD   rsize;
  61.   DWORD   res2;
  62. };
  63. #define PDBR0SIZE 16
  64. static DWORD  dword(const DWORD& dw) { // convert from BE
  65.   BYTE *b=(BYTE*)&dw;
  66.   return ((DWORD)b[0]<<24)|((DWORD)b[1]<<16)|((DWORD)b[2]<<8)|b[3];
  67. }
  68. static WORD   word(const WORD& w) { // convert from BE
  69.   BYTE *b=(BYTE*)&w;
  70.   return ((WORD)b[0]<<8)|b[1];
  71. }
  72. bool  PDBFile::CheckPDB(RFile *fp,PDBHdr& hdr,PDBRec0& r0) {
  73.   // we want to access original RFile methods, not the overridden
  74.   // ones
  75.   fp->RFile::seek(0);
  76.   if (fp->RFile::read2(&hdr,PDBHDRSIZE)!=PDBHDRSIZE)
  77.     return false;
  78.   if (memcmp(hdr.type,"TEXt",4) || memcmp(hdr.creator,"REAd",4))
  79.     return false;
  80.   DWORD   off0;
  81.   if (fp->RFile::read2(&off0,4)!=4)
  82.     return false;
  83.   fp->RFile::seek(dword(off0));
  84.   if (fp->RFile::read2(&r0,PDBR0SIZE)!=PDBR0SIZE)
  85.     return false;
  86.   if (word(r0.ver)!=1 && word(r0.ver)!=2 && word(r0.ver)!=257 && word(r0.nrec)>0)
  87.     return false;
  88.   return true;
  89. }
  90. static DWORD scan_size(BYTE *src,DWORD len) {
  91.   DWORD   ulen=0;
  92.   while (len--) {
  93.     if (*src>=1 && *src<=8) {
  94.       DWORD k=*src++;
  95.       while (k-- && len--)
  96. src++,ulen++;
  97.     } else if (*src<=0x7f)
  98.       src++,ulen++;
  99.     else if (*src>=0xc0)
  100.       src++,ulen+=2;
  101.     else if (len) {
  102.       DWORD k=*src++;
  103.       k<<=8; k|=*src++;
  104.       --len;
  105.       ulen+=(k&7)+3;
  106.     }
  107.   }
  108.   return ulen;
  109. }
  110. PDBFile::PDBFile(const CString& fn) :
  111.   RFile(fn), m_length(0), m_ptr(0)
  112. {
  113.   PDBHdr    hdr;
  114.   PDBRec0   r0;
  115.   if (Reopen() && CheckPDB(this,hdr,r0)) {
  116.     m_comp=word(r0.ver)==2;
  117.     m_rsz=word(r0.rsize);
  118.     DWORD nr=word(r0.nrec);
  119.     m_blocks=Buffer<Rec>(nr);
  120.     // fill in records table
  121.     RFile::seek(PDBHDRSIZE+8);
  122.     for (DWORD j=0;j<nr;++j) {
  123.       DWORD   off[2];
  124.       if (RFile::read2(off,8)!=8)
  125. goto fail;
  126.       m_blocks[j].off=dword(off[0]);
  127.       if (j>0) {
  128. m_blocks[j-1].csize=m_blocks[j].off-m_blocks[j-1].off;
  129. if (m_blocks[j-1].csize>m_rsz)
  130.   goto fail;
  131.       }
  132.     }
  133.     if (nr+1<word(hdr.numrec)) { // minus rec0
  134.       DWORD   off[2];
  135.       if (RFile::read2(off,8)!=8)
  136. goto fail;
  137.       m_blocks[nr-1].csize=dword(off[0])-m_blocks[nr-1].off;
  138.     } else
  139.       m_blocks[nr-1].csize=(DWORD)RFile::size()-m_blocks[nr-1].off;
  140.     if (m_blocks[nr-1].csize>m_rsz)
  141.       goto fail;
  142.     if (m_comp) { // compressed
  143.       Buffer<BYTE>  tmp(m_rsz);
  144.       DWORD     uoff=0;
  145.       for (int i=0;i<m_blocks.size();++i) {
  146. RFile::seek(m_blocks[i].off);
  147. if (RFile::read2(tmp,m_blocks[i].csize)!=m_blocks[i].csize)
  148.   goto fail;
  149. m_blocks[i].usize=scan_size(tmp,m_blocks[i].csize);
  150. if (m_blocks[i].usize>m_rsz)
  151.   goto fail;
  152. m_blocks[i].uoff=uoff;
  153. uoff+=m_blocks[i].usize;
  154.       }
  155.       m_length=uoff;
  156.     } else { // uncompressed
  157.       for (int i=0;i<m_blocks.size();++i) {
  158. m_blocks[i].usize=m_blocks[i].csize;
  159. m_blocks[i].uoff=m_length;
  160. m_length+=m_blocks[i].usize;
  161.       }
  162.     }
  163.     return;
  164.   }
  165. fail:
  166.   CTVApp::Barf(_T("Invalid or unsupported PDB file"));
  167. }
  168. static DWORD pdb_decompress(BYTE *source,DWORD srclen,BYTE *dest,DWORD destlen)
  169. {
  170.   BYTE     *se=source+srclen;
  171.   BYTE     *de=dest+destlen;
  172.   BYTE     *dd=dest;
  173.   while (source<se && dest<de) {
  174.     DWORD c=*source++;
  175.     if (c>=1 && c<=8) { // copy
  176.       while (c-- && source<se && dest<de)
  177. *dest++=*source++;
  178.     } else if (c<=0x7f) // this char
  179.       *dest++=(BYTE)c;
  180.     else if (c>=0xc0) { // space + c&0x7f
  181.       *dest++=' ';
  182.       if (dest<de)
  183. *dest++=(BYTE)c&0x7f;
  184.     } else if (source<se) { // copy from decoded buf
  185.       c=(c<<8)|*source++;
  186.       int k=(c&0x3fff)>>3;
  187.       c=3+(c&7);
  188.       if (dest-k<dd || dest+c>de) // invalid buffer
  189. break;
  190.       while (c-- && dest<de) {
  191. *dest=dest[-k];
  192. ++dest;
  193.       }
  194.     }
  195.   }
  196.   return dest-dd;
  197. }
  198. void  PDBFile::seek(DWORD pos) {
  199.   if (pos>=m_length)
  200.     m_ptr=m_length;
  201.   else
  202.     m_ptr=pos&BMASK;
  203. }
  204. DWORD PDBFile::read(void *buf) {
  205.   if (m_ptr>=m_length)
  206.     return 0;
  207.   // ok, figure what block is needed
  208.   int i;
  209.   for (i=0;i<m_blocks.size();++i)
  210.     if (m_ptr>=m_blocks[i].uoff && m_ptr<m_blocks[i].uoff+m_blocks[i].usize)
  211.       goto found;
  212.   return 0;
  213. found:
  214.   Buffer<BYTE>   tmp(m_rsz),tmp2(m_rsz);
  215.   BYTE   *p=(BYTE*)buf;
  216.   DWORD   n=BSZ;
  217.   while (i<m_blocks.size() && n>0) {
  218.     RFile::seek(m_blocks[i].off);
  219.     if (m_comp) {
  220.       if (RFile::read2(tmp2,m_blocks[i].csize)!=m_blocks[i].csize)
  221. return 0;
  222.       if (pdb_decompress(tmp2,m_blocks[i].csize,tmp,m_rsz)!=m_blocks[i].usize)
  223. return 0;
  224.     } else {
  225.       if (RFile::read2(tmp,m_blocks[i].csize)!=m_blocks[i].csize)
  226. return 0;
  227.     }
  228.     // now we have a decompressed block in tmp
  229.     DWORD   hb=m_blocks[i].uoff+m_blocks[i].usize-m_ptr;
  230.     if (hb>n)
  231.       hb=n;
  232.     memcpy(p,tmp+m_ptr-m_blocks[i].uoff,hb);
  233.     p+=hb;
  234.     m_ptr+=hb;
  235.     n-=hb;
  236.     ++i;
  237.   }
  238.   return BSZ-n;
  239. }
  240. CString PDBFile::CompressionInfo() {
  241.   if (m_comp && m_length>0) {
  242.     CString ret;
  243.     ret.Format(_T("PDB, packed (%.2f)"),
  244.       (double)RFile::size()/(double)m_length);
  245.     return ret;
  246.   }
  247.   return _T("PDB, not packed");
  248. }
  249. bool  PDBFile::IsPDB(RFile *fp) {
  250.   PDBHdr    hdr;
  251.   PDBRec0   r0;
  252.   bool ret=CheckPDB(fp,hdr,r0);
  253.   fp->seek(0);
  254.   return ret;
  255. }