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