         title   ExtractDlg - Normal Window with (.rc)

         .586
         .model flat, stdcall
         option casemap:none   ; Case sensitive

            include  L:\AsmEdit\include\windows.inc
            include  user32.inc
            include  GDI32.inc
            include  kernel32.inc
            include  comdlg32.inc
            include  comctl32.inc
            include  advapi32.inc
            include  ole32.inc
            include  oleaut32.inc

   include  L:\AsmEdit\include\DSPMACRO.asm

            include  ResEdit.inc

ViewImage             PROTO  :DWORD, :DWORD, :DWORD, :DWORD
BaseAscii             PROTO  :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
CreateStreamOnHGlobal PROTO   WINAPI :DWORD, :DWORD, :DWORD
OleLoadPicture        PROTO   WINAPI :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

MOVmd    MACRO Var1, Var2
          push     Var2
           pop     Var1
          ENDM

MOVmw    MACRO Var1, Var2
      pushad 
         lea     esi, Var2
         lea     edi, Var1
         repeat     2
            mov     al, [esi]
            mov     [edi], al
            inc     esi
            inc     edi
         ENDM
        popad
         ENDM

.data
TreeVClass     db  'SysTreeView32',0
AnimateClass   db  'SysAnimate32',0

FontName       db  'Courier New',0
AppName        db  'Extract Resources',0

szError3       db  'This file has been compressed.',0Dh,0Ah
               db  'You will need to decompress it first.',0
szError6       db  'Error Opening The File.',0
szError7       db  'There are no dialogs'
               db  0Dh,0Ah
               db  'for the requested file.',0
szError8       db  'There are no resources'
               db  0Dh,0Ah
               db  'for the requested file.',0

;szDlgNum       db  2 dup(' ')
;               db  '  Dialog(s) have been extracted.',0dh,0ah
;szCtrlNum      db  2 dup(' ')
;               db  '  Controls(s) have been extracted.',0dh,0ah,0

szAccess       db  'This program is in use.'
               db  0Dh,0Ah
               db  'Would you like to open it as read only ?',0

szTitleO       db  'Read File',0
szTitleS       db  'Write File',0

szPE           db  'Files Types(*.exe)-(*.dll)-(*.res)-(*.scr)',0,'*.exe;*.dll;*.res;*.scr',0,
                   'All Files',0,'*.*',0,0
szFilterI      db  'Cursor (*.cur), Bitmap(*.bmp), Icon(*.ico)',0,'*.cur;*.bmp;*.ico',0,
                  'All Files',0,'*.*',0,0

szCur          db  '*.cur',0
szBmp          db  '*.bmp',0
szIco          db  '*.ico',0
szGif          db  '*.gif',0
szJpg          db  '*.jpg',0
szWmf          db  '*.wmf',0
szEmf          db  '*.emf',0
szAni          db  '*.ani',0
szAvi          db  '*.avi',0

szResources    db  'Images',0
szTempAni      db  '\Temp.ani',0
szTempAvi      db  '\Temp.avi',0

;szRsrc00       db  'GIF',0
szRsrc01       db  'Cursors',0
szRsrc02       db  'Bitmaps',0
szRsrc03       db  'Icons',0
szRsrc04       db  'Menus',0
szRsrc05       db  'Dialogs',0
szRsrc06       db  'String Tables',0
szRsrc07       db  'Font Director',0
szRsrc08       db  'Font',0
szRsrc09       db  'Accelerator Tables',0
szRsrc10       db  'RCData',0
szRsrc11       db  'Message Tables',0       ;11
szRsrc12       db  'Group Cursors',0        ;12
szRsrc13       db  ' ',0
szRsrc14       db  'Group Icons',0          ;14
szRsrc15       db  ' ',0
szRsrc16       db  'Version Information',0  ;16
szRsrc17       db  'Dlg Include',0
szRsrc18       db  ' ',0
szRsrc19       db  'Plug Play',0
szRsrc20       db  'VXD',0
szRsrc21       db  'Ani Cursor',0
szRsrc22       db  'Ani Icon',0

RsrcArray      dd  szRsrc01,szRsrc02,szRsrc03,szRsrc04,szRsrc05,szRsrc06,szRsrc07,szRsrc08,
                   szRsrc09,szRsrc10,szRsrc11,szRsrc12,szRsrc13,szRsrc14,szRsrc15,szRsrc16,
                   szRsrc17,szRsrc18,szRsrc19,szRsrc20,szRsrc21,szRsrc22

szMenuex       db  '  MENUEX DISCARDABLE',0

szMFTSTRING    db  'MFT_STRING',0    ; = 0
szMFTSEPARATOR db  'MFT_SEPARATOR',0 ; = 800h

szMFSENABLED   db  'MFS_ENABLED',0   ; = 0
szMFSGRAYED    db  'MFS_GRAYED',0    ; = 3
szMFSCHECKED   db  'MFS_CHECKED',0   ; = 8

szMenu         db  '  MENU DISCARDABLE',0
szBEGIN01      db  'BEGIN',0
szPopup        db  '   POPUP "',0
szBEGIN02      db  '   BEGIN',0
szMENUITEM     db  '      MENUITEM "',0
szSEPARATOR    db  '      MENUITEM SEPARATOR',0
szEND02        db  '   END',0
szEND01        db  'END',0
szGrayed       db  ', GRAYED',0
szChecked      db  ', CHECKED',0

szDlg          db  ' DIALOG LOADONCALL MOVEABLE DISCARDABLE ',0
szDlgEX        db  ' DIALOGEX LOADONCALL MOVEABLE DISCARDABLE ',0
szCapt         db  'CAPTION ',0
szFont         db  'FONT    ',0  
szSty          db  'STYLE   ',0  
szEXSty        db  'EXSTYLE ',0
szClass        db  'CLASS   ',0
szBegin        db  'BEGIN',0dh,0ah,0
szCont         db  '    CONTROL ',0
szEnd          db  'END',0dh,0ah,0

ButtClass      db  'button',0
EditClass      db  'edit',0
StaticClass    db  'static',0
ListboxClass   db  'listbox',0
ScrollClass    db  'scrollbar',0
ComboClass     db  'combobox',0
ClassArray     dd  ButtClass,EditClass,StaticClass,ListboxClass,ScrollClass,ComboClass

szVKaNA        db  ' ',0
szVKa01        db  'VK_BACK',0
szVKa02        db  'VK_TAB',0
szVKa03        db  'VK_CLEAR',0
szVKa04        db  'VK_RETURN',0
szVKa05        db  'VK_SHIFT',0
szVKa06        db  'VK_CONTROL',0
szVKa07        db  'VK_MENU',0
szVKa08        db  'VK_PAUSE',0
szVKa09        db  'VK_CAPITAL',0
szVKa10        db  'VK_ESCAPE',0
szVKa11        db  'VK_CONVERT',0
szVKa12        db  'VK_NONCONVERT',0
szVKa13        db  'VK_ACCEPT',0
szVKa14        db  'VK_MODECHANGE',0
szVKa15        db  'VK_SPACE',0
szVKa16        db  'VK_PGUP',0
szVKa17        db  'VK_PGDN',0
szVKa18        db  'VK_END',0
szVKa19        db  'VK_HOME',0
szVKa20        db  'VK_LEFT',0
szVKa21        db  'VK_UP',0
szVKa22        db  'VK_RIGHT',0
szVKa23        db  'VK_DOWN',0
szVKa24        db  'VK_SELECT',0
szVKa25        db  'VK_PRINT',0
szVKa26        db  'VK_EXECUTE',0
szVKa27        db  'VK_SNAPSHOT',0
szVKa28        db  'VK_INSERT',0
szVKa29        db  'VK_DELETE',0
szVKa30        db  'VK_HELP',0
VKaArray       dd  szVKa01,szVKa02,szVKaNA,szVKaNA,szVKa03,szVKa04,
                   szVKaNA,szVKaNA,szVKa05,szVKa06,szVKa07,szVKa08,
                   szVKa09,szVKaNA,szVKaNA,szVKaNA,szVKaNA,szVKaNA,
                   szVKaNA,szVKa10,szVKa11,szVKa12,szVKa13,szVKa14,
                   szVKa15,szVKa16,szVKa17,szVKa18,szVKa19,szVKa20,
                   szVKa21,szVKa22,szVKa23,szVKa24,szVKa25,szVKa26,
                   szVKa27,szVKa28,szVKa29,szVKa30

szVKb01        db  'VK_NUMPAD0',0
szVKb02        db  'VK_NUMPAD1',0
szVKb03        db  'VK_NUMPAD2',0
szVKb04        db  'VK_NUMPAD3',0
szVKb05        db  'VK_NUMPAD4',0
szVKb06        db  'VK_NUMPAD5',0
szVKb07        db  'VK_NUMPAD6',0
szVKb08        db  'VK_NUMPAD7',0
szVKb09        db  'VK_NUMPAD8',0
szVKb10        db  'VK_NUMPAD9',0
szVKb11        db  'VK_MULTIPLY',0
szVKb12        db  'VK_ADD',0
szVKb13        db  'VK_SEPARATOR',0
szVKb14        db  'VK_SUBTRACT',0
szVKb15        db  'VK_DECIMAL',0
szVKb16        db  'VK_DIVIDE',0
szVKb17        db  'VK_F1',0
szVKb18        db  'VK_F2',0
szVKb19        db  'VK_F3',0
szVKb20        db  'VK_F4',0
szVKb21        db  'VK_F5',0
szVKb22        db  'VK_F6',0
szVKb23        db  'VK_F7',0
szVKb24        db  'VK_F8',0
szVKb25        db  'VK_F9',0
szVKb26        db  'VK_F10',0
szVKb27        db  'VK_F11',0
szVKb28        db  'VK_F12',0
VKbArray       dd  szVKb01,szVKb02,szVKb03,szVKb04,szVKb05,szVKb06,
                   szVKb07,szVKb08,szVKb09,szVKb10,szVKb11,szVKb12,
                   szVKb13,szVKb14,szVKb15,szVKb16,szVKb17,szVKb18,
                   szVKb19,szVKb20,szVKb21,szVKb22,szVKb23,szVKb24,
                   szVKb25,szVKb26,szVKb27,szVKb28

szVKc01        db  'VK_NUMLOCK',0
szVKc02        db  'VK_SCROLL',0
VKcArray       dd  szVKc01,szVKc02

szACCEL        db  ' ACCELERATORS',0
szBEGIN        db  'BEGIN',0
szVIRTKEY      db  'VIRTKEY',0
szNOINVERT2    db  'NOINVERT',0
szNOINVERT     db  ', NOINVERT',0
szSHIFT        db  ', SHIFT',0
szSHIFT4       db  'SHIFT',0
szCONTROL      db  ', CONTROL',0
szCONTROL8     db  'CONTROL',0
szALT          db  ', ALT',0
szALT10        db  'ALT',0
szEND          db  'END',0
szFill         db  '                                   ',0
szNeed         db  '*NEED*',0

szobject       db  'object ',0

szMESSAGE      db  '1 MESSAGETABLE',0

szSTRING       db  'STRINGTABLE DISCARDABLE',0

szVERINFO      db  ' VERSIONINFO',0
szVERFILE      db  'FILEVERSION ',0
szVERPRODUCT   db  'PRODUCTVERSION ',0
szFILEFLAGSM   db  'FILEFLAGSMASK ',0
szFILEFLAGS    db  'FILEFLAGS ',0
szFILEOS       db  'FILEOS ',0
szFILETYPE     db  'FILETYPE ',0
szFILESUBTYPE  db  'FILESUBTYPE ',0
szFILEDATE     db  'FILEDATE ',0
VersionArray   dd  szVERFILE,szVERPRODUCT,szFILEFLAGSM,szFILEFLAGS,szFILEOS,szFILETYPE,szFILESUBTYPE,szFILEDATE

szVarFileInfo  db  'VarFileInfo',0
szBLOCK01      db  '   BLOCK ',0
szBLOCK02      db  '      BLOCK ',0
szBEGIN03      db  '      BEGIN',0
szVALUE01      db  '      VALUE "',0
szVALUE02      db  '         VALUE "',0
szEND03        db  '      END',0

sz0x           db  '0x',0
szQuote        db  '"',0
szComma        db  ',',0
szCommaS       db  ', ',0
szSpace        db  ' ',0
szMinus1       db  '-1',0
szSlashB       db  '\',0
szSlashB0      db  '\0',0
szNULL         db  0
szCRLF         db  0dh,0ah,0
fmat1          db  '%01u',0
fmat2          db  '%02u',0

szRedit        db  'ResEdit',0
szREGSZ        db  'REG_SZ',0
szResB         db  'Last Binary',0

IID_IPicture   dd  07bf80980h
               dw  0bf32h
               dw  0101ah
               db  08bh,0bbh,0,0aah,0,030h,0ch,0abh
;0x7bf80980,0xbf32,0x101a,0x8b,0xbb,0,0xaa,0,0x30,0xc,0xab
;{7bf80980-bf32-101a-8bbb00aa00300cab}

.data?
hREdit         dd  ?
hStatic        dd  ?
hAniCtrl       dd  ?
hIcon          dd  ?
MemRsrc        dd  ?
RsrcInfo       dd  ?
RsrcInfoGrp    dd  ?

hMem           dd  ?
pMem           dd  ?
hMemD          dd  ?
pMemD          dd  ?
hMemID         dd  ?
pMemID         dd  ?
hMap           dd  ?
pMap           dd  ?
hFile          dd  ?
SavpMap        dd  ?
RsrcSize       dd  ?
PE             dd  ?
CompressOn     dd  ?
NumOfSections  dw  ? 
NumOfIDs       dd  ?
NumOfMatchIDs  dd  ?
SavAddr        dd  ?
SavSize        dd  ?
SavStart       dd  ?
SavOffset      dd  ?
ID             dd  ?
OffPosID       dd  ?
NumOfGroups    dd  ?
NumofDlgs      dd  ?
NumofCtrls     dd  ?
NumofItems     dd  ?

hParent        dd  ?
hChild         dd  ?
hImage         dd  ?
PictID         dd  ?
ImageID        dd  ?
hIC            dd  ?
Hold           dd  ?
BytesRead      dd  ?

ipPicture      dd  ?
hBitmap        dd  ?
TypePict       dd  ?
xPos           dd  ?
yPos           dd  ?
pWidth         dd  ?
pHeight        dd  ?
mWidth         dd  ?
mHeight        dd  ?
negmHeight     dd  ?
ExportOn       dd  ?

Test4          dd  ?

hReg           dd  ?
lpType         dd  ?
lpcbData       dd  ?
lpdwDisp       dd  ?

szType         db  10   dup(?)
SavPath        db  256  dup(?)
szResPath      db  256  dup(?)
szBuff         db  2048 dup(?)
szUnicode      db  512  dup(?)

Dialog         STRUCT
   ID          dd ?
   pointsize   dd ?          ; +
   weight      dd ?          ; +
   bItalic     dd ?          ; +
   lpFont      db 64 dup(?)  ; +
   lpMenu      db 32 dup(?)  ; +
   lpName      db 32 dup(?)  ; +
   Class       db 32 dup(?)  ; +
   lpCaption   db 512 dup(?) ; +
   ExStyle     dd ?          ; +
   Style       dd ?          ; +
   Left        dd ?          ; +
   Top         dd ?          ; +
   Wth         dd ?          ; +
   Hgt         dd ?          ; +
Dialog         ENDS
Dlg            Dialog         <?>

Controls       STRUCT
   ID          dd ?
   lpName      db 32 dup(?)  ; +
   Class       db 32 dup(?)  ; +
   lpCaption   db 512 dup(?) ; +
   ExStyle     dd ?          ; +
   Style       dd ?          ; +
   Left        dd ?          ; +
   Top         dd ?          ; +
   Wth         dd ?          ; +
   Hgt         dd ?          ; +
Controls       ENDS
Ctrls          Controls       <?>

lf             LOGFONT        <?>
ofn            OPENFILENAME   <?>
tvis           TV_INSERTSTRUCT <?>

.code

;=======================================
; Extract Resources Dialog
;=======================================
ExtractRsrc PROC  uses ebx esi edi hwnd, hinst, hredit, hDlg
LOCAL    VirAddr:DWORD, PTRData, TypePE, Diff, sw1, NumIds1, NumIds2, SavID
LOCAL    OffPosS:DWORD, OffPosIDGrp, RsrcID, Cnt, Cnt1, CntID, ResOn, ImageOn
LOCAL    rsrcOn:DWORD, SavPos, CtrlCnt, BIOn, Dlgs, DlgVer, Base, SavClass, GrpAddr, GrpSize
LOCAL    szWork[64]:BYTE, szWork1[64]:BYTE, PathName[256]:BYTE

       MOVmd     hREdit, hredit

      INVOKE     GetCurrentDirectory, lengthof SavPath, addr SavPath
      INVOKE     RegCreateKeyEx, HKEY_CURRENT_USER, addr szRedit, 0, addr szREGSZ, 0,\
                 KEY_WRITE or KEY_READ, 0, addr hReg, addr lpdwDisp
         mov     lpcbData, 255
      INVOKE     RegQueryValueEx, hReg, addr szResB, 0, addr lpType, addr szResPath, addr lpcbData
      .if !szResPath
         INVOKE     lstrcpy, addr szResPath, addr szBuff
      .endif
      INVOKE     lstrcpy, addr szBuff, addr szResPath
      INVOKE     lstrcat, addr szBuff, addr szSlashB
      INVOKE     SetCurrentDirectory, addr szBuff

      INVOKE     ShowWindow, hStatic402, SW_HIDE
      INVOKE     ShowWindow, hStatic403, SW_HIDE
      INVOKE     ShowWindow, hWndTree, SW_HIDE

         mov     szBuff, 0

         mov     ofn.lStructSize, sizeof ofn
       MOVmd     ofn.hwndOwner, hREdit
       MOVmd     ofn.hInstance, hinst
         mov     ofn.lpstrFilter, offset szPE
         mov     ofn.lpstrFile, offset szBuff
         mov     ofn.nMaxFile, sizeof szBuff
         mov     ofn.lpstrTitle, offset szTitleO
         mov     ofn.Flags, OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
      INVOKE     GetOpenFileName, addr ofn
      .if eax == FALSE       ; Cancel'ed or error occurred
         INVOKE     SetCurrentDirectory, addr SavPath
         INVOKE     RegCloseKey, hReg
            jmp     ExtractRsrcDone
      .endif
      INVOKE     SetCurrentDirectory, addr SavPath
      INVOKE     lstrlen, addr szBuff
      .while (eax)
         .if byte ptr szBuff[eax] == '\'
            .break
         .endif
            dec     eax
      .endw
         inc     eax
      INVOKE     lstrcpyn, addr szResPath, addr szBuff, eax
      INVOKE     lstrlen, addr szResPath
         mov     lpcbData, eax
      INVOKE     RegSetValueEx, hReg, addr szResB, 0, REG_SZ, addr szResPath, lpcbData
      INVOKE     RegCloseKey, hReg

         and     SavID, 0
         and     TypePE, 0
         and     NumOfIDs, 0
         and     NumofDlgs, 0
         and     NumofCtrls, 0
         and     NumofItems, 0
         and     NumOfMatchIDs, 0
      INVOKE     SetDlgItemInt, hDlg, 701, NumofDlgs, 0
      INVOKE     SetDlgItemInt, hDlg, 702, NumofCtrls, 0
      INVOKE     SetDlgItemInt, hDlg, 704, NumofItems, 0
      INVOKE     UpdateWindow, hDlg

      .if pMap
         INVOKE     UnmapViewOfFile, pMap
         INVOKE     CloseHandle, hMap
            and     pMap, 0
      .endif

;---------- [Allocate memory from the default heap] ----------
      .if RsrcInfo
         INVOKE     HeapFree, hDefHeap, 0, RsrcInfo
         INVOKE     HeapFree, hDefHeap, 0, RsrcInfoGrp
         INVOKE     HeapFree, hDefHeap, 0, MemRsrc
      .endif

      INVOKE     HeapAlloc, hDefHeap, 0, 2000000 ;500000
         mov     RsrcInfo, eax
      INVOKE     HeapAlloc, hDefHeap, 0, 1000000 ;100000
         mov     RsrcInfoGrp, eax
      INVOKE     HeapAlloc, hDefHeap, 0, 4000000 ;1000000
         mov     MemRsrc, eax

      INVOKE     UpdateWindow, hREdit

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0

      .if eax == -1
           call     GetLastError
         .if eax == 5
               jmp     NoWrite

         .elseif eax == 32
            INVOKE     MessageBox, hWnd, addr szAccess, addr AppName, MB_YESNO
            .if IDYES

NoWrite:
               INVOKE     CreateFile, addr szBuff,\
                          GENERIC_READ, FILE_SHARE_READ,\
                          0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
               .if eax == -1
                  INVOKE     MessageBox, hWnd, addr szError6, addr AppName, MB_OK
                     jmp     ExtractRsrcDone
               .endif
            .else
               jmp     ExtractRsrcDone
            .endif
         .else
            INVOKE     MessageBox, hWnd, addr szError6, addr AppName, MB_OK
               jmp     ExtractRsrcDone
         .endif
      .endif

         mov     hFile, eax
      INVOKE     GetFileSize, hFile, 0
         mov     BytesRead, eax

      INVOKE     CreateFileMapping, hFile, NULL, PAGE_READONLY, 0, 0, 0
        push     eax
      INVOKE     CloseHandle, hFile
         pop     eax
         cmp     eax, FALSE           ; Error occurred
          je     ExtractRsrcDone
         mov     hMap, eax
      INVOKE     MapViewOfFile, hMap, FILE_MAP_READ, 0, 0, 0
         cmp     eax, FALSE           ; Error occurred
          je     ExtractRsrcDone
         mov     pMap, eax
mov     SavpMap, eax

;_____________________________________________________________________
;---------- [Check if loaded file is a .res file] ----------
         and     ResOn, 0
      INVOKE     lstrlen, addr PathName
      .if byte ptr PathName[eax-3] == 'r' || byte ptr PathName[eax-3] == 'R'
            xor     eax, eax
            xor     ebx, ebx
            mov     Base, 4
            and     OffPosID, 0
            and     OffPosIDGrp, 0
            and     RsrcID, 0
            mov     esi, pMap

;---------- [Build the dialog address pointer sturctures] ----------
         .while (ebx < BytesRead)
             MOVmw     ID, word ptr[esi+ebx+10]
            .if word ptr[esi+ebx+8] != 0ffffh
                  mov     ID, 44                             ; Image e.g. gif, jpg, wmf, emf
            .endif
            .if ID != 0 && ID < 23 || ID == 44 ;17
                  mov     eax, ID
               .if eax != sw1
                     and     CntID, 0
                     mov     sw1, eax
               .endif
                  mov     ecx, ebx
                  mov     eax, dword ptr[esi+ebx+4]
                  add     ecx, eax                           ; Size of the header
                  add     ecx, pMap
                MOVmw     RsrcID, word ptr[esi+ebx+14]
                  mov     edi, RsrcInfo
                  mov     eax, OffPosID
                  inc     CntID
                MOVmd     dword ptr[edi+eax], ID
                MOVmd     dword ptr[edi+eax+4], RsrcID       ; Resource ID
                  mov     dword ptr[edi+eax+8], ecx          ; Actual address in the .res file
                MOVmd     dword ptr[edi+eax+12], dword ptr[esi+ebx]    ; Size of image or group
                MOVmd     dword ptr[edi+eax+16], dword ptr[esi+ebx+30] ; Code Page
                  mov     dword ptr[edi+eax+20], 0
                  mov     dword ptr[edi+eax+24], 0
                  mov     dword ptr[edi+eax+28], 0
                MOVmd     dword ptr[edi+eax+32], CntID
                MOVmd     dword ptr[edi+eax+36], OffPosID
                  mov     byte ptr[edi+eax+40], 0
                  mov     byte ptr[edi+eax+72], 0

                  mov     GrpAddr, ecx                       ; Save for the group address
                MOVmd     GrpSize, dword ptr[esi+ebx]        ; Group size
                MOVmd     Hold, dword ptr[esi+ebx]           ; Group size

;---------- [See if a named ID] ----------
               .if word ptr[esi+ebx+12] != 0ffffh || ID == 44
                     mov     RsrcID, 6969
                   MOVmd     dword ptr[edi+eax+4], RsrcID
                     mov     edx, ebx
                  .if ID != 44
                        add     edx, 12
                  .else
                        add     edx, 8
                  .endif
                     add     eax, 40                         ; Offset to first nameID out

;---------- [Convert Unicode] ----------
                  .while (byte ptr[esi+edx] != 0)
                        mov     cl, byte ptr[esi+edx]        ; Offset to Name Entry Name
                        mov     byte ptr[edi+eax], cl
                        add     edx, 2
                        inc     eax
                  .endw
                     mov     byte ptr[edi+eax], 0

                  .if ID == 44                               ; Image e.g. gif, jpg, wmf, emf
                        mov     edi, RsrcInfo
                        mov     eax, OffPosID
                        mov     dword ptr[edi+eax], 0
                        xor     ecx, ecx
                     .if word ptr[esi+edx+2] == 00ffffffh    ; No named ID 0000ffffh
                           add     edx, 4
                           mov     cx, word ptr[esi+edx]
                           mov     RsrcID, ecx
                         MOVmd     dword ptr[edi+eax+4], RsrcID
                     .else
                           mov     dword ptr[edi+eax+4], 4848   ; Named image  
                           add     edx, 2
                           add     eax, 72                      ; Offset to second nameID out

;---------- [Convert Unicode] ----------
                        .while (byte ptr[esi+edx] != 0)
                              mov     cl, byte ptr[esi+edx]  ; Offset to Name Entry Name
                              mov     byte ptr[edi+eax], cl
                              add     edx, 2
                              inc     eax
                        .endw
                           mov     byte ptr[edi+eax], 0
                     .endif
                        and     ID, 0
                  .endif
               .endif

;---------- [Build a group array used for later update to the main array] ---------- 
               .if ID == 12 || ID == 14                      ; Group icon or cursor
                     mov     edi, RsrcInfoGrp
                     mov     eax, OffPosIDGrp
                     mov     dx, word ptr[ecx+18]            ; From the group resource
                     mov     word ptr[edi+eax], dx           ; Matching ID for detail and group
                   MOVmd     dword ptr[edi+eax+2], GrpAddr   ; Actual address of group resource
                   MOVmd     dword ptr[edi+eax+6], GrpSize   ; Size of group resource
                     mov     dword ptr[edi+eax+10], 0
                     mov     dl, byte ptr ID
                     mov     byte ptr[edi+eax+14], dl
                     add     OffPosIDGrp, 15
                     inc     NumOfGroups
                  .if Hold > 20
                        sub     Hold, 20
                        add     ecx, 20
                        xor     eax, eax

                     .while (Hold)
                           add     ecx, 14
                           xor     edx, edx
                           mov     eax, OffPosIDGrp
                           mov     dx, word ptr[ecx-2]
                           mov     word ptr[edi+eax], dx         ; Matching ID for detail and group
                         MOVmd     dword ptr[edi+eax+2], GrpAddr ; Actual address of group resource
                         MOVmd     dword ptr[edi+eax+6], GrpSize ; Size of group resource
                           mov     dword ptr[edi+eax+10], 0
                           mov     dl, byte ptr ID
                           mov     byte ptr[edi+eax+14], dl
                           add     OffPosIDGrp, 15
                           inc     NumOfGroups
                           sub     Hold, 14
                        .if sdword ptr Hold < 0 || Hold > 0 && Hold < 14
                           .break
                        .endif
                     .endw
                  .endif
               .endif

                  add     OffPosID, 104                        ; Length of ID array
                  inc     NumOfMatchIDs
            .endif

               mov     eax, dword ptr[esi+ebx]
               add     eax, dword ptr[esi+ebx+4]
               add     ebx, eax

;---------- [Check if next resource address is on a dword boundry] ----------
               xor     edx, edx
               mov     eax, ebx
               div     Base
            .if edx
                  add     ebx, 1
            .endif
               xor     edx, edx
               mov     eax, ebx
               div     Base
            .if edx
                  add     ebx, 1
            .endif

               xor     edx, edx
               mov     eax, ebx
               div     Base
            .if edx
                  add     ebx, 1
            .endif
         .endw

         .if !NumOfMatchIDs
               jmp     NoDialogs
         .endif
         INVOKE     lstrcpy, MemRsrc, addr szCRLF
            inc     ResOn
            jmp     FromRes
      .endif
;_____________________________________________________________________

;---------- [Check for PE type file] ----------
      .if BytesRead < 3ch
            jmp     NoRsrc
      .endif
         mov     ebx, pMap
         mov     ax, word ptr[ebx]
      .if ax == 'ZM'                                         ; IMAGE_DOS_SIGNATURE  -DOS MZ header-
            mov     edx, 3ch
            xor     eax, eax
            mov     ax, word ptr[ebx+edx]
            add     ebx, eax
            mov     eax, dword ptr[ebx]
         .if eax == IMAGE_NT_SIGNATURE                       ; IMAGE_NT_SIGNATURE   -PE header-
               mov     TypePE, 1
         .endif
      .endif
         cmp     TypePE, 0
          je     NoRsrc

         and     rsrcOn, 0
         and     CompressOn, 0
         mov     edi, pMap
      assume edi:ptr IMAGE_DOS_HEADER
         add     edi, [edi].e_lfanew
      assume edi:ptr IMAGE_NT_HEADERS
         mov     ax, [edi].FileHeader.NumberOfSections
         mov     NumOfSections, ax
         add     edi, sizeof IMAGE_NT_HEADERS
         mov     esi, edi
         mov     ax, NumOfSections
       movzx     eax, ax
         mov     edi, eax
      assume esi:ptr IMAGE_SECTION_HEADER
      .while edi > 0
         INVOKE     lstrcpyn, addr szWork, addr [esi].Name1, 8
         .if dword ptr szWork == '0XPU' || dword ptr szWork == '1XPU'
               mov     CompressOn, 1
         .endif
         .if dword ptr szWork+1 == 'crsr'                   ; Resource header
               mov     rsrcOn, esi
             MOVmd     VirAddr, [esi].VirtualAddress
             MOVmd     PTRData, [esi].PointerToRawData
               mov     eax, VirAddr
               sub     eax, PTRData
               mov     Diff, eax
            .break
         .endif
            dec     edi
            add     esi, sizeof IMAGE_SECTION_HEADER
      .endw

      .if !rsrcOn
            jmp     NoRsrc
      .endif
         and     Dlgs, 0
         and     OffPosS, 0
         and     OffPosID, 0
         and     OffPosIDGrp, 0
         and     NumIds2, 0
         mov     esi, pMap
         add     esi, PTRData

;---------- [In Resource Directory (Type)] ----------
      assume esi:ptr IMAGE_RESOURCE_DIRECTORY                ; Resource Directory (Type)
            xor     eax, eax
            mov     ax, [esi].NumberOfNamedEntries
            mov     NumIds1, eax
            mov     ax, [esi].NumberOfIdEntries
            add     NumIds1, eax                             ; Total num of ID entries
            and     SavPos, 0
         INVOKE     lstrcpy, MemRsrc, addr szCRLF

      .while (NumIds1)                                       ; In Resource Directory (Type)
            mov     eax, SavPos
            add     eax, 10h
            mov     SavPos, eax
            sub     SavPos, 8

;---------- [Check for valid resource ID  1-2-3-5-etc.] ----------
               mov     ebx, dword ptr[esi+eax]
               shr     ebx, 24
         .if dword ptr[esi+eax] != 0 && dword ptr[esi+eax] < 23 || ebx == 80h ;17
             MOVmd     SavID, dword ptr[esi+eax]             ; Save the ID
               add     eax, 4
               mov     ebx, dword ptr[esi+eax]               ; Offset to Resource Directory (Name ID)
               and     ebx, 00ffffffh ;0000ffffh
               add     ebx, 0eh                              ; Offset to Total num of ID's for group
               xor     ecx, ecx
               mov     cx, word ptr[esi+ebx]                 ; Total num of ID's for the group
               add     cx, word ptr[esi+ebx-2]               ; Total num of named ID's for the group
               mov     NumIds2, ecx                          ; Total num of items for the group
               mov     Dlgs, ecx
               sub     ebx, 2
               and     CntID, 0

;---------- [In Resource Directory (Name ID)] ----------
            .while (NumIds2)                                 ; In Resource Directory (Name ID)
                MOVmd     ID, SavID
                  add     ebx, 8
                MOVmd     RsrcID, dword ptr[esi+ebx-4]       ; Save the resource or matching ID
                  mov     edi, RsrcInfo
                  mov     eax, OffPosID
                  mov     byte ptr[edi+eax+40], 0
                  mov     byte ptr[edi+eax+72], 0

;---------- [See if Named ID] ----------
               .if byte ptr RsrcID[3] == 80h || byte ptr ID[3] == 80h
                  .if byte ptr RsrcID[3] == 80h
                        mov     edx, dword ptr[esi+ebx-4]
                  .endif
                  .if byte ptr ID[3] == 80h
                        mov     edx, ID
                  .endif
                     and     edx, 00ffffffh ;0000ffffh
                     xor     ecx, ecx
                     mov     cx, word ptr[esi+edx]           ; Offset to Name Entry header
                     mov     Cnt, ecx                        ; Size of Name
                     mov     Cnt1, ecx                       ; Size of Name
                     xor     ecx, ecx
                     add     edx, 2

                     mov     edi, RsrcInfo
                     mov     eax, OffPosID
                     add     eax, 40

;---------- [Convert Unicode] ----------
                  .while (Cnt)
                        mov     cl, byte ptr[esi+edx]        ; Offset to Name Entry Name
                        mov     byte ptr[edi+eax], cl
                        add     edx, 2
                        inc     eax
                        dec     Cnt
                  .endw
                     mov     byte ptr[edi+eax], 0

                  .if byte ptr RsrcID[3] == 80h && byte ptr ID[3] == 80h
                        mov     edx, RsrcID
                        and     edx, 00ffffffh ;0000ffffh
                        xor     ecx, ecx
                        mov     cx, word ptr[esi+edx]        ; Offset to Name Entry header
                        mov     Cnt, ecx                     ; Size of Name
                        mov     Cnt1, ecx                    ; Size of Name
                        xor     ecx, ecx
                        add     edx, 2
                        mov     edi, RsrcInfo
                        mov     eax, OffPosID
                        add     eax, 72                      ; Offset to second nameID out

;---------- [Convert Unicode] ----------
                     .while (Cnt)
                           mov     cl, byte ptr[esi+edx]     ; Offset to Name Entry Name
                           mov     byte ptr[edi+eax], cl
                           add     edx, 2
                           inc     eax
                           dec     Cnt
                     .endw
                        mov     byte ptr[edi+eax], 0
                        mov     RsrcID, 4848
                  .endif

                  .if byte ptr RsrcID[3] == 80h              ; Named ID
                        mov     RsrcID, 6969
                  .endif
                  .if byte ptr ID[3] == 80h                  ; Image e.g. gif, jpg, wmf, emf
                        and     ID, 0
                  .endif
               .endif

                  mov     edx, dword ptr[esi+ebx]            ; Offset to Directory (Language)
                  and     edx, 00ffffffh ;0000ffffh
                  add     edx, 14h
                  mov     ecx, dword ptr[esi+edx]            ; Offset to Directory (Data Entry)
                  mov     edx, ecx
                  mov     ecx, dword ptr[esi+edx]            ; Virtual address of resource
                  sub     ecx, Diff                          ; Actual address of resource in the file
                  add     ecx, pMap

;---------- [Build an array of IDs - ID, actual offset, and size] ----------
                  inc     CntID
                  mov     edi, RsrcInfo
                  mov     eax, OffPosID
                MOVmd     dword ptr[edi+eax], ID             ; Type of resource
                MOVmd     dword ptr[edi+eax+4], RsrcID       ; Resource or matching ID for detail and group
                  mov     dword ptr[edi+eax+8], ecx          ; Actual address of the resource
                MOVmd     dword ptr[edi+eax+12], dword ptr[esi+edx+4] ; Size of image or group
                MOVmd     dword ptr[edi+eax+16], dword ptr[esi+edx+8] ; Code Page
                  mov     dword ptr[edi+eax+20], 0
                  mov     dword ptr[edi+eax+24], 0
                  mov     dword ptr[edi+eax+28], 0
                MOVmd     dword ptr[edi+eax+32], CntID
                MOVmd     dword ptr[edi+eax+36], OffPosID

                  mov     GrpAddr, ecx                       ; Save for the group address
                MOVmd     GrpSize, dword ptr[esi+edx+4]      ; Group size
                MOVmd     Hold, dword ptr[esi+edx+4]         ; Group size

;---------- [Build a group array used for later update to the main array] ---------- 
               .if ID == 12 || ID == 14                      ; Group icon or cursor
                     mov     edi, RsrcInfoGrp
                     mov     eax, OffPosIDGrp
                     mov     dx, word ptr[ecx+18]            ; From the group resource
                     mov     word ptr[edi+eax], dx           ; Matching ID for detail and group
                   MOVmd     dword ptr[edi+eax+2], GrpAddr   ; Actual address of group resource
                   MOVmd     dword ptr[edi+eax+6], GrpSize   ; Size of group resource
                     mov     dword ptr[edi+eax+10], 0
                     mov     dl, byte ptr ID
                     mov     byte ptr[edi+eax+14], dl
                     add     OffPosIDGrp, 15
                     inc     NumOfGroups

                  .if Hold > 20
                        sub     Hold, 20
                        add     ecx, 20
                        xor     eax, eax

                     .while (Hold)
                           add     ecx, 14
                           xor     edx, edx
                           mov     eax, OffPosIDGrp
                           mov     dx, word ptr[ecx-2]
                           mov     word ptr[edi+eax], dx         ; Matching ID for detail and group
                         MOVmd     dword ptr[edi+eax+2], GrpAddr ; Actual address of group resource
                         MOVmd     dword ptr[edi+eax+6], GrpSize ; Size of group resource
                           mov     dword ptr[edi+eax+10], 0
                           mov     dl, byte ptr ID
                           mov     byte ptr[edi+eax+14], dl
                           add     OffPosIDGrp, 15
                           inc     NumOfGroups
                           sub     Hold, 14
                        .if sdword ptr Hold < 0 || Hold > 0 && Hold < 14
                           .break
                        .endif
                     .endw
                  .endif
               .endif
                  add     OffPosID, 104                      ; Length of ID array
                  inc     NumOfMatchIDs
                  dec     NumIds2
            .endw
         .endif
            dec     NumIds1
      .endw

      .if !Dlgs
            jmp     NoDialogs
      .endif

FromRes:

;---------- [Copy cursor and icon group information to the main cursor & icon array] ----------
       MOVmd     Cnt, NumOfMatchIDs
         and     OffPosID, 0
         mov     esi, RsrcInfo
      .while (Cnt)
            mov     eax, OffPosID
         .if dword ptr [esi+eax] == 1 || dword ptr[esi+eax] == 3           ; Cursor or Icon IDs
               mov     dl, 12                                              ; Code for Grp cursor
            .if dword ptr[esi+eax] == 3
                  mov     dl, 14                                           ; Code for Grp icon
            .endif
               mov     ecx, dword ptr[esi+eax+4]
               mov     edi, RsrcInfoGrp
               and     OffPosIDGrp, 0
             MOVmd     CntID, NumOfGroups
            .while (CntID)
                  mov     ebx, OffPosIDGrp
               .if word ptr[edi+ebx] == cx && byte ptr[edi+ebx+14] == dl   ; Matching ID & type
                   MOVmd     dword ptr[esi+eax+20], dword ptr[edi+ebx+2]   ; Offset to group
                   MOVmd     dword ptr[esi+eax+24], dword ptr[edi+ebx+6]   ; Size of group
                   MOVmd     dword ptr[edi+ebx+10], dword ptr[esi+eax+8]   ; Address of the Ico or Cur
                     mov     ecx, dword ptr [edi+ebx+2]
                  .if ecx != Hold
                        mov     Hold, ecx
                     .if dword ptr[edi+ebx+6] > 20                         ; More then 1 image in grp
                           mov     dword ptr[esi+eax+28], 44               ; Flag for mult image
                     .endif
                  .endif
                  .break
               .endif
                  add     OffPosIDGrp, 15
                  dec     CntID
            .endw
         .endif
            add     OffPosID, 104
            dec     Cnt
      .endw

;---------- [Fill the tree] ----------
         mov     byte ptr szWork, 0
      INVOKE     SendMessage, hWndTree, TVM_DELETEITEM, 0, TVI_ROOT
         mov     tvis.hParent, NULL   
         mov     tvis.hInsertAfter, TVI_ROOT
         mov     tvis.item.imask, TVIF_TEXT or TVIF_IMAGE or TVIF_SELECTEDIMAGE or TVIF_PARAM
         mov     tvis.item.pszText, offset szResources
         mov     tvis.item.iImage, 0
         mov     tvis.item.iSelectedImage, 1
      INVOKE     SendMessage, hWndTree, TVM_INSERTITEM, 0, addr tvis
         mov     hParent, eax
         mov     tvis.hParent, eax
         mov     tvis.hInsertAfter, TVI_LAST

       MOVmd     CntID, NumOfMatchIDs
         and     OffPosID, 0
         and     ImageOn, 0
         and     ID, 0
      .while (CntID)
         INVOKE     lstrlen, addr szWork1
            mov     ecx, eax
            mov     esi, RsrcInfo                            ; Resource array
            mov     ebx, OffPosID
            mov     eax, dword ptr[esi+ebx]

.if eax == 1 || eax == 2 || eax == 3 || eax == 12 || eax == 14 || eax == 21 || eax == 22 || eax == 0
      mov     ImageOn, 1

;---------- [Check for mult same type images] ----------
         .if !eax && szWork1
               mov     edx, ebx
               xor     edi, edi
            .while (ecx)
                  mov     al, byte ptr[esi+edx+40]
               .if al == byte ptr szWork1[edi]
               .else
                     xor     eax, eax
                  .break
               .endif
                  inc     edx
                  inc     edi
                  dec     ecx
            .endw
            .if !ecx
                  mov     eax, 44
                  mov     ID, eax
            .endif
         .endif

;---------- [Load the resource name in the tree] ----------
         .if eax != ID || !eax
               mov     ID, eax
            .if !eax
                  lea     ecx, [esi+ebx+40]                  ; Named ID for GIF, WAVE, etc.
            .else
                  dec     eax
                  mov     ecx, RsrcArray[eax*4]
            .endif
               mov     tvis.item.pszText, ecx
             MOVmd     tvis.hParent, hParent
               mov     tvis.item.lParam, 0
            INVOKE     lstrcpy, addr szWork1, ecx
            INVOKE     SendMessage, hWndTree, TVM_INSERTITEM, 0, addr tvis
               mov     hChild, eax
               mov     tvis.hParent, eax
         .endif

;---------- [Load the resource ID in the tree] ----------
            mov     esi, RsrcInfo                            ; Resource array
            mov     ebx, OffPosID
;          MOVmd     tvis.item.lParam, dword ptr[esi+ebx+8]  ; Actual address of the resource
          MOVmd     tvis.item.lParam, dword ptr[esi+ebx+36]  ; Offset address in the RsrcInfo structure
            mov     eax, dword ptr[esi+ebx+4]                ; ID
         .if eax != 6969 && eax != 4848
               INVOKE     wsprintf, addr szWork, addr fmat2, dword ptr[esi+ebx+4]
         .else
            .if eax == 6969
                  lea     ecx, [esi+ebx+40]                    ; Named ID
            .else
                  lea     ecx, [esi+ebx+72]                    ; Named ID of image
            .endif
            INVOKE     lstrcpy, addr szWork, ecx
         .endif
            lea     eax, szWork
            mov     tvis.item.pszText, eax
         INVOKE     SendMessage, hWndTree, TVM_INSERTITEM, 0, OFFSET tvis
.endif
            add     OffPosID, 104
            dec     CntID
      .endw

      INVOKE     lstrcpy, MemRsrc, addr szNULL

      INVOKE     LoadCursor, 0, IDC_WAIT
      INVOKE     SetCursor, eax

         and     NumofDlgs, 0
       MOVmd     CntID, NumOfMatchIDs
         and     OffPosID, 0

      .while (CntID)
            mov     esi, RsrcInfo                            ; Resource array
            mov     ebx, OffPosID
            mov     eax, dword ptr[esi+ebx]
            mov     edx, dword ptr[esi+ebx+8]                ; Actual address of the resource
            mov     SavAddr, edx
            mov     edx, dword ptr[esi+ebx+12]               ; Size of resource
            mov     RsrcSize, edx

         .if eax == 4
              call     RsrcMenu
         .elseif eax == 5
              call     RsrcDialog
         .elseif eax == 6
              call     RsrcString
         .elseif eax == 9
              call     RsrcAccelerator
         .elseif eax == 10
;              call     RsrcRCData
         .elseif eax == 11
              call     RsrcMessage
         .elseif eax == 16
              call     RsrcVersion
         .endif
            add     OffPosID, 104
            dec     CntID
      .endw
      .if ImageOn
         INVOKE     ShowWindow, hStatic402, SW_SHOW
         INVOKE     ShowWindow, hStatic403, SW_SHOW
         INVOKE     ShowWindow, hWndTree, SW_SHOW
      .endif
      INVOKE     SetFocus, hREdit
         jmp     ExtractRsrcDone

NoDialogs:
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, addr szNULL
      INVOKE     MessageBox, hWnd, addr szError7, addr AppName, MB_OK
         jmp     ExtractRsrcDone

NoRsrc:
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, addr szNULL
      .if CompressOn
         INVOKE     MessageBox, hWnd, addr szError3, addr AppName, MB_OK
      .else
         INVOKE     MessageBox, hWnd, addr szError8, addr AppName, MB_OK
      .endif

ExtractRsrcDone:
      INVOKE     LoadCursor, 0, IDC_ARROW
      INVOKE     SetCursor, eax
         mov     eax, FALSE                                  ; Return with FALSE

         ret
ExtractRsrc ENDP

;=======================================
; Extract Miscellaneous Resources
;=======================================
RsrcMisc PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, Cnt1, Len, CntID, BytesOut
LOCAL    szWork1[128]:BYTE, szWork2[128]:BYTE

;      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, addr szNULL

         mov     esi, SavAddr
         mov     edi, MemRsrc
         mov     ecx, RsrcSize
         mov     SavSize, ecx
      .while (ecx)
            mov     al, byte ptr[esi]
            mov     byte ptr[edi], al
            inc     esi
            inc     edi
            dec     ecx
      .endw
         mov     byte ptr[edi], 0

         mov     ecx, MemRsrc
      .if dword ptr [ecx] == '8FIG'
            mov     PictID, 61
         INVOKE     lstrcpy, addr szType, addr szGif+2
      .elseif dword ptr[ecx+6] == 'FIFJ'
            mov     PictID, 62
         INVOKE     lstrcpy, addr szType, addr szJpg+2
      .elseif dword ptr[ecx+72h] == 'PPNT' || dword ptr [ecx] == 9AC6CDD7h
            mov     PictID, 63
         INVOKE     lstrcpy, addr szType, addr szWmf+2
      .elseif dword ptr[ecx+28h] == 'FME '
            mov     PictID, 64
         INVOKE     lstrcpy, addr szType, addr szEmf+2
      .elseif dword ptr[ecx] == 'FFIR' && dword ptr[ecx+8] == ' IVA'
            mov     PictID, 65
      .else
            jmp     NoImage
      .endif

      .if PictID == 65
         INVOKE     lstrcpy, addr szBuff, addr SavPath
         INVOKE     lstrcat, addr szBuff, addr szTempAvi

         INVOKE     CreateFile, addr szBuff,\
                    GENERIC_READ or GENERIC_WRITE,\
                    FILE_SHARE_READ or FILE_SHARE_WRITE,\
                    0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
            mov     hFile, eax

         INVOKE     WriteFile, hFile, MemRsrc, RsrcSize, addr BytesOut, NULL
         INVOKE     CloseHandle, hFile
            mov     ecx, 22
      .else
           call     LoadImageFile
            mov     ecx, 0
      .endif

        push     RsrcSize
         pop     SavSize
      INVOKE     CreateDialogParam, hInst, 4820, hREdit, offset ViewImage, ecx

         ret

NoImage:
;      INVOKE     BuildHex, SavAddr, RsrcSize

         ret
RsrcMisc ENDP

;=======================================
; Extract Cursor/Icon Resources
;=======================================
RsrcCursorIcon PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, CntID, TypeID
LOCAL    szWork[512]:BYTE

         mov     esi, RsrcInfo                               ; Resource array
         mov     ebx, OffPosID

         mov     ecx, dword ptr[esi+ebx]                     ; TypeID of the resource
         mov     TypeID, ecx
         mov     ecx, dword ptr[esi+ebx+4]                   ; ID of the resource
         mov     ID, ecx
         mov     ecx, RsrcSize
         mov     SavSize, ecx

;---------- [Build the Cursor/Icon header] ----------
         xor     eax, eax
         mov     edi, MemRsrc
         mov     word ptr[edi+eax], 0
      .if TypeID == 1
            mov     word ptr[edi+eax+2], 2                   ; Type cursor
      .else
            mov     word ptr[edi+eax+2], 1                   ; Type icon
      .endif
         mov     word ptr[edi+eax+4], 1
         mov     ebx, dword ptr[esi+ebx+20]                  ; Address to group
         xor     ecx, ecx
         mov     cx, word ptr[ebx+4]                         ; Number of arrays
         add     ebx, 6                                      ; header size
         xor     edx, edx
      .while (ecx)
            mov     dx, word ptr[ebx+12]                     ; ID
         .if edx == ID                                       ; Matched main ID with grp ID
               add     eax, 6
               mov     Cnt, 12
            .while (Cnt)
                  mov     dl, byte ptr[ebx]
                  mov     byte ptr[edi+eax], dl
                  inc     eax
                  inc     ebx
                  dec     Cnt
            .endw
            .if TypeID == 3                                  ; Icon
                  mov     dl, byte ptr[edi+eax-12]
                  mov     byte ptr[edi+eax-11], dl           ; Made height same as width
            .endif
            .break
         .endif
            add     ebx, 14                                  ; Length of array
            dec     ecx
      .endw
         mov     dword ptr[edi+eax], 22                      ; Header length
      .if !ecx
            ret
      .endif

;---------- [Fix the size for cursors] ----------
      .if TypeID == 1                                        ; Cursor
            mov     bl, byte ptr [edi+6]
            mov     byte ptr [edi+7], bl
            mov     bx, word ptr [edi+12]
            mov     word ptr [edi+8], bx
      .endif

;---------- [Build the Cursor/Icon file in case the user wants to save it] ----------
         xor     eax, eax
         mov     esi, SavAddr
      .if TypeID == 1                                        ; Cursor
         .if byte ptr[edi+8] == 1
               mov     byte ptr[edi+8], 2                    ; Set max colors to 2 if 1
         .endif
            mov     ecx, dword ptr[esi]
            mov     dword ptr[edi+10], ecx                   ; Set the hot spots (move from file to header)
            mov     ecx, dword ptr[edi+14]
            sub     ecx, 4
            mov     dword ptr[edi+14], ecx                   ; Reduce the cursor size by 4 (hot spots)
            add     esi, 4
      .endif
         add     edi, 22                                     ; Header length
         mov     ecx, RsrcSize
      .if TypeID == 1                                        ; Cursor
            sub     ecx, 4
      .endif
      .while (ecx)
            mov     bl, byte ptr[esi+eax]
            mov     byte ptr[edi+eax], bl
            inc     eax
            dec     ecx
      .endw

      .if TypeID == 1                                        ; Cursor
            sub     SavSize, 4
            sub     edi, 22
            xor     eax, eax
            mov     al, byte ptr[edi+6]
            mov     ebx, eax
            mov     al, byte ptr[edi+7]
            mov     edx, eax
      .endif

      .if hIC
         INVOKE     DestroyIcon, hIC
      .endif

         mov     esi, SavAddr
         mov     ecx, RsrcSize
         mov     edi, 0
      .if TypeID == 3
            mov    edi, 1
            mov    ebx, 32
            mov    edx, 32
      .endif
      INVOKE     CreateIconFromResourceEx, esi, ecx, edi, 30000h, ebx, edx, LR_DEFAULTCOLOR
         mov     hIC, eax

      .if hImage
         INVOKE     SendMessage, hImage, WM_COMMAND, 405, 0
      .endif
      INVOKE     CreateDialogParam, hInst, 4820, hREdit, offset ViewImage, TypeID

         ret
RsrcCursorIcon ENDP

;=======================================
; Extract Bitmap Resources
;=======================================
RsrcBitmap PROC  uses ebx esi edi
LOCAL    CntID:DWORD
LOCAL    szWork[512]:BYTE

;      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, addr szNULL
         mov     ecx, RsrcSize
         mov     SavSize, ecx

;---------- [Build the Bitmap header] ----------
         mov     esi, SavAddr
         xor     eax, eax
         mov     edi, MemRsrc
         mov     word ptr[edi], 'MB'
         add     ecx, 0eh
         mov     dword ptr[edi+2], ecx                       ; Bitmap size
         xor     edx, edx
         mov     dword ptr[edi+6], edx                       ; 0 fill
         mov     edx, 36h
         mov     dword ptr[edi+10], edx                      ; Bitmap bits offset

;---------- [Adjust the offset to the bitmap bits. Find the length of the color table] ----------
         xor     edx, edx
xor     ebx, ebx
         mov     dx, word ptr[esi+ebx+14]                    ; biBitCount
       MOVmd     Hold, dword ptr[esi+ebx+32]

      .if edx == 8 && Hold == 0
            mov     edx, 100h                                ; 1024 bits
      .elseif edx == 4 && Hold == 0
            mov     edx, 10h                                 ; 64 bits
      .else
            mov     edx, dword ptr[esi+ebx+32]               ; biClrUsed 'color array'
      .endif
        imul     edx, 4
         add     dword ptr[edi+eax+10], edx
         add     esi, ebx                                    ; Offset of the Bitmap in the file
         add     edi, 0eh                                    ; Offset of the Bitmap header
         mov     Hold, ecx
         sub     ecx, 0eh                                    ; Remove the header size
         xor     ebx, ebx
      .while (ecx)
            mov     al, byte ptr[esi+ebx]
            mov     byte ptr[edi+ebx], al
            inc     ebx
            dec     ecx
      .endw

      .if hImage
         INVOKE     SendMessage, hImage, WM_COMMAND, 405, 0
      .endif

      INVOKE     CreateDialogParam, hInst, 4820, hREdit, offset ViewImage, 2

         ret
RsrcBitmap ENDP

;=======================================
; Extract Group Cursor/Icon Resources
;=======================================
RsrcGrpImages PROC  uses ebx esi edi
LOCAL    HeaderSize:DWORD, Cnt, CntID, Sesi
LOCAL    Ioffset:DWORD
LOCAL    szWork[64]:BYTE

         mov     esi, RsrcInfo                            ; Resource array
         mov     ebx, OffPosID

         mov     ecx, dword ptr[esi+ebx]                  ; ID of the resource type
         mov     ID, ecx

;---------- [Build the Group cursor/icon header] ----------
         xor     eax, eax
         xor     ecx, ecx
         mov     esi, SavAddr
         mov     edi, MemRsrc
         mov     ax, word ptr[esi]
         mov     word ptr[edi], ax
         mov     ax, word ptr[esi+2]
         mov     word ptr[edi+2], ax
         mov     ax, word ptr[esi+4]                      ; Number of images in the group
         mov     word ptr[edi+4], ax
         mov     cx, ax
        imul     eax, 16
         add     eax, 6
         xor     ebx, ebx
         mov     Ioffset, eax                             ; Offset to first image
         add     esi, 6                                   ; Group header size
         add     edi, 6
      .while (ecx)
            mov     edx, 12
         .while (edx)
               mov     al, byte ptr[esi]
               mov     byte ptr[edi], al
               inc     esi
               inc     edi
               dec     edx
         .endw
         .if ID == 12                                     ; Group cursor fix the size
               mov     al, byte ptr[edi-12]
               mov     byte ptr[edi-11], al
               mov     eax, dword ptr[edi-4]
               sub     eax, 4
               mov     dword ptr[edi-4], eax
         .endif
         .if ID == 14                                     ; Group icon make height same as width
               mov     al, byte ptr[edi-12]
               mov     byte ptr[edi-11], al
         .endif

            add     Ioffset, ebx
          MOVmd     dword ptr[edi], Ioffset               ; Offset to first or next image
            mov     ebx, dword ptr[esi-4]                 ; Size of next image
         .if ID == 12                                     ; Group cursor
               sub     ebx, 4                             ; Adjust length for cursor hot spots
         .endif
            add     esi, 2
            add     edi, 4
            dec     ecx
      .endw
         mov     SavOffset, edi                           ; Save offset to the output file
         mov     eax, edi
         sub     eax, MemRsrc
         mov     HeaderSize, eax

;---------- [Find the cursor/icon resources and build the cursor/icon file] ----------
         and     Hold, 0
         mov     esi, SavAddr
         xor     ecx, ecx
         mov     cx, word ptr[esi+4]                      ; Number of images in the group
         mov     Cnt, ecx
         add     esi, 6
      .while (Cnt)
            mov     ax, word ptr[esi+12]                  ; ID of cursor/icon
            mov     ecx, ID
            mov     edi, RsrcInfoGrp
          MOVmd     CntID, NumOfGroups
         .while (CntID)
            .if ax == word ptr[edi] && cl == byte ptr[edi+14] ; Matching resource ID & type
                 push     esi
                  mov     ecx, dword ptr[esi+8]           ; Size of cursor/icon resource
                  mov     esi, dword ptr[edi+10]          ; Address of cursor/icon resource
                  add     Hold, ecx
                  mov     edi, SavOffset
               .if ID == 12                               ; Adjust length for cursor hot spots
                    push     edi
                     mov     eax, dword ptr[esi]          ; Hot spots
                     mov     edi, MemRsrc
                     mov     dword ptr[edi+10], eax
                     pop     edi
                     add     esi, 4
                     sub     ecx, 4
               .endif

;---------- [Concatenate the cursor/icon resources] ----------
               .while (ecx)
                     mov     al, byte ptr[esi]
                     mov     byte ptr[edi], al
                     inc     esi
                     inc     edi
                     dec     ecx
               .endw
                  pop     esi
                  mov     SavOffset, edi
               .break
            .endif
               add     edi, 15                            ; Size of the RsrcInfoGrp array
               dec     CntID
         .endw
            add     esi, 14                               ; Size of the group array
            dec     Cnt
      .endw

      .if hIC
         INVOKE     DestroyIcon, hIC
            and     hIC, 0
      .endif

         mov     eax, SavOffset
         sub     eax, MemRsrc
         mov     SavSize, eax                             ; Size of the output file

         mov     esi, MemRsrc
         add     esi, HeaderSize                          ; Start of cursor/icon files after header
         mov     ecx, SavSize
         sub     ecx, HeaderSize                          ; Length of cursor/icon files minus header

      INVOKE     CreateIconFromResourceEx, esi, ecx, 1, 30000h, 32, 32, LR_DEFAULTCOLOR ; Grp cursor/Icon
         mov     hIC, eax

      .if hImage
         INVOKE     SendMessage, hImage, WM_COMMAND, 405, 0
      .endif
      INVOKE     CreateDialogParam, hInst, 4820, hREdit, offset ViewImage, ID

         ret
RsrcGrpImages ENDP

;=======================================
; Extract Animated Resources
;=======================================
RsrcAnimate PROC  uses ebx esi edi
LOCAL    BytesOut:DWORD

;      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, addr szNULL

         mov     esi, SavAddr
         mov     edi, MemRsrc
         mov     ecx, RsrcSize
      .while (ecx)
            mov     al, byte ptr[esi]
            mov     byte ptr[edi], al
            inc     esi
            inc     edi
            dec     ecx
      .endw
      INVOKE     lstrcpy, addr szBuff, addr SavPath
      INVOKE     lstrcat, addr szBuff, addr szTempAni

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
         mov     hFile, eax

      INVOKE     WriteFile, hFile, MemRsrc, RsrcSize, addr BytesOut, NULL
      INVOKE     CloseHandle, hFile

         mov     ecx, 32
;---------- [It does not matter if you use IMAGE_CURSOR or IMAGE_ICON] ----------
      INVOKE     LoadImage, 0, addr szBuff, IMAGE_CURSOR, ecx, ecx,
                 LR_LOADFROMFILE or LR_LOADMAP3DCOLORS
         mov     hIcon, eax

      INVOKE     DeleteFile, addr szBuff

      INVOKE     CreateDialogParam, hInst, 4820, hREdit, offset ViewImage, 21

         ret
RsrcAnimate ENDP

;========================================
; Display Images Procedure
;========================================
ViewImage PROC  uses ebx esi edi  hdlg:DWORD, wmsg, wparam, lparam
;LOCAL    ofn:OPENFILENAME
LOCAL    rect:RECT
LOCAL    RsrcAddr:DWORD
LOCAL    hBmp1:DWORD, hOldBmp1, hDC, hMemDC, XP, YP, Iw, Ih, Cnt, sw

      .if wmsg == WM_INITDIALOG
          MOVmd     hImage, hdlg
          MOVmd     ImageID, lparam

         .if ImageID == 21
;---------- [Create a static Control Window] ----------
            INVOKE     CreateWindowEx, 0, addr StaticClass, 0,\
                       WS_CHILD or WS_VISIBLE or SS_ICON or SS_REALSIZEIMAGE,\
                       0, 0, 100, 100, hdlg, 2001, hInst, NULL
               mov     hStatic, eax

         .elseif ImageID == 22  ; ACS_CENTER or
            INVOKE     CreateWindowEx, NULL, addr AnimateClass, NULL,\
                       WS_CHILD or WS_VISIBLE or WS_BORDER or\
                       ACS_TIMER or ACS_TRANSPARENT,\
                       0, 0, 100, 100, hdlg, 2001, hInst, NULL
               mov     hAniCtrl, eax
         .endif

         INVOKE     PostMessage, hdlg, WM_LBUTTONDOWN, 44, 0 ; Post to display opened image
            jmp     ViewDone

;      .elseif wmsg == WM_CTLCOLORDLG || wmsg == WM_CTLCOLORSTATIC && ImageID == 21
;            mov     eax, hBrush
;            ret

      .elseif wmsg == WM_CTLCOLORSTATIC
         INVOKE     SetBkColor, wparam, 00000000h
         INVOKE     GetStockObject, BLACK_BRUSH
            ret

      .elseif wmsg == WM_RBUTTONUP
         INVOKE     GetWindowRect, hdlg, addr rect
            mov     ecx, lparam                              ; x/y pos of window
            mov     ebx, ecx
            and     ebx, 0000ffffh                           ; ebx = LOWORD(lparam) = x pos
            shr     ecx, 16                                  ; eax = HIWORD(lparam) = y pos
            add     ebx, rect.left
            add     ecx, rect.top
            add     ebx, 3                                   ; x Position
            add     ecx, 3                                   ; y Position
         INVOKE     TrackPopupMenu, hSubMenu, TPM_LEFTALIGN or TPM_LEFTBUTTON, ebx, ecx, 0, hdlg, addr rect

      .elseif wmsg == WM_PAINT && hdlg != 0
         INVOKE     PostMessage, hWnd, WM_PAINT, 0, 0        ; Need for NT
            jmp     DisplayEM

      .elseif wmsg == WM_LBUTTONDOWN
         .if wparam != 44
            INVOKE     PostMessage, hdlg, WM_NCLBUTTONDOWN, HTCAPTION, 0 ; Post to drag window in the client area
         .endif
            jmp     ViewDone

      .elseif wmsg != WM_COMMAND
            jmp     ViewDone
      .endif
         mov     eax, wparam
        cwde
         cmp     eax, 404                                    ; Save as
          je     Export
         cmp     eax, 405                                    ; Close
          je     CancelOut
         jmp     ViewDone

Export:
         mov     sw, 1
         jmp     BuildImg

DisplayEM:
         and     sw, 0
      .if !MemRsrc
            jmp     CancelOut
      .endif
      INVOKE     GetWindowRect, hdlg, addr rect
       MOVmd     XP, rect.left
       MOVmd     YP, rect.top

BuildImg:
         cmp     sw, 1
          je     ExportImg
      .if ImageID == 21
            jmp     DoAnimate
      .elseif ImageID == 22
            jmp     DoAvi
      .endif

      INVOKE     GetDC, hdlg                                 ; Get dc the of the window
         mov     hDC, eax
         mov     esi, MemRsrc

         mov     eax, 10
         mov     ebx, dword ptr[esi+eax]
       MOVmd     Iw, dword ptr[esi+eax+8]
       MOVmd     Ih, dword ptr[esi+eax+12]

         add     esi, ebx
      .if ImageID == 2 || ImageID == 0                                      ; 2 = Bitmap
      .else
            jmp     ID13
      .endif

.if ImageID == 2
         mov     edi, MemRsrc
         add     edi, 14                                     ; Po
      INVOKE     CreateDIBitmap, hDC, edi, CBM_INIT, esi, edi, 0 ; Creates a device-dependent bitmap from a device independent bitmap
         mov     hBmp1, eax
      INVOKE     CreateCompatibleDC, hDC                     ; Create a compatible dc in memory
         mov     hMemDC, eax
      INVOKE     SelectObject, hMemDC, hBmp1                 ; Select the opened bitmap into the dc
.else
       MOVmd     Iw, pWidth
       MOVmd     Ih, pHeight
      INVOKE     CreateCompatibleDC, hDC                     ; Create a compatible dc in memory
         mov     hMemDC, eax
      INVOKE     SelectObject, hMemDC, hBitmap               ; Select the opened bitmap into the dc
.endif
       MOVmd     ebx, Iw
       MOVmd     ecx, Ih
         add     ebx, 6
         add     ecx, 6
      INVOKE     MoveWindow, hdlg, XP, YP, ebx, ecx, 1

ID13:
      .if ImageID == 2 || ImageID == 0                                      ; 2 = Bitmap
      .else
            mov     edi, MemRsrc
            add     edi, 6
            xor     eax, eax
            mov     al, byte ptr [edi]
            mov     Iw, eax
            mov     al, byte ptr [edi+1]
            mov     Ih, eax
         INVOKE     CreateCompatibleDC, hDC                  ; Create a compatible dc in memory
            mov     hMemDC, eax
         INVOKE     CreateCompatibleBitmap, hDC, Iw, Ih
            mov     hBmp1, eax
         INVOKE     SelectObject, hMemDC, hBmp1              ; Select the opened bitmap into the dc
            mov     hOldBmp1, eax
          MOVmd     ebx, Iw
          MOVmd     ecx, Ih
            add     ebx, 6
            add     ecx, 6
         INVOKE     MoveWindow, hdlg, XP, YP, ebx, ecx, 1
         INVOKE     DrawIconEx, hDC, 0, 0, hIC, Iw, Ih, 0, 0, DI_NORMAL
         INVOKE     SelectObject, hMemDC, hOldBmp1           ; Select the old bitmap into the dc
            jmp     NoBitBlt
      .endif

      INVOKE     BitBlt, hDC, 0, 0, Iw, Ih, hMemDC, 0, 0, SRCCOPY ; Copy the bitmap

NoBitBlt:
      INVOKE     DeleteDC, hMemDC                            ; Delete the memory dc
      INVOKE     ReleaseDC, hdlg, hDC
      .if ImageID != 0
         INVOKE     DeleteObject, hBmp1
;         INVOKE     DestroyIcon, hIC

      .else 
         INVOKE     GetClientRect, hdlg, addr rect
         INVOKE     GetDC, hdlg
            mov     hDC, eax
         INVOKE     SetTextColor, hDC, 0000ff00h
         INVOKE     SetBkColor, hDC, 0
         INVOKE     SetBkMode, hDC, TRANSPARENT
            add     rect.left, 5
            add     rect.top, 5
            mov     rect.right, 50
            mov     rect.bottom, 30
         INVOKE     DrawText, hDC, addr szType, -1, addr rect, DT_LEFT or DT_SINGLELINE
         INVOKE     ReleaseDC, hdlg, hDC
      .endif
         jmp     ViewDone 

DoAnimate:
      INVOKE     MoveWindow, hdlg, XP, YP, 39, 39, 1
      INVOKE     SendMessage, hStatic, STM_SETIMAGE, IMAGE_ICON, hIcon
         jmp     ViewDone 

DoAvi:
      INVOKE     lstrcpy, addr szBuff, addr SavPath
      INVOKE     lstrcat, addr szBuff, addr szTempAvi
      .if osvMaj == 55555
         INVOKE     MultiByteToWideChar, CP_ACP, 0, addr szBuff, -1, addr szUnicode, 0
         INVOKE     MultiByteToWideChar, CP_ACP, 0, addr szBuff, -1, addr szUnicode, eax
         INVOKE     SendMessage, hAniCtrl, ACM_OPEN, 0, addr szUnicode
      .else
         INVOKE     SendMessage, hAniCtrl, ACM_OPEN, 0, addr szBuff
      .endif
      INVOKE     ShowWindow, hAniCtrl, SW_SHOW
      INVOKE     GetClientRect, hAniCtrl, addr rect
add     rect.right, 8
add     rect.bottom, 8
      INVOKE     MoveWindow, hdlg, XP, YP, rect.right, rect.bottom, 1
         mov     ecx, -1
         shl     ecx, 16
         mov     ax, -1
         mov     cx, ax
      INVOKE     SendMessage, hAniCtrl, ACM_PLAY, 20, ecx
         jmp     ViewDone 

ExportImg:
      INVOKE     ShowWindow, hImage, SW_HIDE
      INVOKE     lstrcpy, addr szBuff, addr SavPath
      INVOKE     lstrcat, addr szBuff, addr szSlashB

      .if ImageID == 1 || ImageID == 12
         INVOKE     lstrcpy, addr szBuff, addr szCur
      .elseif ImageID == 2
         INVOKE     lstrcpy, addr szBuff, addr szBmp
      .elseif ImageID == 3 || ImageID == 14
         INVOKE     lstrcpy, addr szBuff, addr szIco
      .elseif ImageID == 21
         INVOKE     lstrcat, addr szBuff, addr szAni
      .elseif ImageID == 22
         INVOKE     lstrcat, addr szBuff, addr szAvi
      .elseif ImageID == 0
         .if PictID == 61
            INVOKE     lstrcat, addr szBuff, addr szGif
         .elseif PictID == 62
            INVOKE     lstrcat, addr szBuff, addr szJpg
         .elseif PictID == 63
            INVOKE     lstrcat, addr szBuff, addr szWmf
         .elseif PictID == 64
            INVOKE     lstrcat, addr szBuff, addr szEmf
         .endif
      .endif
;---------- [Zero out the structure] ----------
      INVOKE     RtlZeroMemory, addr ofn, sizeof ofn
         mov     ofn.lStructSize, sizeof ofn
       MOVmd     ofn.hwndOwner, hWnd
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szFilterI
         mov     ofn.lpstrFile, offset szBuff
         mov     ofn.nMaxFile, sizeof szBuff
         mov     ofn.lpstrTitle, offset szTitleS
         mov     ofn.Flags, OFN_EXPLORER or OFN_OVERWRITEPROMPT or OFN_CREATEPROMPT
      INVOKE     GetSaveFileName, addr ofn
        push     eax
      INVOKE     ShowWindow, hImage, SW_SHOW
         pop     eax
         cmp     eax, FALSE       ; Cancel'ed or error occurred
          je     ViewDone

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
         mov     hFile, eax
         mov     ecx, SavSize
      .if ImageID == 2
            add     ecx, 14
      .elseif ImageID == 1 || ImageID == 3
            add     ecx, 22
      .endif
      INVOKE     WriteFile, hFile, MemRsrc, ecx, addr Cnt, NULL
      INVOKE     CloseHandle, hFile
         jmp     ViewDone 

CancelOut:
      .if hStatic
         INVOKE     DestroyCursor, hIcon
         INVOKE     DestroyWindow, hStatic
            and     hStatic, 0
      .endif
      .if hAniCtrl
         INVOKE     DestroyWindow, hAniCtrl
            and     hAniCtrl, 0
         INVOKE     DeleteFile, addr szBuff
      .endif
      .if hIC
         INVOKE     DestroyIcon, hIC
            and     hIC, 0
      .endif
      .if ipPicture
            mov     eax, ipPicture
           push     eax
            mov     edx, dword ptr[eax]
           call     dword ptr[edx+8]             ; ipPicture->Release()
         INVOKE     DeleteObject, hBitmap
            and     ipPicture, 0
      .endif
         and     hImage, 0
      INVOKE     DestroyWindow, hdlg
         mov     eax, TRUE          ; Return
         jmp     ViewRet            ; with TRUE

ViewDone:
         mov     eax, FALSE         ; Return with FALSE

ViewRet:

         ret
ViewImage ENDP

;=======================================
; Extract Menu Resources
;=======================================
RsrcMenu PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, Len, CntID, PopOn, Code
LOCAL    CtrlCnt:DWORD, dwType, dwState, dwID, dwHelpId
LOCAL    szWork[64]:BYTE, szMenuID[32]:BYTE, szOffset[32]:BYTE

         mov     esi, RsrcInfo                            ; Resource array
         mov     ebx, OffPosID
         mov     eax, dword ptr[esi+ebx+4]

      .if eax != 6969
         INVOKE     wsprintf, addr szWork, addr fmat2, eax
      .else
            mov     ecx, RsrcInfo
            add     ecx, OffPosID
            add     ecx, 40
         INVOKE     lstrcpy, addr szWork, ecx
      .endif

         mov     ecx, SavAddr
      .if word ptr[ecx] != 1
            jmp     DoMenu
      .endif

;---------- [MENUEX] ----------
         add     SavAddr, 8
         sub     RsrcSize, 8
         mov     Cnt, 1

      INVOKE     lstrcat, MemRsrc, addr szWork
      INVOKE     lstrcat, MemRsrc, addr szMenuex
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN01
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      .while (RsrcSize)
         INVOKE     lstrcpyn, addr szOffset, addr szFill, Cnt
            and     PopOn, 0
            and     Code, 0
            mov     ecx, SavAddr
          MOVmd     dwType, dword ptr[ecx]
          MOVmd     dwState, dword ptr[ecx+4]
          MOVmd     dwID, dword ptr[ecx+8]
            xor     eax, eax
            mov     ax, word ptr[ecx+12]
            mov     Code, eax

         .if word ptr[ecx+12] == 1 || word ptr[ecx+12] == 81h     ; POPUP
               mov     PopOn, 1
            INVOKE     lstrcat, MemRsrc, addr szOffset
            INVOKE     lstrcat, MemRsrc, addr szPopup
         .else
            INVOKE     lstrcat, MemRsrc, addr szOffset
            INVOKE     lstrcat, MemRsrc, addr szMENUITEM
         .endif

            add     SavAddr, 14
            sub     RsrcSize, 14
         INVOKE     WideCharToMultiByte, CP_ACP, 0, SavAddr, -1, addr szBuff, 63, 0, 0
;           push     eax
            shl     eax, 1
            add     SavAddr, eax
            sub     RsrcSize, eax

         INVOKE     lstrcat, MemRsrc, addr szBuff ;szWork
         INVOKE     lstrcat, MemRsrc, addr szQuote
         INVOKE     lstrcat, MemRsrc, addr szCommaS
         INVOKE     BaseAscii, dwID, addr szWork, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szCommaS
         .if dwType == 0
            INVOKE     lstrcat, MemRsrc, addr szMFTSTRING
         .elseif dwType == 800h
            INVOKE     lstrcat, MemRsrc, addr szMFTSEPARATOR
         .else
            INVOKE     lstrcat, MemRsrc, addr szNeed
         .endif
         INVOKE     lstrcat, MemRsrc, addr szCommaS
         .if dwState == 0
            INVOKE     lstrcat, MemRsrc, addr szMFSENABLED
         .elseif dwState == 3
            INVOKE     lstrcat, MemRsrc, addr szMFSGRAYED
         .elseif dwState == 8
            INVOKE     lstrcat, MemRsrc, addr szMFSCHECKED
         .else
            INVOKE     lstrcat, MemRsrc, addr szNeed
         .endif

         .if PopOn
            INVOKE     lstrcat, MemRsrc, addr szCommaS
               mov     ecx, SavAddr
             MOVmd     dwHelpId, dword ptr[ecx]
            INVOKE     BaseAscii, dwHelpId, addr szWork, 1, 10, 1, 1, 0
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               add     SavAddr, 4
               sub     RsrcSize, 4

         .else
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif

         .if PopOn
            INVOKE     lstrcat, MemRsrc, addr szOffset
            INVOKE     lstrcat, MemRsrc, addr szBEGIN02
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               add     Cnt, 3

         .elseif Code == 80h || Code == 81h   ; Last entry of popup
               sub     Cnt, 3
            INVOKE     lstrcpyn, addr szOffset, addr szFill, Cnt
            INVOKE     lstrcat, MemRsrc, addr szOffset
            INVOKE     lstrcat, MemRsrc, addr szEND02
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif

            inc     NumofItems
         INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
         INVOKE     UpdateWindow, hDlg3

;---------- [Align on a DWORD boundry] ----------
            xor     edx, edx
            mov     eax, SavAddr
            mov     ebx, 4
            div     ebx
         .if edx
               add     SavAddr, 2
               sub     RsrcSize, 2
         .endif
            mov     eax, RsrcSize
         .if sdword ptr eax < 0
;DSPValue hWnd, RsrcSize, 1, 'm'
            .break
         .endif
      .endw

         jmp     Getout

;---------- [MENU] ----------
DoMenu:
         add     SavAddr, 4
         sub     RsrcSize, 4
         and     Cnt, 0
         and     PopOn, 0

      INVOKE     lstrcat, MemRsrc, addr szWork
      INVOKE     lstrcat, MemRsrc, addr szMenu
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN01
      INVOKE     lstrcat, MemRsrc, addr szCRLF

LoopM:
      .while (RsrcSize)
            and     Code, 0
            and     PopOn, 0
            mov     byte ptr szMenuID, 0
            mov     ecx, SavAddr
         .if dword ptr[ecx] == 0                               ; Seperator
               add     SavAddr, 6
               sub     RsrcSize, 6
            INVOKE     lstrcat, MemRsrc, addr szSEPARATOR
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               jmp     LoopM

         .elseif word ptr[ecx] == 10h || word ptr[ecx] == 90h ; POPUP
               mov     PopOn, 1
               add     SavAddr, 2
               sub     RsrcSize, 2
            INVOKE     lstrcat, MemRsrc, addr szPopup

         .else
               xor     edx, edx
               mov     dx, word ptr[ecx]                  ; State or end of POPUP
               mov     Code, edx                          
               mov     dx, word ptr[ecx+2]                ; Menu ID
               add     SavAddr, 4
               sub     RsrcSize, 4
            INVOKE     wsprintf, addr szMenuID, addr fmat2, edx
            INVOKE     lstrcat, MemRsrc, addr szMENUITEM
         .endif
         INVOKE     WideCharToMultiByte, CP_ACP, 0, SavAddr, -1, addr szBuff, 63, 0, 0
           push     eax
            shl     eax, 1
            add     SavAddr, eax
            sub     RsrcSize, eax
            lea     esi, szBuff
            lea     edi, szWork
            pop     ecx
         .while (ecx)
               mov     al, byte ptr[esi]
            .if al == 9            ; Tab
                  mov     word ptr[edi], 't\'
                  inc     edi
            .else
                  mov     byte ptr[edi], al
            .endif
               inc     esi
               inc     edi
               dec     ecx
         .endw
            mov     byte ptr[edi], 0

         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szQuote

         .if !PopOn
            INVOKE     lstrcat, MemRsrc, addr szComma
         .endif

         .if szMenuID
            INVOKE     lstrlen, addr szWork
               mov     ecx, 34
            .if eax > 34
                  mov     eax, 34
            .endif
               sub     ecx, eax
            INVOKE     lstrcpyn, addr szWork, addr szFill, ecx
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szMenuID
            .if Code == 1 || Code == 81h
               INVOKE     lstrcat, MemRsrc, addr szGrayed
            .elseif Code == 8 || Code == 88h
               INVOKE     lstrcat, MemRsrc, addr szChecked
            .endif
         .endif
         INVOKE     lstrcat, MemRsrc, addr szCRLF

            inc     NumofItems
         INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
         INVOKE     UpdateWindow, hDlg3

         .if PopOn
            INVOKE     lstrcat, MemRsrc, addr szBEGIN02
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               add     Cnt, 3
         .endif

         .if Code == 80h || Code == 81h
            INVOKE     lstrcat, MemRsrc, addr szEND02
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               sub     Cnt, 3
         .endif
            mov     eax, RsrcSize
;DSPValue hWnd, eax, 1, 'm'
         .if sdword ptr eax < 0
            .break
         .endif
      .endw

Getout:
      INVOKE     lstrcat, MemRsrc, addr szEND01
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcMenu ENDP

;=======================================
; Extract Dialog Resources
;=======================================
RsrcDialog PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, Len, CntID
LOCAL    CtrlCnt:DWORD, BIOn, DlgVer, SavClass
LOCAL    szWork[64]:BYTE

            mov     ecx, SavAddr                             ; Actual address of the resource

            xor     eax, eax
            mov     ax, word ptr[ecx+2]
            mov     DlgVer, eax                              ; ffffh = DLGTEMPLATEEX

            xor     eax, eax
         .if DlgVer == 0ffffh
               mov     ax, word ptr[ecx+16]
         .else
               mov     ax, word ptr[ecx+8]
         .endif
            mov     CtrlCnt, eax
            mov     Dlg.lpMenu, 0
            mov     Dlg.Class, 0
            mov     Dlg.lpCaption, 0
            mov     esi, RsrcInfo                            ; Resource array
            mov     ebx, OffPosID
          MOVmd     Dlg.ID, dword ptr[esi+ebx+4]

         .if Dlg.ID == 6969
              push     ecx
               mov     ecx, RsrcInfo
               add     ecx, OffPosID
               add     ecx, 40
            INVOKE     lstrcpy, addr Dlg.lpName, ecx
               mov     esi, RsrcInfo                         ; Resource array
               mov     ebx, OffPosID
               pop     ecx
         .endif

         .if DlgVer == 0ffffh
             MOVmd     Dlg.ExStyle, dword ptr[ecx+8]
             MOVmd     Dlg.Style, dword ptr[ecx+12]
             MOVmw     Dlg.Left, word ptr[ecx+18]
             MOVmw     Dlg.Top, word ptr[ecx+20]
             MOVmw     Dlg.Wth, word ptr[ecx+22]
             MOVmw     Dlg.Hgt, word ptr[ecx+24]
               add     ecx, 26
         .else
             MOVmd     Dlg.Style, dword ptr[ecx]
             MOVmd     Dlg.ExStyle, dword ptr[ecx+4]
             MOVmw     Dlg.Left, word ptr[ecx+10]
             MOVmw     Dlg.Top, word ptr[ecx+12]
             MOVmw     Dlg.Wth, word ptr[ecx+14]
             MOVmw     Dlg.Hgt, word ptr[ecx+16]
               add     ecx, 18
         .endif

         .if Dlg.Left > 7fffh
               mov     Dlg.Left, 0
         .endif
         .if Dlg.Top > 7fffh
               mov     Dlg.Top, 0
         .endif

         .if word ptr[ecx] != 0   ; = Menu
            .if word ptr[ecx] == 0ffffh
                  xor     eax, eax
                  mov     ax, word ptr[ecx+2]
                  mov     dword ptr Dlg.lpMenu, eax
                  add     ecx, 4
            .else
                 push     ecx
               INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Dlg.lpMenu, 31, 0, 0
                  shl     eax, 1
                  pop     ecx
                  add     ecx, eax
            .endif
         .else
               add     ecx, 2
         .endif

         .if word ptr[ecx] != 0   ; = Class
            .if word ptr[ecx] == 0ffffh
                  xor     eax, eax
                  mov     ax, word ptr[ecx+2]
                  mov     dword ptr Dlg.Class, eax
                  add     ecx, 4
            .else
                 push     ecx
               INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Dlg.Class, 31, 0, 0
                  shl     eax, 1
                  pop     ecx
                  add     ecx, eax
            .endif
         .else
               add     ecx, 2
         .endif

         .if word ptr[ecx] != 0   ; = Caption
              push     ecx
            INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Dlg.lpCaption, 511, 0, 0
               shl     eax, 1
               pop     ecx
               add     ecx, eax
         .else
               add     ecx, 2
         .endif

         .if (Dlg.Style & DS_SETFONT)
             MOVmw     Dlg.pointsize, word ptr[ecx]
            .if DlgVer == 0ffffh
                MOVmw     Dlg.weight, word ptr[ecx+2]
                MOVmw     Dlg.bItalic, word ptr[ecx+4]
                  add     ecx, 6
            .else
                  add     ecx, 2
            .endif
              push     ecx
            INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Dlg.lpFont, 63, 0, 0
               shl     eax, 1
               pop     ecx
               add     ecx, eax

               xor     edx, edx
               mov     eax, ecx
               mov     ebx, 4
               div     ebx
            .if edx
                  add     ecx, 2
            .endif
         .endif

           push     ecx

            inc     NumofDlgs
         INVOKE     SetDlgItemInt, hDlg3, 701, NumofDlgs, 0
         INVOKE     UpdateWindow, hDlg3

         .if Dlg.ID != 6969
            INVOKE     BaseAscii, Dlg.ID, addr szWork, 1, 10, 1, 1, 0
            INVOKE     lstrcat, MemRsrc, addr szWork
         .else
            INVOKE     lstrcat, MemRsrc, addr Dlg.lpName
         .endif
         .if DlgVer == 0ffffh
            INVOKE     lstrcat, MemRsrc, addr szDlgEX
         .else
            INVOKE     lstrcat, MemRsrc, addr szDlg
         .endif
         INVOKE     BaseAscii, Dlg.Left, addr szWork, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     BaseAscii, Dlg.Top, addr szWork, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     BaseAscii, Dlg.Wth, addr szWork, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     BaseAscii, Dlg.Hgt, addr szWork, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szCRLF
         .if Dlg.lpCaption
            INVOKE     lstrcat, MemRsrc, addr szCapt
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr Dlg.lpCaption
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif
         .if Dlg.lpFont
            INVOKE     lstrcat, MemRsrc, addr szFont
            INVOKE     BaseAscii, Dlg.pointsize, addr szWork, 1, 10, 1, 1, 0
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szComma
            INVOKE     lstrcat, MemRsrc, addr szSpace
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr Dlg.lpFont
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif
         INVOKE     lstrcat, MemRsrc, addr szSty
         INVOKE     lstrcat, MemRsrc, addr sz0x
         INVOKE     BaseAscii, Dlg.Style, addr szWork, 8, 16, 1, 1, 1
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szCRLF
         INVOKE     lstrcat, MemRsrc, addr szEXSty
         INVOKE     lstrcat, MemRsrc, addr sz0x
         INVOKE     BaseAscii, Dlg.ExStyle, addr szWork, 8, 16, 1, 1, 1
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szCRLF

         .if Dlg.Class
            INVOKE     lstrcat, MemRsrc, addr szClass
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr Dlg.Class
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif

         INVOKE     lstrcat, MemRsrc, addr szBegin
            pop     ecx

         .while (CtrlCnt)

;---------- [Align on a DWORD boundry] ----------
               xor     edx, edx
               mov     eax, ecx
               mov     ebx, 4
               div     ebx
            .if edx
                  add     ecx, 2
            .endif

               xor     eax, eax
            .if DlgVer == 0ffffh
                  mov     ax, word ptr[ecx+20]
                  mov     Ctrls.ID, eax
                MOVmd     Ctrls.ExStyle, dword ptr[ecx+4]
                MOVmd     Ctrls.Style, dword ptr[ecx+8]
                MOVmw     Ctrls.Left, word ptr[ecx+12]
                MOVmw     Ctrls.Top, word ptr[ecx+14]
                MOVmw     Ctrls.Wth, word ptr[ecx+16]
                MOVmw     Ctrls.Hgt, word ptr[ecx+18]
                  add     ecx, 22
            add     ecx, 2
            .else
                  mov     ax, word ptr[ecx+16]
                  mov     Ctrls.ID, eax
                MOVmd     Ctrls.Style, dword ptr[ecx]
                MOVmd     Ctrls.ExStyle, dword ptr[ecx+4]
                MOVmw     Ctrls.Left, word ptr[ecx+8]
                MOVmw     Ctrls.Top, word ptr[ecx+10]
                MOVmw     Ctrls.Wth, word ptr[ecx+12]
                MOVmw     Ctrls.Hgt, word ptr[ecx+14]
                  add     ecx, 18
            .endif

            .if Ctrls.Left > 7fffh
                  mov     Ctrls.Left, 0
            .endif
            .if Ctrls.Top > 7fffh
                  mov     Ctrls.Top, 0
            .endif

               mov     Ctrls.Class, 0
               and     SavClass, 0
            .if word ptr[ecx] != 0   ; = Class
               .if word ptr[ecx] == 0ffffh
                     xor     eax, eax
                     mov     ax, word ptr[ecx+2]
                     mov     SavClass, eax
                     sub     eax, 80h
                     mov     edx, ClassArray[eax*4]
                    push     ecx
                  INVOKE     lstrcpy, addr Ctrls.Class, edx
                     pop     ecx
                     add     ecx, 4
               .else
                    push     ecx
                  INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Ctrls.Class, 31, 0, 0
                     shl     eax, 1
                     pop     ecx
                     add     ecx, eax
               .endif
            .else
                  add     ecx, 2
            .endif

               and     BIOn, 0
               mov     Ctrls.lpCaption, 0
            .if word ptr[ecx] != 0   ; = Caption
               .if word ptr[ecx] == 0ffffh
                     mov     BIOn, 1
                     xor     ebx, ebx
                     mov     bx, word ptr[ecx+2]
                  INVOKE     BaseAscii, ebx, addr szWork, 1, 10, 1, 1, 0
                    push     ecx
                  INVOKE     lstrcpy, addr Ctrls.lpCaption, addr szWork
                     pop     ecx
                     add     ecx, 4
               .else

                    push     ecx
                  INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr Ctrls.lpCaption, 511, 0, 0
                     shl     eax, 1
                     pop     ecx
                     add     ecx, eax
               .endif

            .else
                  add     ecx, 2
            .endif

            .if DlgVer != 0ffffh

;---------- [Offset + 4 if dword boundry and DLGTEMPLATE DUMP!!!] ----------
                  xor     edx, edx
                  mov     eax, ecx
                  mov     ebx, 4
                  div     ebx
               .if !edx
                     add     ecx, 4
               .endif
            .endif

              push     ecx

               inc     NumofCtrls
               inc     NumofItems
            INVOKE     SetDlgItemInt, hDlg3, 702, NumofCtrls, 0
            INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
            INVOKE     UpdateWindow, hDlg3

            INVOKE     lstrcat, MemRsrc, addr szCont
            .if !BIOn                                        ; BIOn = Bitmap, Icon
               INVOKE     lstrcat, MemRsrc, addr szQuote
            .endif

            INVOKE     lstrcpy, addr szBuff, addr Ctrls.lpCaption
            INVOKE     lstrlen, addr szBuff
               mov     ecx, eax
               xor     eax, eax
               xor     ebx, ebx
            .while (ecx)
                  mov     dl, byte ptr szBuff[eax]
               .if dl == 0ah
                     mov     byte ptr Ctrls.lpCaption[ebx], '\'
                     mov     byte ptr Ctrls.lpCaption[ebx+1], 'n'
                     inc     ebx
               .elseif dl == '"'
                     mov     byte ptr Ctrls.lpCaption[ebx], '"'
                     mov     byte ptr Ctrls.lpCaption[ebx+1], '"'
                     inc     ebx
               .else
                     mov     byte ptr Ctrls.lpCaption[ebx], dl
               .endif
                  inc     eax
                  inc     ebx
                  dec     ecx
            .endw
               mov     byte ptr Ctrls.lpCaption[ebx], 0


            .if SavClass > 82h && SavClass < 86h
                  mov     byte ptr Ctrls.lpCaption, 0
            .endif

;            .if (Ctrls.Style & SS_ETCHEDHORZ) && (Ctrls.Style & SS_ETCHEDVERT) ||\
;                (Ctrls.Style & SS_BLACKFRAME)

               mov     eax, Ctrls.Style
               mov     ebx, Ctrls.Style
               and     eax, 000000f0h
               and     ebx, 0000000fh

            .if SavClass == 82h
               .if ebx == SS_BLACKFRAME || eax == SS_GRAYFRAME || eax == SS_WHITEFRAME
                  mov     byte ptr Ctrls.lpCaption, 0
               .endif
            .endif

            .if (eax == 10h) && (ebx == 2)
                  mov     byte ptr Ctrls.lpCaption, 0
            .endif

            INVOKE     lstrcat, MemRsrc, addr Ctrls.lpCaption
            .if !BIOn
               INVOKE     lstrcat, MemRsrc, addr szQuote
            .endif
            INVOKE     lstrcat, MemRsrc, addr szComma
            .if Ctrls.ID != 0ffffh
               INVOKE     BaseAscii, Ctrls.ID, addr szWork, 1, 10, 1, 1, 0
               INVOKE     lstrcat, MemRsrc, addr szWork
            .else
               INVOKE     lstrcat, MemRsrc, addr szMinus1
            .endif

            INVOKE     lstrcat, MemRsrc, addr szComma
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr Ctrls.Class
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szComma
            INVOKE     lstrcat, MemRsrc, addr sz0x
            INVOKE     BaseAscii, Ctrls.Style, addr szWork, 8, 16, 1, 1, 1
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szComma
               and     Len, 0
               mov     Cnt, 4
            .while (Cnt)
                  mov     ecx, Len
               INVOKE     BaseAscii, Ctrls.Left[ecx*4], addr szWork, 1, 10, 1, 1, 0
               INVOKE     lstrcat, MemRsrc, addr szWork
               INVOKE     lstrcat, MemRsrc, addr szComma
                  inc     Len
                  dec     Cnt
            .endw
            INVOKE     lstrcat, MemRsrc, addr sz0x
            INVOKE     BaseAscii, Ctrls.ExStyle, addr szWork, 8, 16, 1, 1, 1
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               pop     ecx
.if DlgVer == 0ffffh
               add     ecx, 2
.endif
               dec     CtrlCnt
         .endw
         INVOKE     lstrcat, MemRsrc, addr szEnd
;            dec     CntID
;            add     OffPosID, 104
;;      .endw

      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcDialog ENDP

;=======================================
; Extract String Resources
;=======================================
RsrcString PROC  uses ebx esi edi
LOCAL    CntID:DWORD, StringID
LOCAL    szWork[1024]:BYTE, szStringID[32]:BYTE

mov     eax, 7dh
shl     eax, 4
add     eax, 1
;DSPValue hWnd, eax, 1, 'm'
         mov     esi, RsrcInfo                            ; Resource array
         mov     ebx, OffPosID

         mov     ecx, dword ptr[esi+ebx+4]
         dec     ecx
         mov     StringID, ecx
;DSPValue hWnd, StringID, 1, 'm'

         and     CntID, 0
      INVOKE     lstrcat, MemRsrc, addr szSTRING
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      .while (RsrcSize)
            xor     ecx, ecx
            mov     ebx, SavAddr
            mov     cx, word ptr[ebx]
         .if cx
               add     ebx, 2
               add     SavAddr, 2
               sub     RsrcSize, 2
               lea     edi, szWork
            .while (ecx)
                  mov     ax, word ptr[ebx]
                  mov     byte ptr[edi], al

               .if al == 0ah
                     mov     byte ptr[edi], '\'
                     mov     byte ptr[edi+1], 'n'
                     inc     edi
               .elseif al == 0dh
                     dec     edi
               .endif

                  add     ebx, 2
                  add     SavAddr, 2
                  sub     RsrcSize, 2
                  inc     edi
                  dec     ecx
            .endw
               mov     byte ptr[edi], 0
               mov     ecx, StringID
               shl     ecx, 4
               add     ecx, CntID
            INVOKE     wsprintf, addr szStringID, addr fmat2, ecx
            INVOKE     lstrcpyn, addr szBuff, addr szFill, 5
            INVOKE     lstrcat, MemRsrc, addr szBuff
            INVOKE     lstrcat, MemRsrc, addr szStringID
            INVOKE     lstrlen, addr szStringID
               mov     ecx, 10
            .if eax > 10
                  mov     eax, 10
            .endif
               sub     ecx, eax
            INVOKE     lstrcpyn, addr szBuff, addr szFill, ecx
            INVOKE     lstrcat, MemRsrc, addr szBuff
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szWork
            INVOKE     lstrcat, MemRsrc, addr szQuote
            INVOKE     lstrcat, MemRsrc, addr szCRLF
               inc     CntID

               inc     NumofItems
            INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
            INVOKE     UpdateWindow, hDlg3

         .else
               inc     CntID
               add     SavAddr, 2
               sub     RsrcSize, 2
         .endif
      .endw
      INVOKE     lstrcat, MemRsrc, addr szEND01
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcString ENDP

;=======================================
; Extract Accelerator Resources
;=======================================
RsrcAccelerator PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, Len, CntID
LOCAL    szWork[64]:BYTE

         mov     esi, RsrcInfo                            ; Resource array
         mov     ebx, OffPosID
         mov     eax, dword ptr[esi+ebx+4]

      .if eax != 6969
         INVOKE     wsprintf, addr szWork, addr fmat2, eax
      .else
            mov     ecx, RsrcInfo
            add     ecx, OffPosID
            add     ecx, 40
         INVOKE     lstrcpy, addr szWork, ecx
      .endif

      INVOKE     lstrcat, MemRsrc, addr szWork
      INVOKE     lstrcat, MemRsrc, addr szACCEL
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      .while (RsrcSize)
         INVOKE     lstrcpyn, addr szWork, addr szFill, 5
            xor     eax, eax
            xor     ecx, ecx
            mov     ebx, SavAddr
            mov     ax, word ptr[ebx+2]

         .if ax > 0 && ax < 1bh && word ptr[ebx] == 2 ||\
             ax > 0 && ax < 1bh && word ptr[ebx] == 82h ||\
             ax > 0 && ax < 1bh && word ptr[ebx] == 0 ||\
             ax > 0 && ax < 1bh && word ptr[ebx] == 80h

               add     ax, 40h
               inc     ecx
               mov     byte ptr szWork+5, '^'
         .endif

           push     eax
            xor     eax, eax
            xor     edx, edx
            mov     ax, word ptr[ebx]
            mov     ebx, 2
            div     ebx
            pop     eax

         .if ax >= '0' && ax <= '9' || ax >= 'A' && ax <= 'Z' ||\
             ax >= 21h && ax <= 2fh && !dl || ax >= 3ah && ax <= 40h && !dl ||\
             ax >= 5bh && ax <= 60h && !dl || ax >= 7bh && ax <= 7eh && !dl
               mov     byte ptr szWork+4, '"'
               mov     byte ptr szWork[ecx+5], al
               mov     byte ptr szWork[ecx+6], '"'
               mov     byte ptr szWork[ecx+7], 0

;---------- [NOTE! Some virtual keys may be missing] ----------
         .elseif ax >= VK_BACK && ax <= VK_HELP
               sub     eax, 8
               mov     ecx, VKaArray[eax*4]
            INVOKE     lstrcat, addr szWork, ecx
         .elseif ax >= VK_NUMPAD0 && ax <= VK_F12
               sub     eax, 60h
               mov     ecx, VKbArray[eax*4]
            INVOKE     lstrcat, addr szWork, ecx
         .elseif ax >= VK_NUMLOCK && ax <= VK_SCROLL
               sub     eax, 90h
               mov     ecx, VKcArray[eax*4]
            INVOKE     lstrcat, addr szWork, ecx
         .else
            INVOKE     lstrcat, addr szWork, addr szNeed
         .endif
         INVOKE     lstrcat, addr szWork, addr szComma
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrlen, addr szWork
            mov     ecx, 18
         .if eax > 18
               mov     eax, 18
         .endif
            sub     ecx, eax
         INVOKE     lstrcpyn, addr szWork, addr szFill, ecx
         INVOKE     lstrcat, MemRsrc, addr szWork
            xor     eax, eax
            mov     ebx, SavAddr
            mov     ax, word ptr[ebx+4]
         INVOKE     wsprintf, addr szWork, addr fmat2, eax
            xor     eax, eax
            mov     ebx, SavAddr
            mov     ax, word ptr[ebx]
         .if ax == 0 || ax == 80h
         .else
            INVOKE     lstrcat, addr szWork, addr szComma
         .endif
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrlen, addr szWork
            mov     ecx, 10
         .if eax > 10
               mov     eax, 10
         .endif
            sub     ecx, eax
         INVOKE     lstrcpyn, addr szWork, addr szFill, ecx
         INVOKE     lstrcat, MemRsrc, addr szWork
            xor     eax, eax
            mov     ebx, SavAddr
            mov     ax, word ptr[ebx]
         .if ax >= 80h
               sub     ax, 80h
         .endif
           push     eax
            xor     edx, edx
            mov     ebx, 2
            div     ebx
;         .if ax != 2 && ax != 0 && ax != 12h
         .if edx
            INVOKE     lstrcat, MemRsrc, addr szVIRTKEY
         .endif
            pop     eax

;FVIRTKEY   equ 1h
;FNOINVERT  equ 2h
;FSHIFT     equ 4h
;FCONTROL   equ 8h
;FALT       equ 10h
;---------- [I did not check for all combinations] ----------
         .if ax == 0 || ax == 1
         .elseif ax == 2
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
         .elseif ax == 3
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
         .elseif ax == 4
            INVOKE     lstrcpy, addr szWork, addr szSHIFT4
         .elseif ax == 5
            INVOKE     lstrcpy, addr szWork, addr szSHIFT
         .elseif ax == 6
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 7
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 8
            INVOKE     lstrcpy, addr szWork, addr szCONTROL8
         .elseif ax == 9
            INVOKE     lstrcpy, addr szWork, addr szCONTROL
         .elseif ax == 0ah
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 0bh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 0ch
            INVOKE     lstrcpy, addr szWork, addr szSHIFT4
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 0dh
            INVOKE     lstrcpy, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 0eh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 0fh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 10h
            INVOKE     lstrcpy, addr szWork, addr szALT10
         .elseif ax == 11h
            INVOKE     lstrcpy, addr szWork, addr szALT
         .elseif ax == 12h
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szALT
         .elseif ax == 13h
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szALT
         .elseif ax == 14h
            INVOKE     lstrcpy, addr szWork, addr szALT10
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 15h
            INVOKE     lstrcpy, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 16h
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 17h
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
         .elseif ax == 18h
            INVOKE     lstrcpy, addr szWork, addr szALT10
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 19h
            INVOKE     lstrcpy, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1ah
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1bh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1ch
            INVOKE     lstrcat, addr szWork, addr szALT10
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1dh
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1eh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT2
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .elseif ax == 1fh
            INVOKE     lstrcpy, addr szWork, addr szNOINVERT
            INVOKE     lstrcat, addr szWork, addr szALT
            INVOKE     lstrcat, addr szWork, addr szSHIFT
            INVOKE     lstrcat, addr szWork, addr szCONTROL
         .else
;DSPValue hWnd, eax, 1, 'm'
            INVOKE     lstrcpy, addr szWork, addr szComma
            INVOKE     lstrcat, addr szWork, addr szNeed
         .endif
         INVOKE     lstrcat, MemRsrc, addr szWork
         INVOKE     lstrcat, MemRsrc, addr szCRLF
            mov     ebx, SavAddr
            mov     ax, word ptr[ebx]
         .if ax >= 80h
            .break
         .endif
            add     SavAddr, 8
            sub     RsrcSize, 8

            inc     NumofItems
         INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
         INVOKE     UpdateWindow, hDlg3

      .endw
      INVOKE     lstrcat, MemRsrc, addr szEND
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcAccelerator ENDP

;=======================================
; Extract Message Resources
;=======================================
RsrcMessage PROC  uses ebx esi edi
LOCAL    NumBlocks:DWORD, BlockOff, CntL, CntH, MessageAddr, NumMessages, MessageLen, Cnt1, MsgID
LOCAL    szWork[1024]:BYTE

         and     MessageLen, 0

;---------- [MESSAGE_RESOURCE_DATA structure] ----------
         mov     esi, SavAddr                                ; Resource address
         mov     ebx, BlockOff
       MOVmd     NumBlocks, dword ptr[esi]                   ; Number of message blocks
      .if NumBlocks
         INVOKE     lstrcat, MemRsrc, addr szMESSAGE
         INVOKE     lstrcat, MemRsrc, addr szCRLF
         INVOKE     lstrcat, MemRsrc, addr szBEGIN
         INVOKE     lstrcat, MemRsrc, addr szCRLF
      .else
            ret
      .endif
;DSPValue hWnd, NumBlocks, 1, 'm'
         mov     BlockOff, 4                                 ; Header size
      .while (NumBlocks)
            mov     esi, SavAddr                             ; Resource address
            mov     ebx, BlockOff                            ; Block offset
          MOVmd     CntL, dword ptr[esi+ebx]                 ; Start ID
          MOVmd     CntH, dword ptr[esi+ebx+4]               ; End ID
          MOVmd     MessageAddr, dword ptr[esi+ebx+8]        ; Offset to message address
            mov     eax, CntH
            sub     eax, CntL
            inc     eax
            mov     NumMessages, eax                         ; Number of messages in the message block
         .while (NumMessages)
               mov     esi, SavAddr                          ; Resource address
               mov     ebx, MessageAddr                      ; Offset to the message
            .if word ptr[esi+ebx] == 0
                  add     ebx, 2
                  mov     MessageAddr, ebx
            .endif
             MOVmw     MessageLen, word ptr[esi+ebx]         ; Message length
            .if word ptr[esi+ebx+2] == 1                     ; Unicode
               .break
            .endif

;---------- [Get the message ID] ----------
               mov     dword ptr szWork, '    '
               lea     ecx, szWork
               add     ecx, 3
            INVOKE     BaseAscii, CntL, ecx, 1, 10, 1, 1, 0
            INVOKE     lstrcat, addr szWork, addr szComma

;---------- [Insert fill characters] ----------
            INVOKE     lstrlen, addr szWork
              push     eax
               mov     ecx, 17
            .if eax > 17
                  mov     eax, 17
            .endif
               sub     ecx, eax
               pop     ebx
            INVOKE     lstrcpyn, addr szWork[ebx], addr szFill, ecx
            INVOKE     lstrcat, addr szWork, addr szQuote
            INVOKE     lstrlen, addr szWork

;---------- [Get the message] ----------
               mov     esi, SavAddr                          ; Resource address
               add     esi, MessageAddr                      ; Offset to message address
               add     esi, 4
               lea     edi, szWork
               add     edi, eax                              ; Add first part of szWork
               mov     ecx, MessageLen
               sub     ecx, 4
            .while (ecx)
                  mov     al, byte ptr[esi]
                  mov     byte ptr[edi], al
               .if al == 0ah && ecx > 6
                     mov     byte ptr[edi], '\'
                     mov     byte ptr[edi+1], 'n'
                     inc     edi
               .elseif al == 0 || al == 0dh || al == 0ah && ecx < 6
                     dec     edi
               .endif
                  inc     esi
                  inc     edi
                  dec     ecx
            .endw
            .if byte ptr[edi-1] == 0ah
                  mov     byte ptr[edi-1], '\'
                  mov     byte ptr[edi], 'n'
                  inc     edi
            .endif
               mov     byte ptr[edi], 0                      ; Terminate szWork

            INVOKE     lstrcat, addr szWork, addr szQuote
            INVOKE     lstrcat, addr szWork, addr szCRLF
            INVOKE     lstrcat, MemRsrc, addr szWork

               inc     CntL
               mov     eax, MessageLen
               add     MessageAddr, eax
               dec     NumMessages
               inc     NumofItems
            INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
            INVOKE     UpdateWindow, hDlg3

         .endw
            add     BlockOff, 12
            dec     NumBlocks
      .endw
      INVOKE     lstrcat, MemRsrc, addr szEND
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcMessage ENDP

;=======================================
; Extract Version Resources
;=======================================
RsrcVersion PROC  uses ebx esi edi
LOCAL    Cnt:DWORD, Cnt1, TypeFile, Len, CntID, VarFileDone
LOCAL    szWork1[512]:BYTE, szWork2[64]:BYTE

         and     VarFileDone, 0
         and     SavOffset, 0
         mov     esi, SavAddr
         mov     ebx, 2
         mov     cx, word ptr[esi+2]                      ; Value len of VS_VERSIONINFO
      .while (cx)
         .if dword ptr[esi+ebx] == 0feef04bdh             ; Signature start of VS_FIXEDFILEINFO
               add     ebx, 4
               mov     SavOffset, ebx
            .break
         .endif
            inc     ebx
            dec     cx
      .endw
      .if !cx
; Do message
            ret
      .endif

;---------- [VS_FIXEDFILEINFO STRUCTURE] ----------

;---------- [Structure version] ----------
         xor     edx, edx
         mov     dx, word ptr[esi+ebx+2]
      INVOKE     BaseAscii, edx, addr szWork1, 1, 10, 1, 1, 0
         mov     dx, word ptr[esi+ebx]
      INVOKE     BaseAscii, edx, addr szWork2, 1, 10, 1, 1, 0
         add     SavOffset, 4
      INVOKE     lstrcat, MemRsrc, addr szWork1
;      INVOKE     lstrcat, MemRsrc, addr szComma
;      INVOKE     lstrcat, MemRsrc, addr szWork2
      INVOKE     lstrcat, MemRsrc, addr szVERINFO
      INVOKE     lstrcat, MemRsrc, addr szCRLF

;---------- [File & Product version] ----------
         mov     Cnt, 4
      .while (Cnt)
         .if Cnt == 4 
            INVOKE     lstrcat, MemRsrc, addr szVERFILE
         .elseif Cnt == 2
            INVOKE     lstrcat, MemRsrc, addr szVERPRODUCT
         .endif
            mov     esi, SavAddr
            mov     ebx, SavOffset
            xor     edx, edx
            mov     dx, word ptr[esi+ebx+2]
         INVOKE     BaseAscii, edx, addr szWork1, 1, 10, 1, 1, 0
            mov     dx, word ptr[esi+ebx]
         INVOKE     BaseAscii, edx, addr szWork2, 1, 10, 1, 1, 0
            add     SavOffset, 4
         INVOKE     lstrcat, MemRsrc, addr szWork1
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     lstrcat, MemRsrc, addr szWork2
         .if Cnt == 3 || Cnt == 1 
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .elseif Cnt == 4 || Cnt == 2
            INVOKE     lstrcat, MemRsrc, addr szComma
         .endif
            dec     Cnt
      .endw

;---------- [Rest of the VS_FIXEDFILEINFO structure (except the filedate)] ----------
         MOV     TypeFile, 2
         mov     Cnt, 5
      .while (Cnt)
            mov     esi, SavAddr
            mov     ebx, SavOffset
            mov     edx, dword ptr[esi+ebx]
         .if edx || !edx                                            ; Valid fields
            INVOKE     BaseAscii, edx, addr szWork1, 1, 16, 1, 1, 0
               mov     eax, TypeFile
               mov     ecx, VersionArray[eax*4]
            INVOKE     lstrcat, MemRsrc, ecx
            INVOKE     lstrcat, MemRsrc, addr sz0x
            INVOKE     lstrcat, MemRsrc, addr szWork1
            INVOKE     lstrcat, MemRsrc, addr szCRLF
         .endif
            add     SavOffset, 4
            inc     TypeFile
            dec     Cnt
      .endw

;---------- [FileDate version] ----------
         mov     esi, SavAddr
         mov     ebx, SavOffset
      .if dword ptr[esi+ebx] || dword ptr[esi+ebx+4]         ; Valid date fields
            mov     edx, dword ptr[esi+ebx]
         INVOKE     BaseAscii, edx, addr szWork1, 1, 10, 1, 1, 0
            mov     edx, dword ptr[esi+ebx+4]
         INVOKE     BaseAscii, edx, addr szWork2, 1, 10, 1, 1, 0
         INVOKE     lstrcat, MemRsrc, addr szFILEDATE
         INVOKE     lstrcat, MemRsrc, addr sz0x
         INVOKE     lstrcat, MemRsrc, addr szWork1
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     lstrcat, MemRsrc, addr sz0x
         INVOKE     lstrcat, MemRsrc, addr szWork2
         INVOKE     lstrcat, MemRsrc, addr szCRLF
      .endif
         add     SavOffset, 8
         inc     TypeFile

      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN01
      INVOKE     lstrcat, MemRsrc, addr szCRLF

         mov     esi, SavAddr
         mov     ebx, SavOffset
         mov     eax, dword ptr[esi+ebx]
         mov     Cnt, eax

         mov     ecx, SavAddr
         add     ecx, SavOffset
         add     ecx, 6
      INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 511, 0, 0
      INVOKE     lstrcmp, addr szWork1, addr szVarFileInfo
      .if !eax                                               ; VarFileInfo before StringFileInfo
            mov     VarFileDone, 1
           call     GetVarFileInfo
         INVOKE     lstrcat, MemRsrc, addr szCRLF
      .endif

         add     SavOffset, 6
         mov     ecx, SavAddr
         add     ecx, SavOffset
      INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 511, 0, 0
         shl     eax, 1
         add     SavOffset, eax

      INVOKE     lstrcat, MemRsrc, addr szBLOCK01
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szWork1
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN02
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBLOCK02

         mov     esi, SavAddr
         mov     ebx, SavOffset
         mov     eax, dword ptr[esi+ebx]
         mov     Cnt, eax
         add     SavOffset, 6
         mov     ecx, SavAddr
         add     ecx, SavOffset
      INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 511, 0, 0
         shl     eax, 1
         add     SavOffset, eax
         sub     Cnt, eax
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szWork1
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      INVOKE     lstrcat, MemRsrc, addr szBEGIN03
      INVOKE     lstrcat, MemRsrc, addr szCRLF

;---------- [Get the values for the StringFileInfo structure] ----------
      .while (Cnt)
         INVOKE     lstrcat, MemRsrc, addr szVALUE02

            mov     esi, SavAddr
            mov     ecx, SavOffset
            xor     eax, eax
            mov     ax, word ptr[esi+ecx]
            mov     Cnt1, eax
            sub     Cnt1, 6                                  ; String value lencth 

            add     SavOffset, 6
            sub     Cnt, 6
            mov     ecx, SavAddr
            add     ecx, SavOffset
         INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 511, 0, 0
            shl     eax, 1
            add     SavOffset, eax
            sub     Cnt, eax
            sub     Cnt1, eax
         INVOKE     lstrcat, MemRsrc, addr szWork1
         INVOKE     lstrcat, MemRsrc, addr szQuote

            mov     ecx, SavAddr
            add     ecx, SavOffset
         .if !word ptr[ecx]                                  ; Align 0n dword boundry
               add     ecx, 2
               add     SavOffset, 2
               sub     Cnt, 2
               sub     Cnt1, 2
         .endif
         .if !Cnt1 || Cnt1 > 0ffffh                          ; Reached the end of the value
               mov     byte ptr szWork1, 0
               jmp     EndValue
         .endif
         INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 511, 0, 0
            shl     eax, 1
            add     SavOffset, eax
            sub     Cnt, eax
            mov     ecx, SavAddr
            add     ecx, SavOffset
         .if !word ptr[ecx]                                  ; Align 0n dword boundry
               add     SavOffset, 2
               sub     Cnt, 2
         .endif

EndValue:
         INVOKE     lstrcat, MemRsrc, addr szComma
         INVOKE     lstrcat, MemRsrc, addr szSpace
         INVOKE     lstrcat, MemRsrc, addr szQuote
         INVOKE     lstrcat, MemRsrc, addr szWork1
         INVOKE     lstrcat, MemRsrc, addr szSlashB0
         INVOKE     lstrcat, MemRsrc, addr szQuote
         INVOKE     lstrcat, MemRsrc, addr szCRLF
         .if sdword ptr Cnt < 0                              ; Just in case the count went awry
               and     Cnt, 0
         .endif

            inc     NumofItems
         INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
         INVOKE     UpdateWindow, hDlg3

         .if Cnt < 7
            .break
         .endif
      .endw

;---------- [Start the VarFileInfo structure] ----------
      INVOKE     lstrcat, MemRsrc, addr szEND03
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      .if VarFileDone
         INVOKE     lstrcat, MemRsrc, addr szEND02
         INVOKE     lstrcat, MemRsrc, addr szCRLF
            jmp     Pass
      .endif
      INVOKE     lstrcat, MemRsrc, addr szEND02
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szCRLF
        call     GetVarFileInfo

Pass:
      INVOKE     lstrcat, MemRsrc, addr szEND01
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      INVOKE     SendMessage, hREdit, WM_SETTEXT, FALSE, MemRsrc

         ret
RsrcVersion ENDP

;===================================================
; VarFileInfo structure procedure
;===================================================
GetVarFileInfo PROC
LOCAL    szWork1[64]:BYTE, szWork2[64]:BYTE

         add     SavOffset, 6
         mov     ecx, SavAddr
         add     ecx, SavOffset
      INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 63, 0, 0
         shl     eax, 1
         add     SavOffset, eax

      INVOKE     lstrcat, MemRsrc, addr szBLOCK01
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szWork1
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szCRLF
      INVOKE     lstrcat, MemRsrc, addr szBEGIN02
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      INVOKE     lstrcat, MemRsrc, addr szVALUE01
         add     SavOffset, 6
         mov     ecx, SavAddr
         add     ecx, SavOffset
      .if !word ptr[ecx]                                     ; Align 0n dword boundry
            add     ecx, 2
            add     SavOffset, 2
      .endif
      INVOKE     WideCharToMultiByte, CP_ACP, 0, ecx, -1, addr szWork1, 63, 0, 0
         shl     eax, 1
         add     SavOffset, eax
      INVOKE     lstrcat, MemRsrc, addr szWork1
      INVOKE     lstrcat, MemRsrc, addr szQuote
      INVOKE     lstrcat, MemRsrc, addr szComma
      INVOKE     lstrcat, MemRsrc, addr szSpace

         mov     ecx, SavAddr
         add     ecx, SavOffset
      .if !word ptr[ecx]                                     ; Align 0n dword boundry
            add     ecx, 2
            add     SavOffset, 2
      .endif
         xor     edx, edx
         mov     esi, SavAddr
         mov     ebx, SavOffset
         mov     dx, word ptr[esi+ebx]
      INVOKE     BaseAscii, edx, addr szWork1, 4, 16, 1, 1, 0
         mov     dx, word ptr[esi+ebx+2]
      INVOKE     BaseAscii, edx, addr szWork2, 4, 16, 1, 1, 0
         add     SavOffset, 4
      INVOKE     lstrcat, MemRsrc, addr sz0x
      INVOKE     lstrcat, MemRsrc, addr szWork1
      INVOKE     lstrcat, MemRsrc, addr szSpace
      INVOKE     lstrcat, MemRsrc, addr sz0x
      INVOKE     lstrcat, MemRsrc, addr szWork2
      INVOKE     lstrcat, MemRsrc, addr szCRLF

      INVOKE     lstrcat, MemRsrc, addr szEND02
      INVOKE     lstrcat, MemRsrc, addr szCRLF

         inc     NumofItems
      INVOKE     SetDlgItemInt, hDlg3, 704, NumofItems, 0
      INVOKE     UpdateWindow, hDlg3

         ret
GetVarFileInfo ENDP

;===============================================================
; Load and Build the Image information PROCEDURE
;===============================================================
LoadImageFile PROC uses ebx esi edi
LOCAL    rect:RECT
LOCAL    hGlobal:DWORD, ipstm, TempDC
LOCAL    hDC:DWORD, xscreenpixels, yscreenpixels, hBR, OldBitmap
LOCAL    szWork[32]:BYTE 

;---------- [Release the picture if available] ----------
      .if ipPicture
            mov     eax, ipPicture
           push     eax
            mov     edx, dword ptr[eax]
           call     dword ptr[edx+8]          ; ipPicture->Release()
         INVOKE     DeleteObject, hBitmap
      .endif

;         mov     OpenOn, 1
         and     xPos, 0
         and     yPos, 0
      INVOKE     RedrawWindow, hREdit, 0, 0, RDW_INVALIDATE or RDW_ERASE

         and     ipPicture, 0

;---------- [Allocate Global memory for CreateStreamOnHGlobal] ----------
      INVOKE     GlobalAlloc, GMEM_MOVEABLE, RsrcSize
         mov     hGlobal, eax
      INVOKE     GlobalLock, hGlobal
         mov     pMem, eax

;---------- [Read the file into memory] ----------
         mov     esi, SavAddr
         mov     edi, pMem
         mov     ecx, RsrcSize
      .while (ecx)
            mov     al, byte ptr[esi]
            mov     byte ptr[edi], al
            inc     esi
            inc     edi
            dec     ecx
      .endw
;         mov     byte ptr[edi], 0

;---------- [Creates a stream object stored in global memory] ----------
         and     ipstm, 0
      INVOKE     CreateStreamOnHGlobal, hGlobal, TRUE, addr ipstm
      .if eax != 0 || !ipstm
         INVOKE     GlobalUnlock, hGlobal
         INVOKE     GlobalFree, hGlobal
            mov     eax, -1
            ret
      .endif

;---------- [Creates a new picture object and initializes it from the contents of a stream] ----------
      INVOKE     OleLoadPicture, ipstm, RsrcSize, 0, offset IID_IPicture, addr ipPicture
      .if eax != S_OK
            mov     eax, ipstm
           push     eax
            mov     edx, dword ptr[eax]
           call     dword ptr[edx+8]             ; ipstm->Release()
         INVOKE     GlobalUnlock, hGlobal
         INVOKE     GlobalFree, hGlobal
            mov     eax, -1
            ret
      .endif

;---------- [Unlock and Free the Gobal memory] ----------
      INVOKE     GlobalUnlock, hGlobal
      INVOKE     GlobalFree, hGlobal

;---------- [Release the stream] ----------
         mov     eax, ipstm
        push     eax
         mov     edx, dword ptr[eax]
        call     dword ptr[edx+8]                ; ipstm->Release()

;---------- [Get number of pixels per logical inch, x & y] ----------
      INVOKE     GetDC, hREdit
         mov     hDC, eax
      INVOKE     GetDeviceCaps, hDC, LOGPIXELSX
         mov     xscreenpixels, eax
      INVOKE     GetDeviceCaps, hDC, LOGPIXELSY
         mov     yscreenpixels, eax
      INVOKE     ReleaseDC, hREdit, hDC

;PICTYPE_UNINITIALIZED = -1,
;PICTYPE_NONE = 0,
;PICTYPE_BITMAP = 1,
;PICTYPE_METAFILE = 2,
;PICTYPE_ICON = 3
;PICTYPE_ENHMETAFILE = 4

;---------- [Get the Picture type] ----------
         lea     eax, TypePict
        push     eax
        push     ipPicture
         mov     edx, ipPicture
         mov     ecx, dword ptr[edx]
        call     dword ptr[ecx+20]               ; ipPicture->get_Type()

;---------- [Get the image METRIC units for the width and height] ----------
         lea     eax, mWidth
        push     eax
        push     ipPicture
         mov     edx, ipPicture
         mov     ecx, dword ptr[edx]
        call     dword ptr[ecx+24]               ; ipPicture->get_Width()

         lea     eax, mHeight
        push     eax
        push     ipPicture
         mov     edx, ipPicture
         mov     ecx, dword ptr[edx]
        call     dword ptr[ecx+28]               ; ipPicture->get_Height()

;---------- [Convert the METRIC units to pixels] ----------
         mov     eax, mWidth
         mul     xscreenpixels 
         mov     ecx, 2540
         div     ecx
         mov     pWidth, eax
         mov     eax, mHeight
         mul     yscreenpixels 
         mov     ecx, 2540
         div     ecx
         mov     pHeight, eax
         mov     eax, mHeight
         neg     eax
         mov     negmHeight, eax                 ; Convert the mHeight to negative

;---------- [Create a Compatible Bitmap to render the picture] ----------
      INVOKE     GetDC, hREdit
         mov     hDC, eax
      INVOKE     CreateCompatibleDC, hDC
      .if !eax
            ret
      .endif
         mov     TempDC, eax
      INVOKE     CreateCompatibleBitmap, hDC, pWidth, pHeight
      .if !eax
         INVOKE     DeleteDC, TempDC
            ret
      .endif
         mov     hBitmap, eax
      INVOKE     SelectObject, TempDC, hBitmap
      .if !eax
         INVOKE     DeleteDC, TempDC
            ret
      .endif
         mov     OldBitmap, eax

;---------- [Paint the background for transparent pictures] ----------
      INVOKE     GetClientRect, hREdit, addr rect
       MOVmd     rect.right, pWidth
       MOVmd     rect.bottom, pHeight
      INVOKE     CreateSolidBrush, 00ffffffh ;TransBG
         mov     hBR, eax
      INVOKE     FillRect, TempDC, addr rect, eax
      INVOKE     DeleteObject, hBR

; (IPicture)pPicture::Render(hdc, x, y, cx, cy, xpos_himetric, ypos_himetric,
;                            xsize_himetric, ysize_himetric, *rectBounds)

;---------- [Render the picture] ----------
         lea     eax, rect
        push     eax                             ; Pointer to a rectangle
        push     negmHeight                      ; Image negative Height (METRIC units)
        push     mWidth                          ; Image width (METRIC units)
        push     mHeight                         ; Image height (METRIC units)
        push     0                               ; 
        push     pHeight                         ; Vertical dimension of destination rectangle
        push     pWidth                          ; Horizontal dimension of destination rectangle
        push     0                               ; Vertical coordinate in hdc at which to place the image
        push     0                               ; Horizontal coordinate in hdc at which to place the image
        push     TempDC                          ; hDC
        push     ipPicture                       ; IPicture interface pointer
         mov     eax, ipPicture
         mov     edx, dword ptr[eax]
        call     dword ptr[edx+32]               ; ipPicture->Render()

      .if sdword ptr eax < 0
            mov     eax, -1
      .endif
        push     eax
      INVOKE     SelectObject, TempDC, OldBitmap
      INVOKE     DeleteDC, TempDC
      INVOKE     ReleaseDC, hREdit, hDC
         pop     eax

      .if eax == -1 && ipPicture
            mov     eax, ipPicture
           push     eax
            mov     edx, dword ptr[eax]
           call     dword ptr[edx+8]             ; ipPicture->Release()
         INVOKE     DeleteObject, hBitmap
      .endif

         ret
LoadImageFile ENDP

         END
