FFI Structure Help
Ron Teitelbaum
Ron at USMedRec.com
Mon Aug 14 20:32:19 UTC 2006
Hello all,
I'm still having some trouble with FFI and was wondering if someone could
help explain why this is not working.
The following works on C++
typedef struct _CRYPT_KEY_PROV_INFO {
LPWSTR pwszContainerName;
LPWSTR pwszProvName;
DWORD dwProvType;
DWORD dwFlags;
DWORD cProvParam;
PCRYPT_KEY_PROV_PARAM rgProvParam;
DWORD dwKeySpec;
} CRYPT_KEY_PROV_INFO, *PCRYPT_KEY_PROV_INFO;
typedef struct _CRYPT_KEY_PROV_PARAM {
DWORD dwParam;
BYTE *pbData;
DWORD cbData;
DWORD dwFlags;
} CRYPT_KEY_PROV_PARAM, *PCRYPT_KEY_PROV_PARAM;
The equivilent on squeak:
Win32FFICertKeyProviderInfo class>>fields
fields
^#(
(pwszContainerName 'char *')
(pwszProvName 'char *')
(dwProvType 'long')
(dwFlags 'long')
(cProvParam 'long')
(rgProvParam 'Win32FFICertKeyProviderParameter')
(dwKeySpec 'long')
)
Win32FFICertKeyProviderParameter class >> fields
^#(
(dwParam 'long')
(pbData 'byte *')
(cbData 'long')
(dwFlags 'long')
)
The calls in C++:
CertGetCertificateContextProperty(
pCertContext, // A pointer to the certificate
// where the property will be set.
CERT_KEY_PROV_INFO_PROP_ID, // An identifier of the property to get.
// In this case,
// CERT_KEY_PROV_INFO_PROP_ID
NULL, // NULL on the first call to get the
// length.
&cbData)
Returns 200.
In squeak:
getCertProviderInfoSize
"#define CERT_KEY_PROV_INFO_PROP_ID 2"
| buffer result |
[buffer := (ExternalAddress allocate: 4).
self class certGetCertificateContextProperty: self
selectedCertificate getHandle asInteger property: 2 structPointerOrNull: nil
buffer: buffer asInteger
] ensure: [
result := buffer unsignedLongAt: 1.
buffer free.
].
^result
Returns 200. So this apparently works!
Here is the problem:
In C++:
if(!(pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(cbData)))
{
MyHandleError("Error in allocation of memory.");
}
if(CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pCryptKeyProvInfo,
&cbData))
{
printf("\n The current key container is %S.",
pCryptKeyProvInfo->pwszContainerName);
}
Works fine.
In squeak:
Win32FFICertificateStore>>getCertProviderInfo
"#define CERT_KEY_PROV_INFO_PROP_ID 2"
| providerInfo aHandle |
aHandle := ExternalAddress allocate: self getCertProviderInfoSize.
providerInfo := Win32FFICertKeyProviderInfo fromHandle: aHandle.
self class certGetCertificateContextProperty: self
selectedCertificate getHandle asInteger property: 2 structPointerOrNull:
aHandle asInteger buffer: self getCertProviderInfoSize.
self certProviderInfo: providerInfo.
Win32FFICertificateStore class>>certGetCertificateContextProperty: aContext
property: aProperty structPointerOrNull: pvData buffer: aBuffer
"BOOL WINAPI CertGetCertificateContextProperty(
PCCERT_CONTEXT pCertContext,
DWORD dwPropId,
void* pvData,
DWORD* pcbData
);
"
<apicall: bool 'CertGetCertificateContextProperty' (long long long
long) module: 'crypt32.dll'>
^self externalCallFailed
Blows up with a C0000005 access violation error.
I've tried changing the external type form long to
Win32FFICertKeyProviderInfo, and I've tried initializing the
Win32FFICertKeyProviderInfo rgProvParam: Win32FFICertKeyProviderParameter
new.
I've tried using externalNew instead of allocating 200 bytes in an external
address on both structures. But that hasn't worked; I still get the same
error.
I've even tried sending in a ByteArray new: 200, as a handle but that came
back with can not coerce arguments.
Sorry if I've been a bit of a pest. Now that I have the code I need working
in C++ I was hoping that the translation to squeak would go smoothly. I'm
sure I'm missing something, any suggestions are welcome!
Ron Teitelbaum
More information about the Squeak-dev
mailing list
|