c# - Marshaling CTL_USAGE -
i'm doing project work certificates , need convert ctl_usage structure c#. original structure follows:
typedef struct _ctl_usage { dword cusageidentifier; lpstr *rgpszusageidentifier; } ctl_usage, *pctl_usage, cert_enhkey_usage, *pcert_enhkey_usage;
according p/invoke website, c# structure should this:
[structlayout(layoutkind.sequential)] public struct ctl_usage { public int cusageidentifier; public intptr rgpszusageidentifier; }
to use code, convert each string want add structure byte array using encoding.ascii.getbytes(). turn byte array gchandle using gchandle.alloc(bytearray, gchandletype.pinned). add value array of intptrs , create gchandle intptr array , assign rgpszusageidentifier. call cryptencodeobjectex doesn't throw error, resulting data garbage , cannot unencrypted using cryptdecodeobject. encoding follows:
//enhancedusage list<string> containing enhanced usage oids ctl_usage usage = new ctl_usage() { cusageidentifier = enhancedusage.count, }; list<intptr> usagelist = new list<intptr>(); foreach (string s in enhancedusage) usagelist.add(new pinnedhandle(encoding.ascii.getbytes(s))); usage.rgpszusageidentifier = new pinnedhandle(usagelist.toarray()); intptr data = marshal.allochglobal(marshal.sizeof(usage)); marshal.structuretoptr(usage, data, false); int encodedsize = 0; if (!crypt32.cryptencodeobjectex((int)certencoding.x509asn, certoid.szoid_enhanced_key_usage, data, 0, intptr.zero, null, ref encodedsize)) throw new win32exception(); byte[] buffer = new byte[encodedsize]; if (!crypt32.cryptencodeobjectex((int)certencoding.x509asn, certoid.szoid_enhanced_key_usage, data, 0, intptr.zero, buffer, ref encodedsize)) throw new win32exception();
the pinnedhandle class wrapper gchandle. looks this:
public class pinnedhandle : idisposable { private gchandle handle; public pinnedhandle(object value) { handle = gchandle.alloc(value, gchandletype.pinned); } public static implicit operator intptr(pinnedhandle value) { return value.handle.addrofpinnedobject(); } public void dispose() { try { handle.free(); } catch { } } }
i don't think it's causing problem here i've used in other similar situations , they're working properly. idea how make work correctly?
allocate unmanaged memory block allochglobal
, copy intptr
instances usagelist
it, , pass block handle unmanaged function. use marshal.writeintptr method (intptr, int32, intptr)
this.
http://msdn.microsoft.com/en-us/library/ms146679.aspx
in interoperability code avoid pinning managed objects , prefer build native memory regions, using different marshal methods.
Comments
Post a Comment