Link to home
Create AccountLog in
Avatar of lapucca
lapucca

asked on

Getting memory corruption error when I call a C-code function.

Hi, I'm using VS2005, .net 2 for windows application.
The function that I'm trying to call through DLLImport has a parameter that
has a C code's vector's Itrator to a structure.  I Have marshalled the
structure in C# but how apparently C# doesn't have an equivalent of vector and iterator.  
I thought I'll create another C code function like this one but using ony the structure CUserContextData as a parameter.  I need help with the memory allocation in the program below.  Can someone hlep me out here on how to do this correctly?  Thank you.
I get a memory error when I try caling it righ now.


//-------- This is the C code for the import method of the dll
//extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob,
//vector <CUserContextData>::iterator userDataIter)
extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob,
CUserContextData userDataIter)
{
      _bstr_t temp;
      AsnData* pAsn;
      //int boolInt;
      std::wstring wsUID;

     
      if ( ( pAsn = AsnAlloc( NULL ) ) == NULL )
      {
            DbgLog( DL_ERROR, "Unable to allocate ASN.1 buffer" );
            return DE_MEMORY_ALLOCATION_FAILURE;
      }
      if ( !AsnPushTag(pAsn, (ASN_TAG$APPLICATION_START) ) )            
            goto failed;

      if (!AsnWriteInteger( pAsn, REVISION))
            goto failed;      

      if(userDataIter->bUnifiedID)//use UID
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;
      }
      else  //use indep ID
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;      
      }
      if(userDataIter->IID == NULL)
      {
            if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
                  goto failed;
      }
      else
      {
            _bstr_t bstrtUID = L"0"; //initilize the bstr
                  _itow(userDataIter->IID, bstrtUID, 10);

            if ( !AsnWriteGeneralString( pAsn, bstrtUID.operator const char *()))
                  goto failed;      
      }
     
      //WinUser name
      if(userDataIter->bWinLogOn)
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;

      }
      else//use indep User Name
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;            
      }

      //Geco
      if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
            goto failed;

      //Shell
      temp = userDataIter->shell.c_str();
      if ( !AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      //Home Driectory
      temp = userDataIter->homeDir.c_str();
      if ( !AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      //Primary Group SID
      temp = userDataIter->primaryGroupSID.c_str();
      if (!AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      if ( !AsnPopTag( pAsn ) )
            goto failed;
      *ppBlob = AsnExtractData( pAsn );
      AsnFree( pAsn );
      return DE_SUCCESS;
     
failed:
      DbgLog(DL_ERROR, "Failed to encode ASN.1 message packet" );
      AsnFree( pAsn );
      return DE_ENCODE_MESSAGE_PACKET_FAILURE;
}

Avatar of jkr
jkr
Flag of Germany image

Where exactly does the above code fail? And regarding 'temp', shouldn't that be

      //Home Driectory
      temp = userDataIter->homeDir.c_str();
      if ( !AsnWriteGeneralString( pAsn,(char*) temp))
            goto failed;      

      //Primary Group SID
      temp = userDataIter->primaryGroupSID.c_str();
      if (!AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

And, what's even more important - how are you managing that iterator you pass in?
Oh, by "how are you managing that iterator you pass in?" I mean how you are obtaining and storing it before you pass it to that function.

In general, I'd rather advise against marshalling a C++ construct if you are no providing some interpretation layer (line e.g. using "handle" like techniques where such a handle maps to an internal data structure and is seen as "opaque" by the caller). Any chance to redesign the whole thing and keep the iterator at the C++ side only? This would for sure make things easier.
Avatar of lapucca
lapucca

ASKER

Hi ikr,
Sorry, but I copied the wrong version to the question earlier.  The original C function uses a vector iterator as a parameter and I can't use DllImport in C# to call it because C# doesn't have a vector type.  I tried modifiying the original C code's function to accept only the structure of CUserContextData passed in as the parameter that contains the data to be encoded.  I was able to compile it successfully in VS C++ compiler as a un-managed code.  However, when i call this from my C# application, I would get a "memory corruption error".  I'm able to step through this fuction and I don't know if that is becuase it's a DllImport function.  Can you see what's wrong in my code here?  Thank you very much.

Here is how I declare this in C#:
        public class LibWrap
        {
             [DllImport("UnityDecodeAsnUser.dll", CharSet = CharSet.Unicode)]
            public static extern DE_ERRORS EncodeAsnUser(ref Blob blob,
                 [In, Out]CUserContextData m);
        }
Here is my structure marshaling
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public class CUserContextData
        {
            public int bWinLogOn = 0;
            public int bUnifiedID = 0;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String shell = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String homeDir = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String primaryGroupSID = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String LoginName = null;

            public int symarkUID = 0; //Unified User ID
            public int IID = 0;       //Independant ID
            public int Revision = 0;
        }

Here is the c code:

extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, CUserContextData userDataIter)
{
      _bstr_t temp;
      AsnData* pAsn;
      std::wstring wsUID;
      int REVISION=0;
      const char* EMPTY_STRING;
      EMPTY_STRING = "";

      if ( ( pAsn = AsnAlloc( NULL ) ) == NULL )
      {
            DbgLog( DL_ERROR, "Unable to allocate ASN.1 buffer" );
            return DE_MEMORY_ALLOCATION_FAILURE;
      }
      if ( !AsnPushTag(pAsn, (ASN_TAG$APPLICATION_START) ) )            
            goto failed;

      if (!AsnWriteInteger( pAsn, REVISION))
            goto failed;      

      if(userDataIter.bUnifiedID)//use UID
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;
      }
      else  //use indep ID
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;      
      }
      if(userDataIter.IID == NULL)
      {
            if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
                  goto failed;
      }
      else
      {
            _bstr_t bstrtUID = L"0"; //initilize the bstr
                  _itow(userDataIter.IID, bstrtUID, 10);

            if ( !AsnWriteGeneralString( pAsn, bstrtUID.operator const char *()))
                  goto failed;      
      }
      
      //WinUser name
      if(userDataIter.bWinLogOn)
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;

      }
      else//use indep User Name
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;            
      }

      //Geco
      if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
            goto failed;

      //Shell
      temp = userDataIter.shell;
      if ( !AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      //Home Driectory
      temp = userDataIter.homeDir;
      if ( !AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      //Primary Group SID
      temp = userDataIter.primaryGroupSID;
      if (!AsnWriteGeneralString( pAsn, temp.operator const char *()))
            goto failed;      

      if ( !AsnPopTag( pAsn ) )
            goto failed;
      *ppBlob = AsnExtractData( pAsn );
      AsnFree( pAsn );
      return DE_SUCCESS;
      
failed:
      DbgLog(DL_ERROR, "Failed to encode ASN.1 message packet" );
      AsnFree( pAsn );
      return DE_ENCODE_MESSAGE_PACKET_FAILURE;
}
ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
If you are using a vector, I'd rather pass the vector index as an unsigned integer than marshalling an iterator, since that is way less error-prone. E.g.

extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, unsigned int userDataIndex)
{
      _bstr_t temp;
      AsnData* pAsn;
      std::wstring wsUID;
      int REVISION=0;
      const char* EMPTY_STRING;
      EMPTY_STRING = "";

      if ( ( pAsn = AsnAlloc( NULL ) ) == NULL )
      {
            DbgLog( DL_ERROR, "Unable to allocate ASN.1 buffer" );
            return DE_MEMORY_ALLOCATION_FAILURE;
      }
      if ( !AsnPushTag(pAsn, (ASN_TAG$APPLICATION_START) ) )            
            goto failed;

      if (!AsnWriteInteger( pAsn, REVISION))
            goto failed;      

      if(userDataVector[userDataIndex].bUnifiedID)//use UID
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;
      }
      else  //use indep ID
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;      
      }
      if(userDataVector[userDataIndex].IID == NULL)
      {
            if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
                  goto failed;
      }
      else
      {
            _bstr_t bstrtUID = L"0"; //initilize the bstr
                  _itow(userDataVector[userDataIndex].IID, bstrtUID, 10);

            if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID))
                  goto failed;      
      }
     
      //WinUser name
      if(userDataVector[userDataIndex].bWinLogOn)
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;

      }
      else//use indep User Name
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;            
      }

      //Geco
      if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
            goto failed;

      //Shell
      temp = userDataVector[userDataIndex].shell;
      if ( !AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      //Home Driectory
      temp = userDataVector[userDataIndex].homeDir;
      if ( !AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      //Primary Group SID
      temp = userDataVector[userDataIndex].primaryGroupSID;
      if (!AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      if ( !AsnPopTag( pAsn ) )
            goto failed;
      *ppBlob = AsnExtractData( pAsn );
      AsnFree( pAsn );
      return DE_SUCCESS;
     
failed:
      DbgLog(DL_ERROR, "Failed to encode ASN.1 message packet" );
      AsnFree( pAsn );
      return DE_ENCODE_MESSAGE_PACKET_FAILURE;
}

And, please, get rid of calling '.operator const char *()' explicitly ;o)
Avatar of lapucca

ASKER

I changed to the pointer and it seems to be working but I can't be sure until I fix the error that I'm getting in the next line of code in C# where I'm adding the meetingBlg to the meeting class of AD.  I need to figure out how to convert the return pData to a byte array to do that.  But for now the function is retuning OK.  Thank you for all the input.  
ikr, as I said that I don't want to use vector or iterator becuase C# doesn't have that and I just have a user to encode at a time so there is no array.  Thanks and sorry for if I confuse you.
Avatar of lapucca

ASKER

So, this is what I have so far.  Thanks.

        public class CUserContextData
        {
            public int bWinLogOn = 0;
            public int bUnifiedID = 0;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String shell = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String homeDir = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String primaryGroupSID = null;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADSPATH_CHARS)]
            public String LoginName = null;

            public int symarkUID = 0; //Unified User ID
            public int IID = 0;       //Independant ID
            public int Revision = 0;
        }
CUnityDS.CUserContextData userContextData = new CUnityDS.CUserContextData();
//assign data
CUnityDS.DE_ERRORS errcode = CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE;
errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, userContextData);
deNewContextObject.Properties["meetingBlob"].Add((object)blob.pData);


extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, CUserContextData *userDataIter)
{
      _bstr_t temp;
      AsnData* pAsn;
      std::wstring wsUID;
      int REVISION=0;
      const char* EMPTY_STRING;
      EMPTY_STRING = "";

      if ( ( pAsn = AsnAlloc( NULL ) ) == NULL )
      {
            DbgLog( DL_ERROR, "Unable to allocate ASN.1 buffer" );
            return DE_MEMORY_ALLOCATION_FAILURE;
      }
      if ( !AsnPushTag(pAsn, (ASN_TAG$APPLICATION_START) ) )            
            goto failed;

      if (!AsnWriteInteger( pAsn, REVISION))
            goto failed;      

      if(userDataIter->bUnifiedID)//use UID
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;
      }
      else  //use indep ID
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;      
      }
      if(userDataIter->IID == NULL)
      {
            if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
                  goto failed;
      }
      else
      {
            _bstr_t bstrtUID = L"0"; //initilize the bstr
                  _itow(userDataIter->IID, bstrtUID, 10);

            if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID))
                  goto failed;      
      }
      
      //WinUser name
      if(userDataIter->bWinLogOn)
      {
            if (!AsnWriteInteger( pAsn, True) )
                  goto failed;

      }
      else//use indep User Name
      {
            if (!AsnWriteInteger( pAsn, False) )
                  goto failed;            
      }

      //Geco
      if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING))
            goto failed;

      //Shell
      temp = userDataIter->shell;
      if ( !AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      //Home Driectory
      temp = userDataIter->homeDir;
      if ( !AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      //Primary Group SID
      temp = userDataIter->primaryGroupSID;
      if (!AsnWriteGeneralString( pAsn, (char*)temp))
            goto failed;      

      if ( !AsnPopTag( pAsn ) )
            goto failed;
      *ppBlob = AsnExtractData( pAsn );
      AsnFree( pAsn );
      return DE_SUCCESS;
      
failed:
      DbgLog(DL_ERROR, "Failed to encode ASN.1 message packet" );
      AsnFree( pAsn );
      return DE_ENCODE_MESSAGE_PACKET_FAILURE;
}
>>I changed to the pointer

Why not using an integer as the index into the vector? That's easy to handle on the C# side and you just have to increment it...
Avatar of lapucca

ASKER

Hi ikr,
In C# I'm passing a user at a time to decode.  I don't have an array of users.  I thought I mentioned in the quedstion that I would like to use the function to convert 1 user at a time.  I'm sorry if I wasn't clear.  Thank you for your help.  
Can you help me with another problem  ID: 22637643?  I just posted this question and it's kind of the continuation of this question.  Thank you.