Announcement

Collapse
No announcement yet.

Resource question

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

  • Resource question

    When using a resource$ it appears that it always retrieves resources from the EXE even when used from a DLL. This appears to be contrary to what the docs indicate. Has anyone gotten the built in stuff to work?

    Here's a sample.

    Test.bas
    Code:
    #Compile Exe
    #Dim All
     
    #Resource RcData 201, "test.txt"
    Declare Sub Test Lib "TestDLL.dll" Alias "Test"( value As String )
     
    Function PBMain () As Long
      Local value As String
     
      value = Resource$( RcData, 201 )
      ? "From exe:" + $CrLf + value
     
      Test value
     
      ? "From dll: " + $CrLf + value
    End Function

    Testdll.bas
    Code:
    #Compile DLL
    #Dim All
     
    #Include Once "Win32API.inc"
     
    #Resource RcData 101, "test.txt"
     
    Global ghInstance As Dword
     
    Function LibMain (ByVal hInstance   As Long, _
                      ByVal fwdReason   As Long, _
                      ByVal lpvReserved As Long) As Long
     
      Select Case fwdReason
     
        Case %DLL_PROCESS_ATTACH
          ghInstance = hInstance
          Function = 1   'success!
     
        Case %DLL_PROCESS_DETACH
          Function = 1   'success!
     
        Case %DLL_THREAD_ATTACH
          Function = 1   'success!
     
        Case %DLL_THREAD_DETACH
          Function = 1   'success!
      End Select
    End Function
     
    Sub Test Alias "Test"( value As String ) Export
      ' This retrieves nothing
      value = Resource$( RcData, 101 )
     
      ' This retrieves the RCDATA from the EXE
      value = Resource$( RcData, 201 )
     
      ' This seems to work, is this the only way?
      Local hModule, hRes, hMem As Dword
      Local lpResource As StringZ Ptr
      Local sz As Long
     
      hModule = ghInstance
      hRes = FindResource( hModule, ByVal MAKEINTRESOURCE(101), ByVal MAKEINTRESOURCE(10) )
      hMem = LoadResource( hModule, hRes)
      lpResource = LockResource( hMem )
      sz = SizeofResource( ghInstance, hRes )
     
      value = Left$( @lpResource, sz )
    End Sub
    LarryC
    Website
    Sometimes life's a dream, sometimes it's a scream

  • #2
    For this...
    Code:
    #RESOURCE RCDATA 101, "test.txt"
    rsrc$ = RESOURCE$(RCDATA, 101)
    The compilation basically boils down to the following, with hard-coded hModule=NULL for all resource API calls so yep she's always going to dig from the EXE not DLL
    Code:
    PUSH EAX                                         ;|lpName
    PUSH 0                                           ;|hModule = NULL
    CALL DWORD PTR DS:[<&KERNEL32.FindResourceA>]    ;\KERNEL32.FindResourceA
    TEST EAX,EAX
    JE SHORT 00201F95
    MOV EDI,EAX
    PUSH EAX                                         ;/hResource
    PUSH 0                                           ;|hModule = NULL
    CALL DWORD PTR DS:[<&KERNEL32.LoadResource>]     ;\KERNEL32.LoadResource
    TEST EAX,EAX
    JE SHORT 00201F95
    PUSH EAX                                         ;/hResource
    CALL DWORD PTR DS:[<&KERNEL32.LockResource>]     ;\kernel32.LockResource
    TEST EAX,EAX
    JE SHORT 00201F95
    MOV ESI,EAX
    PUSH EDI                                         ;/hResource
    PUSH 0                                           ;|hModule = NULL
    CALL DWORD PTR DS:[<&KERNEL32.SizeofResource>]   ;\KERNEL32.SizeofResource
    There's not really any room for practical patching either with push 0 being just two bytes so your manual implementation as shown in your Test() routine above seems to be the best way to go, and appears to hold true to the original
    Last edited by Wayne Diamond; 20 Apr 2015, 06:32 PM.
    -

    Comment


    • #3
      Hey Wayne!

      MCM wrote in that his experience in using the gbPrint code, compiled as a DLL, allowed him to use "... the ICON and other resources compiled into that DLL."

      Additional comments from MCM:

      I think the disassembly was done on an EXE (stated source not shown); I would be willing to be real money a disassembly of the same code compiled into a DLL would show what is pushed onto the stack for the 'hmodule' parameter is the same as the first parameter passed to the entry point function (instance handle).

      This would result in a rule...

      "RESOURCE statements always refer to the resource type and identkfier compiled into the current code module, not that of the image file used to create the current process [the EXE]."

      .. which is consistent with my experience with the 'gbPrint' library.

      The result in the example provided (Post #1) might be explained with either..,

      Different version of compiler (I used 10.0.3) Different wide/ansi string settings (I used Wide for the DLL, ANSI for the calling EXE) Resources used for "DDT" statements are not handled the same as other resources by the compiler.

      Here is the start of the module I compiled...

      Code:
      #COMPILE DLL "GBPPV3.DLL"
      #DEBUG ERROR ON
      #DIM ALL
      #TOOLS OFF
      #COMPILER PBWIN 10
      
      
      %UNICODE =1    ' this code uses that.
      #INCLUDE "WIN32API.INC"
      
      ' if we are going to do a resource, let's do everything shall we?
      
      #IF NOT %PB_EXE       ' not EXE means DLL or SLL (waiting on my NFS regarding this ambiguity!)
      ' this really needs to be NOT EXE and NOT DLL  you know?
      
      #RESOURCE ICON ppprint, "ppprint.ico"
      #RESOURCE ICON ppleft, "ppleft.ico"
      #RESOURCE ICON ppright, "ppright.ico"
      #RESOURCE ICON pprefresh, "pprefresh.ico"
      #RESOURCE ICON ppprops, "ppprops.ico"
      #RESOURCE ICON ppmargin, "ppmargin.ico"
      ' added by mcm 10/15/13
      #RESOURCE ICON ppsavefile, "ppsavefile.ico"
      ' tsi artwork must be in this module for use w GRAPHIC/XPRINT RENDER stmt. *YUCK! nless I can live with that, which I think ' I can #RESOURCE BITMAP pplogo, "D:\Tal Systems\Corporate\Artwork\Tal_LG_90x45.bmp"
      
      
      ' added MCM
      #RESOURCE VERSIONINFO
      '#define VFT_APP                 0x00000001L
      '#define VFT_DLL                 0x00000002L
          ' %VFT_APP =  1&
          ' %VFT_DLL =  2&
           #RESOURCE FILEFLAGS       2&
           #RESOURCE FILEVERSION 1&, 2&, 1, 1
           #RESOURCE PRODUCTVERSION 1, 3, 1,0
      
           #RESOURCE STRINGINFO "0409", "04B0"   ' US English, Unicode BEST GUESS HELP DEVOID OF GUIDANCE
           #RESOURCE VERSION$ "CompanyName",      "Tal Systems Inc Racine WI."
      
           #RESOURCE VERSION$ "FileDescription",  "Print Preview Library"
           #RESOURCE VERSION$ "FileVersion",      "1.2.1.2"
      
           #RESOURCE VERSION$ "InternalName",     "gbprintpreview"
           #RESOURCE VERSION$ "LegalCopyright",   "2013 Michael C. Mattias Racine WI USA"
           #RESOURCE VERSION$ "LegalTrademarks",  "None"
           #RESOURCE VERSION$ "Comments",          "Library Courtesy Gary Beene Dallas TX USA"
      
           #RESOURCE VERSION$ "OriginalFilename", "gbppv3"
      
           #RESOURCE VERSION$ "PrivateBuild",     "For Tal Systems Inc."
      
           #RESOURCE VERSION$ "ProductName",      "File Too Big Utility"
      
           #RESOURCE VERSION$ "ProductVersion",   "1.3.1.0" '
      
      #ENDIF  ' end resource stmts added only when compiling to DLL.
      
      ' END VERSIONINFO #RESOURCE
      ' end added version 1.1
      All the screens in the library had all their icons. All the specific version info this module was shown on "properties" screen thru Windows' Explorer. None of the ICON or BITMAP resources were included in the resources of the using EXE file.

      Regardless, the disassembly should be performed for the same code compiled to both an EXE and to a DLL. I would think #RESOURCE statements when #COMPILE SLL is in effect should be a compile-time error, as resources for a code library make no common sense.


      Michael C. Mattias
      Tal Systems Inc.
      Racine WI
      [email protected]

      Comment


      • #4
        Didn't want to make a mistake so re-tested to ensure I was looking at a #COMPILE DLL, but yes I was, you can see the hard-coded NULLs for every reference of hModule in the DLL code -


        (the above is basically just "#RESOURCE RCDATA 101, "x.ico"", with "rsrc$ = RESOURCE$(RCDATA, 101)" in LIBMAIN, the target of the disasm)

        More than happy to re-look at it if MCM has a suggestion but it's not looking promising unforch

        ps. I havent done any SLL testing

        psps. could you hit me up with a ZIP of MCMs demo above? cheers

        pspsps.
        I would be willing to bet real money a disassembly of the same code compiled into a DLL
        Any idea how much he was offering?
        Last edited by Wayne Diamond; 28 Apr 2015, 04:56 PM.
        -

        Comment


        • #5
          If I have a Resource in the DLL, then a function in the DLL can access it.

          But, the EXE cannot access the DLL resource directly with Resource$. Instead, a procedure in the DLL must access the DLL Resource and pass it via an exported procedure.

          At least, that's what this test suggests:

          DLL Code:
          Code:
          #Compile DLL
          #Resource String, 200, "FromDLL"
          Function GetLarry Alias "GetLarry"() Export As String
             Function = Resource$(String,200)
          End Function
          EXE Code:
          Code:
          #Compile Exe
          #Resource String, 200, "FromEXE"
          Declare Function GetLarry Lib "dll.dll" Alias "GetLarry"() As String
          
          Function PBMain () As Long
             ? GetLarry                   'gets DLL resource
             ? Resource$(String,200)      'gets EXE resource
          End Function
          In the example above, I even used the same ID for the two resources. But without a #Resource statement in the EXE, the Resource$ statement returns nothing, which says that the EXE cannot access the DLL resource directly using Resource$.

          I don't know how the SDK community does it in general. Does the same limitation apply?
          Last edited by Gary Beene; 28 Apr 2015, 05:01 PM.

          Comment


          • #6
            Yep the resource code for both the EXE and DLL are virtually identical.

            I don't know how the SDK community does it in general. Does the same limitation apply?
            Simple - Larry's four-API demo above is a spot on replication of RESOURCE$ but hModule-friendly so id just use that ie...
            Code:
              hModule = ghInstance
              hRes = FindResource( hModule, ByVal MAKEINTRESOURCE(101), ByVal MAKEINTRESOURCE(10) )
              hMem = LoadResource( hModule, hRes)
              lpResource = LockResource( hMem )
              sz = SizeofResource( ghInstance, hRes )
              value = Left$( @lpResource, sz )
            -

            Comment


            • #7
              ?? I thought Larry said his code did not work? Did I mis-understand his post?

              Comment


              • #8
                Larry's comment immediately before that snippet in his OP:
                ' This seems to work, is this the only way?
                -

                Comment


                • #9
                  Wasn't explicitly stated, but I think what people are saying is many (possibly all but RCData) resources work fine from a DLL. RCData does not using Resource$.

                  I think it got a little confusing when people were talking about two different things in different contexts and agreeing with each other

                  TestExe.bas
                  Code:
                  #Compile Exe "TestExe.exe"
                  #Dim All
                   #Resource String, 101, "From EXE"
                  #Resource RcData, 102, "fromexe.txt"
                   Declare Function DLLStringString Lib "TestDll.dll" Alias "DLLStringString" () As String
                  Declare Function DLLRcDataString Lib "TestDll.dll" Alias "DLLRcDataString" () As String
                   Function PBMain () As Long
                    Local exeString, exeRcData As String
                    Local dllString, dllRcData As String
                     exeString = Resource$( String, 101 )
                    exeRcData = Resource$( RcData, 102 )
                     dllString = DllStringString()
                    dllRcData = DLLRcDataString()
                     Local msg As String
                    msg = Build$( exeString, $CrLf, exeRcData, $CrLf, "----------------------------", $CrLf, dllString, $CrLf, dllRcData)
                    ? msg
                  End Function
                  Testdll.bas
                  Code:
                  #Compile DLL "TestDll.dll"
                  #Dim All
                   #Include "win32api.inc"
                   #Resource String, 101, "FromDLL"
                  #Resource RcData, 102, "fromdll.txt"
                   Global ghInstance As Dword
                   Function LibMain (ByVal hInstance   As Long, _
                                    ByVal fwdReason   As Long, _
                                    ByVal lpvReserved As Long) As Long
                    Select Case fwdReason
                      Case %DLL_PROCESS_ATTACH
                        ghInstance = hInstance
                        Function = 1   'success!
                    End Select
                  End Function
                   Function DLLStringString Alias "DLLStringString" () Export As String
                    Function = Resource$( String, 101 )
                  End Function
                   Function DLLRcDataString Alias "DLLRcDataString" () Export As String
                    Function = Resource$( RcData, 102 )
                  End Function
                  fromexe.txt
                  Code:
                  From exe
                  fromdll.txt
                  Code:
                  From dll
                  Edit:

                  Short summary (I think)
                  • All #Resource statements are stored in a DLL.
                  • RcData resources are not retrievable using Resource$, api code I posted is apparently close to what PB does, just with a module reference.
                  • Several other PB methods of retrieving resources work fine from a dll.
                  Last edited by Larry Charlton; 29 Apr 2015, 03:38 AM.
                  LarryC
                  Website
                  Sometimes life's a dream, sometimes it's a scream

                  Comment

                  Working...
                  X