#include <stdio.h>
#include <windows.h>
#include "ginadlg.h"
#include "ni_common2.h"
#include "pc3comm.h"
#include "scio.h"

#define StrLen 256

int CALLBACK DlgProc(HWND    hDlg,
    UINT    Message,
    WPARAM  wParam,
    LPARAM  lParam);

NISTRUCT niStruct;
//char username[StrLen];
//char password[StrLen];

// for Smart Card
#define CommandClass 0x01
#define SCStrLen 32
int ni_send(LPSTR str, int len);
int ni_recv();
int ni_select(char r0, char r1);
int ni_readbinary(int len);
int ni_writebinary(LPSTR send_data, int len);
int WriteCard();

int port = 2;
void main()
{
    int rv;
	int flag = TRUE;

	// NI : close first 
	SCBclose();
		
	while (flag){
		rv = DialogBoxParam(NULL,
		                (LPTSTR) MAKEINTRESOURCE(IDD_NEW_USER_LOGON),
			                    NULL,
				                DlgProc,
					            0);
		wprintf(L"DlgProc returns %d with (%s)\n", 
			rv, niStruct.username);
		if (rv == IDCANCEL) exit (1);
		if (rv == IDOK) {
			// Since we got username and password, 
			//  I start ni_pam here to check u & p to kerberos4.
			ni_start(NULL, NULL);
			//wcscpy(niStruct.username, L"itoi");
			wcscpy(niStruct.domain, L"");
			//wcscpy(niStruct.password, L""); // password here
	
			// call ni_authenticate()
			rv = ni_authenticate(&niStruct);
			wprintf(L"ni_authenticate() returns %d\n", rv);

			if (rv == NI_SUCCESS) WriteCard();
			// logging out
			rv = ni_logout();
			wprintf(L"ni_logout() returns %d\n", rv);
			rv = ni_end();
			wprintf(L"ni_end() returns %d\n", rv);
			
		}
	}

}

int
CALLBACK
DlgProc(HWND    hDlg,
    UINT    Message,
    WPARAM  wParam,
    LPARAM  lParam)
{
    UINT urv;

	switch (Message)
    {
        case WM_INITDIALOG:
            //CenterWindow(hDlg);
            SetWindowLong(hDlg, GWL_USERDATA, lParam);
			printf("received WM_INITDIALOG\n");
            return(TRUE);

        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK)
            {
				//printf("received IDOK\n");
				urv = GetDlgItemText(hDlg, IDD_USER_NAME, 
					niStruct.username, StrLen);
				urv = GetDlgItemText(hDlg, IDD_PASSWORD,
					niStruct.password, StrLen);
				
                EndDialog(hDlg, IDOK);
			}
		
            if (LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, IDCANCEL);
            }
			return (TRUE);
	}
    return(FALSE);
}

int WriteCard()
{
    char cmd[64], buf[100];
    int i, rtn = 1;
    unsigned short len, r1, r2;
	char ni_str[SCStrLen];
	
    /* open reader */
    stuff_cmd(COMM, cmd);
    cmd[2] = port-1;
    len = 0;
    SCBios(cmd, buf, &len, &r1, &r2);
    if (r2) {
		printf("can't open reader\n");
		goto futz;
    }

    /* reset */
    stuff_cmd(RESET, cmd);
    len = cmd[4];
    SCBios(cmd, buf, &len, &r1, &r2);
    if (r2) {
		printf("Slag!\n");
		goto futz;
    }

	// NI original ...
    // open 3f.00 (serial number?) 
			
	if (ni_select(0x3f, 0x00) < 0) {
		printf("cannot select 3f.00\n");
		goto futz;
	}
	printf("selected 3f.00\n");

	if (ni_select(0x77, 0x77) < 0) {
		printf("cannot select 77.77\n");
		goto futz;
	}
	printf("selected 77.77\n");

	if (ni_select(0x77, 0x01) < 0) {
		printf("cannot select 77.01\n");
		goto futz;
	}
	printf("selected 77.01\n");
	
	for (i=0; i<SCStrLen; i++) ni_str[i]=0;
	WideCharToMultiByte(CP_ACP,0,niStruct.username,-1,ni_str,
						SCStrLen,(LPCSTR)0,(LPBOOL)0);
	printf("writing username %s\n", ni_str);
	
	if (ni_writebinary(ni_str, SCStrLen) < 0) {
		printf("cannot write\n");
		goto futz;
	}
		
	//ni_readbinary(SCStrLen);

	if (ni_select(0x3f, 0x00) < 0) {
		printf("cannot select 3f.00\n");
		goto futz;
	}
	printf("selected 3f.00\n");

	if (ni_select(0x77, 0x77) < 0) {
		printf("cannot select 77.77\n");
		goto futz;
	}
	printf("selected 77.77\n");

	if (ni_select(0x77, 0x02) < 0) {
		printf("cannot select 77.02\n");
		goto futz;
	}
	printf("selected 77.02\n");

	for (i=0; i<SCStrLen; i++) ni_str[i]=0;
		WideCharToMultiByte(CP_ACP,0,niStruct.password,-1,ni_str,
						SCStrLen,(LPCSTR)0,(LPBOOL)0);
	
		printf("writing password\n");
	if (ni_writebinary(ni_str, SCStrLen) < 0) {
		printf("cannot write\n");
		goto futz;
	}
	printf("wrote\n");
	
	//ni_readbinary(SCStrLen);

 //efutz:
    len = stuff_cmd(EJECT, cmd);
    len = 0;
    SCBios(cmd, buf, &len, &r1, &r2);

 futz:
    SCBclose();
    exit(rtn);

	return TRUE;
}

read_rec(rn, buf, n)
int rn, n;
char *buf;
{
    char cmd[8];
    unsigned short len, r1, r2;

    cmd[0] = (char)2;
    cmd[1] = (char)0xb2;
    cmd[2] = (char)(rn + 1);
    cmd[3] = (char)4;
    cmd[4] = len = (char)n;
    SCBios(cmd, buf, &len, &r1, &r2);
    if (r1 != 144 || r2 != 0) {
	printf("read: %x %x\n", r1, r2);
	return -1;
    }
    return 0;
}

/*
print_rec(cmd, buf, n)
char *cmd, *buf;
int n;
{
    int c;

    if (read_rec(n, buf, 0xf) < 0) {
	printf("can't read transaction %d\n", n);
	return -1;
    }

    if (buf[0] == 0)
	// empty record 
	return -1;

    switch (buf[14]) {
    case 0x4c:
	c = '+';
	break;
    case 0x49:
	c = 'I';
	break;
    case 0x50:
	c = '-';
	break;
    case 0x45:
    case 0x76:
	c = '>';
	break;
    default:
	c = '?';
	break;
    }

    // don't bother with uninteresting records unless -v 
    if (!vflag && c == '>')
	return 0;

    dump_date(buf);
    printf("  %c", c);
    dump_pennies(&buf[6]);
    printf("  ");
    if (c == '?') {
	dump_reply(buf, 0xf);
	printf("  ");
    }
    dump_location(buf[9]);
    printf("\n");

    return 0;
}

dump_location(n)
int n;
{
    switch (n) {
    case 0x0:
	printf("ISSUED");
	break;
    case 0x16:
	printf("Argus 535 candy machine");
	break;
    case 0x18:
	printf("snack machine");
	break;
    case 0x19:
	printf("pop machine");
	break;
    case 0x22:
	printf("Buhr pop machine");
	break;
    case 0x23:
	printf("Buhr candy machine");
	break;
    case 0x36:
	printf("EECS pop machine");
	break;
    case 0x37:
	printf("EECS snack machine");
	break;
    case 0x79:
	printf("SAB");
	break;
    case 0x7d:
	printf("NC Commons");
	break;
    case 0x7e:
	printf("Union basement");
	break;
    default:
	printf("unknown location 0x%x", n);
	break;
    }
}
*/
open_file(cmd, f0, f1)
char *cmd;
int f0, f1;
{
    char buf[4];
    unsigned short len, r1, r2;

    //cmd[0] = 1;
	//NI for CyberFlex JavaCard
	cmd[0] = (char)CommandClass;
    cmd[1] = (char)0xa4;
    cmd[2] = (char)0;
    cmd[3] = (char)0;
    cmd[4] = len = (char)2;
    buf[0] = (char)f0;
    buf[1] = (char)f1;
    SCBios(cmd, buf, &len, &r1, &r2);
	// NI
	printf("SCBios() puts %x %x %x %x %x.%x %x\n returns %x %x\n", 
		cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], buf[0], buf[1],
		r1, r2);
		
    if (r1 != 144 || r2 != 0)
	return -1;
    return 0;
}

/*
dump_date(buf)
char *buf;
{
    int month, year;

    year = bcd(buf[2]) + 1900;
    if (year < 1950)
	year += 100;

    month = bcd(buf[0]) - 1;
    if (month < 0 || month >= 12)
	month = 12;

    printf("%2d %s %d %2d:%02d ",
	   bcd(buf[1]),
	   monthtab[month],
	   year,
	   bcd(buf[3]),
	   bcd(buf[4]));
    dump_pennies(&buf[11]);
}
*/
/*
dump_pennies(buf)
char *buf;
{
    int pennies;

    pennies = hex(buf);
    printf("$%2d.%02d", pennies / 100, pennies % 100);
}
*/
/*
bcd(x)
int x;
{
    return (((x >> 4) & 0xf) * 10 + (x & 0xf));
}

  */
hex(buf)
char *buf;
{
    return(((buf[0] & 0xff) << 8) + (buf[1] & 0xff));
}

/*
dump_reply(p, n)
char *p;
int n;
{
    int i;

    for (i = 0; i < n; i++)
	printf("%02x ", p[i] & 0xff);
}
*/

int ni_send(LPSTR str, int len)
{
	int i, rtn;
	for (i=0; i<len; i++){
		rtn = scsend(&str[i], 1, 1/*==NO_LRC*/) ;
	}
	return rtn;
}

int ni_recv()
{
	int rtn;
	char recv[2];

	rtn = screcv(recv, 2, 1/*==NO_LRC*/);
	//printf("%x.%x\n", recv[0], recv[1]);
	if (recv[0] != (char)0x90 || recv[1] != (char)0) return -1;
	else return 0;
}

int ni_select(char r0, char r1)
{
	char str[7];
	
	str[0] = (char)0xc0;
	str[1] = (char)0xa4;
	str[2] = (char)0x00;
	str[3] = (char)0x00;
	str[4] = (char)0x02;
	str[5] = r0;
	str[6] = r1;
	ni_send(str, 7);
	return ni_recv(); 
}

int ni_readbinary(int len)
{
	char str[5], recv[SCStrLen];
	int i;
		
	str[0] = (char)0xf0;
	str[1] = (char)0xb0;
	str[2] = (char)0x00;
	str[3] = (char)0x00;
	str[4] = len;
	
	ni_send(str, 5);
	// the first byte of reply is command number (0xb0).
	screcv(recv, 1, 1);
	screcv(recv, len, 1/*==NO_LRC*/);
	//printf("%x.%x\n", recv[0], recv[1]);
	for (i=0; i<len; i++){
		recv[i] = recv[i] & 0xff;
		printf("%x ", recv[i]);
	}
	puts("");
	return 0;
}

int ni_writebinary(LPSTR send_data, int len)
{
	int i;
	char str[5+SCStrLen];

	str[0] = (char)0xf0;
	str[1] = (char)0xd6;
	str[2] = (char)0x00;
	str[3] = (char)0x00;
	str[4] = (char)len;
	
	for (i=0; i<len; i++){
		str[5+i] = send_data[i];
	}

	ni_send(str, 5+len);
	return ni_recv(); 
}

