2012-02-02 133 views
0

我有一个程序需要将数据从C++传递到C#并返回进行处理。为了做到这一点,我已经检索了一个结构,将其转换为一个字节数组,然后在另一端将其转换回来。但是,在将其转换回来时,数据不正确,即使内存转储显示每个变量的内存值都相同。传递结构似乎损坏数据

这里是检索值的代码:

BYTE * cpiBuffer = (BYTE*)calloc(_PublicKey->Length, sizeof(BYTE)); 
for(int i = 0; i < _PublicKey->Length; i++) 
    cpiBuffer[i] = _PublicKey[i]; 
PCERT_PUBLIC_KEY_INFO cpi = (PCERT_PUBLIC_KEY_INFO)cpiBuffer; 

当看着他们:

array<Byte>^GetPublicKeyBlob(String^ContainerName) { 
    const TCHAR * tContainer = context->marshal_as<const TCHAR*>(ContainerName); 
    HCRYPTPROV hProv = NULL; 
    CryptAcquireContext(&hProv, tContainer, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET); 
    DWORD dwKeySize = 0; 
    CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, &dwKeySize); 
    PCERT_PUBLIC_KEY_INFO pbKey = (PCERT_PUBLIC_KEY_INFO)calloc(dwKeySize, sizeof(BYTE)); 
    CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, (PCERT_PUBLIC_KEY_INFO)pbKey, &dwKeySize); 
    array<Byte>^retVal = gcnew array<Byte>(dwKeySize); 
     for(int i = 0; i < dwKeySize; i++) 
      retVal[i] = ((BYTE*)pbKey)[i]; 

    free(pbKey); 
return retVal; 
} 

然后在另一端,我用下面的代码改回PCERT_PUBLIC_KEY_INFO结构在内存转储中,pbKey,retVal,_PublicKey,cpiBuffer和cpi都具有完全相同的值。但是当将cpi看作一个结构时,Algorithm.pszObjId指向一些错误的内存位置,当我尝试在函数中使用它时,它会失败。我在这里做错了什么?

+0

你是什么意思“Algorithm.pszObjId指向一些错误的内存位置”?它是一个指针吗? – 2012-02-02 16:44:13

+0

这是一个LPSTR。当我在表中扩展结构时,它指向的不是结构内部的存储位置,而当我获得原始值时,它指向结构内的位置。 – 2012-02-02 16:49:49

回答

0
typedef struct _CRYPT_ALGORITHM_IDENTIFIER { 
    LPSTR   pszObjId; 
    CRYPT_OBJID_BLOB Parameters; 
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER; 

正如你所看到的,pszObjId是一个指针,它的内容是在内存中的某个地方。通过将PCERT_PUBLIC_KEY_INFO结构强制转换为字节数组,您只能获取指针的值,而不是它指向的值。

在附注上,我不确定你为什么编组为TCHAR *,如果你想要字节,那么你应该使用char *或unsigned char *。如果定义了UNICODE,则TCHAR将为wchar_t,这可能会造成一些困难。

+0

TCHAR *只是习惯的力量。这是扔在一起的代码,而不是生产。 如果不是来自铸造,我会如何获得原始结构? – 2012-02-02 17:04:01

+0

我没有确定的答案,因为我不知道如何创建这些结构,谁分配字符串以及谁负责释放它。但我猜你可以创建一个函数,该函数知道如何序列化结构,按成员的成员,将字符串序列化为以空字符结尾的字符数组或带有大小前缀。 – 2012-02-02 17:30:37

+0

对CryptExportPublicKeyInfo的第一个调用返回CERT_PUBLIC_KEY_INFO结构所需的缓冲区的长度。然后我分配这些内存并再次调用该函数,并将数据传递到缓冲区。 – 2012-02-02 18:09:13