FFI Structure Help
Ron Teitelbaum
Ron at USMedRec.com
Mon Aug 14 21:13:27 UTC 2006
All,
I answered my own question. As it turned out the problem was not the
structure, but the size. I thought, incorrectly, that the size could be
sent in as an integer, now that we had a value. That was wrong; the
function was expecting an external buffer with the size value. Once I
changed the size function to return the buffer and used:
getCertProviderInfo
"#define CERT_KEY_PROV_INFO_PROP_ID 2"
| providerInfo aHandle buffer |
aHandle := ExternalAddress allocate: ((buffer := self
getCertProviderInfoSize) unsignedLongAt: 1).
providerInfo := Win32FFICertKeyProviderInfo fromHandle: aHandle.
self class certGetCertificateContextProperty: self
selectedCertificate getHandle asInteger property: 2 structPointerOrNull:
aHandle asInteger buffer: buffer asInteger.
buffer free.
self certProviderInfo: providerInfo.
It worked!
If you read the previous email, thank you for considering the problem!
Ron Teitelbaum
> -----Original Message-----
> From: squeak-dev-bounces at lists.squeakfoundation.org [mailto:squeak-dev-
> bounces at lists.squeakfoundation.org] On Behalf Of Ron Teitelbaum
> Sent: Monday, August 14, 2006 4:32 PM
> To: 'The general-purpose Squeak developers list'
> Subject: FFI Structure Help
>
> 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
|