Public Sub ParseOleVariantArray(varArray As Variant, Elements() As String)
'
' Given a stream of bytes that represent a Microsoft SafeArray, wade through
'the garbage and get the actual data found in the array. Write the data to disk.
' SafeArray looks like
'typedef struct FARSTRUCT tagSAFEARRAY {
' unsigned short cDims; // Count of dimensions in this array.
' unsigned short fFeatures; // Flags used by the SafeArray
' // routines documented below.
' unsigned long cbElements; // Size of an element of the array.
' // Does not include size of
' // pointed-to data.
' unsigned long cLocks; // Number of times the array has been
' void HUGEP* pvData; // Pointer to the data.
' SAFEARRAYBOUND rgsabound[1]; // One bound for each dimension.
'} SAFEARRAY;
'SAFEARRAYBOUND is a two-longword structure, the first 32 bits hold the # of
'elements in the array, the second 32 bits hold the lower bound of the array.
'There is one structure for every dimension of the array.
'http://groups-beta.google.com/group/microsoft.public.vc.vcce/browse_thread/thread/7f2bfbdb6ef17e98/a90475b71136f83b?q=OleSafeArray+visual+basic&rnum=2&hl=en#a90475b71136f83b
'Public Type OLEVARIANT
' vt As Integer 'variable type
' wReserved1 As Integer
' wReserved2 As Integer
' wReserved3 As Integer
' lVal As Integer
' iVal As Integer
' bstrVal As Long
' pUnkVal As Long
' pArray As Long
' pvRecord As Long
' pRecInfo As Long
'End Type
Dim pArray As Long
Dim ppArray As Long
Dim ppVarStruct As Long
Dim intDims As Integer
Dim intFeatures As Integer
Dim lElements As Long
Dim lLocks As Long
Dim lDataPtr As Long
Dim lElementCount As Long
Dim lLbound As Long
Dim lOffset As Long
Dim lDataTemp As Long
Dim i As Long
Dim vType As Long
'----------------------------------------------------------------
' First get a pointer to the variant.
ppVarStruct = VarPtr(varArray)
'Get the variable type
'CopyMemory vType, ByVal ppVarStruct, 2
'Debug.Print "vType: " & vType
' Get the pointer to the data *inside* the variant. The VARTYPE is 2 bytes,
' and each of the three reserved words are also 2 bytes, giving 8 bytes total.
'
CopyMemory ppArray, ByVal ppVarStruct + 8, 4
' Now parse the SafeArray structure. The most important parts to me are the
' Number of elements and the pointer to the actual data.
'
lOffset = 0
CopyMemory intDims, ByVal (ppArray + lOffset), ByVal Len(intDims)
lOffset = lOffset + Len(intDims)
CopyMemory intFeatures, ByVal (ppArray + lOffset), ByVal Len(intFeatures)
lOffset = lOffset + Len(intFeatures)
CopyMemory lElements, ByVal (ppArray + lOffset), ByVal Len(lElements)
lOffset = lOffset + Len(lElements)
CopyMemory lLocks, ByVal (ppArray + lOffset), ByVal Len(lLocks)
lOffset = lOffset + Len(lLocks)
CopyMemory lDataPtr, ByVal (ppArray + lOffset), ByVal Len(lDataPtr)
lOffset = lOffset + Len(lDataPtr)
CopyMemory lElementCount, ByVal (ppArray + lOffset), ByVal Len(lElementCount)
lOffset = lOffset + Len(lElementCount)
CopyMemory lLbound, ByVal (ppArray + lOffset), ByVal Len(lLbound)
'===============================================
Dim strElement As String
If lElementCount > 0 Then
ReDim Elements(lElementCount)
For i = 0 To (lElementCount - 1)
'Copy the array string element pointer to lDataTemp
CopyMemory lDataTemp, ByVal lDataPtr, ByVal lElements
'strElement = Space(100)
'************************************************
'************************************************
'************************************************
'Here is my problem, if I comment these lines, everything works fine always, If not, after few function calls I get can not write or read memory errors and the program exits. I guess I am not copying the safearray string variables correctly from the Variantto the returned array, please help here.
'Copy the array string element to the variable strElement
CopyMemory strElement, lDataTemp, ByVal lElements
Elements(i) = StrConv(strElement, vbFromUnicode)
'CopyMemory Elements(i), lDataTemp, ByVal lElements
'************************************************
'************************************************
'************************************************
'Next array element pointer
lDataPtr = lDataPtr + lElements
strElement = ""
Next i
End If
'I tried to free the safearray, it works
'Debug.Print "SafeArrayDestroyData: " & SafeArrayDestroyData(ppArray)
'Debug.Print "SafeArrayDestroy: " & SafeArrayDestroy(ppArray)
End Sub