Microsoft KB Archive/262667

= FIX: Wrong Result Using RtlMoveMemory to Copy Nested UDT with Fixed-Length String Array =

Article ID: 262667

Article Last Modified on 8/7/2007

-

APPLIES TO


 * Microsoft Visual Basic 6.0 Professional Edition
 * Microsoft Visual Basic 6.0 Enterprise Edition

-



This article was previously published under Q262667



SYMPTOMS
If you copy a nested user defined type (UDT) with a fixed-length String array to a fixed-length String by using a RtlMoveMemory API call, you may not get the right result.



RESOLUTION
This problem can be solved in one of two ways:
 * Install the latest service pack for Visual Studio 6.0.
 * Use an intermediate byte array. That is, first copy the UDT to a byte array and then assign the byte array to the fixed-length String.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article. This bug was corrected in the next service pack for Visual Studio 6.0.

For additional information about Visual Studio service packs, click the following article numbers to view the articles in the Microsoft Knowledge Base:

194022 INFO: Visual Studio 6.0 Service Packs, What, Where, Why

194295 HOWTO: Tell That a Visual Studio Service Pack Is Installed

To download the latest Visual Studio service pack, visit the following Microsoft Web site:

http://msdn2.microsoft.com/en-us/vstudio/Aa718353.aspx



MORE INFORMATION
WARNING: One or more of the following functions are discussed in this article; VarPrt, VarPtrArray, VarPtrStringArray, StrPtr, ObjPtr. These functions are not supported by Microsoft Technical Support. They are not documented in the Visual Basic documentation and are provided in this Knowledge Base article &quot;as is&quot;. Microsoft does not guarantee that they will be available in future releases of Visual Basic.

Steps to Reproduce Behavior
 Start a new Standard EXE project in Visual Basic. Form1 is added by default. Place a CommandButton control on Form1. Command1 is added by default.  Paste the following code into Form1's code section: Option Explicit

Private Sub Command1_Click Module1.main End Sub

Private Sub Form_Load Command1.Caption = &quot;Test&quot; End Sub  From the Project menu, click Add Module to add a new module, Module1, to Project1.  Paste the following code into Module1: Option Explicit

Const CASIZE = 14

Type WinDataType ISBalance(1) As String * 1 ISRebate    As String * 1    ' Filler      As String * 1 End Type

Type WinIODataType Filler      As String * 2 Data        As WinDataType End Type

Type WinComDataType Filler      As String * 2 Inp         As WinIODataType Out         As WinIODataType End Type

Public Declare Sub CopyMemory Lib &quot;kernel32&quot; Alias &quot;RtlMoveMemory&quot; _ (Destination As Any, Source As Any, ByVal Length As Long)

Dim IWIN As WinComDataType

Sub main Dim CommonREM As String * CASIZE Dim y(CASIZE * 2 - 1) As Byte IWIN.Inp.Data.ISBalance(0) = &quot;V&quot; IWIN.Inp.Data.ISBalance(1) = &quot;X&quot; IWIN.Inp.Data.ISRebate = &quot;R&quot; IWIN.Inp.Data.Filler = &quot;F&quot; ' ISBalance now starts at position 5 in the IWIN structure: Debug.Print &quot;Mid$(CommonREM, 5, 4) before MoveMemory = &quot; _ & Mid$(CommonREM, 5, 4) CopyMemory ByVal CommonREM, IWIN, CASIZE

Debug.Print &quot;Mid$(CommonREM, 5, 4) after MoveMemory = &quot; _ & Mid$(CommonREM, 5, 4) End Sub  From the View menu, click Immediate Window to open the Immediate window.</li> Press the F5 key to run the project.</li> Click the Test button.</li>  In the Immediate window, you should see the following: <pre class="fixed_text">Mid$(CommonREM, 5, 4) before MoveMemory = Mid$(CommonREM, 5, 4) after MoveMemory = VXXF </li>  This result is incorrect. The correct result should be: <pre class="fixed_text">Mid$(CommonREM, 5, 6) after MoveMemory = VXRF Look at the code in the Main subroutine in Module1, and note that the correct result is &quot;VXRF.&quot; </li></ol>

Workaround
If you do not install Visual Studio 6.0 Service Pack 4, then do the following: <ol>  In the preceding project, replace the code in Module1 with the following: Option Explicit

Const CASIZE = 14

Type WinDataType ISBalance(1) As String * 1 ISRebate    As String * 1    ' Filler      As String * 1 End Type

Type WinIODataType Filler      As String * 2 Data        As WinDataType End Type

Type WinComDataType Filler      As String * 2 Inp         As WinIODataType Out         As WinIODataType End Type

Public Declare Sub CopyMemory Lib &quot;kernel32&quot; Alias &quot;RtlMoveMemory&quot; _ (Destination As Any, Source As Any, ByVal Length As Long)

Dim IWIN As WinComDataType

Sub main Dim CommonREM As String * CASIZE Dim y(CASIZE * 2 - 1) As Byte

' ISBalance is starting from position 5 IWIN.Inp.Data.ISBalance(0) = &quot;V&quot; IWIN.Inp.Data.ISBalance(1) = &quot;X&quot; IWIN.Inp.Data.ISRebate = &quot;R&quot; IWIN.Inp.Data.Filler = &quot;F&quot; ' ISBalance now starts at position 5 in the IWIN structure: Debug.Print &quot;Mid$(CommonREM, 5, 4) before MoveMemory = &quot; _ & Mid$(CommonREM, 5, 4)

CopyMemory ByVal VarPtr(y(0)), ByVal VarPtr(IWIN), CASIZE * 2 CommonREM = y

Debug.Print &quot;Mid$(CommonREM, 5, 4) after MoveMemory = &quot; _ & Mid$(CommonREM, 5, 4) End Sub </li> From the View menu, click Immediate Window to open the Immediate window.</li> Press F5 to run the project.</li> Click the Test button.</li>  In the Immediate window, note the following, which is the correct result: <pre class="fixed_text">Mid$(CommonREM, 5, 4) before MoveMemory = Mid$(CommonREM, 5, 4) after MoveMemory = VXRF </li></ol>

<div class="references_section">