home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / chgct21a.zip / rdc.cmd < prev    next >
OS/2 REXX Batch file  |  1996-01-03  |  14KB  |  443 lines

  1. /* rdc.cmd -- Resource decompiler                             950531 */
  2. /* (c) Copyright Martin Lafaix 1995                                  */
  3.  
  4. say 'Operating System/2  Resource Decompiler'
  5. say 'Version 2.06.000 May 31 1995'
  6. say '(C) Copyright Martin Lafaix 1994, 1995'
  7. say 'All rights reserved.'
  8. say
  9.  
  10. arg param infile outfile x
  11. nl = '0d0a'x; includedlg=0; list = ''; parsed = ''; orgoutfile = ''
  12.  
  13. call RxFuncAdd 'SysTempFileName', 'RexxUtil', 'SysTempFileName'
  14.  
  15. if param = '-L' then
  16.    parse value 'ON -R' with list param
  17.  
  18. if param = '-H' | param = '' | x \= '' then
  19.    do
  20.       say 'Usage:  rdc [<option>] <.EXE input file> [<.RC output file>]'
  21.       say '        -r              - Extract .res file'
  22.       say '        -l              - List resources (but do not extract)'
  23.       say '        -h              - Access Help'
  24.       say
  25.       say 'Environment variables:'
  26.       say '        TMP=temporary file path'
  27.       say '        TEMP=temporary file path'
  28.       if x \= '' then
  29.          exit 1
  30.       else
  31.          exit
  32.    end
  33.  
  34. if param \= '-R' then
  35.    do
  36.       outfile = infile
  37.       infile = param
  38.       orgoutfile = outfile
  39.       outfile = ''
  40.    end
  41. outfile = outname(infile,'res')
  42.  
  43. step1:   /* convert from .EXE to .RES */
  44. if charin(infile,,2) = 'MZ' then
  45.    base = 1+l2d(charin(infile,61,4))
  46. else 
  47.    base = 1
  48. type = charin(infile,base,2)
  49. if  type \= 'LX' & type \= 'NE' then
  50.    do
  51.       if param = '-R' then
  52.          do
  53.          say 'Invalid input file header : 'infile
  54.          exit 1
  55.          end
  56.       else
  57.          signal step2
  58.    end
  59. if type = 'NE' then
  60.    do
  61.       cseg = w2d(charin(infile,base+28,2))
  62.       call skip 4
  63.       segtab = readw()
  64.       rsrctab = readw()
  65.       restab = readw()
  66.       call skip 10
  67.       segshift = readw()
  68.       rsrccnt = readw()
  69.       tabsize = 4
  70.       say 'Reading OS/2 v1.x .EXE file'
  71.    end
  72. else
  73.    do
  74.       call charin infile,base+44,0
  75.       pageshift = readl()
  76.       call skip 16
  77.       objtab = readl()
  78.       call skip 4
  79.       objmap = readl()
  80.       call skip 4
  81.       rsrctab = readl()
  82.       rsrccnt = readl()
  83.       restab = readl()
  84.       call skip 36
  85.       datapage = readl()
  86.       tabsize = 14
  87.       say 'Reading OS/2 v2.x .EXE file'
  88.    end
  89. if rsrccnt = 0 then
  90.    do
  91.       say nl'No resources!'
  92.       exit 2
  93.    end
  94. do cnt = 0 to rsrccnt-1
  95.    call charin infile,base+rsrctab+cnt*tabsize,0
  96.    if type = 'NE' then call tab16in; else call tab32in
  97.    call resout
  98. end /* do */
  99. if list \= 'ON' then
  100.    say nl'Writing binary resources to 'outfile
  101. else
  102.    exit
  103.  
  104. step1a:  /* conversion done */
  105. call stream infile, 'c', 'close'
  106. call stream outfile,'c', 'close'
  107. infile = outfile
  108. outfile = orgoutfile
  109. parsed = 'DONE'
  110.  
  111. step2:   /* convert from .RES to .RC */
  112. if param \= '-R' & list \= 'ON' then
  113.    do
  114.       if parsed \= 'DONE' then
  115.          arg infile outfile
  116.       outfile = outname(infile,'rc2')
  117.       if charin(infile,1,1)\= 'FF'x then
  118.          do
  119.             say 'Invalid RES input file : 'infile
  120.             exit 1
  121.          end
  122.       call charin infile,1,0
  123.       say 'Reading binary resources from .RES file'
  124.       call emit '#include <os2.h>'nl||nl
  125.       do while chars(infile) > 0
  126.          call res2rc
  127.       end /* do */
  128.       if includedlg=1 then
  129.          do 
  130.             outf=outfile; outfile='';
  131.             rcincl=outname(infile,'dlg')
  132.             outfile=outf
  133.             call emit nl'RCINCLUDE 'rcincl||nl
  134.          end /* do */
  135.       say nl'Writing extracted resources to 'outfile
  136.    end 
  137. exit
  138.  
  139. segin:   /* read segment map entry */
  140.    call charin infile,base+segtab+(arg(1)-1)*8,0
  141.    ssector = readw()
  142.    cb = readw()
  143.    sflags = readw()
  144.    smin = readw()
  145.    pos = 1+(2**segshift)*ssector
  146.    flags = 0
  147.    if bit(sflags,10) then flags = flags+64
  148.    if bit(sflags,12) then flags = flags+16
  149.    if bit(sflags,4) then flags = flags+4096
  150.    if \ bit(sflags,11) then flags = flags+32
  151.    return
  152.  
  153. tab16in: /* read resource table entry (16bits) */
  154.    etype = readw()
  155.    ename = readw()
  156.    call segin cseg-rsrccnt+1+cnt
  157.    return
  158.  
  159. objin:   /* read object map entry */
  160.    call charin infile,base+objtab+(arg(1)-1)*24,8
  161.    oflags = readl()
  162.    opagemap = readl()
  163.    omapsize = readl()
  164.    opagedataoffset = l2d(charin(infile,base+objmap+(opagemap-1)*8,4))
  165.    opagedatasize = readw()
  166.    opagedataflags = readw()
  167.    if list \= 'ON' & opagedataflags \= 0 then signal RDCPP
  168.    pos = 1+datapage+eoffset+(2**pageshift)*opagedataoffset
  169.    flags = 0
  170.    if bit(oflags,10) then flags = flags+64
  171.    if bit(oflags,11) then flags = flags+16
  172.    if bit(oflags,12) then flags = flags+4096
  173.    if \ bit(oflags,15) then flags = flags+32
  174.    return
  175.  
  176. tab32in: /* read resource table entry (32bits) */
  177.    etype = readw()
  178.    ename = readw()
  179.    cb = readl()
  180.    eobj = readw()
  181.    eoffset = readl()
  182.    call objin eobj
  183.    return
  184.  
  185. resout:  /* write resource to outfile */
  186.    say '    'ename'.'etype' ('cb' bytes)'
  187.    if list = 'ON' then return
  188.    call emit 'FF'x||d2w(etype)'FF'x||d2w(ename)d2w(flags)d2l(cb)
  189.    call emit charin(infile,pos,cb)
  190.    return
  191.  
  192. res2rc:  /* convert .RES format to .RC */
  193.    call skip 1
  194.    rt = readw()
  195.    call skip 1
  196.    id = readw()
  197.    opt = readw()
  198.    cb = readl()
  199.    select
  200.       when rt = 1  then call emit 'POINTER' id option() file('ptr')nl
  201.       when rt = 2  then call emit 'BITMAP' id option() file('bmp')nl
  202.       when rt = 3  then call emit menuout('  ','MENU 'id option()nl'BEGIN'nl)'END'nl
  203.       when rt = 4  then includedlg=1
  204.       when rt = 5  then call emit 'STRINGTABLE 'option()nl'BEGIN'strout()'END'nl
  205.       when rt = 6  then call emit 'RESOURCE' rt id option() file('dir') '/* FONTDIR */'nl
  206.       when rt = 7  then call emit 'FONT' id option() file('fon')nl
  207.       when rt = 8  then do; call emit 'ACCELTABLE' id option()nl'BEGIN'nl||keyout()'END'nl; end
  208.       when rt = 9  then call emit 'RESOURCE' rt id option() file('rdt') '/* RCDATA */'nl
  209.       when rt = 10 then call emit 'MESSAGETABLE 'option()nl'BEGIN'strout()'END'nl
  210.       when rt = 11 then do; call emit 'DLGINCLUDE' id charin(infile,,cb)nl; cb = 0; end
  211.       when rt = 12 then call emit 'RESOURCE' rt id option() file('vkt') '/* VKEYTBL */'nl
  212.       when rt = 13 then call emit 'RESOURCE' rt id option() file('kt') '/* KEYTBL */'nl
  213.       when rt = 14 then call emit 'RESOURCE' rt id option() file('ct') '/* CHARTBL */'nl
  214.       when rt = 15 then call emit 'RESOURCE' rt id option() file('di') '/*DISPLAYINFO */'nl
  215.       when rt = 16 then call emit 'FKASHORT 'id||nl
  216.       when rt = 17 then call emit 'FKALONG 'id||nl
  217.       when rt = 18 then call emit 'HELPTABLE 'id||nl'BEGIN'htout()'END'nl
  218.       when rt = 19 then call emit 'HELPSUBTABLE 'id||hstout()nl
  219.       when rt = 20 then call emit 'FDDIR 'id||nl
  220.       when rt = 21 then call emit 'FD 'id||nl
  221.    otherwise
  222.       call emit 'RESOURCE' rt id option() file('dat')
  223.    end  /* select */
  224.    if rt \= 4 then
  225.       call emit nl
  226.    call skip cb
  227.    call charout ,'.'
  228.    return
  229.  
  230. emit:    /* write data to output file */
  231.    return charout(outfile,arg(1))
  232.  
  233. option:  /* convert flags to option string */
  234.    if bit(opt,10) then r = 'PRELOAD'; else r = 'LOADONCALL'
  235.    if bit(opt,12) then r = r' MOVEABLE'
  236.    if bit(opt, 4) then r = r' DISCARDABLE'
  237.    if \ (bit(opt,4) | bit(opt,12)) then r = r' FIXED'
  238.    if r = 'LOADONCALL MOVEABLE DISCARDABLE' then r = ''
  239.    return r
  240.  
  241. file:    /* write cb bytes to resxxxx.arg(1) */
  242.    r = SysTempFileName('res?????.'arg(1))
  243.    call charout r,charin(infile,,cb)
  244.    cb = 0
  245.    call stream r,'c','close'
  246.    return r
  247.  
  248. strout:  /* extract strings definitions */
  249.    call skip 2
  250.    id = (id-1)*16; cb = cb-2; r = nl
  251.    do while cb > 0
  252.       len = x2d(c2x(charin(infile,,1)))
  253.       if len > 1 then r = r'  'left(id,8)'"'str2rc(charin(infile,,len-1))'"'nl
  254.       call skip 1
  255.       id = id+1; cb = cb-len-1
  256.    end /* do */
  257.    return r
  258.  
  259. itemout: /* extract menu item definition */
  260.    procedure expose nl cb infile outfile
  261.    cb = cb-6; s = ''; a = ''; r = arg(1)'MENUITEM "'; x = '| MIS_'; y = '| MIA_'
  262.    sty = readw()
  263.    att = readw()
  264.    iid = readw()
  265.    if \ (bit(sty,13) | bit(sty,14)) then
  266.       do
  267.          c = charin(infile); cb = cb-1; str = ''
  268.          if c = 'FF'x & bit(sty,15) then do; str = '#'readw(); cb = cb-2; end
  269.          else do while c \= '00'x; str = str||c; c = charin(infile); cb = cb-1; end
  270.          r = r||str2rc(str)
  271.       end
  272.    if bit(sty,15) then s = s x'BITMAP'
  273.    if bit(sty,14) then s = s x'SEPARATOR'
  274.    if bit(sty,13) then s = s x'OWNERDRAW'
  275.    if bit(sty,12) then s = s x'SUBMENU'
  276.    if bit(sty,11) then s = s x'MULTMENU'
  277.    if bit(sty,10) then s = s x'SYSCOMMAND'
  278.    if bit(sty, 9) then s = s x'HELP'
  279.    if bit(sty, 8) then s = s x'STATIC'
  280.    if bit(sty, 7) then s = s x'BUTTONSEPARATOR'
  281.    if bit(sty, 6) then s = s x'BREAK'
  282.    if bit(sty, 5) then s = s x'BREAKSEPARATOR'
  283.    if bit(sty, 4) then s = s x'GROUP'
  284.    if bit(sty, 3) then s = s x'SINGLE'
  285.    if bit(att,11) then a = a y'NODISMISS'
  286.    if bit(att, 4) then a = a y'FRAMED'
  287.    if bit(att, 3) then a = a y'CHECKED'
  288.    if bit(att, 2) then a = a y'DISABLED'
  289.    if bit(att, 1) then a = a y'HILITED'
  290.    if a \= '' then a = ','substr(a,3)
  291.    if s \= '' then s = ','substr(s,3); else if a \= '' then s = ','
  292.    call emit r'", 'iid||s||a||nl
  293.    if bit(sty,12) then do; call emit arg(1)'BEGIN'nl; call emit menuout(arg(1)'  ','')arg(1)'END'nl; end
  294.    return
  295.  
  296. menuout: /* extract menus definitions */
  297.    procedure expose nl cb infile outfile
  298.    cb = cb-10;
  299.    cbs = readw()
  300.    typ = readw()
  301.    cp = readw()
  302.    off = readw()
  303.    cnt = readw()
  304.    if arg(2) \= '' then
  305.       do
  306.          if cp \= 850 then call emit 'CODEPAGE 'cp||nl
  307.          call emit arg(2)
  308.       end /* do */
  309.    do cnt; call itemout arg(1); end
  310.    return ''
  311.  
  312. keyout:  /* extract acceltable definitions */
  313.    procedure expose nl cb infile outfile
  314.    r = ''
  315.    cnt = readw()
  316.    cp = readw()
  317.    cb = cb-4
  318.    if cp \= 850 then call emit 'CODEPAGE 'cp||nl
  319.    do cnt
  320.       typ = readw()
  321.       key = readw()
  322.       if \ bit(typ,15) & key >= 32 & key <= 255 then key = '"'d2c(key)'"'; else key = '0x'd2x(key)
  323.       if key = '"""' then key = '""""'
  324.       if key = '"\"' then key = '"\\"'
  325.       cmd = readw()
  326.       cb = cb-6; t = ''
  327.       if bit(typ,16) then t = t', CHAR'
  328.       if bit(typ,15) then t = t', VIRTUALKEY'
  329.       if bit(typ,14) then t = t', SCANCODE'
  330.       if bit(typ,13) then t = t', SHIFT'
  331.       if bit(typ,12) then t = t', CONTROL'
  332.       if bit(typ,11) then t = t', ALT'
  333.       if bit(typ,10) then t = t', LONEKEY'
  334.       if bit(typ, 8) then t = t', SYSCOMMAND'
  335.       if bit(typ, 7) then t = t', HELP'
  336.       r = r'  'left(key',',8)left(cmd',',8)substr(t,3)nl
  337.    end /* do */
  338.    return r
  339.  
  340. htout:   /* extract helptable definitions */
  341.    r = nl
  342.    i = readw()
  343.    do while i \= 0
  344.       r = r'  HELPITEM 'i', 'readw()
  345.       call skip 2
  346.       r = r', 'readw()nl; cb = cb-8
  347.       i = readw()
  348.    end /* do */
  349.    cb = cb-2
  350.    return r
  351.  
  352. hstout:  /* extract helpsubtable definitions */
  353.    sis = readw()
  354.    if sis \= 2 then r = nl'SUBITEMSIZE 'sis; else r = ''
  355.    r = r||nl'BEGIN'nl; cb = cb-2
  356.    i = readw()
  357.    do while i \= 0
  358.       r = r||'  HELPSUBITEM 'i
  359.       do sis-1; r = r', 'readw(); end
  360.       cb = cb-2*sis; r = r||nl
  361.       i = readw();
  362.    end /* do */
  363.    cb = cb-2
  364.    return r'END'
  365.  
  366. outname: /* return name made from infile and extension */
  367.    if outfile = '' then
  368.       if lastpos('.',arg(1)) > lastpos('\',arg(1)) then
  369.          outfile = left(arg(1),lastpos('.',arg(1)))arg(2)
  370.       else
  371.          outfile = arg(1)'.'arg(2)
  372.    return outfile
  373.  
  374. RDCPP:   /* call RDCPP.EXE */
  375.    tempdir = value('TMP',,'OS2ENVIRONMENT')
  376.    if tempdir = '' then tempdir = value('TEMP',,'OS2ENVIRONMENT')
  377.    if tempdir = '' then tempdir = directory()
  378.    if tempdir \= '' & right(tempdir,1) \= '\' then tempdir = tempdir||'\'
  379.    call charin infile,base+restab,0
  380.    templen = x2d(c2x(charin(infile,,1)))
  381.    tempmod = charin(infile,,templen)
  382.    tempname = SysTempFileName(tempdir||left('?????RDC',templen)'.DLL')
  383.    if tempname = '' then
  384.       do
  385.       say 'Invalid module name : 'tempmod
  386.       exit 1
  387.       end
  388.    tempmod = left(right(tempname,templen+4),templen)
  389.    call stream infile, 'c', 'close'
  390.    '@copy' infile tempname '>nul'
  391.    call charout tempname,tempmod,base+restab+1
  392.    call stream outfile, 'c', 'close'
  393.    call stream tempname, 'c', 'close'
  394.    say nl'RDCPP' tempname outfile
  395.    '@RDCPP' tempname outfile
  396.    '@del /f' tempname
  397.    signal step1a
  398.  
  399. str2rc:  /* convert a string to its RC-readable equivalent */
  400.    procedure
  401.    i = arg(1); o = ''
  402.    do while i \= ''
  403.       c = left(i,1); i = substr(i,2)
  404.       select
  405.          when c = '\' then o = o||'\\'
  406.          when c = '01'x then o = o||'\a'
  407.          when c = '09'x then o = o||'\t'
  408.          when c = '"' then o = o||'""'
  409.          when c2d(c) < 32 then o = o||'\x'c2x(c)
  410.       otherwise
  411.          o = o||c
  412.       end  /* select */
  413.    end /* do */
  414.    return o
  415.  
  416. readw:   /* read one word from infile */
  417.    return w2d(charin(infile,,2))
  418.  
  419. readl:   /* read one long from infile */
  420.    return l2d(charin(infile,,4))
  421.  
  422. skip:    /* skip arg(1) chars */
  423.    return charin(infile,,arg(1))
  424.  
  425. bit:     /* return bit arg(2) of arg(1) */
  426.    return substr(x2b(d2x(arg(1),4)), arg(2),1)
  427.  
  428. w2d:     /* littleendian word to decimal */
  429.    w = c2x(arg(1))
  430.    return x2d(substr(w,3,2)substr(w,1,2))
  431.  
  432. d2w:     /* decimal to littleendian word */
  433.    w = d2x(arg(1),4)
  434.    return x2c(substr(w,3,2)substr(w,1,2))
  435.  
  436. l2d:     /* littleendian long to decimal */
  437.    l = c2x(arg(1))
  438.    return x2d(substr(l,7,2)substr(l,5,2)substr(l,3,2)substr(l,1,2))
  439.  
  440. d2l:     /* decimal to littleindian long */
  441.    l = d2x(arg(1),8)
  442.    return x2c(substr(l,7,2)substr(l,5,2)substr(l,3,2)substr(l,1,2))
  443.