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