VB에서 EXE, DLL 등의 문자열, 이미지 리소스를 편집을 위한 예제 프로그램

Private Type BITMAP
  bmType As Long      ' this must be zero
  bmWidth As Long     ' bitmap width
  bmHeight As Long     ' bitmap height
  bmWidthBytes As Long   ' bytes in horiz raster line
  bmPlanes As Integer   ' number of color planes
  bmBitsPixel As Integer  ' number of bits per pixel
  bmBits As Long      ' address of pixel data in memory
End Type
Private Type StringTable
  id As Long
  Text As String
End Type
Private Const IMAGE_ARCHIVE_START_SIZE = 8
Private Const IMAGE_BITMAP = 0
Private Const LR_CREATEDIBSECTION = &H2000
' Predefined Resource Types
Private Const DIFFERENCE = 11
Private Const RT_ACCELERATOR = 9&
Private Const RT_ANICURSOR = (21)
Private Const RT_ANIICON = (22)
Private Const RT_BITMAP = 2&
Private Const RT_CURSOR = 1&
Private Const RT_DIALOG = 5&
Private Const RT_DLGINCLUDE = 17
Private Const RT_ICON = 3&
Private Const RT_FONT = 8&
Private Const RT_FONTDIR = 7&
Private Const RT_GROUP_CURSOR = (RT_CURSOR + DIFFERENCE)
Private Const RT_GROUP_ICON = (RT_ICON + DIFFERENCE)
Private Const RT_HTML = 23
Private Const RT_MENU = 4&
Private Const RT_MESSAGETABLE = 11
Private Const RT_PLUGPLAY = 19
Private Const RT_RCDATA = 10&
Private Const RT_STRING = 6&
Private Const RT_VERSION = 16
Private Const RT_MYOWN_TYPE1 = 10001
Private Const RT_MYOWN_TYPE2 = 10002
Private Const ENGLISH_US = 1033

Private Declare Function BeginUpdateResource Lib "kernel32" Alias "BeginUpdateResourceA" ( _
    ByVal pstrFileName As String, ByVal bDeleteExistingResources As Long) As Long
Private Declare Function UpdateResource Lib "kernel32" Alias "UpdateResourceA" ( _
    ByVal hUpdate As Long, ByVal lpType As Long, ByVal lpName As Long, _
    ByVal wLanguage As Integer, lpData As Any, ByVal cbData As Long) As Long
Private Declare Function EndUpdateResource Lib "kernel32" Alias "EndUpdateResourceA" ( _
    ByVal hUpdate As Long, ByVal fDiscard As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _
    ByVal lpLibstrFileName As String) As Long
Private Declare Function FindResourceEx Lib "kernel32" Alias "FindResourceExA" ( _
    ByVal hModule As Long, ByVal lpType As Long, ByVal lpName As Long, _
    ByVal wLanguage As Long) As Long
Private Declare Function LoadResource Lib "kernel32" ( _
    ByVal hInstance As Long, ByVal hResourceInfo As Long) As Long
Private Declare Function LockResource Lib "kernel32" ( _
    ByVal hResourceData As Long) As Long
Private Declare Function SizeofResource Lib "kernel32" ( _
    ByVal hInstance As Long, ByVal hResourceInfo As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
    ByVal hLibModule As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal Length As Long)
'//APIs to display Bitmap from Resource
Private Declare Function BitBlt Lib "gdi32.dll" ( _
    ByVal hDestDC As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long, _
    ByVal hSrcDC As Long, _
    ByVal xSrc As Long, _
    ByVal ySrc As Long, _
    ByVal dwRop As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
    ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" ( _
    ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" ( _
    ByVal hObject As Long) As Long
Private Declare Function LoadImage Lib "user32.dll" Alias "LoadImageA" ( _
    ByVal hInst As Long, _
    ByVal lpsz As String, _
    ByVal un1 As Long, _
    ByVal n1 As Long, _
    ByVal n2 As Long, _
    ByVal un2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal hObject As Long) As Long
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal _
    hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
'//API To display string item from resource
Private Declare Function LoadString Lib "user32.dll" Alias "LoadStringA" ( _
    ByVal hInstance As Long, _
    ByVal wID As Long, _
    ByVal lpBuffer As String, _
    ByVal nBufferMax As Long) As Long
'//1033=ENGLISH (US)
Public Function StringResourceModify(strResExePath As String, id As Integer, _
  ByVal strText As String, Optional LangID As Long = ENGLISH_US) As Boolean
  Dim ret As Long
  Dim hResource As Long
  Dim x As Long
  Dim iGroup As Integer
  Dim hObject As Long
  Dim hResourceData As Long
  Dim lpResourceData As Long
  Dim cbResource As Long
  Dim hModule As Long
  Dim lpData() As Byte
  Dim lpReadData() As Byte
  Dim cbText As Integer
  If id < 1 Then Exit Function
  'Calculate # of groups of strings
  iGroup = Int(id / 16&) + 1
  'Open the file
  hModule = LoadLibrary(strResExePath)
  hObject = FindResourceEx(hModule, RT_STRING, iGroup, LangID)  '//6=StringType
  hResourceData = LoadResource(hModule, hObject)
  lpResourceData = LockResource(hResourceData)
  cbResource = SizeofResource(hModule, hObject)
  If cbResource <= 32 Or hObject = 0 Then
    cbResource = 32& + Len(strText) * 2&
    ReDim lpData(cbResource - 1)
    cbText = Len(strText)
    CopyMemory lpData(2& * (id - (iGroup - 1) * 16&)), cbText, 2&
    If Len(strText) Then
      CopyMemory lpData(2& + 2& * (id - (iGroup - 1) * 16&)), ByVal StrPtr(strText), Len(strText) * 2
    End If
  Else
    ReDim lpReadData(cbResource - 1)
    CopyMemory lpReadData(0), ByVal lpResourceData, cbResource
    Dim countX As Long
    Dim CHECKLNG As Integer
    For x = 0 To (id - (iGroup - 1) * 16&) - 1
      CopyMemory CHECKLNG, lpReadData(countX), 2&
      countX = countX + 2 + CHECKLNG * 2
    Next
    CopyMemory CHECKLNG, lpReadData(countX), 2&
    ReDim lpData(countX + 2 + Len(strText) * 2 + (cbResource - (countX + 2 + CHECKLNG * 2)) - 1)
    CopyMemory lpData(0), lpReadData(0), countX
    cbText = Len(strText)
    CopyMemory lpData(countX), cbText, 2&
    If Len(strText) Then
      CopyMemory lpData(countX + 2), ByVal StrPtr(strText), Len(strText) * 2
    End If
    If (cbResource - (countX + 2 + CHECKLNG * 2)) > 0 Then
      CopyMemory lpData(countX + 2 + Len(strText) * 2), lpReadData(countX + 2 + CHECKLNG * 2), (cbResource - (countX + 2 + CHECKLNG * 2))
    End If
  End If
  'Free the loaded exe/dll file
  FreeLibrary hModule
  'Start resource update to the exe/dll
  hResource = BeginUpdateResource(strResExePath, ByVal 0&)
  'Update the ressource iGroup
  ret = UpdateResource(hResource, 6&, CLng(iGroup), CInt(LangID), lpData(0), UBound(lpData) + 1)
  'This will actually write the update to the disk and end the resource update process
  ret = EndUpdateResource(hResource, ByVal 0&)
  StringResourceModify = ret
End Function
Private Function StringResourceList(strFileName As String, Optional LangID As Long = ENGLISH_US) As StringTable()
  Dim ret As Long
  Dim hResource As Long
  Dim x As Long
  Dim iGroup As Integer
  Dim hObject As Long
  Dim hResourceData As Long
  Dim lpResourceData As Long
  Dim cbResource As Long
  Dim hModule As Long
  Dim lpData() As Byte
  Dim lpReadData() As Byte
  Dim Out() As StringTable
  Dim countX As Long
  Dim CHECKLNG As Integer
  Dim temp As String
  ReDim Out(0)
  hModule = LoadLibrary(strFileName)
  For iGroup = 1 To 4096
    hObject = FindResourceEx(hModule, 6&, iGroup, LangID)
    hResourceData = LoadResource(hModule, hObject)
    lpResourceData = LockResource(hResourceData)
    cbResource = SizeofResource(hModule, hObject)
    If cbResource >= 31 And hObject <> 0 Then
      ReDim lpReadData(cbResource - 1)
      CopyMemory lpReadData(0), ByVal lpResourceData, cbResource
      countX = 0
      x = 0
      Do While countX < UBound(lpReadData)
        CopyMemory CHECKLNG, lpReadData(countX), 2&
        countX = countX + 2
        If CHECKLNG Then
          ReDim Preserve Out(UBound(Out) + 1)
          Out(UBound(Out)).id = (iGroup - 1) * 16& + x
          temp = Space(CHECKLNG * 2)
          CopyMemory ByVal StrPtr(temp), lpReadData(countX), CHECKLNG * 2
          Out(UBound(Out)).Text = temp
          countX = countX + CHECKLNG * 2
        End If
        x = x + 1
      Loop
    End If
  Next
  FreeLibrary hModule
  StringResourceList = Out
End Function

Private Function BitmapResourceModify(strResExePath As String, strFileToLoad As String, _
  Optional nResType As Long = RT_BITMAP, Optional nID As Long = 101, Optional bDelete As Boolean = False) As Boolean
  Dim nFile As Long
  Dim Data() As Byte
  Dim arrSize As Long
  Dim ret As Long
  Dim Handle As Long
  nFile = FreeFile
  '//We need to pass byte buffer so create a ByteArry from file
  Open strFileToLoad For Binary As nFile
  arrSize = LOF(nFile) - 14
  ReDim Data(0 To arrSize - 1)
  Get nFile, 15, Data
  Close nFile
  Handle = BeginUpdateResource(strResExePath, 0)  '//0=Dont delete existing resource items
  If Handle = 0 Then Exit Function
  If bDelete = False Then
    '//Add/Modify
    ret = UpdateResource(Handle, ByVal nResType, ByVal nID, 1033, Data(0), arrSize)
  Else
    '//To Delete Resource item pass lpData=ByVal 0& (NULL) and cbData=0
    ret = UpdateResource(Handle, ByVal nResType, ByVal nID, 1033, ByVal 0&, 0)
  End If
  ret = EndUpdateResource(Handle, 0)
  BitmapResourceModify = ret
End Function
Sub DisplayBitmapRes(hDcDisplay As Long, sResFile As String, ResId As Long)
  Const IMAGE_BITMAP = 0&
  Const LR_CREATEDIBSECTION = &H2000
  Dim hDLL As Long
  Dim sID As String
  Dim sIdent102 As String
  Dim hMemDC As Long
  Dim lret As Long
  Dim hBmp As Long
  Dim oldhBmp As Long
  Dim picwid As Long, pichgt As Long
  Dim BMP As BITMAP
  sID = "#" & ResId    '//Name is in #xxxx format
  hDLL = LoadLibrary(sResFile)
  ' Could use LoadBitmap but it has been superceded by
  ' LoadImage which is more flexible.
  ' Hbmp = LoadBitmap(hDLL, sID)
  ' First bitmap in DLL
  hBmp = LoadImage(hDLL, sID, IMAGE_BITMAP, _
      0, 0, LR_CREATEDIBSECTION)
  GetObjectAPI hBmp, Len(BMP), BMP
  picwid = BMP.bmWidth
  pichgt = BMP.bmHeight
  ' Blit it to a pictureBox
  hMemDC = CreateCompatibleDC(hDcDisplay)
  oldhBmp = SelectObject(hMemDC, hBmp)
  lret = BitBlt(hDcDisplay, 0, 0, picwid, pichgt, _
      hMemDC, 0, 0, vbSrcCopy)
  DeleteObject hBmp
  ' Clean Up
  SelectObject hMemDC, oldhBmp
  DeleteDC hMemDC
  DeleteObject hBmp
  FreeLibrary hDLL
End Sub
Sub DisplayStringRes(sResFile As String, ResId As Long)
  Dim c As Integer, s As String, id As Long, hDLL As Long
  c = 1024
  s = String(c, 0)
  hDLL = LoadLibrary(sResFile)
  c = LoadString(hDLL, ResId, s, c)
  MsgBox s
  FreeLibrary hDLL
End Sub
Private Sub Command1_Click()
  Dim sResExeFilePath As String
  Dim sBMPFileToLoadPath As String
  sResExeFilePath = App.Path & "\test.exe"
  sBMPFileToLoadPath = App.Path & "\bmp_to_load.bmp"
  '//Note: ID Must be unique with in the same group of resource
  '//otherwise resource item will be overwritten by update
  '//Save Bitmap Resource Demo
  MsgBox BitmapResourceModify(sResExeFilePath, sBMPFileToLoadPath, RT_BITMAP, 101), , "BitmapResourceModify"
  '//Delete Bitmap Resource Demo
  '//MsgBox BitmapResourceModify(sResExeFilePath, sBMPFileToLoadPath, RT_BITMAP, 101,True)
  '//Save String Resource Demo
  MsgBox StringResourceModify(sResExeFilePath, 101, "This is test1"), , "StringResourceModify"
  MsgBox StringResourceModify(sResExeFilePath, 102, "This is test2"), , "StringResourceModify"
  MsgBox StringResourceModify(sResExeFilePath, 103, "This is test3"), , "StringResourceModify"
  '//To remove string ID=102 just pass strText=vbNullString
  'MsgBox StringResourceModify(sResExeFilePath, 102, vbNullString)
  Dim st() As StringTable, sMsg As String, i As Long
  st = StringResourceList(sResExeFilePath)
  For i = 0 To UBound(st)
    sMsg = sMsg & st(i).id & " : " & st(i).Text & vbCrLf
  Next
  MsgBox sMsg, , "List of string items"
  DisplayBitmapRes Picture1.hdc, sResExeFilePath, 101
  DisplayStringRes sResExeFilePath, 101
  Me.Caption = "BMP Resource from : " & sResExeFilePath
End Sub
Private Sub Form_Load()
  Command1.Caption = "Modify Resource Demo"
End Sub






원본출처 : http://binaryworld.net/Main/CodeDetail.aspx?CodeId=3778(새 창으로 열기)

2007/11/26 18:00 2007/11/26 18:00

트랙백 주소 :: http://optant.ismine.net/blog/trackback/127

댓글을 달아 주세요