Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport so I can call up a function written in C++ as unmanaged code and compiled as a dll us vs2005. My application is able to call the function, EncodeAsnUser. And it's returning OK but when I display the decoded data in another part of my application it shows no data has been decoded, all fiedls are either null or blanks. For some reason, I am not able to step through this function's code. However, I can see the userContextData does hold all the data that I assigned and that it's passing. I think the pbroblems is with my declaration of the parameters(blob and the userdata structure) . 1. Am I passing the userContextData as a pointer to the function? 2. Am I allocating memory correctly for the Blob? 3. Am I passing the Blob** correctly? Can someone see what I need to correct here to make it work? Thank you. [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; } public struct Blob { public IntPtr pData; public int nLength; public int nSize; } public class LibWrap { [DllImport("UnityDecodeAsnUser.dll", CharSet = CharSet.Unicode)] public static extern DE_ERRORS EncodeAsnUser(ref Blob blob, [In, Out]CUserContextData m); } // create an instance of the Blob structure CUnityDS.Blob blob = new CUnityDS.Blob(); //Encode the user data into a blob int nBytes = Marshal.SizeOf(typeof(CUnityDS.Blob)); IntPtr ptr = Marshal.AllocHGlobal(nBytes); // copy and pin the structure to that location Marshal.StructureToPtr(blob, ptr, true); // Pass it by reference // OK, now it's time to "reconsitute" the structure blob = (CUnityDS.Blob)Marshal.PtrToStructure(ptr, typeof(CUnityDS.Blob)); CUnityDS.DE_ERRORS errcode = CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE; errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, userContextData); //Convert from IntPtr data to byte[] which is needed for adding as meetingBlob int size = Marshal.SizeOf(blob); byte[] meetingBlob = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(blob.pData, meetingBlob, 0, size); //add the blob deNewContextObject.Properties["meetingBlob"].Add((object)meetingBlob); deNewContextObject.CommitChanges(); //This is the C++ function that I'm calling extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, CUserContextData *userData) { _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(userData->bUnifiedID)//use UID { if (!AsnWriteInteger( pAsn, True) ) goto failed; } else //use indep ID { if (!AsnWriteInteger( pAsn, False) ) goto failed; } if(userData->IID == NULL) { if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING)) goto failed; } else { _bstr_t bstrtUID = L"0"; //initilize the bstr _itow(userData->IID, bstrtUID, 10); if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID)) goto failed; } //WinUser name if(userData->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 = userData->shell; if ( !AsnWriteGeneralString( pAsn, (char*)temp)) goto failed; //Home Driectory temp = userData->homeDir; if ( !AsnWriteGeneralString( pAsn, (char*)temp)) goto failed; //Primary Group SID temp = userData->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; --
[quoted text, click to view] "Pucca" <Pucca@discussions.microsoft.com> wrote in message news:D206962A-0EFE-4B5C-858E-AE357A42E487@microsoft.com... > Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport > so > I can call up a function written in C++ as unmanaged code and compiled as > a > dll us vs2005. My application is able to call the function, > EncodeAsnUser. > And it's returning OK but when I display the decoded data in another part > of > my application it shows no data has been decoded, all fiedls are either > null > or blanks. For some reason, I am not able to step through this function's > code. However, I can see the userContextData does hold all the data that > I > assigned and that it's passing. > I think the pbroblems is with my declaration of the parameters(blob and > the > userdata structure) . > 1. Am I passing the userContextData as a pointer to the function? > 2. Am I allocating memory correctly for the Blob? > 3. Am I passing the Blob** correctly? > Can someone see what I need to correct here to make it work? Thank you. > > [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; > } > > public struct Blob > { > public IntPtr pData; > public int nLength; > public int nSize; > } > > public class LibWrap > { > [DllImport("UnityDecodeAsnUser.dll", CharSet = > CharSet.Unicode)] > public static extern DE_ERRORS EncodeAsnUser(ref Blob blob, > [In, Out]CUserContextData m); > } > > // create an instance of the Blob structure > CUnityDS.Blob blob = new CUnityDS.Blob(); > //Encode the user data into a blob > int nBytes = Marshal.SizeOf(typeof(CUnityDS.Blob)); > IntPtr ptr = Marshal.AllocHGlobal(nBytes); > > > // copy and pin the structure to that location > Marshal.StructureToPtr(blob, ptr, true); > > // Pass it by reference > // OK, now it's time to "reconsitute" the structure > blob = (CUnityDS.Blob)Marshal.PtrToStructure(ptr, > typeof(CUnityDS.Blob)); > > > CUnityDS.DE_ERRORS errcode = > CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE; > errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, > userContextData); > > //Convert from IntPtr data to byte[] which is > needed > for adding as meetingBlob > int size = Marshal.SizeOf(blob); > byte[] meetingBlob = new byte[size]; > > System.Runtime.InteropServices.Marshal.Copy(blob.pData, meetingBlob, 0, > size); > //add the blob > > deNewContextObject.Properties["meetingBlob"].Add((object)meetingBlob); > > deNewContextObject.CommitChanges(); > > //This is the C++ function that I'm calling > extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, > CUserContextData *userData) > { > _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(userData->bUnifiedID)//use UID > { > if (!AsnWriteInteger( pAsn, True) ) > goto failed; > } > else //use indep ID > { > if (!AsnWriteInteger( pAsn, False) ) > goto failed; > } > if(userData->IID == NULL) > { > if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING)) > goto failed; > } > else > { > _bstr_t bstrtUID = L"0"; //initilize the bstr > _itow(userData->IID, bstrtUID, 10); > > if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID)) > goto failed; > } > > //WinUser name > if(userData->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 = userData->shell; > if ( !AsnWriteGeneralString( pAsn, (char*)temp)) > goto failed; > > //Home Driectory > temp = userData->homeDir; > if ( !AsnWriteGeneralString( pAsn, (char*)temp)) > goto failed; > > //Primary Group SID > temp = userData->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; > -- > Thanks.
Pucca, You have a wrong idea abut how the Blob structure looks like. This struct holds a pointer and two integers, that means it's length is 12 bytes (in a 32 bit application), while you think that this struct holds the actual data of the blob on return, it just holds a pointer to the data and (I assume) the length of the actual data in nLength and the length of the buffer for the data in nSize. Note that here I assume that the "AsnExtractData" function called in the EncodeAsnUser function effectively fills the Blob with the data pointer and the size of the data in the buffer and the size of buffer . One way to get at the Blob and the Data is shown in the followin: [DllImport(...] public static extern DE_ERRORS EncodeAsnUser(ref IntPtr blob, ... ... // allocate memry for the blob IntPtr pBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Blob))); // call the function passing the pointer to the blob byref EncodeAsnUser(ref pBlob, userContextData); // copy the unmanaged blob to managed struct Blob Blob blob = (Blob)Marshal.PtrToStructure(pBlob, typeof(Blob));
Hi Willy , What you said about the nSize and nLength makes a lot of sense. You're also right about the pointer to the encoded data pointed by a pointer in the Blob struc. However, the length of the data is not return by AsnExtractData(code listed below). I am getting compliation error with my current code below. I'm getting error message below. Can you see what I need to correct here? Thank you. - cannot convert from 'ref System.IntPtr' to 'ref UnityLib.CUnityDS.Blob' - The best overloaded method match for UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref UnityLib.CUnityDS.Blob, UnityLib.CUnityDS.CUserContextData)' has some invalid arguments int dataSize = 512; // assume 512 byte buffer IntPtr pBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CUnityDS.Blob))); IntPtr pData = Marshal.AllocHGlobal(dataSize ); //CUnityDS.Blob blob = new CUnityDS.Blob(); blob.nSize = dataSize ; blob.pData = pData; Marshal.StructureToPtr(blob, pBlob, true); CUnityDS.LibWrap.EncodeAsnUser(ref pBlob, userContextData); // check return value from function // and proceed is success... blob = (CUnityDS.Blob)Marshal.PtrToStructure(pBlob, typeof(CUnityDS.Blob)); // assuming nLength is the size in bytes returned in the buffer pointed to by pData!! byte[] meetingBlob = new byte[blob.nLength]; Marshal.Copy(blob.pData, meetingBlob, 0, blob.nLength); // use data in meetingBlob here... // Free allocated memory! Marshal.FreeHGlobal(pBlob); Marshal.FreeHGlobal(pData); -- Blob * AsnExtractData( AsnData *pAsn ) { Blob *p; if ( pAsn == NULL ) return NULL; p = pAsn->pBlob; pAsn->pBlob = NULL; return p; } Thanks. [quoted text, click to view] "Willy Denoyette [MVP]" wrote: > "Pucca" <Pucca@discussions.microsoft.com> wrote in message > news:D206962A-0EFE-4B5C-858E-AE357A42E487@microsoft.com... > > Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport > > so > > I can call up a function written in C++ as unmanaged code and compiled as > > a > > dll us vs2005. My application is able to call the function, > > EncodeAsnUser. > > And it's returning OK but when I display the decoded data in another part > > of > > my application it shows no data has been decoded, all fiedls are either > > null > > or blanks. For some reason, I am not able to step through this function's > > code. However, I can see the userContextData does hold all the data that > > I > > assigned and that it's passing. > > I think the pbroblems is with my declaration of the parameters(blob and > > the > > userdata structure) . > > 1. Am I passing the userContextData as a pointer to the function? > > 2. Am I allocating memory correctly for the Blob? > > 3. Am I passing the Blob** correctly? > > Can someone see what I need to correct here to make it work? Thank you. > > > > [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; > > } > > > > public struct Blob > > { > > public IntPtr pData; > > public int nLength; > > public int nSize; > > } > > > > public class LibWrap > > { > > [DllImport("UnityDecodeAsnUser.dll", CharSet = > > CharSet.Unicode)] > > public static extern DE_ERRORS EncodeAsnUser(ref Blob blob, > > [In, Out]CUserContextData m); > > } > > > > // create an instance of the Blob structure > > CUnityDS.Blob blob = new CUnityDS.Blob(); > > //Encode the user data into a blob > > int nBytes = Marshal.SizeOf(typeof(CUnityDS.Blob)); > > IntPtr ptr = Marshal.AllocHGlobal(nBytes); > > > > > > // copy and pin the structure to that location > > Marshal.StructureToPtr(blob, ptr, true); > > > > // Pass it by reference > > // OK, now it's time to "reconsitute" the structure > > blob = (CUnityDS.Blob)Marshal.PtrToStructure(ptr, > > typeof(CUnityDS.Blob)); > > > > > > CUnityDS.DE_ERRORS errcode = > > CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE; > > errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, > > userContextData); > > > > //Convert from IntPtr data to byte[] which is > > needed > > for adding as meetingBlob > > int size = Marshal.SizeOf(blob); > > byte[] meetingBlob = new byte[size]; > > > > System.Runtime.InteropServices.Marshal.Copy(blob.pData, meetingBlob, 0, > > size); > > //add the blob > > > > deNewContextObject.Properties["meetingBlob"].Add((object)meetingBlob); > > > > deNewContextObject.CommitChanges(); > > > > //This is the C++ function that I'm calling > > extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, > > CUserContextData *userData) > > { > > _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(userData->bUnifiedID)//use UID > > { > > if (!AsnWriteInteger( pAsn, True) ) > > goto failed; > > } > > else //use indep ID > > { > > if (!AsnWriteInteger( pAsn, False) ) > > goto failed; > > } > > if(userData->IID == NULL) > > { > > if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING)) > > goto failed; > > } > > else > > { > > _bstr_t bstrtUID = L"0"; //initilize the bstr > > _itow(userData->IID, bstrtUID, 10); > > > > if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID)) > > goto failed; > > } > > > > //WinUser name > > if(userData->bWinLogOn) > > {
Hi Willy, I step through my C++ program that calls the same function, EncodeAsnUser, and it does returns the nLength, data length when it returns encoding data into the blob. I think if I am passing in the correct parameters then the nLength will be set. Sorry that i copy the error message incorrectly but you got it right there. It doesn't like the pBlob that I'm declaring and passing. How should I correct this? Thank you. -- Thanks. [quoted text, click to view] "Willy Denoyette [MVP]" wrote: > "Pucca" <Pucca@discussions.microsoft.com> wrote in message > news:8CC5707C-00A1-432B-8A0A-6ACD0045B27E@microsoft.com... > > Hi Willy , > > What you said about the nSize and nLength makes a lot of sense. You're > > also > > right about the pointer to the encoded data pointed by a pointer in the > > Blob > > struc. However, the length of the data is not return by > > AsnExtractData(code > > listed below). > > I am getting compliation error with my current code below. I'm getting > > error message below. Can you see what I need to correct here? Thank you. > > > > - cannot convert from 'ref System.IntPtr' to 'ref > > UnityLib.CUnityDS.Blob' > > - The best overloaded method match for > > UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref UnityLib.CUnityDS.Blob, > > UnityLib.CUnityDS.CUserContextData)' has some invalid arguments > > > > int dataSize = 512; // assume 512 byte buffer > > IntPtr pBlob = > > Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CUnityDS.Blob))); > > IntPtr pData = Marshal.AllocHGlobal(dataSize ); > > //CUnityDS.Blob blob = new CUnityDS.Blob(); > > blob.nSize = dataSize ; > > blob.pData = pData; > > Marshal.StructureToPtr(blob, pBlob, true); > > CUnityDS.LibWrap.EncodeAsnUser(ref pBlob, userContextData); > > // check return value from function > > // and proceed is success... > > blob = (CUnityDS.Blob)Marshal.PtrToStructure(pBlob, > > typeof(CUnityDS.Blob)); > > // assuming nLength is the size in bytes returned in the buffer pointed to > > by pData!! > > byte[] meetingBlob = new byte[blob.nLength]; > > Marshal.Copy(blob.pData, meetingBlob, 0, blob.nLength); > > // use data in meetingBlob here... > > // Free allocated memory! > > Marshal.FreeHGlobal(pBlob); > > Marshal.FreeHGlobal(pData); > > > > -- Blob * > > AsnExtractData( AsnData *pAsn ) > > { > > Blob *p; > > > > if ( pAsn == NULL ) > > return NULL; > > > > p = pAsn->pBlob; > > pAsn->pBlob = NULL; > > > > return p; > > } > > Thanks. > > > UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref UnityLib.CUnityDS.Blob, > UnityLib.CUnityDS.CUserContextData)' has some invalid arguments > > should read: > > UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref IntPtr, > UnityLib.CUnityDS.CUserContextData)' has some invalid arguments > > Don't know who has written the C++ function, I would definitely ask for a > rewrite, anyway it needs to return the length of the Data in the blob, > otherwise there is no way to correctly marshal the data back at the caller > side. > > Willy. >
Very sorry Willy. Sometimes I wonder how much code should I post. It just seems like a lot but I'll post them all in the future. Here are all the C++ functions called by the AsnEncodeUser function. Also, here is my current code. I modify to pass only the blob as the parameter. It gets rid of the compiling error but I'm still getting back 0 nlength after Encode. thank you. errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, userContextData); //current code int dataSize = 512; // assume 512 byte buffer IntPtr pBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (CUnityDS.Blob))); IntPtr pData = Marshal.AllocHGlobal(dataSize ); //CUnityDS.Blob blob = new CUnityDS.Blob(); blob.nSize = dataSize ; blob.pData = pData; Marshal.StructureToPtr(blob, pBlob, true); // check return value from function CUnityDS.DE_ERRORS errcode = CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE; errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, userContextData); if (errcode != CUnityDS.DE_ERRORS.DE_SUCCESS) result = false; else { blob = (CUnityDS.Blob)Marshal.PtrToStructure(pBlob, typeof(CUnityDS.Blob)); // nLength is the size in bytes returned in the buffer pointed to by pData!! // use data in meetingBlob byte[] meetingBlob = new byte[blob.nLength]; Marshal.Copy(blob.pData, meetingBlob, 0, blob.nLength); // Free allocated memory! Marshal.FreeHGlobal(pBlob); Marshal.FreeHGlobal(pData); //add the blob deNewContextObject.Properties["meetingBlob"].Add((object)meetingBlob); deNewContextObject.CommitChanges(); //Additional C++ fucnctions called by AsnEncodeUser AsnData * AsnAlloc( Blob * pBlob ) { AsnData * pAsn; pAsn = (AsnData *)calloc(1, sizeof(AsnData)); if ( pAsn == NULL ) return NULL; if ( pBlob ) pAsn->pBlob = BlobClone( pBlob ); else pAsn->pBlob = BlobAlloc( NULL, 256 ); if ( pAsn->pBlob == NULL ) { free( pAsn ); return NULL; } return pAsn; } Bool AsnPushTag(AsnData *pAsn, ASN_TAG tag) { AsnNode *pNode; if (!AsnWriteByte(pAsn, tag)) return False; pNode = (AsnNode*)calloc(1, sizeof(AsnNode)); if (!pNode) return False; pNode->nStart = BlobGetLength(pAsn->pBlob); pNode->pNext = pAsn->pNode; pAsn->pNode = pNode; return AsnWriteByte(pAsn, 0); /* placeholder for length */ } Bool AsnWriteInteger(AsnData *pAsn, int nValue) { int i = 0; Bit8 szBuf[sizeof(nValue)]; if (!AsnPushTag(pAsn, ASN_TAG$INTEGER)) return False; /* Make sure we store the integer in an endian neutral form */ do { szBuf[i++] = nValue & 0xFF; nValue >>= 8; } while ( nValue ); do { if (!AsnWriteByte(pAsn, szBuf[--i])) return False; } while ( i ); return AsnPopTag(pAsn); } Bool AsnWriteGeneralString(AsnData *pAsn, const char *p) { return (((AsnPushTag(pAsn, ASN_TAG$GENERAL_STRING)==True) && (AsnWrite(pAsn, p, strlen(p))==True) && (AsnPopTag(pAsn)==True) )==True) ? True : False; } Bool AsnPopTag(AsnData *pAsn) { AsnNode *pNode; Bit32 nLength; pNode = pAsn->pNode; if (!pNode) return False; nLength = BlobGetLength(pAsn->pBlob) - (pNode->nStart + 1); /* Now we can go back and write the actual length of the node */ if ( nLength <= 127 ) pAsn->pBlob->pData[pNode->nStart] = nLength; else if ( nLength <= 255 ) { /* We need to write a two-byte length - make sure we have room */ if (!AsnWriteByte(pAsn, 0)) return False; /* Move data down one byte */ memmove(pAsn->pBlob->pData + pNode->nStart + 2, pAsn->pBlob->pData + pNode->nStart + 1, nLength); pAsn->pBlob->pData[pNode->nStart ] = 0x81; pAsn->pBlob->pData[pNode->nStart + 1] = nLength; } else { /* We need to write a three-byte length - make sure we have room */ if (!AsnWriteByte(pAsn, 0)) return False; if (!AsnWriteByte(pAsn, 0)) return False; /* Move data down two bytes */ memmove(pAsn->pBlob->pData + pNode->nStart + 3, pAsn->pBlob->pData + pNode->nStart + 1, nLength); pAsn->pBlob->pData[pNode->nStart ] = 0x82; pAsn->pBlob->pData[pNode->nStart + 1] = nLength >> 8; pAsn->pBlob->pData[pNode->nStart + 2] = nLength & 0xff; } pAsn->pNode = pNode->pNext; free(pNode); return True; } Blob * AsnExtractData( AsnData *pAsn ) { Blob *p; if ( pAsn == NULL ) return NULL; p = pAsn->pBlob; pAsn->pBlob = NULL; return p; } -- Thanks. [quoted text, click to view] "Willy Denoyette [MVP]" wrote: > "Pucca" <Pucca@discussions.microsoft.com> wrote in message > news:CB9B02D1-EEDD-422B-A90A-BDA1285821E7@microsoft.com... > > Hi Willy, > > I step through my C++ program that calls the same function, EncodeAsnUser, > > and it does returns the nLength, data length when it returns encoding data > > into the blob. I think if I am passing in the correct parameters then the > > nLength will be set. > > Sorry that i copy the error message incorrectly but you got it right > > there. > > It doesn't like the pBlob that I'm declaring and passing. How should I > > correct this? Thank you. > > -- > > I can't help you if you don't post *all* of the relevant part of the code, > together with the DllImport declaration of the function you call. > Also you need to tell us what exactly is the error, after you have changed > the first argument into a "ref IntPtr" !!. > > > Willy. >
[quoted text, click to view] "Willy Denoyette [MVP]" <willy.denoyette@telenet.be> wrote in message news:OAFvqaZsHHA.4800@TK2MSFTNGP05.phx.gbl... > "Pucca" <Pucca@discussions.microsoft.com> wrote in message > news:D206962A-0EFE-4B5C-858E-AE357A42E487@microsoft.com... >> Hi, I'm using vs2005, .net 2, C# for Windows application. I use >> DllImport so >> I can call up a function written in C++ as unmanaged code and compiled as >> a >> dll us vs2005. My application is able to call the function, >> EncodeAsnUser. >> And it's returning OK but when I display the decoded data in another part >> of >> my application it shows no data has been decoded, all fiedls are either >> null >> or blanks. For some reason, I am not able to step through this >> function's >> code. However, I can see the userContextData does hold all the data that >> I >> assigned and that it's passing. >> I think the pbroblems is with my declaration of the parameters(blob and >> the >> userdata structure) . >> 1. Am I passing the userContextData as a pointer to the function? >> 2. Am I allocating memory correctly for the Blob? >> 3. Am I passing the Blob** correctly? >> Can someone see what I need to correct here to make it work? Thank you. >> >> [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; >> } >> >> public struct Blob >> { >> public IntPtr pData; >> public int nLength; >> public int nSize; >> } >> >> public class LibWrap >> { >> [DllImport("UnityDecodeAsnUser.dll", CharSet = >> CharSet.Unicode)] >> public static extern DE_ERRORS EncodeAsnUser(ref Blob blob, >> [In, Out]CUserContextData m); >> } >> >> // create an instance of the Blob structure >> CUnityDS.Blob blob = new CUnityDS.Blob(); >> //Encode the user data into a blob >> int nBytes = >> Marshal.SizeOf(typeof(CUnityDS.Blob)); >> IntPtr ptr = Marshal.AllocHGlobal(nBytes); >> >> >> // copy and pin the structure to that location >> Marshal.StructureToPtr(blob, ptr, true); >> >> // Pass it by reference >> // OK, now it's time to "reconsitute" the >> structure >> blob = (CUnityDS.Blob)Marshal.PtrToStructure(ptr, >> typeof(CUnityDS.Blob)); >> >> >> CUnityDS.DE_ERRORS errcode = >> CUnityDS.DE_ERRORS.DE_MEMORY_ALLOCATION_FAILURE; >> errcode = CUnityDS.LibWrap.EncodeAsnUser(ref blob, >> userContextData); >> >> //Convert from IntPtr data to byte[] which is >> needed >> for adding as meetingBlob >> int size = Marshal.SizeOf(blob); >> byte[] meetingBlob = new byte[size]; >> >> System.Runtime.InteropServices.Marshal.Copy(blob.pData, meetingBlob, 0, >> size); >> //add the blob >> >> deNewContextObject.Properties["meetingBlob"].Add((object)meetingBlob); >> >> deNewContextObject.CommitChanges(); >> >> //This is the C++ function that I'm calling >> extern "C" DE_ERRORS __declspec(dllexport)EncodeAsnUser(Blob** ppBlob, >> CUserContextData *userData) >> { >> _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(userData->bUnifiedID)//use UID >> { >> if (!AsnWriteInteger( pAsn, True) ) >> goto failed; >> } >> else //use indep ID >> { >> if (!AsnWriteInteger( pAsn, False) ) >> goto failed; >> } >> if(userData->IID == NULL) >> { >> if ( !AsnWriteGeneralString( pAsn, EMPTY_STRING)) >> goto failed; >> } >> else >> { >> _bstr_t bstrtUID = L"0"; //initilize the bstr >> _itow(userData->IID, bstrtUID, 10); >> >> if ( !AsnWriteGeneralString( pAsn, (char*)bstrtUID)) >> goto failed; >> } >> >> //WinUser name >> if(userData->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 = userData->shell; >> if ( !AsnWriteGeneralString( pAsn, (char*)temp)) >> goto failed; >> >> //Home Driectory >> temp = userData->homeDir; >> if ( !AsnWriteGeneralString( pAsn, (char*)temp)) >> goto failed; >> >> //Primary Group SID >> temp = userData->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; >> -- >> Thanks. > > > > Pucca, You have a wrong idea abut how the Blob structure looks like. > This struct holds a pointer and two integers, that means it's length is 12 > bytes (in a 32 bit application), while you think that this struct holds > the actual data of the blob on return, it just holds a pointer to the data > and (I assume) the length of the actual data in nLength and the length of > the buffer for the data in nSize. > > Note that here I assume that the "AsnExtractData" function called in the > EncodeAsnUser function effectively fills the Blob with the data pointer > and the size of the data in the buffer and the size of buffer . > > One way to get at the Blob and the Data is shown in the followin: > > [DllImport(...]
Hi Willy, I can't thank you enough for helping me with this difficult problem. It is now working! You were right from the very 1st posting. The function takes care of allocating all the memory for the data so I don't need to allocating any memory except for the pointer that I'm passing as you have it in your first example. It didn't work the 1st time because, 1, I used your 2nd example where we allocate all the memory. And 2, I missed the change in the declaration of "ref IntPtr blob" as shown below. That made all the difference. Now all my data are showing up correctly. Thank you and thank you again! DllImport(...] public static extern DE_ERRORS EncodeAsnUser(ref IntPtr blob, ... -- Thanks. [quoted text, click to view] "Willy Denoyette [MVP]" wrote: > "Pucca" <Pucca@discussions.microsoft.com> wrote in message > news:CB9B02D1-EEDD-422B-A90A-BDA1285821E7@microsoft.com... > > Hi Willy, > > I step through my C++ program that calls the same function, EncodeAsnUser, > > and it does returns the nLength, data length when it returns encoding data > > into the blob. I think if I am passing in the correct parameters then the > > nLength will be set. > > Sorry that i copy the error message incorrectly but you got it right > > there. > > It doesn't like the pBlob that I'm declaring and passing. How should I > > correct this? Thank you. > > -- > > I can't help you if you don't post *all* of the relevant part of the code, > together with the DllImport declaration of the function you call. > Also you need to tell us what exactly is the error, after you have changed > the first argument into a "ref IntPtr" !!. > > > Willy. >
[quoted text, click to view] "Pucca" <Pucca@discussions.microsoft.com> wrote in message news:8CC5707C-00A1-432B-8A0A-6ACD0045B27E@microsoft.com... > Hi Willy , > What you said about the nSize and nLength makes a lot of sense. You're > also > right about the pointer to the encoded data pointed by a pointer in the > Blob > struc. However, the length of the data is not return by > AsnExtractData(code > listed below). > I am getting compliation error with my current code below. I'm getting > error message below. Can you see what I need to correct here? Thank you. > > - cannot convert from 'ref System.IntPtr' to 'ref > UnityLib.CUnityDS.Blob' > - The best overloaded method match for > UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref UnityLib.CUnityDS.Blob, > UnityLib.CUnityDS.CUserContextData)' has some invalid arguments > > int dataSize = 512; // assume 512 byte buffer > IntPtr pBlob = > Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CUnityDS.Blob))); > IntPtr pData = Marshal.AllocHGlobal(dataSize ); > //CUnityDS.Blob blob = new CUnityDS.Blob(); > blob.nSize = dataSize ; > blob.pData = pData; > Marshal.StructureToPtr(blob, pBlob, true); > CUnityDS.LibWrap.EncodeAsnUser(ref pBlob, userContextData); > // check return value from function > // and proceed is success... > blob = (CUnityDS.Blob)Marshal.PtrToStructure(pBlob, > typeof(CUnityDS.Blob)); > // assuming nLength is the size in bytes returned in the buffer pointed to > by pData!! > byte[] meetingBlob = new byte[blob.nLength]; > Marshal.Copy(blob.pData, meetingBlob, 0, blob.nLength); > // use data in meetingBlob here... > // Free allocated memory! > Marshal.FreeHGlobal(pBlob); > Marshal.FreeHGlobal(pData); > > -- Blob * > AsnExtractData( AsnData *pAsn ) > { > Blob *p; > > if ( pAsn == NULL ) > return NULL; > > p = pAsn->pBlob; > pAsn->pBlob = NULL; > > return p; > } > Thanks.
UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref UnityLib.CUnityDS.Blob, UnityLib.CUnityDS.CUserContextData)' has some invalid arguments should read: UnityLib.CUnityDS.LibWrap.EncodeAsnUser(ref IntPtr, UnityLib.CUnityDS.CUserContextData)' has some invalid arguments Don't know who has written the C++ function, I would definitely ask for a rewrite, anyway it needs to return the length of the Data in the blob, otherwise there is no way to correctly marshal the data back at the caller side. Willy.
[quoted text, click to view] "Pucca" <Pucca@discussions.microsoft.com> wrote in message news:CB9B02D1-EEDD-422B-A90A-BDA1285821E7@microsoft.com... > Hi Willy, > I step through my C++ program that calls the same function, EncodeAsnUser, > and it does returns the nLength, data length when it returns encoding data > into the blob. I think if I am passing in the correct parameters then the > nLength will be set. > Sorry that i copy the error message incorrectly but you got it right > there. > It doesn't like the pBlob that I'm declaring and passing. How should I > correct this? Thank you. > --
I can't help you if you don't post *all* of the relevant part of the code, together with the DllImport declaration of the function you call. Also you need to tell us what exactly is the error, after you have changed the first argument into a "ref IntPtr" !!. Willy.
Don't see what you're looking for? Try a search.
|