Check in files from Kerbnet-1.2 release. This is an auxiliary library
authorTheodore Tso <tytso@mit.edu>
Wed, 27 May 1998 19:23:34 +0000 (19:23 +0000)
committerTheodore Tso <tytso@mit.edu>
Wed, 27 May 1998 19:23:34 +0000 (19:23 +0000)
used by some of the windows programs.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10589 dc483132-0cff-0310-8789-dd5450dbe970

src/windows/lib/ChangeLog [new file with mode: 0644]
src/windows/lib/Makefile.in [new file with mode: 0644]
src/windows/lib/gic.c [new file with mode: 0644]
src/windows/lib/gic.h [new file with mode: 0644]
src/windows/lib/registry.c [new file with mode: 0644]
src/windows/lib/registry.h [new file with mode: 0644]
src/windows/lib/vardlg.c [new file with mode: 0644]
src/windows/lib/vardlg.h [new file with mode: 0644]

diff --git a/src/windows/lib/ChangeLog b/src/windows/lib/ChangeLog
new file mode 100644 (file)
index 0000000..e371d88
--- /dev/null
@@ -0,0 +1,16 @@
+Tue Mar 18 12:08:50 1997  Michael Graff  <explorer@flame.org>
+
+       * registry.h, registry.c: add.
+
+Thu Mar 13 20:17:12 1997  Michael Graff  <explorer@flame.org>
+
+       * gic.c, gic.h, vardlg.c, vardlg.h: Finish up the variable dialog box
+       code.
+
+Thu Mar  6 21:45:05 1997  Michael Graff  <explorer@flame.org>
+
+       * gic.c, gic.h:  Added to start using get_init_creds.
+
+       * vardlg.c, vardlg.h: on-the-fly variable dialog building functions.
+
+
diff --git a/src/windows/lib/Makefile.in b/src/windows/lib/Makefile.in
new file mode 100644 (file)
index 0000000..95eb691
--- /dev/null
@@ -0,0 +1,19 @@
+CFLAGS = $(CCOPTS2) $(DEFS)
+
+##DOSBUILDTOP = ..\..
+
+lib-windows: libwin.lib
+
+SRCS=  vardlg.c gic.c registry.c
+
+OBJS=  vardlg.obj gic.obj registry.obj
+
+libwin.lib: $(OBJS)
+       lib /nologo /out:$*.lib $(OBJS)
+
+all-windows:: lib-windows
+
+clean-windows::
+       $(RM) *.dll *.exp *.map *.lib *.obj
+
+install-windows::
diff --git a/src/windows/lib/gic.c b/src/windows/lib/gic.c
new file mode 100644 (file)
index 0000000..35ac8a8
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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;
+}
diff --git a/src/windows/lib/gic.h b/src/windows/lib/gic.h
new file mode 100644 (file)
index 0000000..ddea368
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 1997 Cygnus Solutions
+ *
+ * Author:  Michael Graff
+ */
+
+#ifndef _WINDOWS_LIB_GIC_H
+#define _WINDOWS_LIB_GIC_H
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include "krb5.h"
+
+typedef struct {
+       HINSTANCE    hinstance;     /* application instance */
+       HWND         hwnd;          /* parent window */
+       WORD         id;            /* starting ID */
+       WORD         width;         /* max width of the dialog box */
+       const char  *banner;        /* the banner */
+       WORD         num_prompts;   /* the number of prompts we were passed */
+       krb5_prompt *prompts;       /* the prompts themselves */
+} gic_data;
+
+krb5_error_code KRB5_CALLCONV gic_prompter(krb5_context, void *, const char *,
+                                          int, krb5_prompt []);
+
+#endif /* _WINDOWS_LIB_GIC_H */
diff --git a/src/windows/lib/registry.c b/src/windows/lib/registry.c
new file mode 100644 (file)
index 0000000..7dfbb5b
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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;
+}
diff --git a/src/windows/lib/registry.h b/src/windows/lib/registry.h
new file mode 100644 (file)
index 0000000..d628d2b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1997 Cygnus Solutions
+ *
+ * Author:  Michael Graff
+ */
+
+#ifndef LIB_WINDOWS_REGISTRY_H
+#define LIB_WINDOWS_REGISTRY_H
+
+#include <windows.h>
+#include <windowsx.h>
+
+HKEY registry_open(HKEY, char *, REGSAM);
+void registry_close(HKEY);
+HKEY registry_key_create(HKEY, char *, REGSAM);
+int registry_key_delete(HKEY, char *);
+int registry_string_get(HKEY, char *, char **);
+int registry_dword_get(HKEY, char *, DWORD *);
+int registry_string_set(HKEY, char *, char *);
+int registry_dword_set(HKEY, char *, DWORD);
+int registry_keyval_dword_set(HKEY, char *, char *, DWORD);
+int registry_keyval_dword_get(HKEY, char *, char *, DWORD *);
+int registry_keyval_string_get(HKEY, char *, char *, char **);
+int registry_keyval_string_set(HKEY, char *, char *, char *);
+int registry_value_delete(HKEY, char *);
+int registry_keyval_delete(HKEY, char *, char *);
+
+#define CYGNUS_SOLUTIONS     "SOFTWARE\\Cygnus Solutions"
+
+#define KERBNET_SANS_VERSION CYGNUS_SOLUTIONS "\\Kerbnet"
+#define KERBNET_BASE         KERBNET_SANS_VERSION "\\1"
+
+#define KERBNET_TELNET_BASE  KERBNET_BASE "\\telnet"
+#define KERBNET_TELNET_HOST  KERBNET_TELNET_BASE "\\hosts"
+
+#define KERBNET_CNS_BASE     KERBNET_BASE "\\cns"
+
+#define KERBNET_HOME         "KERBNET_HOME"
+
+#endif /* LIB_WINDOWS_REGISTRY_H */
diff --git a/src/windows/lib/vardlg.c b/src/windows/lib/vardlg.c
new file mode 100644 (file)
index 0000000..41d897b
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * 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.
+ */
diff --git a/src/windows/lib/vardlg.h b/src/windows/lib/vardlg.h
new file mode 100644 (file)
index 0000000..e832e51
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1997 Cygnus Solutions
+ *
+ * Author:  Michael Graff
+ */
+
+#ifndef _WINDOWS_LIB_VARDLG_H
+#define _WINDOWS_LIB_VARDLG_H
+
+#include <windows.h>
+#include <windowsx.h>
+
+#define DLG_BUF 4096
+
+/*
+ * The minimum and maximum dialog box widths we will allow.
+ */
+#define MIN_WIDTH 350
+#define MAX_WIDTH 600
+
+/*
+ * "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, const char *, WORD, krb5_prompt *, WORD);
+
+void  vardlg_config(HWND, WORD, const char *, WORD, krb5_prompt *, WORD);
+
+#endif /* _WINDOWS_LIB_VARDLG_H */