dwindows.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:24k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * dwindows.cxx
  3.  *
  4.  * Resource compiler, MS-Windows binary resource decompiler.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: dwindows.cxx,v $
  30.  * Revision 1.19  2000/06/21 02:05:45  robertj
  31.  * Fixed problems in decompile of .ICO file with multiple icons
  32.  *
  33.  * Revision 1.18  1999/10/18 04:41:09  robertj
  34.  * Added decompile of .BMP and .ICO files and fixed ability to have 64x64 icons
  35.  *
  36.  * Revision 1.17  1999/01/21 05:23:24  robertj
  37.  * Fixed build environment problems.
  38.  *
  39.  * Revision 1.16  1998/09/26 01:24:04  robertj
  40.  * Added open source license
  41.  *
  42.  * Revision 1.15  1997/12/12 08:44:24  robertj
  43.  * Update to currect version of PWLIB
  44.  *
  45.  * Revision 1.14  1995/12/10 12:11:59  robertj
  46.  * Changes to support graphical resource file editor.
  47.  *
  48.  * Revision 1.13  1994/07/02 03:25:39  robertj
  49.  * Fixed bug.
  50.  *
  51.  * Revision 1.12  1994/06/25  12:16:28  robertj
  52.  * Synchonsiation with unix implementation.
  53.  *
  54.  * Revision 1.11  1994/04/03  08:37:00  robertj
  55.  * *** empty log message ***
  56.  *
  57.  * Revision 1.10  1994/04/01  14:29:16  robertj
  58.  * New format PRC file
  59.  *
  60.  * Revision 1.9  1994/01/03  04:34:30  robertj
  61.  * Changed scan lines in internal structure to top to bottom.
  62.  *
  63.  * Revision 1.8  1993/12/31  07:05:07  robertj
  64.  * Changed pixmap images for one pixel one number in PRC file.
  65.  *
  66.  * Revision 1.7  1993/12/14  18:54:42  robertj
  67.  * WIN32 port.
  68.  *
  69.  * Revision 1.6  1993/11/30  18:39:11  robertj
  70.  * Standard container macro changed.
  71.  *
  72.  * Revision 1.5  1993/08/21  04:42:42  robertj
  73.  * Clone() function made optional and removed.
  74.  *
  75.  * Revision 1.4  1993/07/19  14:14:52  robertj
  76.  * Fixed major bugs in ICON and CURSOR decompiling.
  77.  *
  78.  * Revision 1.3  1993/07/17  02:57:00  robertj
  79.  * Further implementation
  80.  *
  81.  * Revision 1.2  1993/07/16  14:52:23  robertj
  82.  * Further implementation.
  83.  *
  84.  * Revision 1.1  1993/07/16  12:53:12  robertj
  85.  * Initial revision
  86.  *
  87.  */
  88. #include <ptlib.h>
  89. #ifndef WIN32
  90. #undef NEAR
  91. #endif
  92. #include <windows.h>
  93. #include "pwrc.h"
  94. #include "....includepwlibstdresid.h"
  95. #include <ctype.h>
  96. #include <fcntl.h>
  97. #include <iomanip.h>
  98. ///////////////////////////////////////////////////////////////
  99. //
  100. //  Decompiler
  101. //
  102. PDECLARE_CLASS(WinResource, PObject)
  103.   public:
  104.     WinResource(short tn, PString ts, short i, PINDEX l, off_t p)
  105.       : typeNum(tn), typeStr(ts), ID(i), len(l), pos(p) { }
  106.   
  107.     short typeNum;
  108.     PString typeStr;
  109.     short ID;
  110.     PINDEX len;
  111.     off_t pos;
  112.   protected:
  113.     Comparison Compare(const PObject & obj) const
  114.       { return typeNum == ((const WinResource &)obj).typeNum ? EqualTo : GreaterThan; }
  115. };
  116. PLIST(WinResourceList, WinResource);
  117. static WinResourceList WinResources;
  118. short ReadWord(PFile & in)
  119. {
  120.   short s;
  121.   in.Read(&s, sizeof(s));
  122.   return s;
  123. }
  124. long ReadLong(PFile & in)
  125. {
  126.   long l;
  127.   in.Read(&l, sizeof(l));
  128.   return l;
  129. }
  130. PString ReadStr(PFile & in)
  131. {
  132.   PString s;
  133.   PINDEX count = 256;
  134.   char * p = s.GetPointer(count+1);
  135.   while (count > 0 && in.Read(p, 1) && *p++ != '')
  136.     count--;
  137.   s.MakeMinimumSize();
  138.   return s;
  139. }
  140. short ReadTypeOrID(PFile & in, PString & str)
  141. {
  142.   BYTE c;
  143.   if (in.Read(&c, 1) && c == 0xff) {
  144.     str = "";
  145.     return ReadWord(in);
  146.   }
  147.   str = PString(c) + ReadStr(in);
  148.   return 0;
  149. }
  150. short ReadResHeader(PFile & in, short & ID, long & resLen)
  151. {
  152.   PString resTypeStr, resIDStr;
  153.   short resType = ReadTypeOrID(in, resTypeStr);
  154.   ID = ReadTypeOrID(in, resIDStr);
  155.   if (!resIDStr.IsEmpty()) // Named resources not supported
  156.     resType = 0;
  157.   in.SetPosition(2, PFile::Current);  // Skip load options
  158.   resLen = ReadLong(in);
  159.   return resType;
  160. }
  161. void ScanResources(PFile & in)
  162. {
  163.   in.SetPosition(0);
  164.   while (in.GetPosition() < in.GetLength()) {
  165.     const char * warn = NULL;
  166.     PString resTypeStr, resIDStr;
  167.     short resType = ReadTypeOrID(in, resTypeStr);
  168.     if (resTypeStr != "DIALOGSTRINGS" &&
  169.         resTypeStr.GetLength() != 4 &&
  170.         (resType < 1 || resType > 6) &&
  171.         resType != 9 && resType != 10 && resType != 12 && resType != 14)
  172.       warn = "Usupported resource";
  173.     short resID = ReadTypeOrID(in, resIDStr);
  174.     if (!resIDStr.IsEmpty())
  175.       warn = "Named resources are unsupported";
  176.     if (ReadWord(in) != 0x1030) {
  177.       cerr << "Warning: Unsupported load options in resource, type=";
  178.       if (resTypeStr.IsEmpty())
  179.         cerr << resType;
  180.       else
  181.         cerr << resTypeStr.ToLiteral();
  182.       cerr << " ID=";
  183.       if (resIDStr.IsEmpty())
  184.         cerr << resID;
  185.       else
  186.         cerr << resIDStr.ToLiteral();
  187.     }
  188.     long resLen = ReadLong(in);
  189.     if (warn == NULL)
  190.       WinResources.Append(new WinResource(resType,
  191.                         resTypeStr, resID, (PINDEX)resLen, in.GetPosition()));
  192.     else {
  193.       cerr << "Warning: " << warn << ", type=";
  194.       if (resTypeStr.IsEmpty())
  195.         cerr << resType;
  196.       else
  197.         cerr << resTypeStr.ToLiteral();
  198.       cerr << " ID=";
  199.       if (resIDStr.IsEmpty())
  200.         cerr << resID;
  201.       else
  202.         cerr << resIDStr.ToLiteral();
  203.       cerr << " - ignoring.n";
  204.     }
  205.     in.SetPosition(resLen, PFile::Current);
  206.   }
  207. }
  208. void DecompileStrings(PFile & in, PTextFile & out, const WinResource & res)
  209. {
  210.   for (PINDEX i = 0; i < 16; i++) {
  211.     char len;
  212.     in.Read(&len, 1);
  213.     if (len != 0) {
  214.       PString s;
  215.       in.Read(s.GetPointer(len+1), len);
  216.       out << "String " << (((res.ID-1)<<4)|i) << ", " << s.ToLiteral() << ";n";
  217.     }
  218.   }
  219. }
  220. void DecompileSubMenu(PFile & in, PTextFile & out, const PString & indent)
  221. {
  222.   PString title = ReadStr(in);
  223.   out << indent << "Menu " << title.ToLiteral() << "{n";
  224.   short menuFlags;
  225.   do {
  226.     menuFlags = ReadWord(in);
  227.     if ((menuFlags&MF_POPUP) != 0)
  228.       DecompileSubMenu(in, out, indent+"    ");
  229.     else {
  230.       unsigned short id = (unsigned short)ReadWord(in);
  231.       title = ReadStr(in);
  232.       if (title.IsEmpty())
  233.         out << indent << "    Separator;n";
  234.       else {
  235.         int tab = title.Find('t');
  236.         if (tab > 0)
  237.           title = title(0, tab-1);
  238.         out << indent << "    Item ";
  239.         if (!PProcess::Current().GetArguments().HasOption('i'))
  240.           out << "MenuItem";
  241.         out << id << " {n"
  242.             << indent << "        Title " << title.ToLiteral() << ";n"
  243.             << indent << "    }n";
  244.       }
  245.     }
  246.   } while ((menuFlags&MF_END) == 0);
  247.   out << indent << "}n";
  248. }
  249. void DecompileMenuBar(PFile & in, PTextFile & out, const WinResource & res)
  250. {
  251.   out << "nnnMenuBar ";
  252.   if (!PProcess::Current().GetArguments().HasOption('i'))
  253.     out << "@MenuBar";
  254.   out << res.ID << "n{n";
  255.   short menuFlags;
  256.   do {
  257.     menuFlags = ReadWord(in);
  258.     if ((menuFlags&MF_POPUP) != 0)
  259.       DecompileSubMenu(in, out, "    ");
  260.   } while ((menuFlags&MF_END) == 0);
  261.   out << "}n";
  262. }
  263. void DecompileDialog(PFile & in, PTextFile & out, const WinResource & res)
  264. {
  265.   for (PINDEX strRes = 0; strRes < WinResources.GetSize(); strRes++) {
  266.     if (WinResources[strRes].ID == res.ID &&
  267.                             WinResources[strRes].typeStr == "DIALOGSTRINGS")
  268.       break;
  269.   }
  270.   long style = ReadLong(in);
  271.   if (style != (WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME|DS_SETFONT))
  272.     cerr << "Warning: Unsupported style for dialog " << res.ID << endl;
  273.   char numItems;
  274.   in.Read(&numItems, 1);
  275.   short pos_x = ReadWord(in);
  276.   short pos_y = ReadWord(in);
  277.   short dim_x = ReadWord(in);
  278.   short dim_y = ReadWord(in);
  279.   if (in.ReadChar() != 0) {
  280.     cerr << "Warning: Unsupported menu in dialog " << res.ID << endl;
  281.     ReadStr(in);
  282.   }
  283.   if (in.ReadChar() != 0) {
  284.     cerr << "Warning: Unsupported class for dialog " << res.ID << endl;
  285.     ReadStr(in);
  286.   }
  287.   PString s = ReadStr(in);
  288.   out << "nnnDialog ";
  289.   if (!PProcess::Current().GetArguments().HasOption('i'))
  290.     out << "@Dialog";
  291.   out << res.ID << "n{n"
  292.          "    Title " << s.ToLiteral() << ";n";
  293.   if (pos_x != -10000 || pos_y != -10000)
  294.     out << "    Position " << pos_x << ',' << pos_y << ";n";
  295.   if (dim_x > 0 || dim_y > 0)
  296.     out << "    Dimensions " << dim_x << ',' << dim_y << ";n";
  297.   short fontSize = ReadWord(in);
  298.   s = ReadStr(in);
  299.   if (s != "MS Sans Serif" || fontSize != 8)
  300.     out << "    Font " << s.ToLiteral() << ", " << fontSize << endl;
  301.   out << endl;
  302.   for (PINDEX i = 0; i < numItems; i++) {
  303.     pos_x = ReadWord(in);
  304.     pos_y = ReadWord(in);
  305.     dim_x = ReadWord(in);
  306.     dim_y = ReadWord(in);
  307.     short id = ReadWord(in);
  308.     style = ReadLong(in);
  309.     BYTE type = (BYTE)in.ReadChar();
  310.     int iconID = 0;
  311.     if (type == 0x82 && (style&15) == SS_ICON) {
  312.       if (in.ReadChar() == 0xff) {
  313.         iconID = ReadWord(in);
  314.         in.SetPosition(1, PFile::Current); // Skip the extra null
  315.       }
  316.       else {
  317.         ReadStr(in);
  318.         cerr << "Warning: Unsupported icon name in item " << i+1
  319.              << " (ID=" << id << ") in dialog " << res.ID << endl;
  320.         in.SetPosition(2, PFile::Current); // Skip the terminating nulls
  321.       }
  322.     }
  323.     else {
  324.       s = ReadStr(in);
  325.       in.SetPosition(1, PFile::Current); // Skip the extra null
  326.     }
  327.     char * keyword = "??Control";
  328.     BOOL hasName = TRUE;
  329.     BOOL styleWarning = FALSE;
  330.     switch (type) {
  331.       case 0x80 :
  332.         switch (style & 15) {
  333.           case BS_PUSHBUTTON :
  334.           case BS_DEFPUSHBUTTON :
  335.             keyword = "PushButton";
  336.             break;
  337.                 
  338.           case BS_AUTOCHECKBOX :
  339.           case BS_CHECKBOX :
  340.             keyword = "CheckBox";
  341.             break;
  342.                 
  343.           case BS_AUTO3STATE :
  344.           case BS_3STATE :
  345.             keyword = "Check3Way";
  346.             break;
  347.                 
  348.           case BS_AUTORADIOBUTTON :
  349.           case BS_RADIOBUTTON :
  350.             keyword = "RadioButton";
  351.             break;
  352.           case BS_GROUPBOX :
  353.             keyword = "StaticBox";
  354.             break;
  355.           default:
  356.             styleWarning = TRUE;
  357.         }
  358.         break;
  359.       case 0x81 :
  360.         if ((style&ES_MULTILINE) != 0)
  361.           keyword = "TextEditor";
  362.         else if (s == "INTEDITBOX")
  363.           keyword = "IntEdit";
  364.         else if (s == "REALEDITBOX")
  365.           keyword = "RealEdit";
  366.         else
  367.           keyword = "EditBox";
  368.         hasName = FALSE;
  369.         break;
  370.       case 0x82 :
  371.         switch (style & 15) {
  372.           case SS_LEFT :
  373.           case SS_SIMPLE :
  374.             keyword = "LeftText";
  375.             break;
  376.                 
  377.           case SS_CENTER :
  378.             keyword = "CentreText";
  379.             break;
  380.                 
  381.           case SS_RIGHT :
  382.             keyword = "RightText";
  383.             break;
  384.                 
  385.           case SS_ICON :
  386.             keyword = "StaticIcon";
  387.             hasName = FALSE;
  388.             break;
  389.           default:
  390.             styleWarning = TRUE;
  391.         }
  392.         break;
  393.       case 0x83 :
  394.         keyword = "ListBox";
  395.         hasName = FALSE;
  396.         break;
  397.       case 0x84 :
  398.         keyword = (style&1) == SBS_HORZ ? "HScrollBar" : "VScrollBar";
  399.         hasName = FALSE;
  400.         break;
  401.       case 0x85 :
  402.         switch (style & 15) {
  403.           case CBS_DROPDOWN :
  404.             keyword = "ComboBox";
  405.             break;
  406.           case CBS_DROPDOWNLIST :
  407.             keyword = "ChoiceBox";
  408.             break;
  409.           default:
  410.             styleWarning = TRUE;
  411.         }
  412.         hasName = FALSE;
  413.         break;
  414.     }
  415.     if (styleWarning)
  416.       cerr << "Warning: Unsupported style for item " << i+1
  417.            << " (ID=" << id << ") in dialog " << res.ID << endl;
  418.     out << "    " << keyword << " {n";
  419.     if (hasName)
  420.       out << "        Title " << s.ToLiteral() << ";n";
  421.     else if (type == 0x82 && (style&15) == SS_ICON)
  422.       out << "        Icon " << iconID << ";n";
  423.     if (PProcess::Current().GetArguments().HasOption('i'))
  424.       out << "        Id " << id << ";n";
  425.     out << "        Position " << pos_x << ", " << pos_y << ";n"
  426.            "        Dimensions " << dim_x << ", " << dim_y << ";n";
  427.     PString options;
  428.     switch (type) {
  429.       case 0x83 :
  430.         if ((style&LBS_SORT) != 0)
  431.           options = "Sorted ";
  432.         if ((style&LBS_EXTENDEDSEL) != 0)
  433.           options += "MultiSelect ";
  434.         if ((style&LBS_MULTICOLUMN) != 0)
  435.           options += "MultiColumn";
  436.         break;
  437.       case 0x85 :
  438.         if ((style&CBS_SORT) != 0)
  439.           options = "Sorted";
  440.         break;
  441.       case 0x80 :
  442.         switch (style & 15) {
  443.           case BS_DEFPUSHBUTTON :
  444.           case BS_PUSHBUTTON :
  445.             switch (id) {
  446.               case 1 :
  447.                 options = "Ok";
  448.                 break;
  449.               case 2 :
  450.                 options = "Cancel";
  451.                 break;
  452.               case 3 :
  453.                 options = "Help";
  454.                 break;
  455.             }
  456.             if ((style & 15) == BS_DEFPUSHBUTTON)
  457.               options += " Default";
  458.         }
  459.     }
  460.     if (!options.IsEmpty())
  461.       out << "        Options " << options << ";n";
  462.     if (strRes < WinResources.GetSize()) {
  463.       off_t remember = in.GetPosition();
  464.       in.SetPosition(WinResources[strRes].pos);
  465.       while (in.GetPosition() < in.GetLength()) {
  466.         short strID = ReadWord(in);
  467.         short strLen = ReadWord(in);
  468.         short strCount = ReadWord(in);
  469.         if (strCount == 0)
  470.           break;
  471.         if (strID == id) {
  472.           out << "        String {n";
  473.           while (--strCount > 0)
  474.             out << "            " << ReadStr(in).ToLiteral() << ",n";
  475.           out <<   "            " << ReadStr(in).ToLiteral() << "n"
  476.                    "        }n";
  477.           break;
  478.         }
  479.         in.SetPosition(strLen, PFile::Current);
  480.       }
  481.       in.SetPosition(remember);
  482.     }
  483.     out << "    }n";
  484.   }
  485.   out << "}n";
  486. }
  487. void DecompileClut(PFile & in, PTextFile & out, PINDEX bitCount)
  488. {
  489.   if (bitCount == 24)
  490.     return;
  491.   out << "    Colours {n";
  492.   PINDEX colours = (1 << bitCount)-1;
  493.   for (PINDEX c = 0; c <= colours; c++) {
  494.     RGBQUAD rgb;
  495.     in.Read(&rgb, sizeof(rgb));
  496.     out << "        " << setw(3) << (rgb.rgbRed&0xff)
  497.         << ", "       << setw(3) << (rgb.rgbGreen&0xff)
  498.         << ", "       << setw(3) << (rgb.rgbBlue&0xff)
  499.         << (c != colours ? ",n" : "n");
  500.   }
  501.   out << "    }n";
  502. }
  503. void DecompilePixels(PFile & in, PTextFile & out,
  504.      const char * keyword, PINDEX lines, PINDEX lineWidth, PINDEX bitsPerPixel)
  505. {
  506.   off_t pixbase = in.GetPosition();
  507.   PINDEX lineBytes = ((lineWidth*bitsPerPixel+31)/32)*4;
  508.   out << "    " << keyword << " {n       ";
  509.   for (int l = lines-1; l >= 0; l--) {
  510.     in.SetPosition(pixbase+l*lineBytes);
  511.     if (bitsPerPixel > 8) {
  512.       for (PINDEX byteInLine = 0; byteInLine < lineBytes; byteInLine++)
  513.         out << in.ReadChar() << ' ';
  514.     }
  515.     else {
  516.       PINDEX outWidth = bitsPerPixel > 6 ? 4 : bitsPerPixel > 3 ? 3 : 2;
  517.       PINDEX byteInLine = 0;
  518.       PINDEX pixelsPerByte = 8/bitsPerPixel;
  519.       PINDEX bitsPerPixelMask = (1 << bitsPerPixel)-1;
  520.       PINDEX bitShift = 8 - bitsPerPixel;
  521.       PINDEX pixelInByte = pixelsPerByte;
  522.       PINDEX byte = 0;
  523.       for (PINDEX pix = 0; pix < lineWidth; pix++) {
  524.         if (++pixelInByte >= pixelsPerByte) {
  525.           byte = in.ReadChar();
  526.           byteInLine++;
  527.           pixelInByte = 0;
  528.         }
  529.         out << setw(outWidth) << ((byte >> bitShift)&bitsPerPixelMask);
  530.         byte <<= bitsPerPixel;
  531.       }
  532.     }
  533.     if (l > 0)
  534.       out << "n       ";
  535.   }
  536.   out << "n    }n";
  537.   in.SetPosition(pixbase+lines*lineBytes);
  538. }
  539. BOOL ReadBitmapHeader(PFile & in, BITMAPINFOHEADER & bm)
  540. {
  541.   in.Read(&bm, sizeof(bm));
  542.   if (bm.biPlanes == 1 && bm.biSizeImage < 65536L)
  543.     return TRUE;
  544.   cerr << "Warning: Unsupported image bitmap typen";
  545.   return FALSE;
  546. }
  547. BOOL DecompileIconCursorImage(PFile & in, PTextFile & out)
  548. {
  549.   BITMAPINFOHEADER bm;
  550.   if (!ReadBitmapHeader(in, bm))
  551.     return FALSE;
  552.   bm.biHeight /= 2;
  553.   out << "    Dimensions " << bm.biWidth << ','
  554.       << bm.biHeight << ',' << bm.biBitCount << ";n";
  555.   DecompileClut(in, out, bm.biBitCount);
  556.   DecompilePixels(in, out, "Pixels",
  557.           (PINDEX)bm.biHeight, (PINDEX)bm.biWidth, (PINDEX)bm.biBitCount);
  558.   DecompilePixels(in, out, "AndMask",
  559.                               (PINDEX)bm.biHeight, (PINDEX)bm.biWidth, 1);
  560.   return TRUE;
  561. }
  562. void DecompileIconCursor(PFile & in, PTextFile & out, const WinResource & res,
  563.       const char * keyword, short checkCode, short imgResType, BOOL hasHotspot)
  564. {
  565.   out << "nnn" << keyword << ' ';
  566.   if (!PProcess::Current().GetArguments().HasOption('i'))
  567.     out << '@' << keyword;
  568.   out << res.ID << "n{n";
  569.   in.SetPosition(2, PFile::Current);
  570.   if (ReadWord(in) != checkCode)
  571.     cerr << "Warning: Invalid " << keyword << " directory resource.n";
  572.   int biLevelID = -1;
  573.   int colourID = -1;
  574.   short count = ReadWord(in);
  575.   while (count-- > 0) {
  576.     in.SetPosition(4, PFile::Current);
  577.     if (ReadWord(in) != 1) {
  578.       cerr << "Warning: Multi plane " << keyword << " in resource.n";
  579.       in.SetPosition(8, PFile::Current);
  580.     }
  581.     else {
  582.       short bits = ReadWord(in);
  583.       in.SetPosition(4, PFile::Current);
  584.       if (bits == 1)
  585.         biLevelID = ReadWord(in);
  586.       else if (colourID < 0)
  587.         colourID = ReadWord(in);
  588.       else {
  589.         cerr << "Warning: Only one colour " << keyword << " supported in resource.n";
  590.         in.SetPosition(2, PFile::Current);
  591.       }
  592.     }
  593.   }
  594.   if (colourID >= 0) {
  595.     for (PINDEX colourRes=0; colourRes < WinResources.GetSize(); colourRes++) {
  596.       if (WinResources[colourRes].typeNum == imgResType &&
  597.                                         WinResources[colourRes].ID == colourID)
  598.         break;
  599.     }
  600.     if (colourRes >= WinResources.GetSize())
  601.       cerr << "Warning: Missing " << keyword << " resource.n";
  602.     else {
  603.       off_t remember = in.GetPosition();
  604.       in.SetPosition(WinResources[colourRes].pos);
  605.   
  606.       if (hasHotspot)
  607.         out << "    HOTSPOT "
  608.             << ReadWord(in) << ',' << ReadWord(in) << ";n";
  609.   
  610.       DecompileIconCursorImage(in, out);
  611.       in.SetPosition(remember);
  612.     }
  613.   }
  614.   if (biLevelID >= 0) {
  615.     for (PINDEX biLevelRes=0; biLevelRes<WinResources.GetSize(); biLevelRes++){
  616.       if (WinResources[biLevelRes].typeNum == imgResType &&
  617.                                       WinResources[biLevelRes].ID == biLevelID)
  618.         break;
  619.     }
  620.     if (biLevelRes >= WinResources.GetSize())
  621.       cerr << "Warning: Missing " << keyword << " resource.n";
  622.     else {
  623.       off_t remember = in.GetPosition();
  624.       in.SetPosition(WinResources[biLevelRes].pos);
  625.   
  626.       if (hasHotspot) {
  627.         if (colourID < 0)
  628.           out << "    HOTSPOT "
  629.               << ReadWord(in) << ',' << ReadWord(in) << ";n";
  630.         else
  631.           in.SetPosition(4, PFile::Current);
  632.       }
  633.       BITMAPINFOHEADER bm;
  634.       ReadBitmapHeader(in, bm);
  635.       bm.biHeight /= 2;
  636.   
  637.       if (colourID < 0)
  638.         out << "    Dimensions " << bm.biWidth << ','
  639.             << bm.biHeight << ',' << bm.biBitCount << ";n";
  640.       in.SetPosition(2*sizeof(RGBQUAD), PFile::Current);
  641.       DecompilePixels(in, out, "XorMask",
  642.                                   (PINDEX)bm.biHeight, (PINDEX)bm.biWidth, 1);
  643.       if (colourID < 0)
  644.         DecompilePixels(in, out, "AndMask",
  645.                                   (PINDEX)bm.biHeight, (PINDEX)bm.biWidth, 1);
  646.       in.SetPosition(remember);
  647.     }
  648.   }
  649.   out << "}n";
  650. }
  651. void DecompileIcon(PFile & in, PTextFile & out, const WinResource & res)
  652. {
  653.   DecompileIconCursor(in, out, res, "Icon", 1, 3, FALSE);
  654. }
  655. void DecompileCursor(PFile & in, PTextFile & out, const WinResource & res)
  656. {
  657.   DecompileIconCursor(in, out, res, "Cursor", 2, 1, TRUE);
  658. }
  659. void DecompileImage(PFile & in, PTextFile & out, const WinResource & res)
  660. {
  661.   BITMAPINFOHEADER bm;
  662.   ReadBitmapHeader(in, bm);
  663.   out << "nnnIMAGE " << res.ID << "n{n    Dimensions "
  664.       << bm.biWidth << ',' << bm.biHeight << ',' << bm.biBitCount << ";n";
  665.   DecompileClut(in, out, bm.biBitCount);
  666.   DecompilePixels(in, out, "Pixels",
  667.               (PINDEX)bm.biHeight, (PINDEX)bm.biWidth, (PINDEX)bm.biBitCount);
  668.   out << "}n";
  669. }
  670. void DecompileDataBlock(PFile & in, PTextFile & out, PINDEX len)
  671. {
  672.   out << "n{n    ";
  673.   int lineOutput = 16;
  674.   for (PINDEX i = 0; i < len-1; i++) {
  675.     out << in.ReadChar();
  676.     if (--lineOutput != 0)
  677.       out << ", ";
  678.     else {
  679.       out << ",n    ";
  680.       lineOutput = 16;
  681.     }
  682.   }
  683.   out << in.ReadChar() << "n}n";
  684. }
  685. void DecompileData(PFile & in, PTextFile & out, const WinResource & res)
  686. {
  687.   out << "nnnResource ";
  688.   if (!PProcess::Current().GetArguments().HasOption('i'))
  689.     out << "@Resource";
  690.   out << res.ID;
  691.   DecompileDataBlock(in, out, res.len);
  692. }
  693. void DecompileCustom(PFile & in, PTextFile & out)
  694. {
  695.   for (PINDEX res = 0; res < WinResources.GetSize(); res++) {
  696.     if (WinResources[res].typeStr.GetLength() == 4) {
  697.       in.SetPosition(WinResources[res].pos);
  698.       out << "nnnResource ";
  699.       if (!PProcess::Current().GetArguments().HasOption('i'))
  700.         out << "@Resource";
  701.       out << WinResources[res].ID << ", "
  702.           << WinResources[res].typeStr.ToLiteral();
  703.       DecompileDataBlock(in, out, WinResources[res].len);
  704.     }
  705.   }
  706. }
  707. void DecompileResources(PFile & in, PTextFile & out, short type,
  708.                void (*decompiler)(PFile &, PTextFile &, const WinResource &))
  709. {
  710.   for (PINDEX res = 0; res < WinResources.GetSize(); res++) {
  711.     if (WinResources[res].typeNum == type) {
  712.       in.SetPosition(WinResources[res].pos);
  713.       decompiler(in, out, WinResources[res]);
  714.     }
  715.   }
  716. }
  717. void Decompile(PFile & in, PTextFile & out)
  718. {
  719.   out << "// Portable Windows Library Resource Decompiler Generated File.nn";
  720.   _setmode(in.GetHandle(), _O_BINARY);
  721.   if (in.GetFilePath().GetType() == ".bmp") {
  722.     WinResource res(2, "", 1, 0, 0);
  723.     BITMAPFILEHEADER bmfh;
  724.     in.Read(&bmfh, sizeof(bmfh));
  725.     if (bmfh.bfType != 'MB')
  726.       cerr << "Resource file is not a .BMP file!n";
  727.     else
  728.       DecompileImage(in, out, res);
  729.   }
  730.   else if (in.GetFilePath().GetType() == ".ico") {
  731.     if (ReadWord(in) != 0 || ReadWord(in) != 1)
  732.       cerr << "Resource file is not a .ICO file!n";
  733.     else {
  734.       PINDEX count = ReadWord(in);
  735.       in.SetPosition(16*count, PFile::Current);
  736.       for (PINDEX i = 1; i <= count; i++) {
  737.         out << "nnnICON " << i << "n{n";
  738.         if (!DecompileIconCursorImage(in, out))
  739.           break;
  740.         out << "}n";
  741.       }
  742.     }
  743.   }
  744.   else {
  745. #ifdef WIN32
  746.     cerr << "Warning!!! The decompile facility is not available on Windows NT platforms.n"
  747.             "This will only decompile Windows 3.1 Resource files.nn";
  748. #endif
  749.     ScanResources(in);
  750.     DecompileResources(in, out, 6, DecompileStrings);
  751.     DecompileResources(in, out, 4, DecompileMenuBar);
  752.     DecompileResources(in, out, 5, DecompileDialog);
  753.     DecompileResources(in, out, 14, DecompileIcon);
  754.     DecompileResources(in, out, 12, DecompileCursor);
  755.     DecompileResources(in, out, 2, DecompileImage);
  756.     DecompileResources(in, out, 10, DecompileData);
  757.     DecompileCustom(in, out);
  758.   }
  759.   out << "nnn// End Resources.n";
  760. }