DIALOGS.C
//*--------------------------------------------------------------------------------- 
//|  ODBC System Administrator 
//| 
//|  This code is furnished on an as-is basis as part of the ODBC SDK and is 
//|  intended for example purposes only. 
//| 
//|   Title:   DIALOGS.C 
//|      This module contains the dialog procs which are used to display 
//|         catalog function arguements and display the results.  Note that 
//|         the best way to determine the size of the arguements would be 
//|         to use SQLGetInfo, however, due to ease of coding, the values 
//|         have been hard-coded to constants. 
//*--------------------------------------------------------------------------------- 
#include <windows.h> 
#include "admndemo.h" 
#include "dialogs.h" 
#include "sql.h" 
#include "sqlext.h" 
#include "execute.h" 
#include "info.h" 
#include "results.h" 
#include "strings.h" 
 
VSZFile; 
#define CHKNULL(str)  (*str ? str : NULL) 
 
 
//*--------------------------------------------------------------------------------- 
//|   Local function prototypes 
//*--------------------------------------------------------------------------------- 
BOOL ShowCatalogResults(CHILDINFO FAR * ci, LPSTR szTitle); 
BOOL EXTFUN CatalogWndProc(HWND hDlg, unsigned msg, WPARAM wParam, LPARAM lParam); 
 
 
//*--------------------------------------------------------------------------------- 
//|   Global variables 
//*--------------------------------------------------------------------------------- 
extern char OutStr[MAXBUFF]; 
 
 
// 
// The following set of defines and host vars are used to create a common 
// dialog handler for each of the catalog function dialogs.  This makes 
// the code size smaller while still handling each catalog functions 
// parameters.  It also allows for sharing of values from one function 
// to another. 
// 
#define CAT_LAST         256 
#define CAT_QUALIFIER      1 
#define CAT_TABLE          2 
#define CAT_OWNER          4 
#define CAT_TYPE           8 
#define CAT_COLUMN        16 
#define CAT_QUALIFIER2    32 
#define CAT_OWNER2        64 
#define CAT_TABLE2       128 
#define CAT_PROCS        256 
char szQualifierVal[MAX_QUALIFIER]; 
char szTableVal[MAX_NAME]; 
char szOwnerVal[MAX_OWNER]; 
char szTypeVal[MAX_NAME]; 
char szColumnVal[MAX_NAME]; 
char szQualifierVal2[MAX_QUALIFIER]; 
char szOwnerVal2[MAX_OWNER]; 
char szTableVal2[MAX_NAME]; 
char szProcsVal[MAX_NAME]; 
 
struct { 
   int         mMask;                        // Bit mask value 
   int         id;                           // Edit control id 
   LPSTR       szStr;                        // Buffer location 
   int         cbMax;                        // Maximum size 
   } CatalogVals[] = { 
// mMask                id                      szStr                   cbMax 
// -------------------  ---------------------   ----------------------- ------------------------ 
   CAT_QUALIFIER,       IDE_QUALIFIER,          (LPSTR)szQualifierVal,  MAX_QUALIFIER, 
   CAT_TABLE,           IDE_TABLE,              (LPSTR)szTableVal,      MAX_NAME, 
   CAT_OWNER,           IDE_OWNER,              (LPSTR)szOwnerVal,      MAX_OWNER, 
   CAT_TYPE,            IDE_TYPE,               (LPSTR)szTypeVal,       MAX_NAME, 
   CAT_COLUMN,          IDE_COLUMN,             (LPSTR)szColumnVal,     MAX_NAME, 
   CAT_QUALIFIER2,      IDE_QUALIFIER2,         (LPSTR)szQualifierVal2, MAX_QUALIFIER, 
   CAT_OWNER2,          IDE_OWNER2,             (LPSTR)szOwnerVal2,     MAX_OWNER, 
   CAT_TABLE2,          IDE_TABLE2,             (LPSTR)szTableVal2,     MAX_NAME, 
   CAT_PROCS,           IDE_PROCEDURE,          (LPSTR)szProcsVal,      MAX_NAME, 
   }; 
 
dCSEG(char) szTablesTitle[]               =  "Tables"; 
dCSEG(char) szColumnsTitle[]              =  "Columns"; 
dCSEG(char) szStatistics[]                =  "Statistics"; 
dCSEG(char) szPrimaryKeys[]               =  "Primary Keys"; 
dCSEG(char) szForeignKeys[]               =  "Foreign Keys"; 
dCSEG(char) szTablePrivs[]                =  "Table Privileges"; 
dCSEG(char) szColumnPrivs[]               =  "Column Privileges"; 
dCSEG(char) szSpecialCols[]               =  "Special Columns"; 
dCSEG(char) szProcsTitle[]                =  "Procedures"; 
dCSEG(char) szProcCols[]                  =  "Procedure Columns"; 
dCSEG(char) szCOLON[]                     =  ":"; 
 
 
struct { 
   int               idMenu;                    // Menu identifier 
   int               iDialogName;               // ID of dialog 
// DLGWNDPROC        dlgProc;                   // Dialog procedure 
   LPSTR             szDlgTitle;                // Title of the dialog 
   UINT              mask;                      // Mask for this dialog 
   } Dialogs[] = { 
// idMenu                  iDialogName                szDlgTitle              mask 
// ---------------------   ------------------         ----------------------- ------------------------------------------------- 
   IDM_TABLES,             IDD_SQLTABLES,             (LPSTR)szTablesTitle,   CAT_QUALIFIER | CAT_OWNER | CAT_TABLE | CAT_TYPE, 
   IDM_COLUMNS,            IDD_SQLCOLUMNS,            (LPSTR)szColumnsTitle,  CAT_QUALIFIER | CAT_OWNER | CAT_TABLE | CAT_COLUMN, 
   IDM_STATISTICS,         IDD_SQLSTATISTICS,         (LPSTR)szStatistics,    CAT_QUALIFIER | CAT_OWNER | CAT_TABLE, 
   IDM_PRIMARY_KEYS,       IDD_SQLPRIMARYKEYS,        (LPSTR)szPrimaryKeys,   CAT_QUALIFIER | CAT_OWNER | CAT_TABLE, 
   IDM_FOREIGN_KEYS,       IDD_SQLFOREIGNKEYS,        (LPSTR)szForeignKeys,   CAT_QUALIFIER | CAT_OWNER | CAT_TABLE | CAT_QUALIFIER2 | CAT_OWNER2 | CAT_TABLE2, 
   IDM_TABLE_PRIVS,        IDD_SQLTABLEPRIVILEGES,    (LPSTR)szTablePrivs,    CAT_QUALIFIER | CAT_OWNER | CAT_TABLE, 
   IDM_COLUMN_PRIVS,       IDD_SQLCOLUMNPRIVILEGES,   (LPSTR)szColumnPrivs,   CAT_QUALIFIER | CAT_OWNER | CAT_TABLE | CAT_COLUMN, 
   IDM_SPECIAL_COLUMNS,    IDD_SQLSPECIALCOLUMNS,     (LPSTR)szSpecialCols,   CAT_QUALIFIER | CAT_OWNER | CAT_TABLE, 
   IDM_PROCEDURES,         IDD_SQLPROCEDURES,         (LPSTR)szProcsTitle,    CAT_QUALIFIER | CAT_OWNER | CAT_PROCS, 
   IDM_PROC_COLUMNS,       IDD_SQLPROCEDURECOLUMNS,   (LPSTR)szProcCols,      CAT_QUALIFIER | CAT_OWNER | CAT_PROCS | CAT_COLUMN, 
   }; 
 
// 
// This structure is used to control the catalog fucntions 
// 
typedef struct tagCATALOGINFO { 
   HINSTANCE         hInst;               // Instance handle for this app 
   CHILDINFO FAR *   ci;                  // Child info 
   int               id;                  // Dialog id to indicate function 
   LPSTR             szDlgTitle;          // Title for the dialog 
   UINT              mask;                // Dialog control mask 
// For SQLStatistics 
   UWORD             fUnique; 
   UWORD             fAccuracy; 
// For SQLSpecialColumns 
   UWORD             fColType; 
   UWORD             fScope; 
   UWORD             fNullable; 
   } CATALOGINFO; 
 
// 
// A prototype for radio button controls 
// 
typedef struct tagIDXINFO { 
   int               idxVal; 
   int               fType; 
   } IDXINFO; 
 
// 
// For SQLStatistics, fUnqiue parameter 
// 
struct { 
   int               idxVal;                    // Dialog item number 
   int               fType;                     // SQL constant equivalent 
   } StatsfUnique[] = { 
// idxVal                        fType 
// --------------------------    --------------------------------- 
   IDX_INDEX_UNIQUE,             SQL_INDEX_UNIQUE, 
   IDX_INDEX_ALL,                SQL_INDEX_ALL, 
   }; 
 
// 
// For SQLStatistics, fAccuracy parameter 
// 
struct { 
   int               idxVal;                    // Dialog item number 
   int               fType;                     // SQL constant equivalent 
   } StatsfAccuracy[] = { 
// idxVal                        fType 
// --------------------------    --------------------------------- 
   IDX_ENSURE,                   SQL_ENSURE, 
   IDX_QUICK,                    SQL_QUICK, 
   }; 
 
// 
// For SQLSpecialColumns, fColType parameter 
// 
struct { 
   int               idxVal;                    // Dialog item number 
   int               fType;                     // SQL constant equivalent 
   } SpecColsfColType[] = { 
// idxVal                        fType 
// --------------------------    --------------------------------- 
   IDX_BEST_ROWID,               SQL_BEST_ROWID, 
   IDX_ROWVER,                   SQL_ROWVER, 
   }; 
 
// 
// For SQLSpecialColumns, fNullable parameter 
// 
struct { 
   int               idxVal;                    // Dialog item number 
   int               fType;                     // SQL constant equivalent 
   } SpecColsfNullable[] = { 
// idxVal                        fType 
// --------------------------    --------------------------------- 
   IDX_NO_NULLS,                 SQL_NO_NULLS, 
   IDX_NULLABLE,                 SQL_NULLABLE, 
   }; 
 
// 
// For SQLSpecialColumns, fScope parameter 
// 
struct { 
   int               idxVal;                    // Dialog item number 
   int               fType;                     // SQL constant equivalent 
   } SpecColsfScope[] = { 
// idxVal                        fType 
// --------------------------    --------------------------------- 
   IDX_SCOPE_CURROW,             SQL_SCOPE_CURROW, 
   IDX_SCOPE_TRANSACTION,        SQL_SCOPE_TRANSACTION, 
   IDX_SCOPE_SESSION,            SQL_SCOPE_SESSION, 
   }; 
 
 
 
 
//*--------------------------------------------------------------------------------- 
//| GetRadioValue: 
//|   This function will examine a group of radio buttons based on the control 
//|   structure and see which is checked.  When found, that value is returned. 
//| Parms: 
//|   hDlg           Window handle of dialog with control 
//|   stct           Radio control structure 
//|   cbNum          How many items in control structure 
//| Returns: 
//|   The value for the item checked 
//*--------------------------------------------------------------------------------- 
int GetRadioValue(HWND hDlg, IDXINFO FAR * stct, int cbNum) 
{ 
   int   dex; 
   for(dex=0;  dex<cbNum;  dex++) 
      if(IsDlgButtonChecked(hDlg, stct[dex].idxVal)) 
         return(stct[dex].fType); 
   return 0; 
} 
 
 
//*--------------------------------------------------------------------------------- 
//| ShowCatalogResults: 
//|   This function will display the results set returned by a catalog 
//|   function. 
//| Parms: 
//|   in       ci                   CHILDINFO information 
//|   in       szTitle              Title for the results set 
//| Returns: 
//|   Nothing. 
//*--------------------------------------------------------------------------------- 
BOOL ShowCatalogResults(CHILDINFO FAR * ci, LPSTR szTitle) 
{ 
   RESULTSSET FAR *  rs; 
   int               cbCols; 
 
   if(!(cbCols = GetNumResultsCols(ci->hstmt))) 
      return TRUE; 
   if(cbCols == 0) { 
      szWrite(ci->hwndOut, GetidsString(idsNoDataFound, OutStr, sizeof(OutStr))); 
      return TRUE; 
   } 
   rs = GetConnectWindowResultsNode(ci); 
   if(!CreateResultsSet(rs, ci->hwndClient, ci->hInst, 
                        cbCols, szTitle)) 
      return TRUE; 
   SetMetaDataFromSql(ci->hwndOut, ci->hstmt, rs, cbCols); 
   if(!CreateResultsWindow(ci, rs)) 
      return TRUE; 
   FetchAllRecordsToResults(ci->hwndOut, ci->hstmt, rs, cbCols, TRUE); 
   SQLFreeStmt(ci->hstmt, SQL_CLOSE); 
 
   return FALSE; 
} 
 
 
//*--------------------------------------------------------------------------------- 
//| DoList: 
//|   This function will display a selection dialog for the catalog functions 
//|   then process the request. 
//| Parms: 
//|   in       ci                   CHILDINFO information 
//|   in       idMenuSelection      Menu value 
//| Returns: 
//|   Nothing. 
//*--------------------------------------------------------------------------------- 
void DoList(CHILDINFO FAR * ci, int idMenuSelection) 
{ 
   static BOOL             fInit;            // Have we called before 
   CATALOGINFO             cati; 
   CATALOGINFO FAR *       lpcati=&cati; 
   int                     dex; 
   HWND                    fHwnd=GetFocus(); 
 
   // Clean up all buffers on first catalog function 
   if(!fInit) { 
      for(dex=0;  dex<NumItems(CatalogVals);  dex++) 
         memset(CatalogVals[dex].szStr, 0, CatalogVals[dex].cbMax); 
      fInit = TRUE; 
   } 
 
   // Find the dialog 
   for(dex=0;  dex<NumItems(Dialogs) && 
       Dialogs[dex].idMenu != idMenuSelection;  dex++); 
 
   // Collect information for the dialog proc 
   cati.hInst = ci->hInst; 
   cati.id = idMenuSelection; 
   cati.ci = ci; 
   cati.szDlgTitle = Dialogs[dex].szDlgTitle; 
   cati.mask = Dialogs[dex].mask; 
 
   // Display the dialog 
   if(-1 == DialogBoxParam(cati.hInst, 
                           MAKEINTRESOURCE(Dialogs[dex].iDialogName), 
                           ci->hwnd, 
                           (DLGPROC) CatalogWndProc, (LPARAM)(CATALOGINFO FAR *)lpcati)) 
      MessageBox(NULL, "Could not open dialog box.", 
                 "DoList", MB_ICONEXCLAMATION); 
 
   if(fHwnd) 
      SetFocus(fHwnd); 
} 
 
 
 
//*--------------------------------------------------------------------------------- 
//| DoCatalogFunction: 
//|   The caller should have prepared all the information we need, so we will 
//|   simply invoke the function they want to run. 
//| 
//| Parms: 
//|   cati     CATALOGINFO 
//| Returns: 
//|   Nothing 
//*--------------------------------------------------------------------------------- 
void DoCatalogFunction(CATALOGINFO FAR * cati) 
{ 
   char                 szTitle[MAXBUFF]; 
   RETCODE              retcode; 
   CHILDINFO FAR *      ci=cati->ci; 
 
   SQLFreeStmt(ci->hstmt, SQL_CLOSE); 
 
   switch(cati->id) { 
     case IDM_TABLES: 
      if (!*szTableVal && 
          ((!*szOwnerVal && strcmp(szQualifierVal, "%") == 0)|| 
           (!*szQualifierVal && strcmp(szOwnerVal, "%") == 0))) 
         retcode = SQLTables(ci->hstmt, 
                             szQualifierVal, SQL_NTS, 
                             szOwnerVal, SQL_NTS, 
                             szTableVal, SQL_NTS, 
                             szTypeVal, SQL_NTS); 
      else 
         retcode = SQLTables(ci->hstmt, 
                             CHKNULL(szQualifierVal), SQL_NTS, 
                             CHKNULL(szOwnerVal), SQL_NTS, 
                             CHKNULL(szTableVal), SQL_NTS, 
                             CHKNULL(szTypeVal), SQL_NTS); 
      break; 
 
     case IDM_COLUMNS: 
      retcode = SQLColumns(ci->hstmt, 
                           CHKNULL(szQualifierVal), SQL_NTS, 
                           CHKNULL(szOwnerVal), SQL_NTS, 
                           CHKNULL(szTableVal), SQL_NTS, 
                           CHKNULL(szColumnVal), SQL_NTS); 
      break; 
 
     case IDM_STATISTICS: 
      retcode = SQLStatistics(ci->hstmt, 
                              CHKNULL(szQualifierVal), SQL_NTS, 
                              CHKNULL(szOwnerVal), SQL_NTS, 
                              CHKNULL(szTableVal), SQL_NTS, 
                              cati->fUnique, 
                              cati->fAccuracy); 
      break; 
 
     case IDM_PRIMARY_KEYS: 
      retcode = SQLPrimaryKeys(ci->hstmt, 
                               CHKNULL(szQualifierVal), SQL_NTS, 
                               CHKNULL(szOwnerVal), SQL_NTS, 
                               CHKNULL(szTableVal), SQL_NTS); 
      break; 
 
     case IDM_FOREIGN_KEYS: 
      retcode = SQLForeignKeys(ci->hstmt, 
                               CHKNULL(szQualifierVal), SQL_NTS, 
                               CHKNULL(szOwnerVal), SQL_NTS, 
                               CHKNULL(szTableVal), SQL_NTS, 
                               CHKNULL(szQualifierVal2), SQL_NTS, 
                               CHKNULL(szOwnerVal2), SQL_NTS, 
                               CHKNULL(szTableVal2), SQL_NTS); 
      break; 
 
     case IDM_TABLE_PRIVS: 
      retcode = SQLTablePrivileges(ci->hstmt, 
                                   CHKNULL(szQualifierVal), SQL_NTS, 
                                   CHKNULL(szOwnerVal), SQL_NTS, 
                                   CHKNULL(szTableVal), SQL_NTS); 
      break; 
 
     case IDM_COLUMN_PRIVS: 
      retcode = SQLColumnPrivileges(ci->hstmt, 
                                    CHKNULL(szQualifierVal), SQL_NTS, 
                                    CHKNULL(szOwnerVal), SQL_NTS, 
                                    CHKNULL(szTableVal), SQL_NTS, 
                                    CHKNULL(szColumnVal), SQL_NTS); 
      break; 
 
     case IDM_SPECIAL_COLUMNS: 
      retcode = SQLSpecialColumns(ci->hstmt, 
                                  cati->fColType, 
                                  CHKNULL(szQualifierVal), SQL_NTS, 
                                  CHKNULL(szOwnerVal), SQL_NTS, 
                                  CHKNULL(szTableVal), SQL_NTS, 
                                  cati->fScope, 
                                  cati->fNullable); 
      break; 
 
     case IDM_PROCEDURES: 
      retcode = SQLProcedures(ci->hstmt, 
                              CHKNULL(szQualifierVal), SQL_NTS, 
                              CHKNULL(szOwnerVal), SQL_NTS, 
                              CHKNULL(szProcsVal), SQL_NTS); 
      break; 
 
     case IDM_PROC_COLUMNS: 
      retcode = SQLProcedureColumns(ci->hstmt, 
                                    CHKNULL(szQualifierVal), SQL_NTS, 
                                    CHKNULL(szOwnerVal), SQL_NTS, 
                                    CHKNULL(szProcsVal), SQL_NTS, 
                                    CHKNULL(szColumnVal), SQL_NTS); 
      break; 
 
     default: 
      break; 
   } 
 
   if(retcode != SQL_SUCCESS) { 
      PrintErrors(ci, SQL_HANDLE_STMT); 
      return; 
   } 
 
   lstrcpy((LPSTR)szTitle, (LPSTR)ci->szClientTitle); 
   lstrcat((LPSTR)szTitle, (LPSTR)szCOLON); 
   lstrcat((LPSTR)szTitle, (LPSTR)cati->szDlgTitle); 
   if(ShowCatalogResults(ci, (LPSTR)szTitle)) 
      return; 
} 
 
 
//*------------------------------------------------------------------------ 
//| CatalogWndProc: 
//|   This windows procedure handles all of the catalog function messages. 
//|   Many things such as setting/getting text values are table driven. 
//|   This reduces overall code size significantly. 
//| Parms: 
//|   in       Standard window parms 
//| Returns: 
//|   Depends on message 
//*------------------------------------------------------------------------ 
BOOL EXTFUN CatalogWndProc(HWND hDlg, unsigned msg, WPARAM wParam, LPARAM lParam) 
{ 
   static CATALOGINFO FAR *   cati; 
   int                        dex; 
 
   switch(msg) { 
     case WM_INITDIALOG: 
      cati = (CATALOGINFO FAR *)lParam; 
      CenterDialog(hDlg); 
 
      // Set all default values for edit controls 
      for(dex=0;  dex<NumItems(CatalogVals);  dex++) 
         if(cati->mask & CatalogVals[dex].mMask) { 
            SetWindowText(GetDlgItem(hDlg, CatalogVals[dex].id), 
                          CatalogVals[dex].szStr); 
            SendMessage(GetDlgItem(hDlg, CatalogVals[dex].id), EM_LIMITTEXT, 
                        CatalogVals[dex].cbMax, 0L); 
         } 
      // Special case for dialogs with options 
      if(cati->id == IDM_STATISTICS) { 
         CheckRadioButton(hDlg, IDX_INDEX_UNIQUE, IDX_INDEX_ALL, IDX_INDEX_UNIQUE); 
         CheckRadioButton(hDlg, IDX_ENSURE, IDX_QUICK, IDX_ENSURE); 
      } 
      else if(cati->id == IDM_SPECIAL_COLUMNS) { 
         CheckRadioButton(hDlg, IDX_BEST_ROWID, IDX_ROWVER, IDX_BEST_ROWID); 
         CheckRadioButton(hDlg, IDX_NO_NULLS, IDX_NULLABLE, IDX_NO_NULLS); 
         CheckRadioButton(hDlg, IDX_SCOPE_CURROW, IDX_SCOPE_SESSION, IDX_SCOPE_CURROW); 
      } 
 
      return TRUE; 
 
 
     case WM_COMMAND: 
      switch(GET_WM_COMMAND_ID(wParam, lParam)) { 
        case IDOK: 
         { 
            Busy(TRUE); 
            for(dex=0;  dex<NumItems(CatalogVals);  dex++) 
               if(cati->mask & CatalogVals[dex].mMask) 
                  GetText(GetDlgItem(hDlg, CatalogVals[dex].id), 
                          CatalogVals[dex].szStr); 
            // Special case for dialogs with options 
            if(cati->id == IDM_STATISTICS) { 
               cati->fUnique = GetRadioValue(hDlg, (IDXINFO FAR *)StatsfUnique, NumItems(StatsfUnique)); 
               cati->fAccuracy = GetRadioValue(hDlg, (IDXINFO FAR *)StatsfAccuracy, NumItems(StatsfAccuracy)); 
            } 
            else if(cati->id == IDM_SPECIAL_COLUMNS) { 
               cati->fColType = GetRadioValue(hDlg, (IDXINFO FAR *)SpecColsfColType, 
                                              NumItems(SpecColsfColType)); 
               cati->fScope = GetRadioValue(hDlg, (IDXINFO FAR *)SpecColsfScope, 
                                            NumItems(SpecColsfScope)); 
               cati->fNullable = GetRadioValue(hDlg, (IDXINFO FAR *)SpecColsfNullable, 
                                               NumItems(SpecColsfNullable)); 
            } 
            DoCatalogFunction(cati); 
 
            Busy(FALSE); 
            EndDialog(hDlg, IDOK); 
         } 
         return TRUE; 
 
        case IDCANCEL: 
         SendMessage(hDlg, WM_CLOSE, 0, 0L); 
         EndDialog(hDlg, IDCANCEL); 
         return TRUE; 
      } 
      return TRUE; 
 
     default: 
      return FALSE; 
   } 
   return FALSE; 
}