Groups | Blog | Home
all groups > vb.net upgrade > january 2005 >

vb.net upgrade : Please help me understand


josh via DotNetMonster.com
1/25/2005 10:34:15 PM
when using a call statement to a movememory function:
Call MoveMemory(x, y, 4)

what is it doing? is it moving 4 bytes of the address of y to x? i'm not quite sure what it is doing. it works much different than VB 6.0.

any help would be appreciated

--
mosimu
1/25/2005 10:55:01 PM
This function will copy four bytes at address Y to overwrite memory at
location X. For example suppose memory looks like this:

Memory address:
1000 "ABCD"
1004 "EFGH"
1008 "IJKL"
1012 "MNOP"
1016 "QRST"

MoveMemory(1012, 1000, 8);

Result:
1000 "ABCD"
1004 "EFGH"
1008 "IJKL"
1012 "ABCD" <-- These eight bytes copied from address 1000
1016 "EFGH"

[quoted text, click to view]
mosimu
1/27/2005 9:17:02 AM
What is your API declaration? It should be,

Private Declare Sub MoveMemory Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Long, ByVal _
Source As Long, ByVal Length As Integer)

However I think what your problem is, is that VB.NET is entirely managed
code, MoveMemory is an unmanaged Win32 API call. Even if you did get this to
work once or twice, since data on the managed heap is not pinned down and can
move at any time -- even between the start of your MoveMemory call and before
it finishes -- I would strongly recommend you NOT use this function. The
application may become unstable and could crash at any time without warning.
Managed code is based on "trust" levels, in which it is explicitly designed
to prevent you from doing any such thing as this -- writing any number of
bytes you desire at any memory location. Managed code and all of its .NET
libraries have an assigned level of trust or security, so Windows can control
what executes on the computer in the Internet Zone and other insecure
environments. MoveMemory absolutely whole heartedly violates this trust
principle and should not be used, if it even can be.

Please explain what you are trying to do, copy an array? copy strings?
overwrite pointers? There must be another way.

[quoted text, click to view]
mosimu
1/27/2005 12:35:03 PM
What they were trying to do is extract the high order byte from the number.
There is a much more efficient way to do this in VB.NET since the language
now has bit shift operators, start by commenting out the lines shown and add
the new line.

'ChangedSeconds = seconds
'
'fltbin = Space(4)
'Call MoveMemory(fltbin, ChangedSeconds, 4)
'nib = Asc(Mid(fltbin, 4, 1))

nib = (seconds >> 24) And 255

[quoted text, click to view]
josh via DotNetMonster.com
1/27/2005 2:11:55 PM
So how would you implement that in VB.NET? In VB 6.0, it will put the "ABCD" into 1012 but in VB.NET it gives me a different answer.

ex. VB 6.0
Call MoveMemory(ByVal 1012, 1000, 8)

when I implement this in VB 6 it works great.

ex. VB.NET
Call MoveMemory(1012, 1000, 8)

when I implement this I get a different answer than that from vb 6.

any reason why? and what can I do to match them?

--
josh via DotNetMonster.com
1/27/2005 7:11:19 PM
here is a sample of what I want to do. Sorry so long. this is the code in vb.NET.

Option Strict Off
Option Explicit On

Friend Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Name = "Form1"
Me.Text = "Form1"

End Sub

#End Region
'============================================================
Const SECS_PER_DAY As Integer = 86400
Const SECS_PER_MINUTE As Integer = 60&
Const SECS_PER_HOUR As Integer = 3600&
Const BASE_YEAR As Integer = 1970&

Public PublicInt1 As String
Public PublicInt2 As String

Dim ChangedSeconds As Integer
Dim seconds As Integer
Dim daycnt As Integer
Dim fltbin As String
Dim num_days(11) As Object
Dim nib As String

Private Declare Sub MoveMemory Lib "KERNEL32" Alias _
"RtlMoveMemory" (ByRef hpvDest As Object, _
ByRef hpvSource As Object, _
ByVal cbCopy As Integer)

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

PublicInt1 = "01/25/2005"
PublicInt2 = "14:00:00"

daycnt = 365 * (Mid(PublicInt1, 7, 4) - BASE_YEAR)
daycnt = daycnt + (Mid(PublicInt1, 7, 4) - BASE_YEAR + 1) \ 4
daycnt = daycnt + num_days(Mid(PublicInt1, 1, 2) - 1)
daycnt = daycnt + (Mid(PublicInt1, 4, 2) - 1)

If ((Mid(PublicInt1, 7, 4) Mod 4) = 0) And _
(Mid(PublicInt1, 1, 2) > 2) Then

daycnt = daycnt + 1
End If

seconds = daycnt * SECS_PER_DAY
seconds = seconds + Mid(PublicInt2, 1, 2) * SECS_PER_HOUR
seconds = seconds + Mid(PublicInt2, 4, 2) * SECS_PER_MINUTE
seconds = seconds + Mid(PublicInt2, 7, 2)

ChangedSeconds = seconds

fltbin = Space(4)
Call MoveMemory(fltbin, ChangedSeconds, 4)
nib = Asc(Mid(fltbin, 4, 1))
End Sub

End Class

Now, in my program in vb6, i get fltbin = "?P?A" and nib = 65, this always gives me the correct output.

In vb.NET, i get fltbin = "1631788" and this gives me incorrect output.

PublicInt1 = the date that is entered by the user, and
PublicInt2 = the time that is entered by the user.
daycnt = # of days since 1970 = 17808
seconds = # of sec's since 1970 = 1106661600

We just are trying to understand this movememory thing because we didn't write the program, but we are responsable for converting it to vb.NET.

--
Jay B. Harlow [MVP - Outlook]
1/28/2005 11:20:38 AM
Mosimu,
[quoted text, click to view]
First I totally agree!!!

[quoted text, click to view]
No it should NOT!

Long is a 64-bit number, a memory address in .NET 1.1 is 32-bit, a memory
address in .NET 2.0 is either 32-bit or 64-bit, depending on if which
runtime/platform you are on.

Its recommend that you use System.IntPtr which is a "platform-specific type
that is used to represent a pointer or a handle".

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemintptrclasstopic.asp

So the API should really be something like:

[quoted text, click to view]

NOTE: I'm not sure if Length should be IntPtr or Int32, as its "SIZE_T", I
would expect SIZE_T be 64-bit on 64-bit platforms, however I'm really not
sure...

However as you stated, I would not use MoveMemory in .NET!

In addition to the "trust" you mention, memory itself is laid out totally
different... The methods of System.Runtime.InteropServices.Marshal are much
better prepared for "moving memory" around as it fully understands how
managed memory is laid out & how to deal with the GC.

Hope this helps
Jay


[quoted text, click to view]

AddThis Social Bookmark Button