#include <stdio.h>
#include <time.h>
#include <sys/stat.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
#ifndef _WIN32
  typedef unsigned long DWORD;
  typedef unsigned char BYTE;
  typedef void *HINSTANCE;
  typedef char CHAR;
#endif
typedef unsigned long hCERTSTORE;
typedef unsigned long hCERTCONTEXT;
typedef unsigned long hCERTCOLLECTION;
typedef unsigned long hCRYPTMSG;
typedef unsigned long HCRYPTPROV;
//Константы для Хранилища :
#define STORE_TYPE "t=L;"
#define STORE_HOST "127.0.0.1"
#define STORE_PORT "62222"
#define HEXCNUM    "861523C415DECF401B6ED30676A0A7E5CF95321D96D1A7023A658FA9B01011C6"
#define DN         "C=KZ;O=GAMMA;CN=cen1;"
void h2b(unsigned char *inbuf, long  insize, unsigned char *oubuf);
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 char* (_cdecl *errorstring)                     (const int err);
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 int (_cdecl *getnumbercertificate)
							(hCERTSTORE hStore,
							const char *DName,
							const unsigned char *serNum,
							const long len,
							const bool isRevoked,
							unsigned char *certBody,
							unsigned long *bodySize);							

cspopencontext				CSPOpenContext;
crtopenstore				CrtOpenStore;
crtclosestore				CrtCloseStore;
cspclosecontext				CSPCloseContext;
errorstring					ErrorString;
crtsetstorepropertyext		CrtSetStorePropertyExt;		
getnumbercertificate		GetNumberCertificate;

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;
   }
   ErrorString = (errorstring) GetProcAddress(lib,"ErrorString");
   if(!ErrorString)
   {
       printf("error load function - %s", "ErrorString");
       return 1;
   }   
   CrtSetStorePropertyExt = (crtsetstorepropertyext) GetProcAddress(lib,"CrtSetStorePropertyExt");
   if(!CrtSetStorePropertyExt)
   {
       printf("error load function - %s", "CrtSetStorePropertyExt");
       return 1;
   }  
   GetNumberCertificate = (getnumbercertificate) GetProcAddress (lib, "GetNumberCertificate");
   if (!GetNumberCertificate)
   {
        printf ("error load function - %s", "GetNumberCertificate");
        return 1;
   }
   return 0;
}
//---------------------------------------------------------------------------
int main(void)
{
HINSTANCE lib					=  NULL;
int ret							= 0;
int code						= 0;
int i, count;
hCERTSTORE hStore				= 0;
HCRYPTPROV hP					= 0;
unsigned char BinCerNum[32];
unsigned char *certBlob			= NULL;
unsigned long certSize;
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 ("%s [CSPOpenContext: error = %i\n]", ErrorString(code), code);
    throw code;
  }
  //открыть хранилище сертификатов
  code = CrtOpenStore(0, hP, 0, false, NULL, &hStore);
  if( code )
  {
    printf ("%s [CrtOpenStore: error = %i\n]", ErrorString(code), code);
    throw code;
  }
  //настроить хранилище сертификатов
  code = CrtSetStorePropertyExt(hStore, 0, STORE_TYPE, STORE_HOST, STORE_PORT, 300, 0, 0);
  if( code )
  {
    printf ("%s [CrtSetStorePropertyExt: error = %i\n]", ErrorString(code), code);
    throw code;
  }
  //получение сертификата по серийному номеру, функция обращается к хранилищю LDAP, поэтому вызов CrtSetStorePropertyExt обязателен
  h2b((unsigned char *)HEXCNUM,sizeof(HEXCNUM),BinCerNum);
  //получение размера сертификата
  code = GetNumberCertificate (hStore, DN, BinCerNum, sizeof(BinCerNum), false,  NULL, &certSize);
  if ( code )
  {
    printf ("%s [GetNumberCertificate: error = %i\n]", ErrorString(code), code);
    throw code;
  }
  printf ("GetNumberCertificate - OK\nCertificate size = %d\n",certSize);
  certBlob = (unsigned char*) calloc (certSize,sizeof(unsigned char));
  memset(certBlob,0,certSize);
  //получение сертификата в certBlob
  code = GetNumberCertificate (hStore, DN, BinCerNum, sizeof(BinCerNum), false,  certBlob, &certSize);
  if ( code )
  {
    printf ("%s [GetNumberCertificate: error = %i\n]", ErrorString(code), code);
    throw code;
  }
  printf ("GetNumberCertificate - OK\nGet Certificate Body - OK\n");
}
catch(int er){ret=er;}
if (certBlob) free (certBlob);
//закрыть хранилище сертификатов
if( hStore ) 
{
  CrtCloseStore(&hStore); 
  hStore = (hCERTSTORE) NULL;
}
//удалить контекст криптопровайдера
if( hP )
{
  CSPCloseContext(&hP); 
  hP = (HCRYPTPROV) NULL;
}
if (lib) lib_free( lib );
return ret;
}
//---------------------------------------------------------------------------
void h2b(unsigned char *inbuf, long  insize, unsigned char *oubuf)
{
 char *HAlf =(char*)"0123456789ABCDEF";
 long l;
 for (l=0;l<insize/2;l++) oubuf[l]=(unsigned char)
   ((((unsigned char) (strchr(HAlf,inbuf[2*l])-HAlf)<<4))|
     ((unsigned char) (strchr(HAlf,inbuf[(2*l)+1])-HAlf)));
}
//---------------------------------------------------------------------------
