Help using openCertStore() from crypt32.dll in java

934 views
Skip to first unread message

opa114

unread,
Dec 15, 2014, 9:47:55 AM12/15/14
to jna-...@googlegroups.com
Hi again,

i need help on running the openCertStore()-Function vom crypt32.dll in Java.

This is the way i imported the dll:

    public interface ExampleDLL extends Library {
         
ExampleDLL INSTANCE = (ExampleDLL) Native.loadLibrary("crypt32.dll", ExampleDLL.class);
       
}

The i want to call the openCertStore()-Function. More details about it here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376559%28v=vs.85%29.aspx. In C++ it looks liek this:

HCERTSTORE WINAPI CertOpenStore( _In_  LPCSTR lpszStoreProvider, _In_  DWORD dwMsgAndCertEncodingType, _In_  HCRYPTPROV_LEGACY hCryptProv, _In_  DWORD dwFlags, _In_  const void *pvPara );

But i don't know how do declare this function as native function in my class and which typed the c++ datatypes from the arguments match in java? So it would be so great and helpful if someone could paste a little bit of code here. So that i can understand it and go on.

Hope someone could help me. Thanks!



Daniel Doubrovkine

unread,
Dec 15, 2014, 3:00:17 PM12/15/14
to jna-...@googlegroups.com
There're quite a few examples in https://github.com/twall/jna/blob/master/contrib/platform/src/com/sun/jna/platform/win32/Crypt32.java, you should take a look at that and the associated tests.

Please contribute this code to JNA, see https://github.com/twall/jna/blob/master/www/Contributing.md

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

opa114

unread,
Dec 16, 2014, 6:59:10 AM12/16/14
to jna-...@googlegroups.com
i looked there, but problems not gone. i'm not a good programmer :(

this is my actual code:

package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;


public interface Crypt32 extends StdCallLibrary {
   
   
Crypt32 INSTANCE = (Crypt32) Native.loadLibrary("Crypt32", Crypt32.class, W32APIOptions.UNICODE_OPTIONS);
   
   
public HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, int dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, int dwFlags, const void *pvPara);

}

Following problems:
- What is the equvivalent data type of HCERTSTORE, LPCSTR, HCRYPTPROV_LEGACY and CONST VOID in Java? LPCSTR ist String i think - right? but what the others?

And how did i initialize and declare these Strings? For example the lpszStoreProvider? in C++ Documentation i could use CERT_STORE_PROV_SYSTEM. How do i match this in java? thanks.

Daniel Doubrovkine

unread,
Dec 16, 2014, 7:21:48 AM12/16/14
to jna-...@googlegroups.com
All the H* ones are HANDLE types, so probably just a declaration inheriting from HANDLE. 

CONST VOID is a Pointer.

LPCSTR is a String, in Java you just use it as is, a String.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

opa114

unread,
Dec 16, 2014, 11:02:16 AM12/16/14
to jna-...@googlegroups.com
now my code looks like this:

Codpublic class Example {  
   
public interface Crypt32 extends Library {
       
       
public boolean CertOpenStore(String lpszStoreProvider, int dwMsgAndCertEncodingType, Pointer hCryptProv, int dwFlags, Pointer pvPara);
       
       
/*      
       HCERTSTORE WINAPI CertOpenStore(
               _In_  LPCSTR lpszStoreProvider,
               _In_  DWORD dwMsgAndCertEncodingType,
               _In_  HCRYPTPROV_LEGACY hCryptProv,
               _In_  DWORD dwFlags,
               _In_  const void *pvPara
             );
       */
       
       
       
   
}
 
   
public static void main(String[] args) {    
   
Crypt32 lib = (Crypt32) Native.loadLibrary("Crypt32", Crypt32.class);
   
System.out.println(lib.CertOpenStore(10, 0, null, 0, null));
   

   
}
}

but on the msdn doku LPCSTR lpszStoreProvider is a Pointer to a String, so here it should be a String or not? An what are the exact values i have to set when i want to access the keystore MY on the local machine? and don't know what the return type is. it's very hard and complex for me :((

Daniel Doubrovkine

unread,
Dec 16, 2014, 11:39:18 AM12/16/14
to jna-...@googlegroups.com
Try to spend some time reading about mappings, first, I would start here: http://twall.github.io/jna/4.1.0/overview-summary.html#overview_description

JNA does all this work for you, so use a String and it will translate this correctly into a pointer when in native code. So yes, it should be a string. See MDSN for what the actual arguments to this need to be. The return time is a HANDLE it looks like, so HCERTSTORE which you should define as inheriting from HANDLE I suppose.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

opa114

unread,
Dec 17, 2014, 12:09:15 PM12/17/14
to jna-...@googlegroups.com
okay thanks. now it is running for first time :)

public class Example {  
   
public interface Crypt32 extends StdCallLibrary {
       
//public boolean CertEnumSystemStore(int dwFlags, Pointer pvSystemStoreLocationPara, Pointer pvArg, Pointer pfnEnum);
       
       
public HANDLE CertOpenStore(int lpszStoreProvider, int dwMsgAndCertEncodingType, int hCryptProv, int dwFlags, String pvPara);
       
// HANLDE


             
       
/*      
       HCERTSTORE WINAPI CertOpenStore(
               _In_  LPCSTR lpszStoreProvider,
               _In_  DWORD dwMsgAndCertEncodingType,
               _In_  HCRYPTPROV_LEGACY hCryptProv,
               _In_  DWORD dwFlags,
               _In_  const void *pvPara
             );
       */

       
       
public HANDLE CertEnumCertificatesInStore(HANDLE hCertStore, int pPrevCertContext);
       
// int certstore
       
/*
        PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
          _In_  HCERTSTORE hCertStore,
          _In_  PCCERT_CONTEXT pPrevCertContext
        */

       
// pcert = CAPI.CertEnumCertificatesInStore(store,pcert);
       
       
/*
       public native String CertGetNameStringW(
               int pCertContext,
               int dwType,
               int dwFlags,
               int TypePara) throws CryptoAPIException;
       */

       
public String CertGetNameStringW(HANDLE pCertContext, int dwType, int dwFlags, int TypePara);
       
       
       
/* int pCertContext
        DWORD WINAPI CertGetNameString(
          _In_   PCCERT_CONTEXT pCertContext,
          _In_   DWORD dwType,
          _In_   DWORD dwFlags,
          _In_   void *pvTypePara,
          _Out_  LPTSTR pszNameString,
          _In_   DWORD cchNameString
        );
        */


       
}
 
   
public static void main(String[] args) throws UnsupportedEncodingException, CryptoAPIException {    
   
Crypt32 lib2 = (Crypt32) Native.loadLibrary("Crypt32", Crypt32.class);
   
    HANDLE x
= lib2.CertOpenStore(9, 0, 0, 65536, "My");
   
if(x != null) {
       
System.out.println("yes " + x);
   
}

    HANDLE pcert
= null;
   
String pszNameString = null;
    pcert
= lib2.CertEnumCertificatesInStore(x, 0);
   
System.out.println(pcert);
   
String certname = lib2.CertGetNameStringW(pcert, 4, 0, 0);

   

but i got invalid memory acess error when running the CertGetNameStringW() function. How can i validate that the return values from the other functions are correct??


Daniel Doubrovkine

unread,
Dec 17, 2014, 1:31:35 PM12/17/14
to jna-...@googlegroups.com
Your signature for CertGetNameStringW is wrong. That function takes a pointer to a string and the number of characters, it doesn't magically return a String. There're other Win32 functions that are similar, but you'll have to dig a bit around the code to find a good example and how it's implemented.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

opa114

unread,
Dec 17, 2014, 1:56:15 PM12/17/14
to jna-...@googlegroups.com
i fixed it and added the parameters

public String CertGetNameStringW(HANDLE pCertContext, int dwType, int dwFlags, Pointer TypePara, String pszNameString, int cchNameString);

when i run it like:

CertGetNameStringW(pcert, 4, 0, null, pszNameString, 128);
i get invalid memory access, too. don't know how to solve it :((

Daniel Doubrovkine

unread,
Dec 17, 2014, 3:21:45 PM12/17/14
to jna-...@googlegroups.com

opa114

unread,
Dec 17, 2014, 6:50:32 PM12/17/14
to jna-...@googlegroups.com
didn't help me :(

croudet

unread,
Dec 17, 2014, 7:16:35 PM12/17/14
to jna-...@googlegroups.com
/* int pCertContext
        DWORD WINAPI CertGetNameString(
          _In_   PCCERT_CONTEXT pCertContext,
          _In_   DWORD dwType,
          _In_   DWORD dwFlags,
          _In_   void *pvTypePara,
          _Out_  LPTSTR pszNameString,
          _In_   DWORD cchNameString
        );
        */


pszNameString is the return value so you can't pass a String.
You can try
:
public String CertGetNameStringW(HANDLE pCertContext, int dwType, int dwFlags, Pointer TypePara, char[] pszNameString, int cchNameString);

char[] myNameString = new char[512]; // somethng big enough
CertGetNameStringW(..., myNameString, myNameString.length);

opa114

unread,
Dec 18, 2014, 6:37:47 AM12/18/14
to jna-...@googlegroups.com
i tried it with your solution, but same error (invalid memory access)
i set the char[] length to 4096 but did not work, too.

opa114

unread,
Dec 18, 2014, 7:23:50 AM12/18/14
to jna-...@googlegroups.com
this is the entire error message:

Exception in thread "main" java.lang.Error: Invalid memory access
    at com.sun.jna.Native.getStringBytes(Native Method)
    at com.sun.jna.Native.getString(Native.java:1830)
    at com.sun.jna.Pointer.getString(Pointer.java:718)
    at com.sun.jna.Function.invokeString(Function.java:658)
    at com.sun.jna.Function.invoke(Function.java:395)
    at com.sun.jna.Function.invoke(Function.java:315)
    at com.sun.jna.Library$Handler.invoke(Library.java:212)
    at com.sun.proxy.$Proxy0.CertGetNameStringW(Unknown Source)
    at com.sun.jna.platform.win32.Example.main(Example.java:79) -> this is the line where i call: CertGetNameStringW(pcert, 4, 0, null, myNameString, myNameString.length)

Daniel Doubrovkine

unread,
Dec 18, 2014, 8:19:43 AM12/18/14
to jna-...@googlegroups.com
You're merely in the beginning of your pain. Doing what you're trying to do is quite involved: you have to port all the structures into WinCrypt.java, then the method signatures, then getting the above to work. Even for someone very familiar with JNA, C and the Win32 API this is a fairly sizable amount of work - may I suggest finding a colleague who can help you with this? 

I am not saying you can't do it, but these issues that you are having are fairly basic and it's best if you found someone to pair with because the learning curve is going to have to be very steep.
 

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

opa114

unread,
Dec 18, 2014, 10:02:16 AM12/18/14
to jna-...@googlegroups.com
i notice that i'm in the beginnging of my pain :( theoreticaly i know what to do, but the problem is to write this in proper working code.

Can you tell me, how i could verify the returnin data from my functions? for exmaple when i call the openCertStore-Function and open the MY-Keystore on CurrentUser and i got a return value. But how can i check that that the function openend the right store and that the return value is valid. Maybe there is the problem.

I also rite a simple code in C++ with the CertOpenStore-Function. There i print out the return value which is a number, so this didn't help me, because when i run it again the return value is another number (on my java programm, too). so is there any way to check if the return value is a valid value?

i know i have so many questions and maybe i nerve, but i hoped that i get a little bit help here for this hard thing here :)

opa114

unread,
Dec 18, 2014, 10:28:48 AM12/18/14
to jna-...@googlegroups.com
is is not possible to edit an post here?

i verified some of my code now: the CertOpenStore() Function works. i checked it out and added the OpenExistingFlag to it and changed the storename to one which does not exist on my machine and then i get null as return value which is right. then i changed the name of the store to one which exists and i get a return value.
so i think this function works properly. now i have to test the CertEnumCertificatesInStore() and then in combiantion with the CertGetNameStringW

opa114

unread,
Dec 18, 2014, 10:44:05 AM12/18/14
to jna-...@googlegroups.com
i'm again :D have i to implement a structure like

typedef struct _CERT_CONTEXT {
  DWORD      dwCertEncodingType
;
  BYTE      
*pbCertEncoded;
  DWORD      cbCertEncoded
;
  PCERT_INFO pCertInfo
;
  HCERTSTORE hCertStore
;
} CERT_CONTEXT, *PCERT_CONTEXT;typedef const CERT_CONTEXT *PCCERT_CONTEXT;
by my own in java for the CertEnumCertificatesInStore() or is it enough to take the argument there (public HANDLE CertEnumCertificatesInStore(HANDLE hCertStore, HANDLE pPrevCertContext);) ?

opa114

unread,
Dec 18, 2014, 11:49:14 AM12/18/14
to jna-...@googlegroups.com
CertEnumCertificatesInStore() works, too. i access a keystore which has 2 entries - the functions put out 2 entries. tried with another keystore and worked.
the only problem is the CertGetNameStringW().. i tried so much but everytime the invalid memory access error comes. i think is must be something with the myNameString as parameter.

CertGetNameStringW(pcert, 5, 0, null, myNameString, myNameString.length);

When i run the function without the two parameters char[] pszNameString, int cchNameString i get no error but no output, too. i know that pszNameString is the output return string. but i think there is the problem. any tips? :) i do my best to solve the erros by myself, but a little bit help or tips would be nice.

public String CertGetNameStringW(HANDLE pCertContext, int dwType, int dwFlags, Pointer TypePara, char[] pszNameString, int cchNameString); --> invalid Memory Access Error

public String CertGetNameStringW(HANDLE pCertContext, int dwType, int dwFlags, int TypePara); -> No Error and no output


Daniel Doubrovkine

unread,
Dec 18, 2014, 11:55:15 AM12/18/14
to jna-...@googlegroups.com
Did you check out the implementation for GetUserNameW? You need to make a buffer, then potentially grow the buffer. You can't use a String.


--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

opa114

unread,
Dec 18, 2014, 12:19:59 PM12/18/14
to jna-...@googlegroups.com
Thanks. i've read it again. It's working now. I get the certificate name :) now the next steps are coming :D so for today i stop working now. thanks again! :)

opa114

unread,
Dec 19, 2014, 2:48:36 PM12/19/14
to jna-...@googlegroups.com
another question again: Is there a function for receiving all the certificate informations in C++? i don't found one in the msdn documentation. So i think i have to implement all the stuff by myself, like CERT_CONTEXT structure and CERT_INFO structure and then with a own Certificate class? Or is there an easier working way? thanks again! :)

opa114

unread,
Dec 23, 2014, 10:34:33 AM12/23/14
to jna-...@googlegroups.com
i implemented the Structure CERT_CONTEXT in a java class with some functions.

there i want to read the cbCertEncoded property. for this i need to read the memory address. How can i do this with JNA?

Jakub Sznapka

unread,
Feb 19, 2015, 2:21:50 AM2/19/15
to jna-...@googlegroups.com
Hi, can you post here the fully working code. I'm doing the same. Spent a half day on it and without any progress. Still with Memory Access error. Thanks!
Reply all
Reply to author
Forward
0 new messages