#line 1 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
/* -*- c -*-
 * $Id: nt.cmod,v 1.10 2005/11/04 20:23:55 nilsson Exp $
 */

#ifdef __NT__

/* We need to do this before including global.h /Hubbe */
/* (because global.h includes windows.h which includes wincrypt.h ) */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif

#include "global.h"
#include "interpret.h"
#include "svalue.h"
#include "object.h"
#include "module_support.h"
#include "pike_macros.h"
#include "stralloc.h"

#include "nettle.h"

#include <winerror.h>
#include <wincrypt.h>

#ifndef NTE_EXISTS
#define NTE_EXISTS		0x8009000FL
#endif
#ifndef NTE_BAD_KEYSET
#define NTE_BAD_KEYSET		0x80090016
#endif
#ifndef NTE_KEYSET_NOT_DEF
#define NTE_KEYSET_NOT_DEF	0x80090019
#endif

/*! @module Crypto
 */

/*! @module NT
 */

/*! @class CryptContext
 *!
 *! Class representing an HCRYPTPROV handle.
 */


#undef class_CryptContext_defined
#define class_CryptContext_defined
struct program *CryptContext_program=NULL;
static int CryptContext_program_fun_num=-1;

#undef var_handle_CryptContext_defined
#define var_handle_CryptContext_defined

#undef THIS
#define THIS ((struct CryptContext_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef THIS_CRYPTCONTEXT
#define THIS_CRYPTCONTEXT ((struct CryptContext_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef OBJ2_CRYPTCONTEXT
#define OBJ2_CRYPTCONTEXT(o) ((struct CryptContext_struct *)(o->storage+CryptContext_storage_offset))

#undef GET_CRYPTCONTEXT_STORAGE
#define GET_CRYPTCONTEXT_STORAGE ((struct CryptContext_struct *)(o->storage+CryptContext_storage_offset)
static ptrdiff_t CryptContext_storage_offset;
struct CryptContext_struct {

#ifdef var_handle_CryptContext_defined
#line 51 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
HCRYPTPROV handle;
#endif /* var_handle_CryptContext_defined */
};
/*! @decl void create(string name, string csp, int type,@
   *!                   int flags)
   *! @param name
   *! Key container name. When flags is set to @[CRYPT_VERIFYCONTEXT]
   *! the name must be @expr{0@}.
   *!
   *! @param csp
   *! The name of the Crypto Service Provider to use. If set to
   *! @expr{0@} the user default CSP will be used.
   */
  #define f_CryptContext_create_defined
ptrdiff_t f_CryptContext_create_fun_num = 0;
void f_CryptContext_create(INT32 args) {
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
struct svalue * str1;
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
struct svalue * str2;
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
INT_TYPE type;
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
INT_TYPE flags;
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(args != 4) wrong_number_of_args_error("create",args,4);
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
str1=Pike_sp+0-4; dmalloc_touch_svalue(Pike_sp+0-4);
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
str2=Pike_sp+1-4; dmalloc_touch_svalue(Pike_sp+1-4);
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(Pike_sp[2-4].type != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("create",3,"int");
type=Pike_sp[2-4].u.integer;
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(Pike_sp[3-4].type != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("create",4,"int");
flags=Pike_sp[3-4].u.integer;
{
    if(THIS->handle) Pike_error("Already initialized.\n");
    if(!CryptAcquireContext(&THIS->handle,
			    (str1->type==T_STRING ? str1->u.string->str : 0),
			    (str2->type==T_STRING ? str2->u.string->str : 0),
			    type, flags)) {
      INT32 errcode = GetLastError();

      switch(errcode) {
      case NTE_EXISTS:
	Pike_error("CryptContext->create(): Key container already exists.\n");
	break;
      case NTE_BAD_KEYSET:
	Pike_error("CryptContext->create(): No default key container.\n");
	break;
      case NTE_KEYSET_NOT_DEF:
	Pike_error("CryptContext->create(): Crypto Service Provider not set up correctly.\n");
	break;
      default:
	Pike_error("CryptContext->create(): Failed with code 0x%08x.\n",
		   errcode);
	break;
      }
    }
    pop_n_elems(args);
  }

  }
/*! @decl string read(int size, string|void init)
   *!
   *! Retreive some random data. Calls CryptGenRandom in the NT API.
   */
  #define f_CryptContext_read_defined
ptrdiff_t f_CryptContext_read_fun_num = 0;
void f_CryptContext_read(INT32 args) {
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
INT_TYPE size;
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
struct pike_string * init;
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(args < 1) wrong_number_of_args_error("read",args,1);
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(args > 2) wrong_number_of_args_error("read",args,2);
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(Pike_sp[0-args].type != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("read",1,"int");
size=Pike_sp[0-args].u.integer;
if ((args > 1) && 
    ((Pike_sp[1-args].type != PIKE_T_INT) ||
     (Pike_sp[1-args].u.integer))) {
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
if(Pike_sp[1-args].type != PIKE_T_STRING) SIMPLE_BAD_ARG_ERROR("read",2,"string|void");
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
debug_malloc_pass(init=Pike_sp[1-args].u.string);
} else init=0;
{
    struct pike_string *res;
    if(size<0)
      Pike_error("Negative string length.\n");
    if(init) {
      NO_WIDE_STRING(init);
      if(size==0)
	size = init->len;
    }
    res = begin_shared_string(size);
    if(init && size>0)
      MEMCPY(res->str, init->str, MINIMUM(init->len,size));
    if(CryptGenRandom(THIS->handle, size, (BYTE*)res->str)) {
      pop_n_elems(args);
      push_string(end_shared_string(res));
    }
    else {
      pop_n_elems(args);
      free_string(end_shared_string(res));
      push_int(0);
    }
  }

  }

#undef internal_init_CryptContext_defined
#define internal_init_CryptContext_defined

#undef CryptContext_event_handler_defined
#define CryptContext_event_handler_defined
static void init_CryptContext_struct(void)
#line 122 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
{
    THIS->handle = 0;
  }
  
#undef internal_exit_CryptContext_defined
#define internal_exit_CryptContext_defined

#undef CryptContext_event_handler_defined
#define CryptContext_event_handler_defined
static void exit_CryptContext_struct(void)
#line 126 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
{
    if(THIS->handle)
      CryptReleaseContext(THIS->handle, 0);
  }

#ifdef CryptContext_event_handler_defined
static void CryptContext_event_handler(int ev) {
  switch(ev) {

#ifdef internal_init_CryptContext_defined
  case PROG_EVENT_INIT: init_CryptContext_struct(); break;

#endif /* internal_init_CryptContext_defined */

#ifdef internal_exit_CryptContext_defined
  case PROG_EVENT_EXIT: exit_CryptContext_struct(); break;

#endif /* internal_exit_CryptContext_defined */
  default: break; 
  }
}

#endif /* CryptContext_event_handler_defined */
/*! @endclass
 */

/*! @endmodule
 */

/*! @endmodule
 */

#line 141 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
void nt_init()
{
  
#ifdef class_CryptContext_defined

#ifdef PROG_CRYPTCONTEXT_ID
#line 49 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
  START_NEW_PROGRAM_ID(CRYPTCONTEXT);
#else
#line 49 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
  start_new_program();

#endif /* PROG_CRYPTCONTEXT_ID */

#ifndef tObjImpl_CRYPTCONTEXT

#undef tObjImpl_CRYPTCONTEXT
#define tObjImpl_CRYPTCONTEXT tObj

#endif /* tObjImpl_CRYPTCONTEXT */

#ifdef THIS_CRYPTCONTEXT

  CryptContext_storage_offset=ADD_STORAGE(struct CryptContext_struct);

#endif /* THIS_CRYPTCONTEXT */

#ifdef CryptContext_event_handler_defined
  pike_set_prog_event_callback(CryptContext_event_handler);

#endif /* CryptContext_event_handler_defined */

#ifdef f_CryptContext_create_defined
  f_CryptContext_create_fun_num =
#line 63 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
    ADD_FUNCTION2("create", f_CryptContext_create, tFunc(tOr("\10\200\0\0\0\177\377\377\377",tString) tOr("\10\200\0\0\0\177\377\377\377",tString) "\10\200\0\0\0\177\377\377\377" "\10\200\0\0\0\177\377\377\377",tVoid), ID_STATIC, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_CryptContext_create_defined */

#ifdef f_CryptContext_read_defined
  f_CryptContext_read_fun_num =
#line 96 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
    ADD_FUNCTION2("read", f_CryptContext_read, tFunc("\10\200\0\0\0\177\377\377\377" tOr(tString,tVoid),tString), 0, OPT_EXTERNAL_DEPEND);

#endif /* f_CryptContext_read_defined */
#line 49 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
  CryptContext_program=end_program();
#line 49 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
  CryptContext_program_fun_num=add_program_constant("CryptContext",CryptContext_program,0);

#endif /* class_CryptContext_defined */
#line 143 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
;

#define SIMPCONST(X) \
      add_integer_constant(#X,X,0);

  SIMPCONST(PROV_RSA_FULL);
  SIMPCONST(PROV_RSA_SIG);
  SIMPCONST(PROV_DSS);
  SIMPCONST(PROV_FORTEZZA);
  SIMPCONST(PROV_MS_EXCHANGE);
  SIMPCONST(PROV_SSL);

  SIMPCONST(CRYPT_VERIFYCONTEXT);
  SIMPCONST(CRYPT_NEWKEYSET);
  SIMPCONST(CRYPT_DELETEKEYSET);
#ifdef CRYPT_MACHINE_KEYSET
  SIMPCONST(CRYPT_MACHINE_KEYSET);
#endif
#ifdef CRYPT_SILENT
  SIMPCONST(CRYPT_SILENT);
#endif

}

void nt_exit()
{
  
#ifdef class_CryptContext_defined
  if(CryptContext_program) {
#line 49 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
    free_program(CryptContext_program);
    CryptContext_program=0;
  }

#endif /* class_CryptContext_defined */
#line 169 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Nettle/nt.cmod"
;
}

#endif /* __NT__ */

