From f6e7e6667ed480c99c05b736c5fb568a48a55f23 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Wed, 27 May 1998 19:23:34 +0000 Subject: [PATCH] Check in files from Kerbnet-1.2 release. This is an auxiliary library 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 | 16 ++ src/windows/lib/Makefile.in | 19 ++ src/windows/lib/gic.c | 156 +++++++++++++ src/windows/lib/gic.h | 28 +++ src/windows/lib/registry.c | 231 ++++++++++++++++++ src/windows/lib/registry.h | 40 ++++ src/windows/lib/vardlg.c | 450 ++++++++++++++++++++++++++++++++++++ src/windows/lib/vardlg.h | 32 +++ 8 files changed, 972 insertions(+) create mode 100644 src/windows/lib/ChangeLog create mode 100644 src/windows/lib/Makefile.in create mode 100644 src/windows/lib/gic.c create mode 100644 src/windows/lib/gic.h create mode 100644 src/windows/lib/registry.c create mode 100644 src/windows/lib/registry.h create mode 100644 src/windows/lib/vardlg.c create mode 100644 src/windows/lib/vardlg.h diff --git a/src/windows/lib/ChangeLog b/src/windows/lib/ChangeLog new file mode 100644 index 000000000..e371d88ed --- /dev/null +++ b/src/windows/lib/ChangeLog @@ -0,0 +1,16 @@ +Tue Mar 18 12:08:50 1997 Michael Graff + + * registry.h, registry.c: add. + +Thu Mar 13 20:17:12 1997 Michael Graff + + * gic.c, gic.h, vardlg.c, vardlg.h: Finish up the variable dialog box + code. + +Thu Mar 6 21:45:05 1997 Michael Graff + + * 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 index 000000000..95eb6910c --- /dev/null +++ b/src/windows/lib/Makefile.in @@ -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 index 000000000..35ac8a86f --- /dev/null +++ b/src/windows/lib/gic.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 1997 Cygnus Solutions. + * + * Author: Michael Graff + */ + +#include +#include + +#include +#include +#include + +#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 index 000000000..ddea368e4 --- /dev/null +++ b/src/windows/lib/gic.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#ifndef _WINDOWS_LIB_GIC_H +#define _WINDOWS_LIB_GIC_H + +#include +#include + +#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 index 000000000..7dfbb5bff --- /dev/null +++ b/src/windows/lib/registry.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#include +#include + +#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 index 000000000..d628d2bcb --- /dev/null +++ b/src/windows/lib/registry.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#ifndef LIB_WINDOWS_REGISTRY_H +#define LIB_WINDOWS_REGISTRY_H + +#include +#include + +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 index 000000000..41d897bf7 --- /dev/null +++ b/src/windows/lib/vardlg.c @@ -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 +#include + +#include +#include +#include + +#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 index 000000000..e832e51de --- /dev/null +++ b/src/windows/lib/vardlg.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#ifndef _WINDOWS_LIB_VARDLG_H +#define _WINDOWS_LIB_VARDLG_H + +#include +#include + +#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 */ -- 2.26.2