413 lines
13 KiB
C
413 lines
13 KiB
C
|
|
/* Module: setup.c
|
|
*
|
|
* Description: This module contains the setup functions for
|
|
* adding/modifying a Data Source in the ODBC.INI portion
|
|
* of the registry.
|
|
*
|
|
* Classes: n/a
|
|
*
|
|
* API functions: ConfigDSN
|
|
*
|
|
* Comments: See "notice.txt" for copyright and license information.
|
|
*
|
|
*************************************************************************************/
|
|
|
|
#include "psqlodbc.h"
|
|
#include "connection.h"
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <odbcinst.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "resource.h"
|
|
#include "dlg_specific.h"
|
|
|
|
|
|
#define INTFUNC __stdcall
|
|
|
|
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
|
|
extern GLOBAL_VALUES globals;
|
|
|
|
/* Constants --------------------------------------------------------------- */
|
|
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
|
|
|
#ifdef WIN32
|
|
#define MAXPGPATH (255+1)
|
|
#endif
|
|
|
|
#define MAXKEYLEN (15+1) /* Max keyword length */
|
|
#define MAXDESC (255+1) /* Max description length */
|
|
#define MAXDSNAME (32+1) /* Max data source name length */
|
|
|
|
|
|
/* Globals ----------------------------------------------------------------- */
|
|
/* NOTE: All these are used by the dialog procedures */
|
|
typedef struct tagSETUPDLG {
|
|
HWND hwndParent; /* Parent window handle */
|
|
LPCSTR lpszDrvr; /* Driver description */
|
|
ConnInfo ci;
|
|
char szDSN[MAXDSNAME]; /* Original data source name */
|
|
BOOL fNewDSN; /* New data source flag */
|
|
BOOL fDefault; /* Default data source flag */
|
|
|
|
} SETUPDLG, FAR *LPSETUPDLG;
|
|
|
|
|
|
|
|
/* Prototypes -------------------------------------------------------------- */
|
|
void INTFUNC CenterDialog(HWND hdlg);
|
|
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
|
|
void INTFUNC ParseAttributes (LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
|
|
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
|
|
|
|
|
|
/* ConfigDSN ---------------------------------------------------------------
|
|
Description: ODBC Setup entry point
|
|
This entry point is called by the ODBC Installer
|
|
(see file header for more details)
|
|
Input : hwnd ----------- Parent window handle
|
|
fRequest ------- Request type (i.e., add, config, or remove)
|
|
lpszDriver ----- Driver name
|
|
lpszAttributes - data source attribute string
|
|
Output : TRUE success, FALSE otherwise
|
|
--------------------------------------------------------------------------*/
|
|
|
|
BOOL CALLBACK ConfigDSN (HWND hwnd,
|
|
WORD fRequest,
|
|
LPCSTR lpszDriver,
|
|
LPCSTR lpszAttributes)
|
|
{
|
|
BOOL fSuccess; /* Success/fail flag */
|
|
GLOBALHANDLE hglbAttr;
|
|
LPSETUPDLG lpsetupdlg;
|
|
|
|
|
|
/* Allocate attribute array */
|
|
hglbAttr = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(SETUPDLG));
|
|
if (!hglbAttr)
|
|
return FALSE;
|
|
lpsetupdlg = (LPSETUPDLG)GlobalLock(hglbAttr);
|
|
|
|
/* Parse attribute string */
|
|
if (lpszAttributes)
|
|
ParseAttributes(lpszAttributes, lpsetupdlg);
|
|
|
|
/* Save original data source name */
|
|
if (lpsetupdlg->ci.dsn[0])
|
|
lstrcpy(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn);
|
|
else
|
|
lpsetupdlg->szDSN[0] = '\0';
|
|
|
|
/* Remove data source */
|
|
if (ODBC_REMOVE_DSN == fRequest) {
|
|
/* Fail if no data source name was supplied */
|
|
if (!lpsetupdlg->ci.dsn[0])
|
|
fSuccess = FALSE;
|
|
|
|
/* Otherwise remove data source from ODBC.INI */
|
|
else
|
|
fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn);
|
|
}
|
|
|
|
/* Add or Configure data source */
|
|
else {
|
|
/* Save passed variables for global access (e.g., dialog access) */
|
|
lpsetupdlg->hwndParent = hwnd;
|
|
lpsetupdlg->lpszDrvr = lpszDriver;
|
|
lpsetupdlg->fNewDSN = (ODBC_ADD_DSN == fRequest);
|
|
lpsetupdlg->fDefault = !lstrcmpi(lpsetupdlg->ci.dsn, INI_DSN);
|
|
|
|
/* Display the appropriate dialog (if parent window handle supplied) */
|
|
if (hwnd) {
|
|
/* Display dialog(s) */
|
|
fSuccess = (IDOK == DialogBoxParam(s_hModule,
|
|
MAKEINTRESOURCE(DLG_CONFIG),
|
|
hwnd,
|
|
ConfigDlgProc,
|
|
(LONG)(LPSTR)lpsetupdlg));
|
|
}
|
|
|
|
else if (lpsetupdlg->ci.dsn[0])
|
|
fSuccess = SetDSNAttributes(hwnd, lpsetupdlg);
|
|
else
|
|
fSuccess = FALSE;
|
|
}
|
|
|
|
GlobalUnlock(hglbAttr);
|
|
GlobalFree(hglbAttr);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
|
|
/* CenterDialog ------------------------------------------------------------
|
|
Description: Center the dialog over the frame window
|
|
Input : hdlg -- Dialog window handle
|
|
Output : None
|
|
--------------------------------------------------------------------------*/
|
|
void INTFUNC CenterDialog(HWND hdlg)
|
|
{
|
|
HWND hwndFrame;
|
|
RECT rcDlg, rcScr, rcFrame;
|
|
int cx, cy;
|
|
|
|
hwndFrame = GetParent(hdlg);
|
|
|
|
GetWindowRect(hdlg, &rcDlg);
|
|
cx = rcDlg.right - rcDlg.left;
|
|
cy = rcDlg.bottom - rcDlg.top;
|
|
|
|
GetClientRect(hwndFrame, &rcFrame);
|
|
ClientToScreen(hwndFrame, (LPPOINT)(&rcFrame.left));
|
|
ClientToScreen(hwndFrame, (LPPOINT)(&rcFrame.right));
|
|
rcDlg.top = rcFrame.top + (((rcFrame.bottom - rcFrame.top) - cy) >> 1);
|
|
rcDlg.left = rcFrame.left + (((rcFrame.right - rcFrame.left) - cx) >> 1);
|
|
rcDlg.bottom = rcDlg.top + cy;
|
|
rcDlg.right = rcDlg.left + cx;
|
|
|
|
GetWindowRect(GetDesktopWindow(), &rcScr);
|
|
if (rcDlg.bottom > rcScr.bottom)
|
|
{
|
|
rcDlg.bottom = rcScr.bottom;
|
|
rcDlg.top = rcDlg.bottom - cy;
|
|
}
|
|
if (rcDlg.right > rcScr.right)
|
|
{
|
|
rcDlg.right = rcScr.right;
|
|
rcDlg.left = rcDlg.right - cx;
|
|
}
|
|
|
|
if (rcDlg.left < 0) rcDlg.left = 0;
|
|
if (rcDlg.top < 0) rcDlg.top = 0;
|
|
|
|
MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE);
|
|
return;
|
|
}
|
|
|
|
/* ConfigDlgProc -----------------------------------------------------------
|
|
Description: Manage add data source name dialog
|
|
Input : hdlg --- Dialog window handle
|
|
wMsg --- Message
|
|
wParam - Message parameter
|
|
lParam - Message parameter
|
|
Output : TRUE if message processed, FALSE otherwise
|
|
--------------------------------------------------------------------------*/
|
|
|
|
|
|
int CALLBACK ConfigDlgProc(HWND hdlg,
|
|
WORD wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
|
|
switch (wMsg) {
|
|
/* Initialize the dialog */
|
|
case WM_INITDIALOG:
|
|
{
|
|
LPSETUPDLG lpsetupdlg = (LPSETUPDLG) lParam;
|
|
ConnInfo *ci = &lpsetupdlg->ci;
|
|
|
|
/* Hide the driver connect message */
|
|
ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE);
|
|
|
|
SetWindowLong(hdlg, DWL_USER, lParam);
|
|
CenterDialog(hdlg); /* Center dialog */
|
|
|
|
/* NOTE: Values supplied in the attribute string will always */
|
|
/* override settings in ODBC.INI */
|
|
|
|
/* Get the rest of the common attributes */
|
|
getDSNinfo(ci, CONN_DONT_OVERWRITE);
|
|
|
|
/* Fill in any defaults */
|
|
getDSNdefaults(ci);
|
|
|
|
|
|
/* Initialize dialog fields */
|
|
SetDlgStuff(hdlg, ci);
|
|
|
|
|
|
if (lpsetupdlg->fDefault) {
|
|
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
|
|
EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
|
|
}
|
|
else
|
|
SendDlgItemMessage(hdlg, IDC_DSNAME,
|
|
EM_LIMITTEXT, (WPARAM)(MAXDSNAME-1), 0L);
|
|
|
|
SendDlgItemMessage(hdlg, IDC_DESC,
|
|
EM_LIMITTEXT, (WPARAM)(MAXDESC-1), 0L);
|
|
return TRUE; /* Focus was not set */
|
|
}
|
|
|
|
|
|
/* Process buttons */
|
|
case WM_COMMAND:
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
/* Ensure the OK button is enabled only when a data source name */
|
|
/* is entered */
|
|
case IDC_DSNAME:
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
|
|
{
|
|
char szItem[MAXDSNAME]; /* Edit control text */
|
|
|
|
/* Enable/disable the OK button */
|
|
EnableWindow(GetDlgItem(hdlg, IDOK),
|
|
GetDlgItemText(hdlg, IDC_DSNAME,
|
|
szItem, sizeof(szItem)));
|
|
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
/* Accept results */
|
|
case IDOK:
|
|
{
|
|
LPSETUPDLG lpsetupdlg;
|
|
|
|
lpsetupdlg = (LPSETUPDLG)GetWindowLong(hdlg, DWL_USER);
|
|
/* Retrieve dialog values */
|
|
if (!lpsetupdlg->fDefault)
|
|
GetDlgItemText(hdlg, IDC_DSNAME,
|
|
lpsetupdlg->ci.dsn,
|
|
sizeof(lpsetupdlg->ci.dsn));
|
|
|
|
|
|
/* Get Dialog Values */
|
|
GetDlgStuff(hdlg, &lpsetupdlg->ci);
|
|
|
|
/* Update ODBC.INI */
|
|
SetDSNAttributes(hdlg, lpsetupdlg);
|
|
}
|
|
|
|
/* Return to caller */
|
|
case IDCANCEL:
|
|
EndDialog(hdlg, wParam);
|
|
return TRUE;
|
|
|
|
case IDC_DRIVER:
|
|
|
|
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
|
|
hdlg, driver_optionsProc, (LPARAM) NULL);
|
|
|
|
return TRUE;
|
|
|
|
case IDC_DATASOURCE:
|
|
{
|
|
LPSETUPDLG lpsetupdlg;
|
|
|
|
lpsetupdlg = (LPSETUPDLG)GetWindowLong(hdlg, DWL_USER);
|
|
|
|
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
|
|
hdlg, ds_optionsProc, (LPARAM) &lpsetupdlg->ci);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* Message not processed */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* ParseAttributes ---------------------------------------------------------
|
|
Description: Parse attribute string moving values into the aAttr array
|
|
Input : lpszAttributes - Pointer to attribute string
|
|
Output : None (global aAttr normally updated)
|
|
--------------------------------------------------------------------------*/
|
|
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
|
{
|
|
LPCSTR lpsz;
|
|
LPCSTR lpszStart;
|
|
char aszKey[MAXKEYLEN];
|
|
int cbKey;
|
|
char value[MAXPGPATH];
|
|
|
|
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
|
|
|
|
for (lpsz=lpszAttributes; *lpsz; lpsz++)
|
|
{ /* Extract key name (e.g., DSN), it must be terminated by an equals */
|
|
lpszStart = lpsz;
|
|
for (;; lpsz++)
|
|
{
|
|
if (!*lpsz)
|
|
return; /* No key was found */
|
|
else if (*lpsz == '=')
|
|
break; /* Valid key found */
|
|
}
|
|
/* Determine the key's index in the key table (-1 if not found) */
|
|
cbKey = lpsz - lpszStart;
|
|
if (cbKey < sizeof(aszKey))
|
|
{
|
|
|
|
_fmemcpy(aszKey, lpszStart, cbKey);
|
|
aszKey[cbKey] = '\0';
|
|
}
|
|
|
|
/* Locate end of key value */
|
|
lpszStart = ++lpsz;
|
|
for (; *lpsz; lpsz++);
|
|
|
|
|
|
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
|
|
_fmemcpy(value, lpszStart, MIN(lpsz-lpszStart+1, MAXPGPATH));
|
|
|
|
mylog("aszKey='%s', value='%s'\n", aszKey, value);
|
|
|
|
/* Copy the appropriate value to the conninfo */
|
|
copyAttributes(&lpsetupdlg->ci, aszKey, value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/* SetDSNAttributes --------------------------------------------------------
|
|
Description: Write data source attributes to ODBC.INI
|
|
Input : hwnd - Parent window handle (plus globals)
|
|
Output : TRUE if successful, FALSE otherwise
|
|
--------------------------------------------------------------------------*/
|
|
|
|
BOOL INTFUNC SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
|
|
{
|
|
LPCSTR lpszDSN; /* Pointer to data source name */
|
|
|
|
lpszDSN = lpsetupdlg->ci.dsn;
|
|
|
|
/* Validate arguments */
|
|
if (lpsetupdlg->fNewDSN && !*lpsetupdlg->ci.dsn)
|
|
return FALSE;
|
|
|
|
/* Write the data source name */
|
|
if (!SQLWriteDSNToIni(lpszDSN, lpsetupdlg->lpszDrvr))
|
|
{
|
|
if (hwndParent)
|
|
{
|
|
char szBuf[MAXPGPATH];
|
|
char szMsg[MAXPGPATH];
|
|
|
|
LoadString(s_hModule, IDS_BADDSN, szBuf, sizeof(szBuf));
|
|
wsprintf(szMsg, szBuf, lpszDSN);
|
|
LoadString(s_hModule, IDS_MSGTITLE, szBuf, sizeof(szBuf));
|
|
MessageBox(hwndParent, szMsg, szBuf, MB_ICONEXCLAMATION | MB_OK);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Update ODBC.INI */
|
|
writeDSNinfo(&lpsetupdlg->ci);
|
|
|
|
|
|
/* If the data source name has changed, remove the old name */
|
|
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
|
|
{
|
|
SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
|
|
}
|
|
return TRUE;
|
|
}
|