#include  <stdio.h>
#ifdef _WIN32
  #include <windows.h>
  #define CRYPT_VERIFYCONTEXT     0xF0000000
  #define strlib "lib\\strlib.dll"
#else
  #define GetProcAddress dlsym
  #define FreeLibrary dlclose
  #include <string>
  #include  <unistd.h>
  #include  <dlfcn.h>
  #define strlib "lib/libstr.1.0.0.sl"
  #define _cdecl
  #define CRYPT_VERIFYCONTEXT 0xF0000000
  #define TRUE 1
  #define FALSE 0
#endif
typedef unsigned long hPKICONTEXT;
typedef unsigned long hCRYPTMSG;
typedef unsigned long hCERTSTORE;
typedef unsigned long HCRYPTPROV;
typedef unsigned long hCERTCOLLECTION;
#ifndef _WIN32
  typedef unsigned long DWORD;
  typedef unsigned char BYTE;
  typedef void *HINSTANCE;
  typedef char CHAR;
#endif
// Константы для Хранилища :
#define STORE_HOST "127.0.0.1"
#define STORE_PORT "62222"

typedef int (_cdecl *cspopencontext)
                              (HCRYPTPROV *phProv,
                               CHAR *pszContainer,
                               DWORD dwProvType,
                               DWORD dwProvParam,
                               DWORD dwFlags,
                               BYTE * pbSignature,
                               DWORD dwSigLen,
                               BYTE * pbContainer,
                               DWORD * dwContLen,
                               HINSTANCE *phLib);
typedef int (_cdecl *crtopenstore)
                              (DWORD StoreProvider,
                               HCRYPTPROV hProv,
                               unsigned long dwFlags,
                               bool  bFlag,
                               const void *pvParam,
                               hCERTSTORE *phStore);
typedef int (_cdecl *crtclosestore)    (hCERTSTORE *phStore);
typedef int (_cdecl *cspclosecontext)  (HCRYPTPROV *phProv);
typedef int (_cdecl *crtsetstorepropertyext)
                              (const hCERTSTORE hStore,
                               const unsigned long Flags,
                               const char *DName,
                               const char *host,
                               const char *port,
                               const int timeOut,
                               const char *name,
                               const char *pass);
typedef char* (_cdecl *errorstring) (const int err);							   
typedef int (_cdecl *getnamecertificate)
                              (hCERTSTORE hStore,
                               const char *DName,
                               const char *keyOID,
                               const bool isValid,
                               const bool isRevoked,
                               unsigned char *certBody,
                               unsigned long *bodySize);							   

cspopencontext         CSPOpenContext;
crtopenstore           CrtOpenStore;
crtclosestore          CrtCloseStore;
cspclosecontext        CSPCloseContext;
crtsetstorepropertyext CrtSetStorePropertyExt;
getnamecertificate     GetNameCertificate;
errorstring            ErrorString;							   

HINSTANCE load_lib(char *lib)
{
   #ifdef _WIN32
	  return LoadLibraryA(lib);
   #else
	  return dlopen(lib,RTLD_LAZY);
   #endif
}
void lib_free( HINSTANCE Instance )
{
#ifdef _WIN32
  FreeLibrary(Instance);
#else
  dlclose(Instance);
#endif
}
int get_func(HINSTANCE lib)
{
   CSPOpenContext = (cspopencontext) GetProcAddress(lib,"CSPOpenContext");
   if(!CSPOpenContext)
   {
       printf("error load function - %s", "CSPOpenContext");
       return 1;
   }
   CrtOpenStore = (crtopenstore) GetProcAddress(lib,"CrtOpenStore");
   if(!CrtOpenStore)
   {
       printf("error load function - %s", "CrtOpenStore");
       return 1;
   }
   CSPCloseContext= (cspclosecontext) GetProcAddress(lib,"CSPCloseContext");
   if(!CSPCloseContext)
   {
       printf("error load function - %s", "CSPCloseContext");
       return 1;
   }
   CrtCloseStore= (crtclosestore) GetProcAddress(lib,"CrtCloseStore");
   if(!CrtCloseStore)
   {
       printf("error load function - %s", "CrtCloseStore");
       return 1;
   }
   CrtSetStorePropertyExt = (crtsetstorepropertyext)  GetProcAddress(lib,"CrtSetStorePropertyExt");
   if(!CrtSetStorePropertyExt)
   {
       printf("error load function - %s", "CrtSetStorePropertyExt");
       return 1;
   }
   GetNameCertificate = (getnamecertificate)  GetProcAddress(lib,"GetNameCertificate");
   if(!GetNameCertificate)
   {
       printf("error load function - %s", "GetNameCertificate");
       return 1;
   }   
   ErrorString = (errorstring) GetProcAddress(lib,"ErrorString");
   if(!ErrorString)
   {
       printf("error load function - %s", "ErrorString");
       return 1;
   }   
   return 0;
}
//------------------------------------------------------------------------------
 int main(void)
 {
   HINSTANCE        lib    	= NULL;
   int 				ret  	= 0;
   int 				code 	= 0;
   HCRYPTPROV 		hP     	=  0;
   hCERTSTORE 		hStore 	= (hCERTSTORE) 0;
   unsigned char 	*CertSignBlob;
   unsigned long 	CertSignSize=0;
   char DName[] = "CN=USER;O=LOCAL;C=KZ;"; 
   try
   {
	lib = load_lib(strlib);
	if( get_func(lib) )
	{
      printf("error load func.\n");
      exit(1);
	}   
     // Открыть контекст криптопровайдера :
     code = CSPOpenContext(&hP, NULL, 25, 0, CRYPT_VERIFYCONTEXT, NULL, 0, NULL, 0, NULL);
     if( code ) 
     {
       printf("CSPOpenContext, Error = %d (%s)\n", code, ErrorString(code));
       throw code;
     }
     // Открыть конекст хранилища :
     code = CrtOpenStore(0, hP, 0, false, NULL, &hStore);
     if( code ) 
     {
       printf("CrtOpenStore, Error = %d (%s)\n", code, ErrorString(code));
       throw code;
     }
     // Настроить хранилище сертификатов (обязательно, так как следующbt функциb обращаются к LDAP-хранилищу):
     code = CrtSetStorePropertyExt(hStore, 0, "t=L;", STORE_HOST, STORE_PORT, 300, "", "");
     if( code ) 
     {
       printf("CrtSetStorePropertyExt, Error = %d (%s)\n", code, ErrorString(code));
       throw code;
     }
     //Получить размер сертификата пользователя
     code = GetNameCertificate(hStore, DName, "1.3.6.1.4.1.6801.1.2.2", true, false, NULL, &CertSignSize);
     if( code )
     {
       printf("GetNameCertificate, Error = %d (%s)\n", code, ErrorString(code));
       throw code;
     }
     CertSignBlob = new unsigned char [CertSignSize];
     // Получить сертификат пользователя
     code = GetNameCertificate(hStore, DName, "1.3.6.1.4.1.6801.1.2.2", true, false, CertSignBlob, &CertSignSize);
     if( code )
     {
       printf("GetNameCertificate, Error = %d (%s)\n", code, ErrorString(code));
       throw code;
     }
     printf("Certificate was found, size = %d\n",CertSignSize);
     // Если не было ошибки, то сертификат хранится в CertSignBlob.
   }
   catch( int er )
   {
     ret = er;
   }
   if(CertSignBlob) delete [] CertSignBlob;
   // Освободить контекст хранилища :
   if( hStore ) 
   {
     CrtCloseStore(&hStore); 
     hStore = (hCERTSTORE) 0;
   }
   // Освободить контекст криптопровайдера :
   if( hP )
   { 
     CSPCloseContext(&hP); 
     hP = (HCRYPTPROV) 0;
   }
   if (lib) lib_free(lib);
   return ret;
 }
