home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / resmgr.zip / rdc.cmd < prev    next >
OS/2 REXX Batch file  |  1996-02-17  |  14KB  |  447 lines

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