CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH1);
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, IDC_KEYSSH1);
static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,				WPARAM wParam, LPARAM lParam){    enum {	controlidstart = 100,	IDC_TITLE,	IDC_BOX_KEY,	IDC_NOKEY,	IDC_GENERATING,	IDC_PROGRESS,	IDC_PKSTATIC, IDC_KEYDISPLAY,	IDC_FPSTATIC, IDC_FINGERPRINT,	IDC_COMMENTSTATIC, IDC_COMMENTEDIT,	IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,	IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT,	IDC_BOX_ACTIONS,	IDC_GENSTATIC, IDC_GENERATE,	IDC_LOADSTATIC, IDC_LOAD,	IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,	IDC_BOX_PARAMS,	IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,	IDC_BITSSTATIC, IDC_BITS,	IDC_ABOUT,    };    static const int nokey_ids[] = { IDC_NOKEY, 0 };    static const int generating_ids[] =	{ IDC_GENERATING, IDC_PROGRESS, 0 };    static const int gotkey_ids[] = {	IDC_PKSTATIC, IDC_KEYDISPLAY,	IDC_FPSTATIC, IDC_FINGERPRINT,	IDC_COMMENTSTATIC, IDC_COMMENTEDIT,	IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,	IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0    };    static const char generating_msg[] =	"Please wait while a key is generated...";    static const char entropy_msg[] =	"Please generate some randomness by moving the mouse over the blank area.";    struct MainDlgState *state;    switch (msg) {      case WM_INITDIALOG:	/*	 * Centre the window.	 */	{			       /* centre the window */	    RECT rs, rd;	    HWND hw;	    hw = GetDesktopWindow();	    if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))		MoveWindow(hwnd,			   (rs.right + rs.left + rd.left - rd.right) / 2,			   (rs.bottom + rs.top + rd.top - rd.bottom) / 2,			   rd.right - rd.left, rd.bottom - rd.top, TRUE);	}	state = smalloc(sizeof(*state));	state->generation_thread_exists = FALSE;	state->collecting_entropy = FALSE;	state->entropy = NULL;	state->key_exists = FALSE;	SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);	{	    struct ctlpos cp, cp2;	    /* Accelerators used: acglops1rbd */	    ctlposinit(&cp, hwnd, 10, 10, 10);	    bartitle(&cp, "Public and private key generation for PuTTY",		     IDC_TITLE);	    beginbox(&cp, "Key", IDC_BOX_KEY);	    cp2 = cp;	    statictext(&cp2, "No key.", 1, IDC_NOKEY);	    cp2 = cp;	    statictext(&cp2, "", 1, IDC_GENERATING);	    progressbar(&cp2, IDC_PROGRESS);	    bigeditctrl(&cp,			"&Public key for pasting into authorized_keys file:",			IDC_PKSTATIC, IDC_KEYDISPLAY, 7);	    SendDlgItemMessage(hwnd, IDC_KEYDISPLAY, EM_SETREADONLY, 1, 0);	    staticedit(&cp, "Key fingerprint:", IDC_FPSTATIC,		       IDC_FINGERPRINT, 75);	    SendDlgItemMessage(hwnd, IDC_FINGERPRINT, EM_SETREADONLY, 1,			       0);	    staticedit(&cp, "Key &comment:", IDC_COMMENTSTATIC,		       IDC_COMMENTEDIT, 75);	    staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASE1STATIC,			   IDC_PASSPHRASE1EDIT, 75);	    staticpassedit(&cp, "C&onfirm passphrase:",			   IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 75);	    endbox(&cp);	    beginbox(&cp, "Actions", IDC_BOX_ACTIONS);	    staticbtn(&cp, "Generate a public/private key pair",		      IDC_GENSTATIC, "&Generate", IDC_GENERATE);	    staticbtn(&cp, "Load an existing private key file",		      IDC_LOADSTATIC, "&Load", IDC_LOAD);	    static2btn(&cp, "Save the generated key", IDC_SAVESTATIC,		       "Save p&ublic key", IDC_SAVEPUB,		       "&Save private key", IDC_SAVE);	    endbox(&cp);	    beginbox(&cp, "Parameters", IDC_BOX_PARAMS);	    radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 3,		      "SSH&1 (RSA)", IDC_KEYSSH1,		      "SSH2 &RSA", IDC_KEYSSH2RSA,		      "SSH2 &DSA", IDC_KEYSSH2DSA, NULL);	    staticedit(&cp, "Number of &bits in a generated key:",		       IDC_BITSSTATIC, IDC_BITS, 20);	    endbox(&cp);	}	CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH1);	SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);	/*	 * Initially, hide the progress bar and the key display,	 * and show the no-key display. Also disable the Save	 * buttons, because with no key we obviously can't save	 * anything.	 */	hidemany(hwnd, nokey_ids, FALSE);	hidemany(hwnd, generating_ids, TRUE);	hidemany(hwnd, gotkey_ids, TRUE);	EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);	EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);	return 1;      case WM_MOUSEMOVE:	state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	if (state->collecting_entropy &&	    state->entropy && state->entropy_got < state->entropy_required) {	    state->entropy[state->entropy_got++] = lParam;	    state->entropy[state->entropy_got++] = GetMessageTime();	    SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS,			       state->entropy_got, 0);	    if (state->entropy_got >= state->entropy_required) {		struct rsa_key_thread_params *params;		DWORD threadid;		/*		 * Seed the entropy pool		 */		random_add_heavynoise(state->entropy, state->entropy_size);		memset(state->entropy, 0, state->entropy_size);		sfree(state->entropy);		state->collecting_entropy = FALSE;		SetDlgItemText(hwnd, IDC_GENERATING, generating_msg);		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,				   MAKELPARAM(0, PROGRESSRANGE));		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);		params = smalloc(sizeof(*params));		params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);		params->dialog = hwnd;		params->keysize = state->keysize;		params->is_dsa = state->is_dsa;		params->key = &state->key;		params->dsskey = &state->dsskey;		if (!CreateThread(NULL, 0, generate_rsa_key_thread,				  params, 0, &threadid)) {		    MessageBox(hwnd, "Out of thread resources",			       "Key generation error",			       MB_OK | MB_ICONERROR);		    sfree(params);		} else {		    state->generation_thread_exists = TRUE;		}	    }	}	break;      case WM_COMMAND:	switch (LOWORD(wParam)) {	  case IDC_COMMENTEDIT:	    if (HIWORD(wParam) == EN_CHANGE) {		state = (struct MainDlgState *)		    GetWindowLong(hwnd, GWL_USERDATA);		if (state->key_exists) {		    HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT);		    int len = GetWindowTextLength(editctl);		    if (*state->commentptr)			sfree(*state->commentptr);		    *state->commentptr = smalloc(len + 1);		    GetWindowText(editctl, *state->commentptr, len + 1);		    if (state->ssh2) {			setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,				      &state->ssh2key);		    } else {			setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,				      &state->key);		    }		}	    }	    break;	  case IDC_ABOUT:	    EnableWindow(hwnd, 0);	    DialogBox(hinst, MAKEINTRESOURCE(213), NULL, AboutProc);	    EnableWindow(hwnd, 1);	    SetActiveWindow(hwnd);	    return 0;	  case IDC_GENERATE:	    state =		(struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	    if (!state->generation_thread_exists) {		BOOL ok;		state->keysize = GetDlgItemInt(hwnd, IDC_BITS, &ok, FALSE);		if (!ok)		    state->keysize = DEFAULT_KEYSIZE;		/* If we ever introduce a new key type, check it here! */		state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1);		state->is_dsa = IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA);		if (state->keysize < 256) {		    int ret = MessageBox(hwnd,					 "PuTTYgen will not generate a key"					 " smaller than 256 bits.\n"					 "Key length reset to 256. Continue?",					 "PuTTYgen Warning",					 MB_ICONWARNING | MB_OKCANCEL);		    if (ret != IDOK)			break;		    state->keysize = 256;		    SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);		}		hidemany(hwnd, nokey_ids, TRUE);		hidemany(hwnd, generating_ids, FALSE);		hidemany(hwnd, gotkey_ids, TRUE);		EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 0);		EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 0);		EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);		EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);		EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 0);		EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0);		EnableWindow(GetDlgItem(hwnd, IDC_BITS), 0);		state->key_exists = FALSE;		SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);		state->collecting_entropy = TRUE;		/*		 * My brief statistical tests on mouse movements		 * suggest that there are about 2.5 bits of		 * randomness in the x position, 2.5 in the y		 * position, and 1.7 in the message time, making		 * 5.7 bits of unpredictability per mouse movement.		 * However, other people have told me it's far less		 * than that, so I'm going to be stupidly cautious		 * and knock that down to a nice round 2. With this		 * method, we require two words per mouse movement,		 * so with 2 bits per mouse movement we expect 2		 * bits every 2 words.		 */		state->entropy_required = (state->keysize / 2) * 2;		state->entropy_got = 0;		state->entropy_size = (state->entropy_required *				       sizeof(*state->entropy));		state->entropy = smalloc(state->entropy_size);		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,				   MAKELPARAM(0, state->entropy_required));		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);	    }	    break;	  case IDC_SAVE:	    state =		(struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	    if (state->key_exists) {		char filename[FILENAME_MAX];		char passphrase[PASSPHRASE_MAXLEN];		char passphrase2[PASSPHRASE_MAXLEN];		GetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,			       passphrase, sizeof(passphrase));		GetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,			       passphrase2, sizeof(passphrase2));		if (strcmp(passphrase, passphrase2)) {		    MessageBox(hwnd,			       "The two passphrases given do not match.",			       "PuTTYgen Error", MB_OK | MB_ICONERROR);		    break;		}		if (!*passphrase) {		    int ret;		    ret = MessageBox(hwnd,				     "Are you sure you want to save this key\n"				     "without a passphrase to protect it?",				     "PuTTYgen Warning",				     MB_YESNO | MB_ICONWARNING);		    if (ret != IDYES)			break;		}		if (prompt_keyfile(hwnd, "Save private key as:",				   filename, 1)) {		    int ret;		    FILE *fp = fopen(filename, "r");		    if (fp) {			char buffer[FILENAME_MAX + 80];			fclose(fp);			sprintf(buffer, "Overwrite existing file\n%.*s?",				FILENAME_MAX, filename);			ret = MessageBox(hwnd, buffer, "PuTTYgen Warning",					 MB_YESNO | MB_ICONWARNING);			if (ret != IDYES)			    break;		    }		    if (state->ssh2) {			ret = ssh2_save_userkey(filename, &state->ssh2key,						*passphrase ? passphrase :						NULL);		    } else {			ret = saversakey(filename, &state->key,					 *passphrase ? passphrase : NULL);		    }		    if (ret <= 0) {			MessageBox(hwnd, "Unable to save key file",				   "PuTTYgen Error", MB_OK | MB_ICONERROR);		    }		}	    }	    break;	  case IDC_SAVEPUB:	    state =		(struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	    if (state->key_exists) {		char filename[FILENAME_MAX];		if (prompt_keyfile(hwnd, "Save public key as:",				   filename, 1)) {		    int ret;		    FILE *fp = fopen(filename, "r");		    if (fp) {			char buffer[FILENAME_MAX + 80];			fclose(fp);			sprintf(buffer, "Overwrite existing file\n%.*s?",				FILENAME_MAX, filename);			ret = MessageBox(hwnd, buffer, "PuTTYgen Warning",					 MB_YESNO | MB_ICONWARNING);			if (ret != IDYES)			    break;		    }		    if (state->ssh2) {			ret = save_ssh2_pubkey(filename, &state->ssh2key);		    } else {			ret = save_ssh1_pubkey(filename, &state->key);		    }		    if (ret <= 0) {			MessageBox(hwnd, "Unable to save key file",				   "PuTTYgen Error", MB_OK | MB_ICONERROR);		    }		}	    }	    break;	  case IDC_LOAD:	    state =		(struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	    if (!state->generation_thread_exists) {		char filename[FILENAME_MAX];		if (prompt_keyfile(hwnd, "Load private key:", filename, 0)) {		    char passphrase[PASSPHRASE_MAXLEN];		    int needs_pass;		    int ver;		    int ret;		    char *comment;		    struct PassphraseProcStruct pps;		    struct RSAKey newkey1;		    struct ssh2_userkey *newkey2 = NULL;		    ver = keyfile_version(filename);		    if (ver == 0) {			MessageBox(NULL, "Couldn't load private key.",				   "PuTTYgen Error", MB_OK | MB_ICONERROR);			break;		    }		    comment = NULL;		    if (ver == 1)			needs_pass = rsakey_encrypted(filename, &comment);		    else			needs_pass =			    ssh2_userkey_encrypted(filename, &comment);		    pps.passphrase = passphrase;		    pps.comment = comment;		    do {			if (needs_pass) {			    int dlgret;			    dlgret = DialogBoxParam(hinst,						    MAKEINTRESOURCE(210),						    NULL, PassphraseProc,						    (LPARAM) & pps);			    if (!dlgret) {				ret = -2;				break;			    }			} else			    *passphrase = '\0';			if (ver == 1)			    ret =				loadrsakey(filename, &newkey1, passphrase);			else {			    newkey2 =				ssh2_load_userkey(filename, passphrase);			    if (newkey2 == SSH2_WRONG_PASSPHRASE)				ret = -1;			    else if (!newkey2)				ret = 0;			    else				ret = 1;			}		    } while (ret == -1);		    if (comment)			sfree(comment);		    if (ret == 0) {			MessageBox(NULL, "Couldn't load private key.",				   "PuTTYgen Error", MB_OK | MB_ICONERROR);		    } else if (ret == 1) {			EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);			EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);			EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);			EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1);			EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);			EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);			EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);			/*			 * Now update the key controls with all the			 * key data.			 */			{			    SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,					   passphrase);			    SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,					   passphrase);			    if (ver == 1) {				char buf[128];				char *savecomment;				state->ssh2 = FALSE;				state->commentptr = &state->key.comment;				state->key = newkey1;				/*				 * Set the key fingerprint.				 */				savecomment = state->key.comment;				state->key.comment = NULL;				rsa_fingerprint(buf, sizeof(buf),						&state->key);				state->key.comment = savecomment;				SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);				/*				 * Construct a decimal representation				 * of the key, for pasting into				 * .ssh/authorized_keys on a Unix box.				 */				setupbigedit1(hwnd, IDC_KEYDISPLAY,					      IDC_PKSTATIC, &state->key);			    } else {				char *fp;				char *savecomment;				state->ssh2 = TRUE;				state->commentptr =				    &state->ssh2key.comment;				state->ssh2key = *newkey2;	/* structure copy */				sfree(newkey2);				savecomment = state->ssh2key.comment;				state->ssh2key.comment = NULL;				fp =				    state->ssh2key.alg->				    fingerprint(state->ssh2key.data);				state->ssh2key.comment = savecomment;				SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);				sfree(fp);				setupbigedit2(hwnd, IDC_KEYDISPLAY,					      IDC_PKSTATIC, &state->ssh2key);			    }			    SetDlgItemText(hwnd, IDC_COMMENTEDIT,					   *state->commentptr);			}			/*			 * Finally, hide the progress bar and show			 * the key data.			 */			hidemany(hwnd, nokey_ids, TRUE);			hidemany(hwnd, generating_ids, TRUE);			hidemany(hwnd, gotkey_ids, FALSE);			state->key_exists = TRUE;		    }		}	    }	    break;	}	return 0;      case WM_DONEKEY:	state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	state->generation_thread_exists = FALSE;	state->key_exists = TRUE;	SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,			   MAKELPARAM(0, PROGRESSRANGE));	SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0);	EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);	EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);	EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);	EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1);	EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);	EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);	EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);	if (state->ssh2) {	    if (state->is_dsa) {		state->ssh2key.data = &state->dsskey;		state->ssh2key.alg = &ssh_dss;	    } else {		state->ssh2key.data = &state->key;		state->ssh2key.alg = &ssh_rsa;	    }	    state->commentptr = &state->ssh2key.comment;	} else {	    state->commentptr = &state->key.comment;	}	/*	 * Invent a comment for the key. We'll do this by including	 * the date in it. This will be so horrifyingly ugly that	 * the user will immediately want to change it, which is	 * what we want :-)	 */	*state->commentptr = smalloc(30);	{	    time_t t;	    struct tm *tm;	    time(&t);	    tm = localtime(&t);	    if (state->is_dsa)		strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", tm);	    else		strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", tm);	}	/*	 * Now update the key controls with all the key data.	 */	{	    char *savecomment;	    /*	     * Blank passphrase, initially. This isn't dangerous,	     * because we will warn (Are You Sure?) before allowing	     * the user to save an unprotected private key.	     */	    SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, "");	    SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, "");	    /*	     * Set the comment.	     */	    SetDlgItemText(hwnd, IDC_COMMENTEDIT, *state->commentptr);	    /*	     * Set the key fingerprint.	     */	    savecomment = *state->commentptr;	    *state->commentptr = NULL;	    if (state->ssh2) {		char *fp;		fp = state->ssh2key.alg->fingerprint(state->ssh2key.data);		SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);		sfree(fp);	    } else {		char buf[128];		rsa_fingerprint(buf, sizeof(buf), &state->key);		SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);	    }	    *state->commentptr = savecomment;	    /*	     * Construct a decimal representation of the key, for	     * pasting into .ssh/authorized_keys or	     * .ssh/authorized_keys2 on a Unix box.	     */	    if (state->ssh2) {		setupbigedit2(hwnd, IDC_KEYDISPLAY,			      IDC_PKSTATIC, &state->ssh2key);	    } else {		setupbigedit1(hwnd, IDC_KEYDISPLAY,			      IDC_PKSTATIC, &state->key);	    }	}	/*	 * Finally, hide the progress bar and show the key data.	 */	hidemany(hwnd, nokey_ids, TRUE);	hidemany(hwnd, generating_ids, TRUE);	hidemany(hwnd, gotkey_ids, FALSE);	break;      case WM_CLOSE:	state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	sfree(state);	EndDialog(hwnd, 1);	return 0;    }    return 0;}