sfree(buffer);
static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,				WPARAM wParam, LPARAM lParam){    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:        if (help_path)            SetWindowLong(hwnd, GWL_EXSTYLE,                          GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP);        else {            /*             * If we add a Help button, this is where we destroy it             * if the help file isn't present.             */        }        requested_help = FALSE;	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);	{	    HMENU menu, menu1;	    menu = CreateMenu();	    menu1 = CreateMenu();	    AppendMenu(menu1, MF_ENABLED, IDC_LOAD, "&Load private key");	    AppendMenu(menu1, MF_ENABLED, IDC_SAVEPUB, "Save p&ublic key");	    AppendMenu(menu1, MF_ENABLED, IDC_SAVE, "&Save private key");	    AppendMenu(menu1, MF_SEPARATOR, 0, 0);	    AppendMenu(menu1, MF_ENABLED, IDC_QUIT, "E&xit");	    AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&File");	    state->filemenu = menu1;	    menu1 = CreateMenu();	    AppendMenu(menu1, MF_ENABLED, IDC_GENERATE, "&Generate key pair");	    AppendMenu(menu1, MF_SEPARATOR, 0, 0);	    AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH1, "SSH&1 key (RSA)");	    AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH2 &RSA key");	    AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH2 &DSA key");	    AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key");	    state->keymenu = menu1;	    menu1 = CreateMenu();	    AppendMenu(menu1, MF_ENABLED, IDC_IMPORT, "&Import key");	    AppendMenu(menu1, MF_SEPARATOR, 0, 0);	    AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH,		       "Export &OpenSSH key");	    AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM,		       "Export &ssh.com key");	    AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1,		       "&Conversions");	    state->cvtmenu = menu1;	    menu1 = CreateMenu();	    AppendMenu(menu1, MF_ENABLED, IDC_ABOUT, "&About");	    if (help_path)		AppendMenu(menu1, MF_ENABLED, IDC_GIVEHELP, "&Help");	    AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Help");	    SetMenu(hwnd, menu);	}	/*	 * 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);	}	{	    struct ctlpos cp, cp2;	    /* Accelerators used: acglops1rbd */	    ctlposinit(&cp, hwnd, 4, 4, 4);	    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, 5);	    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_KEYSSH2DSA, IDC_KEYSSH1);	CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,			   IDC_KEYSSH1, MF_BYCOMMAND);	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.	 */	ui_set_state(hwnd, state, 0);	/*	 * Load a key file if one was provided on the command line.	 */	if (cmdline_keyfile)	    load_key_file(hwnd, state, cmdline_keyfile, 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_KEYSSH1:	  case IDC_KEYSSH2RSA:	  case IDC_KEYSSH2DSA:	    {		state = (struct MainDlgState *)		    GetWindowLong(hwnd, GWL_USERDATA);		if (!IsDlgButtonChecked(hwnd, LOWORD(wParam)))		    CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA,				     LOWORD(wParam));		CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,				   LOWORD(wParam), MF_BYCOMMAND);	    }	    break;	  case IDC_QUIT:	    PostMessage(hwnd, WM_CLOSE, 0, 0);	    break;	  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_GIVEHELP:            if (HIWORD(wParam) == BN_CLICKED ||                HIWORD(wParam) == BN_DOUBLECLICKED) {                if (help_path) {                    WinHelp(hwnd, help_path, HELP_COMMAND,                            (DWORD)"JI(`',`puttygen.general')");                    requested_help = TRUE;                }            }	    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);		}		ui_set_state(hwnd, state, 1);		SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);		state->key_exists = FALSE;		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:          case IDC_EXPORT_OPENSSH:          case IDC_EXPORT_SSHCOM:	    state =		(struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	    if (state->key_exists) {		char filename[FILENAME_MAX];		char passphrase[PASSPHRASE_MAXLEN];		char passphrase2[PASSPHRASE_MAXLEN];                int type, realtype;                if (state->ssh2)                    realtype = SSH_KEYTYPE_SSH2;                else                    realtype = SSH_KEYTYPE_SSH1;                if (LOWORD(wParam) == IDC_EXPORT_OPENSSH)                    type = SSH_KEYTYPE_OPENSSH;                else if (LOWORD(wParam) == IDC_EXPORT_SSHCOM)                    type = SSH_KEYTYPE_SSHCOM;                else                    type = realtype;                if (type != realtype &&                    import_target_type(type) != realtype) {                    char msg[256];                    sprintf(msg, "Cannot export an SSH%d key in an SSH%d"                            " format", (state->ssh2 ? 2 : 1),                            (state->ssh2 ? 1 : 2));		    MessageBox(hwnd, msg,                               "PuTTYgen Error", MB_OK | MB_ICONERROR);		    break;                }		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, (type == realtype))) {		    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) {                        if (type != realtype)                            ret = export_ssh2(filename, type, &state->ssh2key,                                              *passphrase ? passphrase : NULL);                        else                            ret = ssh2_save_userkey(filename, &state->ssh2key,                                                    *passphrase ? passphrase :                                                    NULL);		    } else {                        if (type != realtype)                            ret = export_ssh1(filename, type, &state->key,                                              *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, 0)) {		    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:	  case IDC_IMPORT:	    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, LOWORD(wParam)==IDC_LOAD))		    load_key_file(hwnd, state, filename,				  LOWORD(wParam) != IDC_LOAD);	    }	    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);	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.	 */	ui_set_state(hwnd, state, 2);	break;      case WM_HELP:        if (help_path) {            int id = ((LPHELPINFO)lParam)->iCtrlId;            char *cmd = NULL;            switch (id) {              case IDC_GENERATING:              case IDC_PROGRESS:              case IDC_GENSTATIC:              case IDC_GENERATE:                cmd = "JI(`',`puttygen.generate')"; break;              case IDC_PKSTATIC:              case IDC_KEYDISPLAY:                cmd = "JI(`',`puttygen.pastekey')"; break;              case IDC_FPSTATIC:              case IDC_FINGERPRINT:                cmd = "JI(`',`puttygen.fingerprint')"; break;              case IDC_COMMENTSTATIC:              case IDC_COMMENTEDIT:                cmd = "JI(`',`puttygen.comment')"; break;              case IDC_PASSPHRASE1STATIC:              case IDC_PASSPHRASE1EDIT:              case IDC_PASSPHRASE2STATIC:              case IDC_PASSPHRASE2EDIT:                cmd = "JI(`',`puttygen.passphrase')"; break;              case IDC_LOADSTATIC:              case IDC_LOAD:                cmd = "JI(`',`puttygen.load')"; break;              case IDC_SAVESTATIC:              case IDC_SAVE:                cmd = "JI(`',`puttygen.savepriv')"; break;              case IDC_SAVEPUB:                cmd = "JI(`',`puttygen.savepub')"; break;              case IDC_TYPESTATIC:              case IDC_KEYSSH1:              case IDC_KEYSSH2RSA:              case IDC_KEYSSH2DSA:                cmd = "JI(`',`puttygen.keytype')"; break;              case IDC_BITSSTATIC:              case IDC_BITS:                cmd = "JI(`',`puttygen.bits')"; break;              case IDC_IMPORT:              case IDC_EXPORT_OPENSSH:              case IDC_EXPORT_SSHCOM:                cmd = "JI(`',`puttygen.conversions')"; break;            }            if (cmd) {                WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);                requested_help = TRUE;            } else {                MessageBeep(0);            }        }        break;      case WM_CLOSE:	state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);	sfree(state);        if (requested_help) {            WinHelp(hwnd, help_path, HELP_QUIT, 0);            requested_help = FALSE;        }	EndDialog(hwnd, 1);	return 0;    }    return 0;}