• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 632
  • Last Modified:

Passing byte array as variant from VC-ActiveX to VB will crash

I'm passing binary byte data as a variant from a VC++ OCX to a VB program during a fired event. The application is crashing.
Pls. see code below:
Environment VS 6.0 prof.
==========================================================

// The VB side:
Private Sub Tool4MActX1_OnControlMessageReceived(ClientID As Integer, _
                                                 MsgType As Integer, _
                                                 SourceDeviceID As Integer, _
                                                 InstanceID As Integer, _
                                                 FBlockID As Integer, _
                                                 FunctionID As Integer, _
                                                 OpType As Integer, _
                                                 TelegramID As Integer, _
                                                 Timestamp As Long, _
                                                 DataLength As Long, _
                                                 MsgData As Variant _
                                                )
Dim DataBytes As String
Dim idx As Integer


DataBytes = " "

DataBytes = "Control message RX " _
           + Hex(SourceDeviceID) _
           + "." _
           + Hex(InstanceID) _
           + "." _
           + Hex(FBlockID) _
           + "." _
           + Hex(FunctionID) _
           + "." _
           + Hex(TelegramID) _
           + " (" _
           + Hex(DataLength) _
           + ") "
For idx = 0 To DataLength - 1
   DataBytes = DataBytes + Hex(MsgData(idx))
   DataBytes = DataBytes + " "
Next idx

OutputText (DataBytes)

End Sub




// The VC++ side:
{
  SAFEARRAYBOUND sabound[1] ;
  SAFEARRAY      *psa ;
  VARIANT        varTemp ;

  P_MA_MESSAGE   pM = &iMsg ;
  long           DataLength = pM->Length ;

  short ClientID   = pM->ClientID ;
  short MsgType    = pM->Type ;
  short DeviceID   = pM->DeviceID ;
  short FBlockID   = pM->FBlockID ;
  short InstanceID = pM->InstID ;
  short FunctionID = pM->FunctionID ;
  short OpType     = pM->OpType ;
  short TelegramID = pM->TelID ;
  long  Timestamp  = pM->Timestamp.HighResCnt ;

  // Create safearray of unsigned char.
  sabound[0].cElements = DataLength ;
  sabound[0].lLbound   = 0 ;
  psa = SafeArrayCreate( VT_UI1, 1, sabound ) ;

  if( psa )
  {
     // Copy binary data into array    
     unsigned char *pc ;

     SafeArrayAccessData( psa, (void HUGEP*  FAR*)&pc ) ;
     memcpy( pc, pM->Data, pM->Length ) ;
     SafeArrayUnaccessData( psa ) ;

     varTemp.vt = VT_ARRAY | VT_UI1 ;
     varTemp.parray  = psa ;
  }
 
  // Fire the event (will crash with an acces violation
  FireOnControlMessageReceived( &ClientID,
                                &MsgType,
                                &DeviceID,
                                &FBlockID,
                                &InstanceID,
                                &FunctionID,
                                &OpType,
                                &TelegramID,
                                &Timestamp,
                                &DataLength,
                                &varTemp
                              ) ;


Calling FireOnControlMessageReceived will cause an
access violation in MSVBVM60.DLL!

Output from the disassemble window within VS:

660FEA36   adc         byte ptr [esi-1],ah
660FEA39   adc         dword ptr [eax],edx
660FEA3B   push        es
660FEA3D   adc         dl,byte ptr [eax]
660FEA3F   sub         ax,offset ProcCallEngine+19E4h (660fea41)
660FEA43   pop         ss
660FEA45   adc         dl,byte ptr [eax]
660FEA47   cmp         di,word ptr [ecx]
660FEA4A   adc         byte ptr [esi+56h],ah
660FEA4D   mov         esi,ecx
660FEA4F   mov         cx,word ptr [esi]   // crash because ESI is 0x00000050
0
optitas
Asked:
optitas
  • 3
  • 2
  • 2
  • +1
1 Solution
 
rdrunnerCommented:
Try this when creating the array and passing it to the C OCX

dim a() as byte
a = StrConv(DataBytes, vbFromUnicode)
OutputText a

0
 
optitasAuthor Commented:
Just for clarification:
I'm not passing binary data (byte array) to the C++ OCX but to the VB part.
The problem is when calling the FireOnControlMessageReceived() function.
The "OutputText" function is a local funtion in the VB file and does not make any problems.
The problem must be somewhere in the declaration (and usage) of the variant varTemp which causes the VB6 dll to crash when transferring it to the VB part..
0
 
aquila98Commented:
maybe declaring
SAFEARRAY FAR* psa;

and replace
 SafeArrayAccessData( psa, (void HUGEP*  FAR*)&pc ) ;
 memcpy( pc, pM->Data, pM->Length ) ;
 SafeArrayUnaccessData( psa ) ;

 varTemp.vt = VT_ARRAY | VT_UI1 ;
 varTemp.parray  = psa ;

it is after all an array of byte that your are passing as a variant...
HRESULT hr;
long idx[ 1 ] ;
_variant_t vt;
for(i=0;i<pM->Length;i++)
{
   idx[0]= i;
   vt= _variant_t(pM->Data[i]);
   hr = SafeArrayPutElement(      psa ,      idx,  &vt ) ;
   assert(SUCCEEDED(hr));
}
VARIANT v ;
VariantInit(&v);

 v.parray = psa ;
 v.vt = VT_ARRAY | VT_VARIANT ;
 return v ;

...
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
optitasAuthor Commented:
Does NOT work.
Application still crashing...
First of all now VB gives me an error when running in debug mode in function: Tool4MActX1_OnControlMessageReceived():
Runtime error '458'
Variabel uses an automation type not supported in VisualBasic

Here's the modified code of the C++ OCX (VB code left unchanged!):

void CTool4MActXCtrl::FireTestEvent()
{
  SAFEARRAYBOUND sabound[1] ;
  SAFEARRAY FAR  *psa ;

  P_MA_MESSAGE   pM = &iMsg ;
  long           DataLength = pM->Length ;

  short ClientID   = pM->ClientID ;
  short MsgType    = pM->Type ;
  short DeviceID   = pM->DeviceID ;
  short FBlockID   = pM->FBlockID ;
  short InstanceID = pM->InstID ;
  short FunctionID = pM->FunctionID ;
  short OpType     = pM->OpType ;
  short TelegramID = pM->TelID ;
  long  Timestamp  = pM->Timestamp.HighResCnt ;

  // Create safearray of unsigned char.
  sabound[0].cElements = DataLength ;
  sabound[0].lLbound   = 0 ;
  psa = SafeArrayCreate( VT_UI1, 1, sabound ) ;

  HRESULT hr ;
  long    i ;
  long    idx[ 1 ] ;
  _variant_t vt ;

  if( psa )
  {
    for( i=0; i < DataLength; i++ )
    {
      idx[0]= i ;
      vt = _variant_t( pM->Data[ i ] ) ;
      hr = SafeArrayPutElement( psa, idx, &vt ) ;
      ASSERT( SUCCEEDED( hr ) ) ;
    }
  }
 
  VARIANT v ;
  VariantInit( &v ) ;

  v.parray = psa ;
  v.vt     = VT_ARRAY | VT_VARIANT ;

  // Fire the event (will still crash with an acces violation)
  FireOnControlMessageReceived( &ClientID,
                                &MsgType,
                                &DeviceID,
                                &FBlockID,
                                &InstanceID,
                                &FunctionID,
                                &OpType,
                                &TelegramID,
                                &Timestamp,
                                &DataLength,
                                &v
                              ) ;
}
0
 
aquila98Commented:
Try to create the array thus:
SafeArrayCreate(      VT_VARIANT,      1 , saBound ) ;

that's the only difference I noticed...

On the VB side, which variable cause the 458 error?

Cheers

TGIF!
0
 
rdrunnerCommented:
Hello optitas,

Please dont use the feedback function oin this way (Asking/explaining a question). Its a permanent record for finished questions. Dont give someone a negative feedback just for misunderstanding your question. The feedback is a permanent record. Please consider removing the feedback you gave. As you can imagine I dont like negative feedback ;)

Thanks in advance

P.s. : Try changing the Variable to long this will return you the memory address of the String. Then use memcopy to copy the data in a predefined string with the same size or byte array. VB and C handle stings quite differently internally.
0
 
optitasAuthor Commented:
To the moderator of this question:
Could you pls. close the request.
I solved the problem by myself.
The problem was that in multithreaded application some tricky posting of windows-messages had to be used to ensure proper operation of firing events to the ActiveX control.
In addition to that, some mutexes had to be used to wait unitll the message has been handled by the ActiveX container.
All of the abive code was correct and worked fine if the above mentioned solution was added to the ActiveX code.
Thanks for all the support, but none of the posted comments did get enough into depth to find a solution.
0
 
moduloCommented:
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 3
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now