Convert C Strings to VB Strings

Level:
Level2

These two simple functions will save you a lot of redundant code when working with the Win32 API.
Most Win32 API functions that work with and return strings have two things in common:
  1. You are expected to provide a prepared buffer of adequate size for the string to be returned.
  2. Strings returned will be null terminated C strings, rather than regular VB strings.
In addition to simple null terminated C strings, the Win32 API will sometimes return another type of string. This type will have multiple values returned in a single buffer, with nulls separating the individual values. This type of string is terminated by two consecutive nulls - the null terminating the last string and another null terminating the entire multi-string variable.

The CStringToVBString function will extract everything to the left of the first null character it finds in a string. If no null is found, it simply returns the original string.

The MultiCStringToStringArray sub will convert a multi-string buffer into an array of strings (which is provided as a parameter to the procedure).

Allocating a string buffer for variables that will be passed to the API is simple. If you already know how long the variable needs to be, you can use the Space$() function to fill it:

  Dim sAPIReturn As String

  sAPIReturn = Space$(256)
The value of 256 chosen for this snippet is no accident. In most cases, the API will not return strings longer than 256 characters (although that's not always the case). In those cases where you don't know the required length in advance, 256 makes for a pretty good guess. Fortunately, in those cases where you don't know how long the string needs to be the API will provide a means of determining it. Often, simply calling the function with too small a buffer will return the required length either in the parameter list or as the function return value. You can then reallocate your string buffer and call the function again. In some cases, however, a separate call will be required to determine the necessary length. Check the documentation for the function you are calling to determine what method you need to use to prepare your string variable.

Here is the CStringToVBString function:

Public Function CStringToVBString(psCString As String) As String
' **********
' Purpose:     Convert a C string to a VB string
' Parameters:  (Input Only)
'  psCString - the C string to convert
' Returns:     The converted VB string
' Notes:
'  Returns everything to the left of the first Null character
' **********

  Dim sReturn As String
  Dim iNullCharPos As Integer

  iNullCharPos = InStr(psCString, vbNullChar)

  If iNullCharPos > 0 Then
    sReturn = Left(psCString, iNullCharPos - 1)
  Else
    sReturn = psCString
  End If

  CStringToVBString = sReturn

End Function

Here is the MultiCStringToStringArray sub:
Public Sub MultiCStringToStringArray(psMultiCString As String, psaStrings() As String)
'Created: Joe Garrick 01/06/97 9:28 AM
'********************
' Purpose:    Convert a multi-string C string to an array of strings
' Parameters:
'  (Input)
'  psMultiCString - the multiple C string
'  (Output)
'  psaStrings - returned array of strings
' Notes:
'  The original array should be empty and ReDim-able
'********************

  Dim iNullPos As Integer
  Dim iPrevPos As Integer
  Dim iIdx As Integer

  ' initialize array, setting first element to a zero-length string
  iIdx = 0
  ReDim psaStrings(0 To iIdx + 1)
  psaStrings(iIdx + 1) = ""

  Do
    ' find null char
    iNullPos = InStr(iPrevPos + 1, psMultiCString, vbNullChar)
    ' double null encountered if next pos is old pos + 1
    If iNullPos > iPrevPos + 1 Then
      ' assing to the string array
      psaStrings(iIdx) = Mid$(psMultiCString, (iPrevPos + 1), ((iNullPos - 1) - iPrevPos))
      iIdx = iIdx + 1
      ReDim Preserve psaStrings(0 To iIdx)
      iPrevPos = iNullPos
    Else
      ' double null found, remove last (empty) element and exit
      ReDim Preserve psaStrings(0 To iIdx - 1)
      Exit Do
    End If
  Loop

End Sub

Notes

  • Not all Win32 API functions that work with strings return null terminated strings. In some cases, the length of a returned string will be passed back as one of the function parameters or as the function return value.
  • When you need to preallocate strings for the API, remember to include room for the terminating null.
  • No API function will ever return a string directly.
  • Check the documentation in the SDK to see how it handles strings for any function you intend to call from a Visual Basic application.
  • ALWAYS pad strings with enough space for the value to be returned before calling an API procedure. While in most cases functions will simply return an error code if the string buffer is not large enough, some may simply overwrite whatever exists past the end of the buffer provided. This can generate very unpredictable behavior or (if you're lucky) a general protection fault and the abrupt termination of your application. I say "if you're lucky" here because if the app terminates you'll at least know that you have a bug.
  • ALWAYS use Option Explicit - especially when working with the API.
  • Save your work often when debugging API routines as a bad call can potentially take down not only your own app but the entire VB environment as well.

Originally written by Joe Garrick

If you enjoyed this post, subscribe for updates (it's free)

hi

I have a project made by visual basic programming language,so help me by send a simple worked example

Private Sub

Private Sub Command1_Click()

End Sub

Private Sub cmdadd_Click()
List1.AddItem Text1.Text
Text1.Text = ""
Text1.SetFocus
Label4.Caption = List1.ListCount
End Sub

Private Sub cmdcle_Click()
List1.Clear
cmdrevo.Enabled = False
Label4.Caption = List1.ListCount
End Sub

Private Sub cmdclo_Click()
End
End Sub

Private Sub cmdrevo_Click()
Dim ind As Integer
ind = List1.ListIndex
If ind > 0 Then
List1.RemoveItem ind
Label4.Caption = List1.ListCount
End If
cmdrevo.Enabled = (List1.ListIndex <> -1)
End Sub

Private Sub List1_Click()
cmdrevo.Enabled = (List1.ListIndex <> -1)
End Sub

Private Sub Text1_Change()
cmdadd.Enabled = (Len(Text1.Text) > 0)
End Sub

OK....

ok so i see the point of this
but my question is how to get the double null terminated string from the pointer
i used copymemory i was able to see the items after the single string lstrcpy returns because it sees a null and stops
but there is no way to limit how far you need to copy the memory because you don't know the size of the whole string
so maybe you can tell me how to get that double null terminated string from the pointer into a string to actually use this function... thx

vb6 btw