--- /dev/null
+/*
+ * Copyright (C) 1997 Cygnus Solutions.
+ *
+ * Author: Michael Graff
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "krb5.h"
+
+#include "vardlg.h"
+#include "gic.h"
+
+/*
+ * Steps performed:
+ *
+ * 1) Create the dialog with all the windows we will need
+ * later. This is done by calling vardlg_build() from
+ * gic_prompter().
+ *
+ * 2) Run the dialog from within gic_prompter(). If the return
+ * value of the dialog is -1 or IDCANCEL, return an error.
+ * Otherwise, return success.
+ *
+ * 3) From within the dialog initialization code, call
+ * vardlg_config(), which will:
+ *
+ * a) Set all the label strings in all the entry labels and
+ * the banner.
+ *
+ * b) Set the maximum input lengths on the entry fields.
+ *
+ * c) Calculate the size of the text used within the banner.
+ *
+ * d) Calculate the longest string of text used as a label.
+ *
+ * e) Resize each label and each entry within the dialog
+ * to "look nice."
+ *
+ * f) Place the OK and perhaps the Cancel buttons at the bottom
+ * of the dialog.
+ *
+ * 4) When the OK button is clicked, copy all the values from the
+ * input fields and store them in the pointers we are given.
+ * Also, set the actual lengths to what we collected from the
+ * entries. Finally, call EndDialog(IDOK) to end the dialog.
+ */
+
+/*
+ * Yes, a global. It is a PITA to not use them in windows.
+ */
+gic_data *gd;
+
+
+/*
+ * initialize the dialog
+ */
+static BOOL
+gic_dialog_init(HWND hwnd, HWND hwndFocus, LPARAM lParam)
+{
+ vardlg_config(hwnd, gd->width, gd->banner, gd->num_prompts,
+ gd->prompts, (WORD)(gd->id));
+
+ return FALSE;
+}
+
+/*
+ * process dialog "commands"
+ */
+static void
+gic_dialog_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify)
+{
+
+ int n;
+ WORD id;
+
+ /*
+ * We are only interested in button clicks, and then only of
+ * type IDOK or IDCANCEL.
+ */
+ if (codeNotify != BN_CLICKED)
+ return;
+ if (cid != IDOK && cid != IDCANCEL)
+ return;
+
+ /*
+ * If we are canceled, wipe all the fields and return IDCANCEL.
+ */
+ if (cid == IDCANCEL) {
+ EndDialog(hwnd, IDCANCEL);
+ return;
+ }
+
+ /*
+ * must be IDOK...
+ */
+ id = (gd->id + 2);
+ for (n = 0 ; n < gd->num_prompts ; n++) {
+ Edit_GetText(GetDlgItem(hwnd, id), gd->prompts[n].reply->data,
+ gd->prompts[n].reply->length);
+ gd->prompts[n].reply->length = strlen(gd->prompts[n].reply->data);
+ id += 2;
+ }
+
+ EndDialog(hwnd, IDOK);
+}
+
+/*
+ * The dialog callback.
+ */
+static BOOL CALLBACK
+gic_dialog(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ HANDLE_MSG(hwnd, WM_INITDIALOG, gic_dialog_init);
+
+ HANDLE_MSG(hwnd, WM_COMMAND, gic_dialog_command);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * All the disgusting code to use the get_init_creds() functions in a
+ * broken environment
+ */
+krb5_error_code KRB5_CALLCONV
+gic_prompter(krb5_context ctx, void *data, const char *banner,
+ int num_prompts, krb5_prompt prompts[])
+{
+ int rc;
+ void *dlg;
+
+ gd = data;
+
+ gd->banner = banner;
+ gd->num_prompts = num_prompts;
+ gd->prompts = prompts;
+ if (gd->width == 0)
+ gd->width = 450;
+
+ dlg = vardlg_build((WORD)(gd->width), gd->banner, (WORD)num_prompts, prompts, (WORD)(gd->id));
+
+ rc = DialogBoxIndirect(gd->hinstance, (LPDLGTEMPLATE)dlg, gd->hwnd, gic_dialog);
+
+ if (rc != IDOK)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 1997 Cygnus Solutions
+ *
+ * Author: Michael Graff
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include "registry.h"
+
+HKEY
+registry_open(HKEY hkey, char *base, REGSAM sam)
+{
+ HKEY k = INVALID_HANDLE_VALUE;
+ DWORD err;
+
+ /*
+ * if the base path is null, return the already open key in hkey
+ */
+ if (base == NULL)
+ return hkey;
+
+ err = RegOpenKeyEx(hkey, base, 0, sam, &hkey);
+ if (err != ERROR_SUCCESS)
+ return INVALID_HANDLE_VALUE;
+
+ return hkey;
+}
+
+void
+registry_close(HKEY hkey)
+{
+ CloseHandle(hkey);
+}
+
+HKEY
+registry_key_create(HKEY hkey, char *sub, REGSAM sam)
+{
+ HKEY key;
+ DWORD err;
+ DWORD disp;
+
+ err = RegCreateKeyEx(hkey, sub, 0, 0, REG_OPTION_NON_VOLATILE, sam,
+ NULL, &key, &disp);
+ if (err != ERROR_SUCCESS)
+ return INVALID_HANDLE_VALUE;
+
+ return key;
+}
+
+int
+registry_key_delete(HKEY hkey, char *sub)
+{
+ DWORD err;
+
+ err = RegDeleteKey(hkey, sub);
+ if (err != ERROR_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+int
+registry_string_get(HKEY hkey, char *sub, char **val)
+{
+ DWORD err;
+ DWORD type;
+ DWORD datasize;
+
+ err = RegQueryValueEx(hkey, sub, 0, &type, 0, &datasize);
+ if (err != ERROR_SUCCESS || type != REG_SZ) {
+ *val = NULL;
+ return -1;
+ }
+
+ *val = malloc(datasize);
+ if (*val == NULL)
+ return -1;
+
+ err = RegQueryValueEx(hkey, sub, 0, &type, *val, &datasize);
+ if (err != ERROR_SUCCESS) {
+ free(*val);
+ *val = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+registry_dword_get(HKEY hkey, char *sub, DWORD *val)
+{
+ DWORD err;
+ DWORD type;
+ DWORD datasize;
+
+ err = RegQueryValueEx(hkey, sub, 0, &type, 0, &datasize);
+ if (err != ERROR_SUCCESS || type != REG_DWORD) {
+ *val = 0;
+ return -1;
+ }
+
+ err = RegQueryValueEx(hkey, sub, 0, &type, (BYTE *)val, &datasize);
+ if (err != ERROR_SUCCESS) {
+ *val = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+registry_string_set(HKEY hkey, char *sub, char *x)
+{
+ DWORD err;
+
+ err = RegSetValueEx(hkey, sub, 0, REG_SZ, (BYTE *)x, strlen(x) + 1);
+ if (err != ERROR_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+int
+registry_dword_set(HKEY hkey, char *sub, DWORD x)
+{
+ DWORD err;
+
+ err = RegSetValueEx(hkey, sub, 0, REG_DWORD, (CONST BYTE *)&x, sizeof(DWORD));
+ if (err != ERROR_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+int
+registry_keyval_dword_set(HKEY hkey, char *base, char *sub, DWORD val)
+{
+ HKEY k;
+ int err;
+
+ k = registry_open(hkey, base, KEY_WRITE);
+ if (k == INVALID_HANDLE_VALUE)
+ return -1;
+
+ err = registry_dword_set(k, sub, val);
+
+ registry_close(k);
+
+ return err;
+}
+
+int
+registry_keyval_dword_get(HKEY hkey, char *base, char *sub, DWORD *val)
+{
+ HKEY k;
+ int err;
+
+ k = registry_open(hkey, base, KEY_READ);
+ if (k == INVALID_HANDLE_VALUE)
+ return -1;
+
+ err = registry_dword_get(k, sub, val);
+
+ registry_close(k);
+
+ return err;
+}
+
+int
+registry_keyval_string_get(HKEY hkey, char *base, char *sub, char **val)
+{
+ HKEY k;
+ int err;
+
+ k = registry_open(hkey, base, KEY_READ);
+ if (k == INVALID_HANDLE_VALUE) {
+ *val = NULL;
+ return -1;
+ }
+
+ err = registry_string_get(k, sub, val);
+
+ registry_close(k);
+
+ return err;
+}
+
+int
+registry_keyval_string_set(HKEY hkey, char *base, char *sub, char *val)
+{
+ HKEY k;
+ int err;
+
+ k = registry_open(hkey, base, KEY_WRITE);
+ if (k == INVALID_HANDLE_VALUE)
+ return -1;
+
+ err = registry_string_set(k, sub, val);
+
+ registry_close(k);
+
+ return err;
+}
+
+int
+registry_value_delete(HKEY hkey, char *sub)
+{
+ if (RegDeleteValue(hkey, sub))
+ return -1;
+
+ return 0;
+}
+
+int
+registry_keyval_delete(HKEY hkey, char *base, char *sub)
+{
+ HKEY k;
+ int err;
+
+ k = registry_open(hkey, base, KEY_WRITE);
+ if (k == INVALID_HANDLE_VALUE)
+ return -1;
+
+ err = registry_value_delete(k, sub);
+
+ registry_close(k);
+
+ return err;
+}
--- /dev/null
+/*
+ * Dialog box building for various numbers of (label, entry) fields.
+ *
+ * This code is somewhat hardcoded to build boxes for the krb5_get_init_creds()
+ * function.
+ *
+ * Copyright (C) 1997 Cygnus Solutions.
+ *
+ * Author: Michael Graff
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "krb5.h"
+#include "vardlg.h"
+
+/*
+ * a hack, I know... No error checking below, either.
+ */
+static unsigned char dlg[DLG_BUF];
+
+/*
+ * Add a WORD (16-bit int) to the buffer. Return the number of characters
+ * added.
+ */
+static int
+ADD_WORD(unsigned char *p, WORD w)
+{
+ *((WORD *)p) = w;
+
+ return 2;
+}
+
+static int
+ADD_DWORD(unsigned char *p, DWORD dw)
+{
+ *((DWORD *)p) = dw;
+
+ return 4;
+}
+
+static int
+ADD_UNICODE_STRING(unsigned char *p, const char *s)
+{
+ WORD *w;
+ int i;
+ int len;
+
+ w = (WORD *)p;
+
+ len = strlen(s) + 1; /* copy the null, too */
+
+ for (i = 0 ; i < len ; i++)
+ *w++ = *s++;
+
+ return (len * 2);
+}
+
+#define DWORD_ALIGN(p) { while ((DWORD)p % 4) *p++ = 0x00; }
+
+static int
+ADD_DLGTEMPLATE(unsigned char *dlg, short x, short y, short cx, short cy,
+ const char *caption, const char *fontname, WORD fontsize,
+ WORD n)
+{
+ unsigned char *p;
+ DLGTEMPLATE dlt;
+
+ p = dlg;
+
+ dlt.style = (DS_MODALFRAME | WS_POPUP);
+ if (caption != NULL)
+ dlt.style |= WS_CAPTION;
+ if (fontname != NULL)
+ dlt.style |= DS_SETFONT;
+ dlt.dwExtendedStyle = 0;
+ dlt.cdit = n;
+ dlt.x = x;
+ dlt.y = y;
+ dlt.cx = cx;
+ dlt.cy = cy;
+ memcpy(p, &dlt, sizeof(dlt));
+ p += sizeof(dlt);
+
+ p += ADD_WORD(p, 0x0000); /* menu == none */
+
+ p += ADD_WORD(p, 0x0000); /* class == default? */
+
+ if (caption != NULL)
+ p += ADD_UNICODE_STRING(p, caption);
+ else
+ p += ADD_WORD(p, 0x0000);
+
+ if (fontname != NULL) {
+ p += ADD_WORD(p, fontsize);
+ p += ADD_UNICODE_STRING(p, fontname);
+ }
+
+ DWORD_ALIGN(p);
+
+ return (p - dlg);
+}
+
+static int
+ADD_DLGITEM(unsigned char *dlg, short x, short y, short cx, short cy,
+ const char *label, WORD id, WORD type, DWORD style)
+{
+ unsigned char *p;
+ DLGITEMTEMPLATE dit;
+
+ p = dlg;
+
+ dit.style = style;
+ dit.dwExtendedStyle = 0;
+ dit.x = x;
+ dit.y = y;
+ dit.cx = cx;
+ dit.cy = cy;
+ dit.id = id;
+ memcpy(p, &dit, sizeof(dit));
+ p += sizeof(dit);
+
+ p += ADD_WORD(p, 0xffff);
+ p += ADD_WORD(p, type);
+
+ p += ADD_UNICODE_STRING(p, label);
+
+ /*
+ * creation data? For now, just make this empty, like the resource
+ * compiler does.
+ */
+ p += ADD_WORD(p, 0x0000);
+
+ DWORD_ALIGN(p);
+
+ return (p - dlg);
+}
+
+#define ADD_DLGITEM_defpushbutton(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010001);
+
+#define ADD_DLGITEM_pushbutton(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010000);
+
+#define ADD_DLGITEM_left_static(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020000);
+
+#define ADD_DLGITEM_centered_static(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020001);
+
+#define ADD_DLGITEM_right_static(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020002);
+
+#define ADD_DLGITEM_entry(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x50810080);
+
+#define ADD_DLGITEM_hidden_entry(a, b, c, d, e, f, g) \
+ ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x508100a0);
+
+
+/*
+ * "build" the dialog box. In this bit of code, we create the dialog box,
+ * create the OK button, and a static label for the banner text.
+ *
+ * If there are items, we also create a Cancel button and one (label, entry)
+ * fields for each item.
+ */
+void *
+vardlg_build(WORD cx, const char *banner, WORD n, krb5_prompt prompts[],
+ WORD id)
+{
+ unsigned char *p;
+ WORD i;
+
+ p = dlg; /* global */
+
+ if (cx < MIN_WIDTH)
+ cx = MIN_WIDTH;
+ if (cx > MAX_WIDTH)
+ cx = MAX_WIDTH;
+
+ /*
+ * Store the dialog template
+ */
+ p += ADD_DLGTEMPLATE(p, 0, 0, cx, 0, "KerbNet", "MS Sans Serif", 8,
+ (WORD)(n * 2 + 3));
+
+ /*
+ * Create a label for the banner. This will be ID (id).
+ */
+ p += ADD_DLGITEM_left_static(p, 0, 0, 0, 0, "", id++);
+
+ /*
+ * Each label field is ID (id + 1) + (item * 2), and each entry field
+ * is (id + 2) + (item * 2)
+ */
+ for (i = 0 ; i < n ; i++) {
+ p += ADD_DLGITEM_right_static(p, 0, 0, 0, 0, "", id++);
+ if (prompts[i].hidden) {
+ p += ADD_DLGITEM_hidden_entry(p, 0, 0, 0, 0, "", id++);
+ } else {
+ p += ADD_DLGITEM_entry(p, 0, 0, 0, 0, "", id++);
+ }
+ }
+
+ /*
+ * Create the OK and Cancel buttons.
+ */
+ p += ADD_DLGITEM_defpushbutton(p, 0, 0, 0, 0,
+ "OK", IDOK);
+ if (n != 0)
+ p += ADD_DLGITEM_pushbutton(p, 0, 0, 0, 0,
+ "Cancel", IDCANCEL);
+
+ return dlg;
+}
+
+#define SPACE_Y 4 /* logical units */
+#define SPACE_X 4 /* logical units */
+#define ENTRY_PX 120 /* pixels */
+#define BUTTON_PX 70 /* pixels */
+#define BUTTON_PY 30 /* pixels */
+
+void
+vardlg_config(HWND hwnd, WORD width, const char *banner, WORD num_prompts,
+ krb5_prompt *prompts, WORD id)
+{
+ int n;
+ WORD cid;
+ HDC hdc;
+ SIZE csize;
+ SIZE maxsize;
+ LONG cx, cy;
+ LONG ccx, ccy;
+ LONG space_x, space_y;
+ LONG max_x, max_y;
+ LONG banner_y;
+ RECT rect;
+ int done;
+ const char *p;
+
+ /*
+ * First, set the banner's text.
+ */
+ Static_SetText(GetDlgItem(hwnd, id), banner);
+
+ /*
+ * Next, run through the items and set their static text.
+ * Also, set the corresponding edit string and set the
+ * maximum input length.
+ */
+ cid = (id + 1);
+
+ for (n = 0 ; n < num_prompts ; n++) {
+ Static_SetText(GetDlgItem(hwnd, cid), prompts[n].prompt);
+ cid++;
+ Edit_SetText(GetDlgItem(hwnd, cid), "");
+ Edit_LimitText(GetDlgItem(hwnd, cid), prompts[n].reply->length);
+ cid++;
+ }
+
+ /*
+ * Now run through the entry fields and find the longest string.
+ */
+ maxsize.cx = maxsize.cy = 0;
+ cid = (id + 1);
+ hdc = GetDC(GetDlgItem(hwnd, cid)); /* assume one label is the same as all the others */
+
+ for (n = 0 ; n < num_prompts ; n++) {
+ GetTextExtentPoint32(hdc, prompts[n].prompt, strlen(prompts[n].prompt), &csize);
+ if (csize.cx > maxsize.cx)
+ maxsize.cx = csize.cx;
+ if (csize.cy > maxsize.cy)
+ maxsize.cy = csize.cy;
+ }
+
+#if 0
+ /*
+ * convert the maximum values into pixels. Ugh.
+ */
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = maxsize.cx;
+ rect.bottom = maxsize.cy;
+ MapDialogRect(hwnd, &rect);
+
+ max_x = rect.right;
+ max_y = rect.bottom;
+#else
+ max_x = maxsize.cx;
+ max_y = (long)(((double)maxsize.cy) * 1.5);
+#endif
+
+ /*
+ * convert the spacing values, too. Ugh. Ugh.
+ */
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = SPACE_X;
+ rect.bottom = SPACE_Y;
+ MapDialogRect(hwnd, &rect);
+
+ space_x = rect.right;
+ space_y = rect.bottom;
+
+ /*
+ * Now we know the maximum length of the string for the entry labels. Guestimate
+ * that the entry fields should be ENTRY_PX pixels long and resize the dialog
+ * window to fit the longest string plus the entry fields (plus a little for the
+ * spacing between the edges of the windows and the static and edit fields, and
+ * between the static and edit fields themselves.)
+ */
+ cx = max_x + ENTRY_PX + (space_x * 3);
+ cy = (max_y + space_y) * num_prompts;
+
+ /*
+ * resize the dialog box itself (take 1)
+ */
+ SetWindowPos(hwnd, HWND_TOPMOST,
+ 0, 0,
+ cx + 10, cy + 30,
+ SWP_NOMOVE);
+
+ /*
+ * position the dialog items. First, the banner. (take 1)
+ */
+ SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM,
+ space_x, space_y,
+ (cx - space_x * 2), max_y,
+ 0);
+
+ /*
+ * Now that the window for the banner is in place, convert the width into logical units
+ * and find out how many lines we need to reserve room for.
+ */
+ done = 0;
+ p = banner;
+ banner_y = 0;
+
+ do {
+ int nFit;
+ int pDx[128];
+
+ hdc = GetDC(GetDlgItem(hwnd, id));
+
+ GetTextExtentExPoint(hdc, p, strlen(p), cx, &nFit,
+ pDx, &csize);
+
+ banner_y += csize.cy;
+
+ p += nFit;
+
+ } while (*p != 0);
+
+ banner_y += space_y;
+
+ /*
+ * position the banner (take 2)
+ */
+ SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM,
+ space_x, space_y,
+ (cx - space_x * 2), banner_y,
+ 0);
+
+ /*
+ * Don't forget to include the banner estimate and the buttons, too. Once again,
+ * assume the buttons are BUTTON_PY pixels high. The extra three space_y's are
+ * for between the top of the dialog and the banner, between the banner and the
+ * first label, and between the buttons and the bottom of the screen.
+ */
+ cy += banner_y + BUTTON_PY + (space_y * 3);
+
+ /*
+ * resize the dialog box itself (Again... ugh!)
+ */
+ SetWindowPos(hwnd, HWND_TOPMOST,
+ 0, 0,
+ cx + 10, cy + 30,
+ SWP_NOMOVE);
+
+ cid = (id + 1);
+ ccy = banner_y + (space_y * 2);
+ ccx = max_x + (space_x * 2); /* where the edit fields start */
+
+ for (n = 0 ; n < num_prompts ; n++) {
+ SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM,
+ space_x, ccy,
+ max_x, max_y, 0);
+ cid++;
+ SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM,
+ ccx, ccy,
+ ENTRY_PX, max_y - 3, 0);
+ cid++;
+ ccy += (max_y + space_y);
+ }
+
+ /*
+ * Now the buttons. If there are any entries we will have both an OK and a
+ * Cancel button. If we don't have any entries, we will have only an OK.
+ */
+ if (num_prompts == 0) {
+ SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM,
+ (cx / 2), cy - space_y - BUTTON_PY,
+ BUTTON_PX, BUTTON_PY, 0);
+ } else {
+ SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM,
+ space_x, cy - space_y - BUTTON_PY,
+ BUTTON_PX, BUTTON_PY, 0);
+ SetWindowPos(GetDlgItem(hwnd, IDCANCEL), HWND_BOTTOM,
+ cx - space_x - BUTTON_PX, cy - space_y - BUTTON_PY,
+ BUTTON_PX, BUTTON_PY, 0);
+ }
+
+ return;
+}
+
+/*
+ * To use these functions, first create the dialog box and entries.
+ * You will always get an OK button. If there are at least one item,
+ * you will also get a cancel button. The OK button is IDOK, and the cancel
+ * button is IDCANCEL, as usual.
+ *
+ * After calling bld_dlg, the banner will have ID "id", and the labels
+ * will be "1 + id + i * 2" (i is the entry number, starting with zero) and
+ * the entries will be "2 + id + i * 2".
+ *
+ * unsigned char *dlg = vardlg_build(minwidth, banner, num_prompts,
+ * krb5_prompt[], id);
+ *
+ * Then, "run" the dialog using:
+ *
+ * rc = DialogBoxIndirect(hinstance, (LPDLGTEMPLATE)dlg,
+ * HWND_DESKTOP, myDialogProc);
+ *
+ * Note that the vardlg_build function uses a static data area and so cannot
+ * be used more than once before the DialogBoxIndirect() procedure is called.
+ * I assume windows won't need that area after that call is complete.
+ *
+ * In the dialog's _initialization_ procedure, call
+ *
+ * vardlg_config(hwnd, banner, num_prompts, krb5_prompt[], id);
+ *
+ * This function will resize the various elements of the dialog and fill in the
+ * labels.
+ */