Announcement

Collapse
No announcement yet.

Extract files from VB6 .FRX (Discussion)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Extract files from VB6 .FRX (Discussion)

    Note that this a discussion thread for Wayne Diamond's
    Extract files from VB6 .FRX in the Source Code forum.


    I suspect that the dwUnknown1 is the number of bytes to skip
    to get to the next item (or EOF)

    I.e. ItmSz-HdrSz-SizeofMe (or looking at it simply, sizeofObjet+8

    This seems consistent with you hex dump and from what I seem to
    (very vaguely) remember when I look at frx files years ago.

    Why MS needs/wants a separate field that can be simply calculated
    is unclear.

    Still no clue as to dwUnknown2.

    BTW, I hate Hungarian notation, but that is my failing.

    Mike
    Last edited by Mike Simmonds; 19 Nov 2014, 12:04 AM. Reason: Link back to the Source Code forum
    There are only two speeds for computers: fast enough, and too bloody slow.
    And there are 10 types of programmer -- those that know binary, and those that don't.

    #2
    Mike good catch re dwUnknown1! it seems so obvious now... it didn't this morning when i was writing it at 4am lol

    So perhaps dwUnknown1 is "dwTotalSize" (ie. headersize + datasize), allowing for a header that is > 12 bytes, which would mean I'm currently reading it slightly wrong (due to current assumption that header is always 12) ... but that's easy to accomodate for, I'll post an alternative version using that method later.

    As to dwUnknown2, perhaps its something like "dwFlags"... i'm running out of ideas as to what else it could be

    Anyway i've updated the hex dump gif, cheers!

    [EDIT] I've just updated the source code in the first post of the thread to accomodate for the newly-described dwTotalSize field (cheers Mike!), allowing for variable-size headers. This definitely seems the more correct way to read it, rather than assuming each header is 12 bytes, and also explains why an otherwise seemingly superfluous field exists.
    Last edited by Wayne Diamond; 18 Nov 2014, 02:25 PM.
    -

    Comment


      #3
      Hi Wayne,

      I had a trawl through some of my VB5 code wrt frx files.

      There is a fly in the ointment in the form of stored text.

      When you set the initial contents of a text box or pre-populate members
      of a drop down list VB stashes the strings in the frx in the [Pascal] format

      <length byte> <text-char> ... NB: No null is stored.
      No 12-byte header here!

      Also, in case you did'nt twig it, the "...frx:xxx" offsets in the frm files
      are in hex.

      Do you want me to zip and post sample showing text. I won't be able to
      post full source as well because these are company property, but I can
      show the frm textbox or combobox defs.

      From my (albeit brief) look all icons, bmps, jpgs, gifs? [and I suspect
      anything that has an equivalent documented API resource format]
      has the 00006C774 (in LE format) possibly as a resource tag. (dwUnk2)

      Cheers now, Mike
      There are only two speeds for computers: fast enough, and too bloody slow.
      And there are 10 types of programmer -- those that know binary, and those that don't.

      Comment


        #4
        Cheers Mike, another nice catch! I've dropped you a privmsg

        So I just did a couple quick experiments with adding pre-text, basically it now appears like this...

        To start reading the header, simply look at its first byte...
        00 = The size field is a DWORD, use bytes 1-4 to get the size
        FF = The size field is a WORD. Ignore this first FF byte, and use bytes 2 & 3 to get the size
        Else = The size field is a BYTE, and is simply the value of this 1st byte

        Anyway a bit more experimenting to do after i get some more sleep in, but the next code revision later today to add support for pretext etc should be pretty straightforward, and due to the 'headerless' nature of pretext it helps show the correct roads to go down when walking this beast ... ie answers your Q "Why MS needs/wants a separate field that can be simply calculated is unclear"
        -

        Comment


          #5
          Sample &quot;Real World&quot; Files

          Wayne,

          No need to PM, I removed anything proprietry. So just a zip
          with frx's and the VB form def/ref for the items.

          Mike
          Attached Files
          There are only two speeds for computers: fast enough, and too bloody slow.
          And there are 10 types of programmer -- those that know binary, and those that don't.

          Comment


            #6
            Cheers Mike! I'll have to add you to the credits after this eheh

            Its handy also to test VB5 compatibility... from memory it was very similar to VB6 so Im assuming there'll be virtually no difference. I searched last night for some VB5 source code on google hoping to find an FRX to test... but no luck. (I even checked piratebay for VB5, hah....... but no luck)

            btw, in regards to checking the 1st byte to determine if its a byte/word/dword... there's still a bit more to it than that!

            For example... if it were true that 00 as first byte = the field is a dword, then that would mean the largest possible value it can contain is 0xFFFFFF (16,777,215). So I created a new project, added a large BMP of size 0x1233E86 (19,086,982) ... the very first dword in the FRX file is 0x01233E8E (or 8E3E2301 as it appears in file) ... thus ruling out using 00 to determine that it's a dword.

            Hrmmmmm! ... more experimenting required

            ps. Cheers Gary for splitting the thread for me (gotta make ya earn your crust somehow)

            psps. Ok, just a brief look at the three VB5 FRX's... they do indeed seem compatible, likewise it's still just a matter of working out whether its a byte/word/dword...
            Last edited by Wayne Diamond; 18 Nov 2014, 10:19 PM.
            -

            Comment


              #7
              A thought:

              See if second dword from current filePos (initially 0) is the magic marker
              006C74 (in LE order) [Beware this may start at any byte pos not just
              4-tuples] Then dword (bytes) 0..3 = total, 4..7 = magic, 8..11 = ItmSz
              followed by item.
              This can't be a string because the length would be 74 hex and the first
              three chars would then be "l" (6C) followed bt two nulls.
              VB strings in code can have nulls, but rermember this is ordinary text
              in the form description part.

              Else check for a string sz = byte at 0, bytes 1..sz are 20..7F or 08, 0D, 0A
              [I make assumptions on string text characters].

              Else its some sort of listbox item values list (which are numeric).
              [Haven't worked that bit out yet.]

              BTW I often copied VB6 code from e.g vbAccelerator and apart from
              removing (I think) "[MTA=??? ]" or something like that from the form files
              and something else from project files, they ALL compiled in my VB5.

              Cheers, MIke
              There are only two speeds for computers: fast enough, and too bloody slow.
              And there are 10 types of programmer -- those that know binary, and those that don't.

              Comment


                #8
                I just PMed you with info re VB5 availability wink-wink. Mike
                There are only two speeds for computers: fast enough, and too bloody slow.
                And there are 10 types of programmer -- those that know binary, and those that don't.

                Comment


                  #9
                  hrmm... the Pretext and Combo/Listbox has me wondering if the .FRM file is actually also required to properly process the .FRX, in order for VB to know exactly what type of data it's looking at ... that's how it's looking at the moment (I just can't see any way otherwise for VB to distinguish between a picture and say a chunk of text)
                  ... eg. lines like this: Text = "Form1.frx":0000

                  So far i've found Text, Icon, MouseIcon, DragIcon, ItemData, List, Palette, Picture, DisabledPicture, DownPicture ... pretty sure that's all common controls covered, and comprising just 5 different data types... Icon/MouseIcon/DragIcon ... List/ItemData... Palette... Picture/DisabledPicture/DownPicture... Text. Actually, Icons and Pictures im pretty sure are the same structure, ie with 12 byte header etc ... and as Palette is a bitmap image its probably safe to throw that into the mix too, leaving us with just 3 datatypes ... Binary, List, Text. (Perhaps then using header and content analysis we can make a rough determination as to which datatype it is even if the FRM isnt available, just the FRX)

                  So if that's the case, no big drama... I mean I guess if somebody has a .FRX file they want to extract files from then more than likely theyve also got the .FRM with it, so I could modify it so it uses both FRM and FRX ... and perhaps if only the FRX is available - no FRM - then drop back to a previous method, such as assuming 12-byte headers, etc
                  Last edited by Wayne Diamond; 19 Nov 2014, 03:12 AM.
                  -

                  Comment


                    #10
                    LIST is done... (well, there's an unknown Word variable but its no biggie, it can seemingly just be ignored)
                    Its a Word-oriented structure. Here is the FRX of a Listbox with two list items "OneXX6" and "TwoXXX7". When you create a List, the associated ItemData list array is also filled, and they're both of the same structure.


                    In the image you can see the ItemData starting at 0x0000, and the List starting at 0x000A (the byte immediately after the second "0").

                    0000: ItemData ...
                    0200 = Number of list items
                    0300 = wUnknown
                    0100 = Length of next item (1)
                    30 = Data of next item ("0")
                    0100 = Length of next item (1)
                    30 = Data of next item ("0")
                    000A: List ...
                    0200 = Number of list items
                    0700 = wUnknown
                    0600 = Length of next item (6)
                    4F6E65585836 = Data of next item ("OneXX6")
                    0700 = Length of next item (7)
                    54776F58585837 = Data of next item ("TwoXXX7")
                    (EOF)


                    Code:
                    #COMPILE EXE
                    
                    SUB DumpFRXList(sFRXFile AS STRING, BYVAL dwOffset AS DWORD)  '// dwOffset is as it appears in the FRM file, ie "0000" for first byte of file.
                    LOCAL hFile AS DWORD, sBuf AS STRING, wPtr AS WORD PTR, sTmp AS STRING, dwCnt AS DWORD, i AS LONG
                    hFile = FREEFILE
                    OPEN sFRXFile FOR BINARY ACCESS READ LOCK SHARED AS #hFile BASE = 0
                     SEEK #hFile, dwOffset
                     GET$ #hFile, LOF(hFile), sBuf
                    CLOSE #hFile
                    wPtr = STRPTR(sBuf)
                    dwCnt = @wPtr
                    STDOUT "Total ListItems = " & FORMAT$(dwCnt)
                    wPtr = wPtr + 2
                    STDOUT "wUnknown = 0x" & HEX$(@wPtr,4)
                    wPtr = wPtr + 2
                    FOR i = 1 TO dwCnt
                        STDOUT " Item #" & FORMAT$(i) & ": Len=" & FORMAT$(@wPtr);
                        sTmp = MID$(sBuf, wPtr - STRPTR(sBuf) + 3, @wPtr)
                        STDOUT " Txt=" & sTmp
                        wPtr = wPtr + @wPtr + 2
                    NEXT i
                    END SUB
                    
                    FUNCTION PBMAIN () AS LONG
                    DumpFRXList "e:\dev\vb98\temp\frx\1list\2.frx", &h0000   '// ItemData    The offset is the same as referenced in the FRM file
                    DumpFRXList "e:\dev\vb98\temp\frx\1list\2.frx", &h000A   '// List
                    STDOUT "Done": WAITKEY$
                    END FUNCTION
                    Sample Output:
                    Total ListItems = 2
                    wUnknown = 0x0003
                    Item #1: Len=1 Txt=0
                    Item #2: Len=1 Txt=0
                    Total ListItems = 2
                    wUnknown = 0x0007
                    Item #1: Len=6 Txt=OneXX6
                    Item #2: Len=7 Txt=TwoXXX7
                    Last edited by Wayne Diamond; 19 Nov 2014, 05:59 AM.
                    -

                    Comment


                      #11
                      Wanye, VB5 sample for you.

                      NOTE This is NOT intended to be run as exe. Very Old 98 stuff!

                      I had an app for a customer that added itself to
                      the HKLM Run list so they wouldn't have to launch
                      manually after a re-boot/crash.

                      For debugging, this was a pain. This removes the
                      entry from the startup list.

                      Mike
                      Attached Files
                      There are only two speeds for computers: fast enough, and too bloody slow.
                      And there are 10 types of programmer -- those that know binary, and those that don't.

                      Comment


                        #12
                        I've done some web search, not sure if this is of any help to you in regards to decoding the .frx format. Might be nonetheless worth a look: http://btmtz.mvps.org/gfxfromfrx/

                        That's a sample from Brad Martinez, whose name should ring a bell for any VB6 programmer.

                        Comment


                          #13
                          Ok, I think I'm done ...


                          All three VB datatypes (Text, List, Binary) are now fully supported, including smart detecting of binary datatype, so I think that's pretty much it.

                          Stan, enjoy!
                          -

                          Comment


                            #14
                            Originally posted by Wayne Diamond View Post
                            Ok, I think I'm done ...


                            All three VB datatypes (Text, List, Binary) are now fully supported, including smart detecting of binary datatype, so I think that's pretty much it.

                            Stan, enjoy!
                            OUTstanding! It works perfectly. It solves a major VB refugee problem because they don't have to risk losing any critical elements. This will certainly be a part of the Translator.

                            Still amazed at how quickly you solved a problem that has existed ever since MS announced the end of VB6. I followed the discussion between youself and Mike Simmons with much excitement. All I can say is

                            Outstanding work. Thank you.
                            Do not go quiet into that good night,
                            ... Rage, rage against the dark.

                            Comment


                              #15
                              Hows that translator coming along?
                              -

                              Comment


                                #16
                                Working on iteration #4. More details in PM. Should have something I can show in public in another week or two.
                                Do not go quiet into that good night,
                                ... Rage, rage against the dark.

                                Comment

                                Working...
                                X
                                😀
                                🥰
                                🤢
                                😎
                                😡
                                👍
                                👎