Cloning native resources - vb.net

This question is related to Visual Basic .NET 2010
I'm trying to clone the "native" resources of one file and applying them to another. I tried enumerating the resource names and then applying them with UpdateResource.
Imports System.Runtime.InteropServices
Public Class ResourceCloner
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, EntryPoint:="EnumResourceNamesW", SetLastError:=True)> _
Private Shared Function EnumResourceNames(ByVal hModule As IntPtr, ByVal lpszType As String, ByVal lpEnumFunc As EnumResNameProcDelegate, ByVal lParam As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, EntryPoint:="EnumResourceNamesW", SetLastError:=True)> _
Private Shared Function EnumResourceNames(ByVal hModule As IntPtr, ByVal lpszType As Integer, ByVal lpEnumFunc As EnumResNameProcDelegate, ByVal lParam As IntPtr) As Integer
End Function
<DllImport("kernel32", EntryPoint:="BeginUpdateResourceA", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)> _
Private Shared Function BeginUpdateResource(<MarshalAs(UnmanagedType.VBByRefStr)> ByRef pFileName As String, ByVal bDeleteExistingResources As Integer) As Integer
End Function
<DllImport("kernel32", EntryPoint:="EndUpdateResourceA", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)> _
Private Shared Function EndUpdateResource(ByVal hUpdate As Integer, ByVal fDiscard As Integer) As Integer
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, ByVal lpType As String, ByVal lpName As String, ByVal wLanguage As UShort, ByVal lpData As IntPtr, ByVal cbData As UInteger) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function FindResource(ByVal hModule As IntPtr, ByVal lpName As String, ByVal lpType As String) As IntPtr
End Function
<DllImport("kernel32.dll")> _
Private Shared Function LoadLibraryEx(ByVal lpFileName As String, ByVal hReservedNull As IntPtr, ByVal dwFlags As UInt32) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="FreeLibrary")> _
Public Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
End Function
Private Delegate Sub EnumResNameProcDelegate(ByVal hModule As IntPtr, ByVal lpszType As IntPtr, ByVal lpszName As IntPtr, ByVal lParam As IntPtr)
Private Target_file As String
Private Clone_file As String
Sub New(ByVal Target_file As String, ByVal Clone_file As String)
Me.Target_file = Target_file
Me.Clone_file = Clone_file
End Sub
Public Sub Clone()
Flush(Target_file)
Dim dll_hInst As IntPtr
dll_hInst = LoadLibraryEx(Clone_file, 0, &H200)
If Not dll_hInst.Equals(IntPtr.Zero) Then
EnumResourceNames(dll_hInst, 0, AddressOf EnumResNameProc, IntPtr.Zero)
FreeLibrary(dll_hInst)
End If
End Sub
Private Sub EnumResNameProc(ByVal hModule As IntPtr, ByVal lpszType As IntPtr, ByVal lpszName As IntPtr, ByVal a As IntPtr)
Dim Resource As IntPtr = FindResource(hModule, lpszName, lpszType)
'Dim x = LoadLibraryEx(Target_file, 0, &H200)
Dim FileHandle As IntPtr = BeginUpdateResource(Target_file, False)
Dim Success As Boolean = UpdateResource(FileHandle, lpszType, lpszName, 0, a, Len(a))
EndUpdateResource(FileHandle, 0)
End Sub
Private Sub Flush(ByVal File As String)
EndUpdateResource(BeginUpdateResource(File, 1), 0)
End Sub
End Class
Some explanation: Target_file is the file I want to apply the cloned resources to, and Clone_file is the file I want to clone the resources from.
I tried my code and it doesn't throw any errors, it's just, nothing seems to happen.

Related

VB.NET using ReadProcessMemory API

I am trying to use basic windows API functions in VB.NET. I have the following code:
Imports System.Runtime.InteropServices
Public Class testClass
Declare Function CreateProcessA Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String,
ByVal lpCommandLine As String, ByVal lpProcessAttributes As IntPtr,
ByVal lpThreadAttributes As IntPtr,
<MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandles As Boolean,
ByVal dwCreationFlags As Integer, ByVal lpEnvironment As IntPtr,
ByVal lpCurrentDirectory As String, ByVal lpStartupInfo As Byte(),
ByVal lpProcessInformation As IntPtr()) As <MarshalAs(UnmanagedType.Bool)> Boolean
Declare Function GetThreadContext Lib "kernel32" Alias "GetThreadContext" (ByVal hThread As IntPtr,
ByVal lpContext As UInteger()) As <MarshalAs(UnmanagedType.Bool)> Boolean
Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As IntPtr,
ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As IntPtr,
ByVal nSize As Integer,
ByRef lpNumberOfBytesRead As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
Public Sub Test()
Dim locProcess As String = "C:\Windows\notepad.exe"
Dim iPtr1 As IntPtr = IntPtr.Zero
Dim startInfo As Byte() = New Byte(67) {}
Dim procInfo As IntPtr() = New IntPtr(3) {}
Dim cpResult = CreateProcessA(locProcess, vbNullString, iPtr1, iPtr1, False, 0, iPtr1, Nothing, startInfo, procInfo)
Dim pContext As UInteger() = New UInteger(178) {}
pContext(0) = &H10002
If GetThreadContext(procInfo(1), pContext) Then
Dim pAddress As New IntPtr(pContext(&H29) + 8L)
Dim pSize As New IntPtr(4)
Dim bAddress As IntPtr = IntPtr.Zero
Dim iPtr2 As IntPtr = IntPtr.Zero
If ReadProcessMemory(procInfo(0), pAddress, bAddress, CInt(pSize), iPtr2) <> 0 Then
MessageBox.Show("Success!")
Else
MessageBox.Show("ReadProcessMemory Error code is :" & Err.LastDllError)
End If
Else
MessageBox.Show("GetThreadContext Error code is :" & Err.LastDllError)
End If
End Sub
End Class
Public Class Form1
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim tc As New testClass
tc.Test()
End Sub
End Class
I am getting an error on ReadProcessMemory. The code results in
"ReadProcessMemory Error code is : 299".
I have been struggling to find the issue seeing as the error can be vague when dealing directly with windows DLLs. Any help on the issue would be greatly appreciated. Or, is there another solution to debugging properly (other than LastDllError) that may point me in the right direction of solving this issue. Thank you!

Expression cannot be converted to long error

im getting the following error, and have no idea how to solve this:
BC30581: Adressoff Expression cannot be converted to Long because Long is not a delegate type.
Public Declare Function SetTimer Lib "user32" (
ByVal HWnd As Long,
ByVal nIDEvent As Long,
ByVal uElapse As Long,
ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (
ByVal HWnd As Long,
ByVal nIDEvent As Long) As Long
Public TimerID As Long
Public TimerSeconds As Single
Sub StartTimer()
TimerSeconds = 1000 ' how often to "pop" the timer.
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
Sub EndTimer()
On Error Resume Next
KillTimer(0&, TimerID)
End Sub
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long,
ByVal nIDEvent As Long, ByVal dwTimer As Long)
MsgBox("test123")
End Sub
It appears that your PInvoke signature is wrong. Try this one instead:
Public Delegate Sub TimerProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)
<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function SetTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr, ByVal uElapse As UInteger, ByVal lpTimerFunc As TimerProc) As IntPtr
End Function
You will need to change your pinvoke signature for KillTimer as well. See pinvoke.net for more information.
I got it to work with this:
Imports System.Runtime.InteropServices
Public Class TimerMethods
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function SetTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr, ByVal uElapse As UInteger, ByVal lpTimerFunc As TimerProc) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function KillTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr) As Boolean
End Function
Public Delegate Sub TimerProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)
Public timerID As IntPtr
Sub StartTimer(windowHandle As IntPtr)
Dim timerSeconds = 3 ' how often to "pop" the timer.
timerID = SetTimer(windowHandle, IntPtr.Zero, CUInt(timerSeconds * 1000), AddressOf TimerMethods.TimerCallback)
If timerID = IntPtr.Zero Then
Debug.WriteLine("Timer start error.")
Else
Debug.WriteLine("Timer started.")
End If
End Sub
Sub EndTimer()
KillTimer(IntPtr.Zero, timerID)
End Sub
Public Shared Sub TimerCallback(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)
MsgBox(uMsg)
End Sub
End Class
and a simple form with just a button on it to start the timer:
Public Class Form1
Dim t As TimerMethods
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
t = New TimerMethods
t.StartTimer(Me.Handle)
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If t IsNot Nothing Then
t.EndTimer()
End If
End Sub
End Class
You don't have to use windowHandle to tie the timer to the form: you could use IntPtr.Zero instead.
Any time you see a variable name like hWnd, it wants a handle, which is an IntPtr in VB.NET.
Reference: pinvoke.net/default.aspx/user32.SetTimer
There seems little point in using PInvoke to do this. There is a Windows Forms Timer that you can use easily:
Public Class Form3
Private _timer As Timer
Public Sub StartTimer()
_timer = New Timer()
_timer.Interval = 1000 ' timer interval in ms
AddHandler _timer.Tick, AddressOf TimerProc
_timer.Enabled = True
End Sub
Public Sub EndTimer()
_timer.Enabled = False
RemoveHandler _timer.Tick, AddressOf TimerProc
End Sub
Sub TimerProc(sender As Object, e As EventArgs)
MsgBox("test123")
End Sub
End Class
I have tested the code in VBE in Excel 2013 and run successfully.
I state beforehand that this solution is for VBA environment
since that was a possible one at the stage I wrote it
I made it run with some edits:
added the continuation escape sequence "_" at the end of each but the last line of SetTimer() and KillTimer () function declaration
in EndTimer() assigned KillTimer to a Long variable, which I also declared
in TimerProc() added a call to EndTimer() to stop it !!!
here follows the working code for me:
Option Explicit
Public Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long) As Long
Public TimerID As Long
Public TimerSeconds As Single
Sub StartTimer()
TimerSeconds = 1000 ' how often to "pop" the timer.
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
Sub EndTimer()
Dim i As Long '<--| added
On Error Resume Next
i = KillTimer(0&, TimerID) '<--| added
End Sub
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
ByVal nIDEvent As Long, ByVal dwTimer As Long)
MsgBox ("test123")
EndTimer '<--| added !!!
End Sub

VB.Net api affects windows forms

I am creating a application in vb.net and i am using some API functions.For example : GetForegroundWindow,SetWindowPos .So my app should change the active window's size and position when clicked.But it is affecting also the system forms like taskbar , StartMenu.How can i avoid this?
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Integer
End Function ''SETTTING THE WINDOW POSITION
<Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function GetAsyncKeyState(ByVal vKey As System.Windows.Forms.Keys) As Short
End Function
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetForegroundWindow() As IntPtr
End Function
Private ReadOnly HWND_TOP As New IntPtr(0)
Public Const SWP_FRAMECHANGED As Integer = &H20
Dim cX As Integer, cY As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
cX = CInt(Windows.Forms.Cursor.Position.X.ToString())
cY = CInt(Windows.Forms.Cursor.Position.Y.ToString())
If GetAsyncKeyState(1) <> 0 Then
If cX <= 10 Then
If GetForegroundWindow() <> 1 Then
SetWindowPos(GetForegroundWindow(), HWND_TOP, 0, 0, 100, 100, SWP_FRAMECHANGED)
End If
End If
End If
End Sub
<Runtime.InteropServices.DllImport("User32")>
Public Shared Function GetWindowThreadProcessId(hWnd As IntPtr, ByRef lpdwProcessId As IntPtr) As IntPtr
End Function
Private Sub Button1_Click() Handles Button1.Click
Dim ID As IntPtr, hWnd As IntPtr '// hWnd By GetForegroundWindow
GetWindowThreadProcessId(hWnd, ID)
If Process.GetProcessById(ID).ProcessName.ToLower <> "Explorer".ToLower Then 'Without.exe
MessageBox.Show("Set Position")
End If
End Sub

How to turn this VB.net declaration into the equivalent for VB6 style and what's the process?

<DllImport("ieframe.dll", EntryPoint:="IEGetProtectedModeCookie")> _
Public Function IEGetProtectedModeCookie( _
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal lpszURL As String, _
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal lpszCookieName As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal pszCookieData As StringBuilder, _
ByRef pcchCookieData As UInteger, _
ByVal dwFlags As UInteger) As Integer
End Function
Those marshalas thingy look ugly
For comparison, typical vb6 style is:
Declare Function InternetGetCookieEx Lib "wininet.dll" Alias "InternetGetCookieExA" (ByVal pchURL As String, ByVal pchCookieName As String, ByVal pchCookieData As String, ByRef pcchCookieData As System.UInt32, ByVal dwFlags As System.UInt32, ByVal lpReserved As Integer) As Boolean
No marshal this no marshal that no [in] thingy. How do I turn that?
Is this the right way?
Declare Function IEGetProtectedModeCookie Lib "ieframe.dll" (ByVal lpszURL As String, ByVal lpszCookieName As String, ByVal pszCookieData As System.Text.StringBuilder, ByRef pcchCookieData As UInteger, ByVal dwFlags As UInteger) As Integer

Error Getting Form Handler (Vb.net)

I have the current code:
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As HandleRef, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
End Function
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Public Function WindowHandle(ByVal sTitle As String) As Long
WindowHandle = FindWindow(vbNullString, sTitle)
End Function
Dim CurrentProcess As Process
Dim CurrentHandle As IntPtr
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
SendMessage(CurrentHandle, 256, Keys.A, 0)
SendMessage(CurrentHandle, 257, Keys.A, 65539)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
CurrentProcess = Process.GetProcessesByName(ListBox1.SelectedItem.ToString.Remove(0, ListBox1.SelectedItem.ToString.IndexOf("{") + 1).Replace("}", ""))(0)
CurrentHandle = New IntPtr(WindowHandle(CurrentProcess.MainWindowTitle))
Timer1.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
If you take a look at the button sub, every time it runs, it errors with "Arithmetic overflow error!"
What is wrong here? This should work... right?
Sorry, this is a bit vague but it's as much as I know.
Your Declare statements are correct but the way you call them is not. The loose typing allowed by VB.NET is getting you in trouble, the kind you can't diagnose. The cure for that is letting the compiler tell you that you did it wrong. Put this at the top of your source code file:
Option Strict On