home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Internet Business Development Kit / PRODUCT_CD.iso / sqlsvr / odbcsdk / samples / admndemo / info.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-07  |  59.2 KB  |  1,790 lines

  1. //*---------------------------------------------------------------------------------
  2. //|  ODBC System Administrator
  3. //|
  4. //|  This code is furnished on an as-is basis as part of the ODBC SDK and is
  5. //|  intended for example purposes only.
  6. //|
  7. //|    Title:    INFO.C
  8. //|        This module contains the functions which handle the Info menu items.
  9. //|            This module relies on RESULTS and EXECUTE to 
  10. //|        This file contains the actual code to execute SQL Statements and
  11. //|            display them.  This file is dependent on the SA Tool data structures
  12. //|            and the independent module RESULTS.
  13. //|
  14. //|        NOTE:  Due to the timing of this sample, only the 1.0 GetInfo constants
  15. //|            are shown.  To see all GetInfo constants for a 2.0 driver, use the
  16. //|            ODBC Test Tool which comes with this SDK.
  17. //*---------------------------------------------------------------------------------
  18. #include "info.h"
  19. #include "ini.h"
  20. #include "sql.h"
  21. #include "sqlext.h"
  22. #include "stdlib.h"
  23. #include "strings.h"
  24. VSZFile;
  25.  
  26. //*---------------------------------------------------------------------------------
  27. //|    Defines and macros
  28. //*---------------------------------------------------------------------------------
  29. #define MAXNAME                35
  30. #define MAXPARMS                18
  31. #define MAXSQL                    300
  32.  
  33. #define szCOMMA                ","
  34. #define szBLANK                " "
  35.  
  36. typedef struct tagNEWPIPE {
  37.     HWND            hwnd;
  38.     HINSTANCE    hInst;
  39.     char            szName[MAXNAME];
  40.     BOOL            fSuccess;
  41.     } NEWPIPE;
  42.  
  43. //*---------------------------------------------------------------------------------
  44. //|    Local Function Prototypes
  45. //*---------------------------------------------------------------------------------
  46. BOOL EXTFUN EditPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam);
  47. void NewPipe(NEWPIPE FAR * np);
  48. BOOL EXTFUN NewPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam);
  49. BOOL EXTFUN DoPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam);
  50. void DoPipe(RESULTSSET FAR * rs, CHILDINFO FAR * ci, LPSTR szPipeName,
  51.             int FAR xPipes[], int cbCnt);
  52. void DoPipeByValue(RESULTSSET FAR * rs, CHILDINFO FAR * ci, LPSTR sqlpsql,
  53.         LPSTR szparms, int FAR xPipes[], int cbCnt, LPSTR szPipeName);
  54. void PrepareParmList(LPSTR str);
  55. SDWORD RefreshList(HWND hDlg, RESULTSSET FAR * rs, CHILDINFO FAR * ci, int state, 
  56.             LPSTR szQual, LPSTR szOwner, LPSTR szName, int cbCols);
  57. SDWORD RefreshPipeList(HWND hDlg);
  58.  
  59.  
  60. //*---------------------------------------------------------------------------------
  61. //|    Global variables
  62. //*---------------------------------------------------------------------------------
  63. extern dCSEG(char) szMSSansSerif[];
  64. extern dCSEG(char) szPIPES[];
  65. extern dCSEG(char) szFONT[];
  66. extern char             OutStr[MAXBUFF];
  67. extern dCSEG(char) szVALUE[];
  68. dCSEG(char) szCore[]                    =    "Core";
  69. dCSEG(char) szLvl1[]                    =    "Level 1";
  70. dCSEG(char) szLvl2[]                    =    "Level 2";
  71. dCSEG(char) szYes[]                    =    "Yes";
  72. dCSEG(char) szNo[]                    =    "No";
  73. dCSEG(char) szODBCFunctions[]        =    "Functions";
  74. dCSEG(char) szODBCDataSources[]    =    "Data Sources";
  75. dCSEG(char) szODBCDataTypes[]        =    "Data Types";
  76. dCSEG(char)    szGetInfoTitle[]        =    "Get Info";
  77. dCSEG(char) szQualifier[]            =    "Qualifier";
  78. dCSEG(char) szOwner[]                =    "Owner";
  79. dCSEG(char) szName[]                    =    "Name";
  80. dCSEG(char) szType[]                    =    "Type";
  81. dCSEG(char) szSQL[]                    =    "Sql";
  82. dCSEG(char) szPARMS[]                =    "Parms";
  83. dCSEG(char) szPARMOPT[]                =    "ParmOpt";
  84. dCSEG(char) szDELETEOPT[]            =    "Delete";
  85. dCSEG(char) szBothTypes[]            =    "'%s','%s'";
  86. dCSEG(char) szOneType[]                =  "'%s'";
  87. dCSEG(char) szBlank[]                =    " ";
  88. dCSEG(char) szTABLETYPE[]            =     "TABLE";
  89. dCSEG(char) szVIEWTYPE[]            =     "VIEW";
  90. dCSEG(char)    szVALUE[]                =    "value";
  91. dCSEG(char)    szADDRESS[]                =    "address";
  92. dCSEG(char) szDeletePipe[]            =    "Delete pipe %s?";
  93. dCSEG(char)    szEditPipe[]            =    "Edit Pipe";
  94. dCSEG(char) szDuplicatePipe[]        =    "Pipe already exists";
  95. dCSEG(char) szInstalled[]            =    "Installed";
  96. dCSEG(char) szDROPPROCSEMI[]        =  "Drop Procedure (with semi-colon)";
  97.  
  98. static char szErrorMsgTitle[]        =    "Error";
  99.  
  100.  
  101.  
  102. struct {
  103.     UWORD                fFunction;                        // Identifier for SQLGetFunctions
  104.     LPSTR                szLevel;                            // Conformance Level
  105.     int                idFunction;                        // String table identifier for function name
  106.     } ODBCFunctions[] = {
  107. // fFunction                                szLevel                 idFunction
  108. //    -------------------------------    ---------------    --------------------------------
  109.     SQL_API_SQLALLOCCONNECT,            (LPSTR)szCore,        idsSQLAllocConnect,
  110.     SQL_API_SQLALLOCENV,                    (LPSTR)szCore,        idsSQLAllocEnv,
  111.     SQL_API_SQLALLOCSTMT,                (LPSTR)szCore,        idsSQLAllocStmt,
  112.     SQL_API_SQLBINDCOL,                    (LPSTR)szCore,        idsSQLBindCol,
  113.     SQL_API_SQLCANCEL,                    (LPSTR)szCore,        idsSQLCancel,
  114.     SQL_API_SQLCOLATTRIBUTES,            (LPSTR)szCore,        idsSQLColAttributes,
  115.     SQL_API_SQLCONNECT,                    (LPSTR)szCore,        idsSQLConnect,
  116.     SQL_API_SQLDESCRIBECOL,                (LPSTR)szCore,        idsSQLDescribeCol,
  117.     SQL_API_SQLDISCONNECT,                (LPSTR)szCore,        idsSQLDisconnect,
  118.     SQL_API_SQLERROR,                        (LPSTR)szCore,        idsSQLError,
  119.     SQL_API_SQLEXECDIRECT,                (LPSTR)szCore,        idsSQLExecDirect,
  120.     SQL_API_SQLEXECUTE,                    (LPSTR)szCore,        idsSQLExecute,
  121.     SQL_API_SQLFETCH,                        (LPSTR)szCore,        idsSQLFetch,
  122.     SQL_API_SQLFREECONNECT,                (LPSTR)szCore,        idsSQLFreeConnect,
  123.     SQL_API_SQLFREEENV,                    (LPSTR)szCore,        idsSQLFreeEnv,
  124.     SQL_API_SQLFREESTMT,                    (LPSTR)szCore,        idsSQLFreeStmt,
  125.     SQL_API_SQLGETCURSORNAME,            (LPSTR)szCore,        idsSQLGetCursorName,
  126.     SQL_API_SQLNUMRESULTCOLS,            (LPSTR)szCore,        idsSQLNumResultCols,
  127.     SQL_API_SQLPREPARE,                    (LPSTR)szCore,        idsSQLPrepare,
  128.     SQL_API_SQLROWCOUNT,                    (LPSTR)szCore,        idsSQLRowCount,
  129.     SQL_API_SQLSETCURSORNAME,            (LPSTR)szCore,        idsSQLSetCursorName,
  130.     SQL_API_SQLSETPARAM,                    (LPSTR)szCore,        idsSQLSetParam,
  131.     SQL_API_SQLTRANSACT,                    (LPSTR)szCore,        idsSQLTransact,
  132. //---- Level 1 Conformance ----------------------------------    
  133.     SQL_API_SQLCOLUMNS,                    (LPSTR)szLvl1,        idsSQLColumns,
  134.     SQL_API_SQLDRIVERCONNECT,            (LPSTR)szLvl1,        idsSQLDriverConnect,
  135.     SQL_API_SQLGETCONNECTOPTION,        (LPSTR)szLvl1,        idsSQLGetConnectOption,
  136.     SQL_API_SQLGETDATA,                    (LPSTR)szLvl1,        idsSQLGetData,
  137.     SQL_API_SQLGETFUNCTIONS,            (LPSTR)szLvl1,        idsSQLGetFunctions,
  138.     SQL_API_SQLGETSTMTOPTION,            (LPSTR)szLvl1,        idsSQLGetStmtOption,
  139.     SQL_API_SQLGETTYPEINFO,                (LPSTR)szLvl1,        idsSQLGetTypeInfo,
  140.     SQL_API_SQLPARAMDATA,                (LPSTR)szLvl1,        idsSQLParamData,
  141.     SQL_API_SQLPUTDATA,                    (LPSTR)szLvl1,        idsSQLPutData,
  142.     SQL_API_SQLSETCONNECTOPTION,        (LPSTR)szLvl1,        idsSQLSetConnectOption,
  143.     SQL_API_SQLSETSTMTOPTION,            (LPSTR)szLvl1,        idsSQLSetStmtOption,
  144.     SQL_API_SQLSPECIALCOLUMNS,            (LPSTR)szLvl1,        idsSQLSpecialColumns,
  145.     SQL_API_SQLSTATISTICS,                (LPSTR)szLvl1,        idsSQLStatistics,
  146.     SQL_API_SQLTABLES,                    (LPSTR)szLvl1,        idsSQLTables,
  147. //---- Level 2 Conformance ----------------------------------
  148.     SQL_API_SQLBROWSECONNECT,            (LPSTR)szLvl2,        idsSQLBrowseConnect,
  149.     SQL_API_SQLCOLUMNPRIVILEGES,        (LPSTR)szLvl2,        idsSQLColumnPrivileges,
  150.     SQL_API_SQLDATASOURCES,                (LPSTR)szLvl2,        idsSQLDataSources,
  151.     SQL_API_SQLDESCRIBEPARAM,            (LPSTR)szLvl2,        idsSQLDescribeParam,
  152.     SQL_API_SQLEXTENDEDFETCH,            (LPSTR)szLvl2,        idsSQLExtendedFetch,
  153.     SQL_API_SQLFOREIGNKEYS,                (LPSTR)szLvl2,        idsSQLForeignKeys,
  154.     SQL_API_SQLMORERESULTS,                (LPSTR)szLvl2,        idsSQLMoreResults,
  155.     SQL_API_SQLNATIVESQL,                (LPSTR)szLvl2,        idsSQLNativeSql,
  156.     SQL_API_SQLNUMPARAMS,                (LPSTR)szLvl2,        idsSQLNumParams,
  157.     SQL_API_SQLPARAMOPTIONS,            (LPSTR)szLvl2,        idsSQLParamOptions,
  158.     SQL_API_SQLPRIMARYKEYS,                (LPSTR)szLvl2,        idsSQLPrimaryKeys,
  159.     SQL_API_SQLPROCEDURECOLUMNS,        (LPSTR)szLvl2,        idsSQLProcedureColumns,
  160.     SQL_API_SQLPROCEDURES,                (LPSTR)szLvl2,        idsSQLProcedures,
  161.     SQL_API_SQLSETPOS,                    (LPSTR)szLvl2,        idsSQLSetPos,
  162.     SQL_API_SQLSETSCROLLOPTIONS,        (LPSTR)szLvl2,        idsSQLSetScrollOptions,
  163.     SQL_API_SQLTABLEPRIVILEGES,        (LPSTR)szLvl2,        idsSQLTablePrivileges,
  164.     };
  165.  
  166.  
  167. //
  168. // Generic prototype for bitmap structures
  169. // 
  170. typedef struct tagINFOSTRUCT {
  171.     UDWORD            fVal;                                // Which constant
  172.     int                idsStr;                            // String index number
  173.     } INFOSTRUCT;
  174. typedef INFOSTRUCT FAR * lpINFOSTRUCT;
  175.  
  176. typedef struct tagDEXSTRUCT {
  177.     int                idsStr;                            // String index number
  178.     } DEXSTRUCT;
  179. typedef DEXSTRUCT FAR * lpDEXSTRUCT;
  180.     
  181. //
  182. //    Structure for SQL_FETCH_DIRECTION
  183. //
  184. struct {
  185.     UDWORD            fVal;                                // Which constant
  186.     int                idsStr;                            // String index number
  187.     } GetInfoFetchDir[] = {
  188. //    fVal                                    idsStr
  189. //    -----------------------------    -------------------------------
  190.     SQL_FD_FETCH_NEXT,                idsSQL_FD_FETCH_NEXT,
  191.     SQL_FD_FETCH_FIRST,                idsSQL_FD_FETCH_FIRST,
  192.     SQL_FD_FETCH_LAST,                idsSQL_FD_FETCH_LAST,
  193.     SQL_FD_FETCH_PREV,                idsSQL_FD_FETCH_PREV,
  194.     SQL_FD_FETCH_ABSOLUTE,            idsSQL_FD_FETCH_ABSOLUTE,
  195.     SQL_FD_FETCH_RELATIVE,            idsSQL_FD_FETCH_RELATIVE,
  196.     SQL_FD_FETCH_RESUME,                idsSQL_FD_FETCH_RESUME,
  197.     };
  198.     
  199. //
  200. //    Structure for SQL_DEFAULT_TXN_ISOLATION
  201. //
  202. struct {
  203.     UDWORD            fVal;                                // Which constant
  204.     int                idsStr;                            // String index number
  205.     } GetInfoTXNIsolation[] = {
  206. //    fVal                                    idsStr
  207. //    -----------------------------    -------------------------------
  208.     SQL_TXN_READ_UNCOMMITTED,        idsSQL_TXN_READ_UNCOMMITTED,
  209.     SQL_TXN_READ_COMMITTED,            idsSQL_TXN_READ_COMMITTED,
  210.     SQL_TXN_REPEATABLE_READ,        idsSQL_TXN_REPEATABLE_READ,
  211.     SQL_TXN_SERIALIZABLE,            idsSQL_TXN_SERIALIZABLE,
  212.     SQL_TXN_VERSIONING,                idsSQL_TXN_VERSIONING,
  213.     };
  214.     
  215. //
  216. //    Structure for SQL_SCROLL_CONCURRENCY
  217. //
  218. struct {
  219.     UDWORD            fVal;                                // Which constant
  220.     int                idsStr;                            // String index number
  221.     } GetInfoConcurr[] = {
  222. //    fVal                                    idsStr
  223. //    -----------------------------    -------------------------------
  224.     SQL_SCCO_READ_ONLY,                idsSQL_SCCO_READ_ONLY,
  225.     SQL_SCCO_LOCK,                        idsSQL_SCCO_LOCK,
  226.     SQL_SCCO_OPT_TIMESTAMP,            idsSQL_SCCO_OPT_TIMESTAMP,
  227.     SQL_SCCO_OPT_VALUES,                idsSQL_SCCO_OPT_VALUES,
  228.     };
  229.     
  230. //
  231. //    Structure for SQL_SCROLL_OPTIONS
  232. //
  233. struct {
  234.     UDWORD            fVal;                                // Which constant
  235.     int                idsStr;                            // String index number
  236.     } GetInfoScrollOptions[] = {
  237. //    fVal                                    idsStr
  238. //    -----------------------------    -------------------------------
  239.     SQL_SO_FORWARD_ONLY,                idsSQL_SO_FORWARD_ONLY,
  240.     SQL_SO_KEYSET_DRIVEN,            idsSQL_SO_KEYSET_DRIVEN,
  241.     SQL_SO_DYNAMIC,                    idsSQL_SO_DYNAMIC,
  242.     SQL_SO_MIXED,                        idsSQL_SO_MIXED,
  243.     };
  244.     
  245. //
  246. //    Structure for SQL_TXN_ISOLATION_OPTIONS
  247. //
  248. struct {
  249.     UDWORD            fVal;                                // Which constant
  250.     int                idsStr;                            // String index number
  251.     } GetInfoTxnIsoOptions[] = {
  252. //    fVal                                    idsStr
  253. //    -----------------------------    -------------------------------
  254.     SQL_TXN_READ_UNCOMMITTED,        idsSQL_TXN_READ_UNCOMMITTED,
  255.     SQL_TXN_READ_COMMITTED,            idsSQL_TXN_READ_COMMITTED,
  256.     SQL_TXN_REPEATABLE_READ,        idsSQL_TXN_REPEATABLE_READ,
  257.     SQL_TXN_SERIALIZABLE,            idsSQL_TXN_SERIALIZABLE,
  258.     SQL_TXN_VERSIONING,                idsSQL_TXN_VERSIONING,
  259.     };
  260.  
  261. //
  262. //    Structure for SQL_CONVERT_FUNCTIONS
  263. //
  264. struct {
  265.     UDWORD            fVal;                                // Which constant
  266.     int                idsStr;                            // String index number
  267.     } GetInfoConvert[] = {
  268. //    fVal                                    idsStr
  269. //    -----------------------------    -------------------------------
  270.     SQL_FN_CVT_CONVERT,                idsSQL_FN_CVT_CONVERT,
  271.     };
  272.  
  273. //
  274. //    Structure for SQL_NUMERIC_FUNCTIONS
  275. //
  276. struct {
  277.     UDWORD            fVal;                                // Which constant
  278.     int                idsStr;                            // String index number
  279.     } GetInfoNumeric[] = {
  280. //    fVal                                    idsStr
  281. //    -----------------------------    -------------------------------
  282.     SQL_FN_NUM_ABS,                    idsSQL_FN_NUM_ABS,
  283.     SQL_FN_NUM_ACOS,                    idsSQL_FN_NUM_ACOS,
  284.     SQL_FN_NUM_ASIN,                    idsSQL_FN_NUM_ASIN,
  285.     SQL_FN_NUM_ATAN,                    idsSQL_FN_NUM_ATAN,
  286.     SQL_FN_NUM_ATAN2,                    idsSQL_FN_NUM_ATAN2,
  287.     SQL_FN_NUM_CEILING,                idsSQL_FN_NUM_CEILING,
  288.     SQL_FN_NUM_COS,                    idsSQL_FN_NUM_COS,
  289.     SQL_FN_NUM_COT,                    idsSQL_FN_NUM_COT,
  290.     SQL_FN_NUM_EXP,                    idsSQL_FN_NUM_EXP,
  291.     SQL_FN_NUM_FLOOR,                    idsSQL_FN_NUM_FLOOR,
  292.     SQL_FN_NUM_LOG,                    idsSQL_FN_NUM_LOG,
  293.     SQL_FN_NUM_MOD,                    idsSQL_FN_NUM_MOD,
  294.     SQL_FN_NUM_RAND,                    idsSQL_FN_NUM_RAND,
  295.     SQL_FN_NUM_PI,                        idsSQL_FN_NUM_PI,
  296.     SQL_FN_NUM_SIGN,                    idsSQL_FN_NUM_SIGN,
  297.     SQL_FN_NUM_SIN,                    idsSQL_FN_NUM_SIN,
  298.     SQL_FN_NUM_SQRT,                    idsSQL_FN_NUM_SQRT,
  299.     SQL_FN_NUM_TAN,                    idsSQL_FN_NUM_TAN,
  300.     };
  301.  
  302. //
  303. //    Structure for SQL_STRING_FUNCTIONS
  304. //
  305. struct {
  306.     UDWORD            fVal;                                // Which constant
  307.     int                idsStr;                            // String index number
  308.     } GetInfoStrings[] = {
  309. //    fVal                                    idsStr
  310. //    -----------------------------    -------------------------------
  311.     SQL_FN_STR_ASCII,                    idsSQL_FN_STR_ASCII,
  312.     SQL_FN_STR_CHAR,                    idsSQL_FN_STR_CHAR,
  313.     SQL_FN_STR_CONCAT,                idsSQL_FN_STR_CONCAT,
  314.     SQL_FN_STR_INSERT,                idsSQL_FN_STR_INSERT,
  315.     SQL_FN_STR_LEFT,                    idsSQL_FN_STR_LEFT,
  316.     SQL_FN_STR_LTRIM,                    idsSQL_FN_STR_LTRIM,
  317.     SQL_FN_STR_LENGTH,                idsSQL_FN_STR_LENGTH,
  318.     SQL_FN_STR_LOCATE,                idsSQL_FN_STR_LOCATE,
  319.     SQL_FN_STR_LCASE,                    idsSQL_FN_STR_LCASE,
  320.     SQL_FN_STR_REPEAT,                idsSQL_FN_STR_REPEAT,
  321.     SQL_FN_STR_REPLACE,                idsSQL_FN_STR_REPLACE,
  322.     SQL_FN_STR_RIGHT,                    idsSQL_FN_STR_RIGHT,
  323.     SQL_FN_STR_RTRIM,                    idsSQL_FN_STR_RTRIM,
  324.     SQL_FN_STR_SUBSTRING,            idsSQL_FN_STR_SUBSTRING,
  325.     SQL_FN_STR_UCASE,                    idsSQL_FN_STR_UCASE,
  326.     };
  327.  
  328. //
  329. //    Structure for SQL_SYSTEM_FUNCTIONS
  330. //
  331. struct {
  332.     UDWORD            fVal;                                // Which constant
  333.     int                idsStr;                            // String index number
  334.     } GetInfoSystem[] = {
  335. //    fVal                                    idsStr
  336. //    -----------------------------    -------------------------------
  337.     SQL_FN_SYS_USERNAME,                idsSQL_FN_SYS_USERNAME,
  338.     SQL_FN_SYS_DBNAME,                idsSQL_FN_SYS_DBNAME,
  339.     SQL_FN_SYS_IFNULL,                idsSQL_FN_SYS_IFNULL,
  340.     };
  341.  
  342. //
  343. //    Structure for SQL_TIMEDATE_FUNCTIONS
  344. //
  345. struct {
  346.     UDWORD            fVal;                                // Which constant
  347.     int                idsStr;                            // String index number
  348.     } GetInfoTimeDate[] = {
  349. //    fVal                                    idsStr
  350. //    -----------------------------    -------------------------------
  351.     SQL_FN_TD_NOW,                        idsSQL_FN_TD_NOW,
  352.     SQL_FN_TD_CURDATE,                idsSQL_FN_TD_CURDATE,
  353.     SQL_FN_TD_DAYOFMONTH,            idsSQL_FN_TD_DAYOFMONTH,
  354.     SQL_FN_TD_DAYOFWEEK,                idsSQL_FN_TD_DAYOFWEEK,
  355.     SQL_FN_TD_DAYOFYEAR,                idsSQL_FN_TD_DAYOFYEAR,
  356.     SQL_FN_TD_MONTH,                    idsSQL_FN_TD_MONTH,
  357.     SQL_FN_TD_QUARTER,                idsSQL_FN_TD_QUARTER,
  358.     SQL_FN_TD_WEEK,                    idsSQL_FN_TD_WEEK,
  359.     SQL_FN_TD_YEAR,                    idsSQL_FN_TD_YEAR,
  360.     SQL_FN_TD_CURTIME,                idsSQL_FN_TD_CURTIME,
  361.     SQL_FN_TD_HOUR,                    idsSQL_FN_TD_HOUR,
  362.     SQL_FN_TD_MINUTE,                    idsSQL_FN_TD_MINUTE,
  363.     SQL_FN_TD_SECOND,                    idsSQL_FN_TD_SECOND,
  364.     };
  365.  
  366. //
  367. //    Structure for SQL_CONVERT_xxxx
  368. //
  369. struct {
  370.     UDWORD            fVal;                                // Which constant
  371.     int                idsStr;                            // String index number
  372.     } GetInfoConvertTypes[] = {
  373. //    fVal                                    idsStr
  374. //    -----------------------------    -------------------------------
  375.     SQL_CVT_BIGINT,                    idsCVT_BIGINT,
  376.     SQL_CVT_BINARY,                    idsCVT_BINARY,
  377.     SQL_CVT_BIT,                        idsCVT_BIT,
  378.     SQL_CVT_CHAR,                        idsCVT_CHAR,
  379.     SQL_CVT_DATE,                        idsCVT_DATE,
  380.     SQL_CVT_DECIMAL,                    idsCVT_DECIMAL,
  381.     SQL_CVT_DOUBLE,                    idsCVT_DOUBLE,
  382.     SQL_CVT_FLOAT,                        idsCVT_FLOAT,
  383.     SQL_CVT_INTEGER,                    idsCVT_INTEGER,
  384.     SQL_CVT_LONGVARBINARY,            idsCVT_LONGVARBINARY,
  385.     SQL_CVT_LONGVARCHAR,                idsCVT_LONGVARCHAR,
  386.     SQL_CVT_NUMERIC,                    idsCVT_NUMERIC,
  387.     SQL_CVT_REAL,                        idsCVT_REAL,
  388.     SQL_CVT_SMALLINT,                    idsCVT_SMALLINT,
  389.     SQL_CVT_TIME,                        idsCVT_TIME,
  390.     SQL_CVT_TIMESTAMP,                idsCVT_TIMESTAMP,
  391.     SQL_CVT_TINYINT,                    idsCVT_TINYINT,
  392.     SQL_CVT_VARBINARY,                idsCVT_VARBINARY,
  393.     SQL_CVT_VARCHAR,                    idsCVT_VARCHAR,
  394.     };
  395.     
  396. //
  397. //    Structure for SQL_ODBC_API_CONFORMANCE
  398. //
  399. struct {
  400.     int                idsStr;                            // String index number
  401.     } GetInfoAPIConform[] = {
  402. //    idsStr
  403. //    -----------------------------
  404.     idsSQL_CONFORM_NONE,
  405.     idsSQL_LEVEL1_NONE,
  406.     idsSQL_LEVEL2_NONE,
  407.     };
  408.     
  409. //
  410. //    Structure for SQL_ODBC_SAG_API_CONFORMANCE
  411. //
  412. struct {
  413.     int                idsStr;                            // String index number
  414.     } GetInfoSAGCLIConform[] = {
  415. //    idsStr
  416. //    -----------------------------
  417.     idsSQL_NONSAG,
  418.     idsSQL_SAG,
  419.     };
  420.     
  421. //
  422. //    Structure for SQL_ODBC_SQL_CONFORMANCE
  423. //
  424. struct {
  425.     int                idsStr;                            // String index number
  426.     } GetInfoODBCSQL[] = {
  427. //    idsStr
  428. //    -----------------------------
  429.     idsCONFORM_MINIMUM,
  430.     idsCONFORM_CORE,
  431.     idsCONFORM_EXTENDED,
  432.     };
  433.     
  434. //
  435. //    Structure for SQL_CONCAT_NULL_BEHAVIOR
  436. //
  437. struct {
  438.     int                idsStr;                            // String index number
  439.     } GetInfoConcat[] = {
  440. //    idsStr
  441. //    -----------------------------
  442.     idsCONCAT_0,
  443.     idsCONCAT_1,
  444.     };
  445.     
  446. //
  447. //    Structure for SQL_CURSOR_COMMIT_BEHAVIOR
  448. //
  449. struct {
  450.     int                idsStr;                            // String index number
  451.     } GetInfoCommit[] = {
  452. //    idsStr
  453. //    -----------------------------
  454.     idsCOMMIT_0,
  455.     idsCOMMIT_1,
  456.     idsCOMMIT_2,
  457.     };
  458.     
  459. //
  460. //    Structure for SQL_CURSOR_ROLLBACK_BEHAVIOR
  461. //
  462. struct {
  463.     int                idsStr;                            // String index number
  464.     } GetInfoRollback[] = {
  465. //    idsStr
  466. //    -----------------------------
  467.     idsROLLBACK_0,
  468.     idsROLLBACK_1,
  469.     idsROLLBACK_2,
  470.     };
  471.     
  472. //
  473. //    Structure for SQL_IDENTIFIER_CASE
  474. //
  475. struct {
  476.     int                idsStr;                            // String index number
  477.     } GetInfoIDCase[] = {
  478. //    idsStr
  479. //    -----------------------------
  480.     0,
  481.     idsUPPERCASE,
  482.     idsLOWERCASE,
  483.     idsCASESENSITIVE,
  484.     idsNOTCASESENSITIVE,
  485.     };
  486.     
  487. //
  488. //    Structure for SQL_TXN_CAPABLE
  489. //
  490. struct {
  491.     int                idsStr;                            // String index number
  492.     } GetInfoTxnCapable[] = {
  493. //    idsStr
  494. //    -----------------------------
  495.     idsNOTRANS,
  496.     idsDMLSUPPORT,
  497.     idsDDLSUPPORT,
  498.     };
  499.  
  500. //
  501. //    The following structure is used to retrieve information about the driver.  There
  502. //        are 5 types of GetInfo structures:
  503. //                INT16            16-bit value
  504. //                INT32            32-bit value
  505. //                STRVAL        String value
  506. //                DEXVAL        Indexed item (eg: 0-x)
  507. //                BITVAL        Bit-mask value
  508. //
  509. char                szGetInfo[MAXBUFF];
  510. UWORD                cb16;
  511. UDWORD            cb32;
  512. #define            INT16                    1
  513. #define            INT32                    2
  514. #define            STRVAL                3
  515. #define            DEXVAL                4
  516. #define            BITVAL                5
  517. struct {
  518.     UWORD                fInfoType;                        // What we're looking for
  519.     int                fOutType;                        // string, 16-bit or 32-bit
  520.     PTR                rgbInfoValue;                    // Output buffer
  521.     SWORD                cbInfoMax;                        // Size of output buffer
  522.     void FAR *        ptr;                                // Generic constant structure
  523.     int                cbNum;                            // Count of items in ptr
  524.     } GetInfo[] = {
  525. //    fInfoType                                fOutType            rgbInfoValue        cbInfoMax        ptr                            cbNum
  526. //    --------------------                    -----------        -----------------    -------------     ----------------------    --------------------------
  527. // Connection and environment info
  528.     SQL_ACTIVE_CONNECTIONS,                INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  529.     SQL_ACTIVE_STATEMENTS,                INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  530.     SQL_DATA_SOURCE_NAME,                STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  531.     SQL_DRIVER_HENV,                        INT32,            &cb32,                sizeof(HENV),    NULL,                            0,
  532.     SQL_DRIVER_HDBC,                        INT32,            &cb32,                sizeof(HDBC),    NULL,                            0,
  533.     SQL_DRIVER_HSTMT,                        INT32,            &cb32,                sizeof(HSTMT),    NULL,                            0,
  534.     SQL_DRIVER_NAME,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  535.     SQL_DRIVER_VER,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  536.     SQL_FETCH_DIRECTION,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoFetchDir,            NumItems(GetInfoFetchDir),
  537.     SQL_ODBC_API_CONFORMANCE,            DEXVAL,            &cb16,                sizeof(cb16),    GetInfoAPIConform,        NumItems(GetInfoAPIConform),
  538.     SQL_ODBC_SAG_CLI_CONFORMANCE,        DEXVAL,            &cb16,                sizeof(cb16),    GetInfoSAGCLIConform,    NumItems(GetInfoSAGCLIConform),
  539.     SQL_ODBC_SQL_CONFORMANCE,            DEXVAL,            &cb16,                sizeof(cb16),    GetInfoODBCSQL,            NumItems(GetInfoODBCSQL),
  540.     SQL_ODBC_SQL_OPT_IEF,                STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  541.     SQL_ODBC_VER,                            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  542.     SQL_PROCEDURES,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  543.     SQL_ROW_UPDATES,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  544.     SQL_SEARCH_PATTERN_ESCAPE,            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  545.     SQL_SERVER_NAME,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  546. // DBMS Info
  547.     SQL_DATABASE_NAME,                    STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  548.     SQL_DBMS_NAME,                            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  549.     SQL_DBMS_VER,                            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  550. //    Status Info
  551.     SQL_ACCESSIBLE_TABLES,                STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  552.     SQL_ACCESSIBLE_PROCEDURES,            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  553.     SQL_CONCAT_NULL_BEHAVIOR,            DEXVAL,            &cb16,                sizeof(cb16),    GetInfoConcat,                NumItems(GetInfoConcat),
  554.     SQL_CURSOR_COMMIT_BEHAVIOR,        DEXVAL,            &cb16,                sizeof(cb16),    GetInfoCommit,                NumItems(GetInfoCommit),
  555.     SQL_CURSOR_ROLLBACK_BEHAVIOR,        DEXVAL,            &cb16,                sizeof(cb16),    GetInfoRollback,            NumItems(GetInfoRollback),
  556.     SQL_DATA_SOURCE_READ_ONLY,            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  557.     SQL_DEFAULT_TXN_ISOLATION,            BITVAL,            &cb32,                sizeof(cb32),    GetInfoTXNIsolation,        NumItems(GetInfoTXNIsolation),
  558.     SQL_EXPRESSIONS_IN_ORDERBY,        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  559.     SQL_IDENTIFIER_CASE,                    DEXVAL,            &cb16,                sizeof(cb16),    GetInfoIDCase,                NumItems(GetInfoIDCase),
  560.     SQL_IDENTIFIER_QUOTE_CHAR,            INT16,            szGetInfo,            MAXBUFF,            NULL,                            0,
  561.     SQL_MAX_COLUMN_NAME_LEN,            INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  562.     SQL_MAX_CURSOR_NAME_LEN,            INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  563.     SQL_MAX_OWNER_NAME_LEN,                INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  564.     SQL_MAX_PROCEDURE_NAME_LEN,        INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  565.     SQL_MAX_QUALIFIER_NAME_LEN,      INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  566.     SQL_MAX_TABLE_NAME_LEN,                INT16,            &cb16,                sizeof(cb16),    NULL,                            0,
  567.     SQL_MULT_RESULT_SETS,                STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  568.     SQL_MULTIPLE_ACTIVE_TXN,            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  569.     SQL_OUTER_JOINS,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  570.     SQL_OWNER_TERM,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  571.     SQL_PROCEDURE_TERM,                    STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  572.     SQL_QUALIFIER_NAME_SEPARATOR,        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  573.     SQL_QUALIFIER_TERM,                    STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  574.     SQL_SCROLL_CONCURRENCY,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoConcurr,            NumItems(GetInfoConcurr),
  575.     SQL_SCROLL_OPTIONS,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoScrollOptions,    NumItems(GetInfoScrollOptions),
  576.     SQL_TABLE_TERM,                        STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  577.     SQL_TXN_CAPABLE,                        DEXVAL,            &cb16,                sizeof(cb16),    GetInfoTxnCapable,        NumItems(GetInfoTxnCapable),
  578.     SQL_TXN_ISOLATION_OPTION,            BITVAL,            &cb32,                sizeof(cb32),    GetInfoTxnIsoOptions,    NumItems(GetInfoTxnIsoOptions),
  579.     SQL_USER_NAME,                            STRVAL,            szGetInfo,            MAXBUFF,            NULL,                            0,
  580. //    Scalar functions
  581.     SQL_CONVERT_FUNCTIONS,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvert,            NumItems(GetInfoConvert),
  582.     SQL_NUMERIC_FUNCTIONS,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoNumeric,            NumItems(GetInfoNumeric),
  583.     SQL_STRING_FUNCTIONS,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoStrings,            NumItems(GetInfoStrings),
  584.     SQL_SYSTEM_FUNCTIONS,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoSystem,                NumItems(GetInfoSystem),
  585.     SQL_TIMEDATE_FUNCTIONS,                BITVAL,            &cb32,                sizeof(cb32),     GetInfoTimeDate,            NumItems(GetInfoTimeDate),
  586. // Conversions
  587.     SQL_CONVERT_BIGINT,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  588.     SQL_CONVERT_BINARY,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  589.     SQL_CONVERT_BIT,                        BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  590.     SQL_CONVERT_CHAR,                        BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  591.     SQL_CONVERT_DATE,                        BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  592.     SQL_CONVERT_DECIMAL,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  593.     SQL_CONVERT_DOUBLE,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  594.     SQL_CONVERT_FLOAT,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  595.     SQL_CONVERT_INTEGER,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  596.     SQL_CONVERT_LONGVARBINARY,            BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  597.     SQL_CONVERT_LONGVARCHAR,            BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  598.     SQL_CONVERT_NUMERIC,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  599.     SQL_CONVERT_REAL,                        BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  600.     SQL_CONVERT_SMALLINT,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  601.     SQL_CONVERT_TIME,                        BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  602.     SQL_CONVERT_TIMESTAMP,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  603.     SQL_CONVERT_TINYINT,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  604.     SQL_CONVERT_VARBINARY,                BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  605.     SQL_CONVERT_VARCHAR,                    BITVAL,            &cb32,                sizeof(cb32),    GetInfoConvertTypes,        NumItems(GetInfoConvertTypes),    
  606.     };
  607.  
  608.     
  609. //*---------------------------------------------------------------------------------
  610. //| GetIndexVal:
  611. //|    Call this function to retrieve the string values for all items which meet
  612. //|    the bitwise and condition.
  613. //| Parms:
  614. //|    in            rs                            Pointer to the results set
  615. //|    in            szConstant                The constant value being retrieve
  616. //|    in            is                            Structure with resource ids and values
  617. //|    in            maxdex                    Number of items in struct
  618. //|    in            mask                        The value to compare against
  619. //|    in            szOut                        Output buffer for retrieval
  620. //|    in            cbOut                        Size of output buffer
  621. //| Returns:              
  622. //|    Nothing
  623. //*---------------------------------------------------------------------------------
  624. BOOL GetBitVal(RESULTSSET FAR * rs, LPSTR szConstant,
  625.                 lpINFOSTRUCT is, int maxdex, UDWORD mask,
  626.                 LPSTR szVal, int cbVal)
  627. {
  628.     int                tdex;
  629.     ROWDATA FAR *     rd;
  630.     COLORREF            rgbDft=GetDefaultRGB();
  631.     
  632.     for(tdex=0;  tdex<maxdex;  tdex++) 
  633.         if(is[tdex].fVal & mask) {
  634.             rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  635.             SetColumnData(0, rd, szConstant);
  636.             iLoadString(is[tdex].idsStr, (LPSTR)szVal, cbVal);
  637.             SetColumnData(1, rd, (LPSTR)szVal);
  638.             if(AddRowData(rs, rd) == LB_ERRSPACE)
  639.                 return FALSE;
  640.             }
  641.      return TRUE;
  642. }
  643.  
  644.     
  645. //*---------------------------------------------------------------------------------
  646. //| GetIndexVal:
  647. //|    Call this function to retrieve the string value for a constant.
  648. //| Parms:
  649. //|    in            rs                            Pointer to the results set
  650. //|    in            szConstant                The constant value being retrieve
  651. //|    in            dex                        String index value 
  652. //|    in            szOut                        Output buffer for retrieval
  653. //|    in            cbOut                        Size of output buffer
  654. //| Returns:              
  655. //|    FALSE if there is an error
  656. //*---------------------------------------------------------------------------------
  657. BOOL GetIndexVal(RESULTSSET FAR * rs, LPSTR szConstant, 
  658.         int dex, LPSTR szOut, int cbOut)
  659. {
  660.     ROWDATA FAR *     rd;
  661.     COLORREF            rgbDft=GetDefaultRGB();
  662.                 
  663.     rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  664.     SetColumnData(0, rd, szConstant);
  665.     iLoadString(dex, (LPSTR)szOut, cbOut);
  666.     SetColumnData(1, rd, (LPSTR)szOut);
  667.     if(AddRowData(rs, rd) == LB_ERRSPACE)
  668.         return FALSE;
  669.     return TRUE;
  670. }
  671.  
  672.     
  673. //*---------------------------------------------------------------------------------
  674. //| DisplayGetInfo:
  675. //|    This function goes through all of the SQLGetInfo constants defined in the
  676. //|    ODBC reference guide and displays them in a results set.
  677. //| Parms:
  678. //|    in            ci                            CHILDINFO information
  679. //| Returns:              
  680. //|    TRUE if successful,
  681. //|    FALSE on error
  682. //*---------------------------------------------------------------------------------
  683. BOOL DisplayGetInfo(CHILDINFO FAR * ci)
  684. {
  685.     char                        szConstant[40];
  686.     char                        szTitle[MAXBUFF];
  687.     char                        szVal[MAXBUFF];
  688.     int                         dex;
  689.     lpDEXSTRUCT                lpDEX;
  690.     lpINFOSTRUCT            lpINFS;
  691.     RESULTSSET FAR *         rs;
  692.     ROWDATA FAR *            rd;
  693.     RETCODE                    retcode;
  694.     COLORREF                    rgbDft=GetDefaultRGB();
  695.  
  696.     //
  697.     //    Create a hard coded results set with 2 columns
  698.     //
  699.     lstrcpy((LPSTR)szTitle, (LPSTR)ci->szClientTitle);
  700.     lstrcat((LPSTR)szTitle, (LPSTR)szDash);
  701.     lstrcat((LPSTR)szTitle, (LPSTR)szGetInfoTitle);
  702.     rs = GetConnectWindowResultsNode(ci);
  703.     if(!CreateResultsSet(rs, ci->hwndClient, ci->hInst, 2, (LPSTR)szTitle))
  704.         return FALSE;    
  705.  
  706.     //
  707.     // Set the meta data
  708.     //
  709.     SetMetaDataColumn(rs, 0, (LPSTR)"fInfoType", 
  710.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 40, 0,
  711.             45, TA_LEFT);
  712.     SetMetaDataColumn(rs, 1, (LPSTR)"Value", 
  713.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 25, 0,
  714.             35, TA_LEFT);
  715.  
  716.     //
  717.     // Now create the MDI child window which will hold the results.
  718.     //
  719.     if(!CreateResultsWindow(ci, rs)) 
  720.         goto exit00;
  721.  
  722.    
  723.     //
  724.     // Loop through the control structure and check each fInfoType.  Certain
  725.     //        types require extra processing.
  726.     //
  727.     for(dex=0;  dex<NumItems(GetInfo);  dex++) {
  728.         if(GetInfo[dex].fInfoType == SQL_DRIVER_HSTMT)                // Input arg also
  729.             *(HSTMT FAR *)GetInfo[dex].rgbInfoValue = ci->hstmt;
  730.             
  731.         retcode = SQLGetInfo(ci->hdbc, 
  732.                     GetInfo[dex].fInfoType, 
  733.                     GetInfo[dex].rgbInfoValue, 
  734.                     GetInfo[dex].cbInfoMax, 
  735.                     NULL);
  736.         if(retcode != SQL_SUCCESS)
  737.             PrintErrors(ci);
  738.  
  739.         iLoadString(idsGetInfoBase+GetInfo[dex].fInfoType, 
  740.                     (LPSTR)szConstant, sizeof(szConstant));
  741.  
  742.         switch(GetInfo[dex].fInfoType) {
  743.             case SQL_DRIVER_HENV:
  744.             case SQL_DRIVER_HDBC:
  745.             case SQL_DRIVER_HSTMT:
  746.                 rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  747.                 SetColumnData(0, rd, szConstant);
  748.                 wsprintf(szVal, "%04X:%04X", HIWORD(cb32), LOWORD(cb32));
  749.                 SetColumnData(1, rd, (LPSTR)szVal);
  750.                 if(AddRowData(rs, rd) == LB_ERRSPACE)
  751.                     goto exit00;
  752.                 break;
  753.                 
  754.             //
  755.             //    The default action is taken when we only need to display the
  756.             //        value as is.  We can use the structure to figure out what
  757.             //        format it is in.
  758.             //
  759.             default:
  760.                 rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  761.                 SetColumnData(0, rd, szConstant);
  762.                 switch(GetInfo[dex].fOutType) {
  763.                     case INT16:
  764.                         wsprintf(szVal, "%d", cb16);
  765.                         SetColumnData(1, rd, (LPSTR)szVal);
  766.                         if(AddRowData(rs, rd) == LB_ERRSPACE)
  767.                             goto exit00;
  768.                         break;
  769.                         
  770.                     case INT32:
  771.                         wsprintf(szVal, "%ld", cb32);
  772.                         SetColumnData(1, rd, (LPSTR)szVal);
  773.                         if(AddRowData(rs, rd) == LB_ERRSPACE)
  774.                             goto exit00;
  775.                         break;
  776.  
  777.                     case DEXVAL:
  778.                         lpDEX = (lpDEXSTRUCT)GetInfo[dex].ptr;
  779.                         if(!GetIndexVal(rs, (LPSTR)szConstant, 
  780.                                     lpDEX[cb16].idsStr,
  781.                                     (LPSTR)szVal, sizeof(szVal)))
  782.                             goto exit00;
  783.                         break;
  784.                         
  785.                     case BITVAL:
  786.                         lpINFS = (lpINFOSTRUCT)GetInfo[dex].ptr;
  787.                         if(!GetBitVal(rs, (LPSTR)szConstant,
  788.                                     lpINFS,
  789.                                     GetInfo[dex].cbNum, cb32,
  790.                                     (LPSTR)szVal, sizeof(szVal)))
  791.                             goto exit00;
  792.                         break;
  793.                         
  794.                     default: 
  795.                         SetColumnData(1, rd, (LPSTR)GetInfo[dex].rgbInfoValue);
  796.                         if(AddRowData(rs, rd) == LB_ERRSPACE)
  797.                             goto exit00;
  798.                         break;
  799.                     }
  800.             }
  801.             
  802.         }
  803.         
  804.     return TRUE;
  805.     
  806. exit00:
  807.     return FALSE;
  808. }
  809.  
  810.     
  811. //*---------------------------------------------------------------------------------
  812. //| DisplayODBCFunctions:
  813. //|    This function will enumerate all of the ODBC functions in a results set
  814. //|        and indicate which ones are supported.  The results set is attatched
  815. //|        as a valid results window on the current child.
  816. //| Parms:
  817. //|    in            ci                            CHILDINFO information
  818. //| Returns:              
  819. //|    TRUE if successful,
  820. //|    FALSE on error
  821. //*---------------------------------------------------------------------------------
  822. BOOL DisplayODBCFunctions(CHILDINFO FAR * ci)
  823. {
  824.     UWORD                        fSupport;
  825.     char                        szFuncName[35];
  826.     char                        szTitle[MAXBUFF];
  827.     int                         dex;
  828.     RESULTSSET FAR *         rs;
  829.     ROWDATA FAR *            rd;
  830.     RETCODE                    retcode;
  831.     COLORREF                    rgbDft=GetDefaultRGB();
  832.     //
  833.     //    Create a hard coded results set with 3 columns
  834.     //
  835.     lstrcpy((LPSTR)szTitle, (LPSTR)ci->szClientTitle);
  836.     lstrcat((LPSTR)szTitle, (LPSTR)szDash);
  837.     lstrcat((LPSTR)szTitle, (LPSTR)szODBCFunctions);
  838.     rs = GetConnectWindowResultsNode(ci);
  839.     if(!CreateResultsSet(rs, ci->hwndClient, ci->hInst, 3, (LPSTR)szTitle))
  840.         return FALSE;    
  841.  
  842.     //
  843.     // Set the meta data
  844.     //
  845.     SetMetaDataColumn(rs, 0, (LPSTR)"Function", 
  846.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 20, 0,
  847.             25, TA_LEFT);
  848.     SetMetaDataColumn(rs, 1, (LPSTR)"Conformance", 
  849.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 10, 0,
  850.             10, TA_LEFT);
  851.     SetMetaDataColumn(rs, 2, (LPSTR)"Supported", 
  852.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 10, 0,
  853.             10, TA_LEFT);
  854.  
  855.     //
  856.     // Now create the MDI child window which will hold the results.
  857.     //
  858.     if(!CreateResultsWindow(ci, rs)) 
  859.         goto exit00;
  860.  
  861.    
  862.     //
  863.     // Loop through the control structure and check each function.  For each row
  864.     //        add a record with the function name, conformance level, and Yes if
  865.     //        supported, No if not.
  866.     //
  867.     for(dex=0;  dex<NumItems(ODBCFunctions);  dex++) {
  868.         retcode = SQLGetFunctions(ci->hdbc, 
  869.                     ODBCFunctions[dex].fFunction, &fSupport);
  870.         if(retcode != SQL_SUCCESS)
  871.             PrintErrors(ci);
  872.         iLoadString(ODBCFunctions[dex].idFunction, (LPSTR)szFuncName, sizeof(szFuncName));
  873.         rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  874.         SetColumnData(0, rd, szFuncName);
  875.         SetColumnData(1, rd, ODBCFunctions[dex].szLevel);
  876.         SetColumnData(2, rd, (fSupport) ? (LPSTR)szYes : (LPSTR)szNo);
  877.         AddRowData(rs, rd);
  878.         }
  879.         
  880.     return TRUE;
  881.     
  882. exit00:
  883.     SQLFreeStmt(ci->hstmt, SQL_CLOSE);
  884.     return FALSE;
  885. }
  886.  
  887.  
  888. //*---------------------------------------------------------------------------------
  889. //| DisplayODBCDataSources:
  890. //|    This function will enumerate all of the ODBC Data sources.
  891. //| Parms:
  892. //|    in            ci                            CHILDINFO information
  893. //| Returns:              
  894. //|    TRUE if successful,
  895. //|    FALSE on error
  896. //*---------------------------------------------------------------------------------
  897. BOOL DisplayODBCDataSources(CHILDINFO FAR * ci)
  898. {  
  899.     HENV                        henv;
  900.     RESULTSSET FAR *         rs;
  901.     ROWDATA FAR *            rd;
  902.     RETCODE                    retcode;
  903.     char                        szDSN[SQL_MAX_DSN_LENGTH + 1];
  904.     char                        szDesc[MAXBUFF];
  905.     char                        szTitle[MAXBUFF];
  906.     COLORREF                    rgbDft=GetDefaultRGB();
  907.  
  908.     //
  909.     //    Create a hard coded results set with 2 columns
  910.     //
  911.     lstrcpy((LPSTR)szTitle, (LPSTR)ci->szClientTitle);
  912.     lstrcat((LPSTR)szTitle, (LPSTR)szDash);
  913.     lstrcat((LPSTR)szTitle, (LPSTR)szODBCDataSources);
  914.     rs = GetConnectWindowResultsNode(ci);
  915.     if(!CreateResultsSet(rs, ci->hwndClient, ci->hInst, 2, (LPSTR)szTitle))
  916.         return FALSE;    
  917.  
  918.     //
  919.     // Set the meta data
  920.     //
  921.     SetMetaDataColumn(rs, 0, (LPSTR)"Driver", 
  922.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 15, 0,
  923.             15, TA_LEFT);
  924.     SetMetaDataColumn(rs, 1, (LPSTR)"Description", 
  925.             GetTypeName(SQL_TYPE, SQL_CHAR), SQL_CHAR, 35, 0,
  926.             35, TA_LEFT);
  927.  
  928.     //
  929.     // Now create the MDI child window which will hold the results.
  930.     //
  931.     if(!CreateResultsWindow(ci, rs)) 
  932.         goto exit00;
  933.  
  934.    
  935.     //
  936.     // Loop through each data source and add it to the results set.
  937.     //
  938.     SQLAllocEnv(&henv);
  939.     retcode = SQLDataSources(henv, SQL_FETCH_FIRST, szDSN, sizeof(szDSN),
  940.                     NULL, szDesc, sizeof(szDesc), NULL);
  941.     while(retcode != SQL_NO_DATA_FOUND) {
  942.         if(retcode != SQL_SUCCESS)
  943.             PrintErrors(ci);
  944.         rd = AllocateRowData(rs, rgbDft, RDATA_DEFAULT_BKGRND);
  945.         SetColumnData(0, rd, szDSN);
  946.         SetColumnData(1, rd, szDesc);
  947.         AddRowData(rs, rd);
  948.         retcode = SQLDataSources(henv, SQL_FETCH_NEXT, szDSN, sizeof(szDSN),
  949.                     NULL, szDesc, sizeof(szDesc), NULL);
  950.         }
  951.     SQLFreeEnv(henv);    
  952.     return TRUE;
  953.     
  954. exit00:
  955.     return FALSE;
  956. }
  957.  
  958.  
  959.  
  960. //*---------------------------------------------------------------------------------
  961. //| DisplayODBCDataTypes:
  962. //|    This function will enumerate data type information.
  963. //| Parms:
  964. //|    in            ci                            CHILDINFO information
  965. //| Returns:              
  966. //|    TRUE if successful,
  967. //|    FALSE on error
  968. //*---------------------------------------------------------------------------------
  969. BOOL DisplayODBCDataTypes(CHILDINFO FAR * ci)
  970. {  
  971.     RESULTSSET FAR *         rs;
  972.     RETCODE                    retcode;
  973.     SWORD                        cbCols;
  974.     char                        szTitle[MAXBUFF];
  975.  
  976.     //
  977.     //    We'll use SQLGetTypeInfo for this query.  Since this function can return more
  978.     //        than the standard types, we must first execute the query and then create
  979.     //        the results set.
  980.     //
  981.     lstrcpy((LPSTR)szTitle, (LPSTR)ci->szClientTitle);
  982.     lstrcat((LPSTR)szTitle, (LPSTR)szDash);
  983.     lstrcat((LPSTR)szTitle, (LPSTR)szODBCDataTypes);
  984.     retcode = SQLGetTypeInfo(ci->hstmt, SQL_ALL_TYPES);
  985.     if(retcode != SQL_SUCCESS) {
  986.         PrintErrors(ci);
  987.         return FALSE;
  988.         }
  989.  
  990.     if(!(cbCols = GetNumResultsCols(ci->hstmt)))
  991.         return FALSE;
  992.  
  993.     rs = GetConnectWindowResultsNode(ci);
  994.     if(!CreateResultsSet(rs, ci->hwndClient, ci->hInst, cbCols, (LPSTR)szTitle))
  995.         return FALSE;    
  996.  
  997.     //
  998.     // Set the meta data
  999.     //
  1000.     SetMetaDataFromSql(ci->hwndOut, ci->hstmt, rs, cbCols);
  1001.  
  1002.     //
  1003.     // Now create the MDI child window which will hold the results.
  1004.     //
  1005.     if(!CreateResultsWindow(ci, rs)) 
  1006.         goto exit00;
  1007.  
  1008.    
  1009.     //
  1010.     // Loop through each data source and add it to the results set.
  1011.     //
  1012.     FetchAllRecordsToResults(ci->hwndOut, ci->hstmt, rs, cbCols, TRUE);
  1013.     SQLFreeStmt(ci->hstmt, SQL_CLOSE);
  1014.  
  1015.     return TRUE;
  1016.     
  1017. exit00:
  1018.     return FALSE;
  1019. }
  1020.  
  1021.  
  1022.  
  1023. //*---------------------------------------------------------------------------------
  1024. //| EditPipe:
  1025. //|    This function allows the user to create a new pipe.
  1026. //| Parms:
  1027. //|    in            ci                            CHILDINFO information
  1028. //| Returns:              
  1029. //|    TRUE if successful,
  1030. //|    FALSE on error
  1031. //*---------------------------------------------------------------------------------
  1032. void EditPipe(CHILDINFO FAR * ci)
  1033. {
  1034.     DLGPROC  dlgproc;
  1035.     HWND        fHwnd=GetFocus();
  1036.  
  1037.     dlgproc = MakeProcInstance(EditPipeWndProc, ci->hInst);
  1038.     if(-1 == DialogBoxParam(ci->hInst, 
  1039.             MAKEINTRESOURCE(IDD_EDIT_PIPE),
  1040.             ci->hwnd, 
  1041.             dlgproc, (LPARAM)ci))
  1042.         MessageBox(NULL, "Could not open dialog box.",
  1043.             "Pipe", MB_ICONEXCLAMATION);
  1044.     FreeProcInstance((FARPROC) dlgproc);
  1045.     
  1046.     if(fHwnd)
  1047.         SetFocus(fHwnd);
  1048. }
  1049.  
  1050.  
  1051.  
  1052. //*------------------------------------------------------------------------
  1053. //| IsValidParms:
  1054. //|    Verify that the parameters specified are the correct comma
  1055. //|    separated format.
  1056. //| Parms:
  1057. //|    hwnd                    Window handle for errors
  1058. //|    szParms                The null terminated list of parms
  1059. //| Returns:              
  1060. //|    TRUE if they are valid, FALSE on error
  1061. //*------------------------------------------------------------------------
  1062. BOOL WINAPI IsValidParms(HWND hwnd, LPSTR szParms)
  1063. {
  1064.     LPSTR            str=szParms, nstr;
  1065.     char            sztmp[MAXSQL];
  1066.     int            iNum, iCnt=0;
  1067.  
  1068.     lstrcpy(sztmp, szParms);
  1069.     nstr = str = strtok(sztmp, szCOMMA);
  1070.     while(str) {
  1071.         ++iCnt;
  1072.         if(!(strlen(str) == 1 && *str == '0')) {
  1073.             iNum = atoi(str);
  1074.             while(*str) {
  1075.                 if(*str < '0' ||
  1076.                     *str > '9')
  1077.                     goto invalidint;
  1078.                 ++str;
  1079.                 }
  1080.             
  1081.             // It was not 0, so if atoi returned 0 it was invalid
  1082.             if(!iNum)
  1083.                 goto invalidint;
  1084.             }
  1085.         
  1086.         nstr = str = strtok(NULL, szCOMMA);
  1087.         }
  1088.         
  1089.     if(iCnt <= MAXPARMS)
  1090.         return TRUE;
  1091.     else {
  1092.         szMessageBox(hwnd,
  1093.                 MB_ICONEXCLAMATION | MB_OK,
  1094.                 (LPSTR)szErrorMsgTitle,
  1095.                 iLoadString(idsTooManyParms, OutStr, MAXBUFF),
  1096.                 iCnt,
  1097.                 MAXPARMS);
  1098.         return FALSE;
  1099.         }
  1100.  
  1101. invalidint:
  1102.     szMessageBox(hwnd, 
  1103.             MB_ICONEXCLAMATION | MB_OK,
  1104.             (LPSTR)szErrorMsgTitle,
  1105.             iLoadString(idsInvalidInt, OutStr, MAXBUFF),
  1106.             nstr);
  1107.             
  1108.     return FALSE;
  1109. }
  1110.  
  1111.  
  1112. //*------------------------------------------------------------------------
  1113. //| EditPipeWndProc:
  1114. //|    Message handler for creating a new pipe.
  1115. //| Parms:
  1116. //|    in            Standard window parms
  1117. //| Returns:              
  1118. //|    Depends on message
  1119. //*------------------------------------------------------------------------
  1120. BOOL EXTFUN EditPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
  1121. {
  1122.     static CHILDINFO FAR *         ci;
  1123.     static                            cbNames;
  1124.     static char                        szName[MAXNAME];
  1125.  
  1126.     switch(msg) {
  1127.         case WM_INITDIALOG:
  1128.             {
  1129.             ci = (CHILDINFO FAR *)lParam;
  1130.             CenterDialog(hDlg);
  1131.  
  1132.             SendMessage(GetDlgItem(hDlg, IDC_NAME), CB_LIMITTEXT, MAXPARMS, 0L);
  1133.             SendMessage(GetDlgItem(hDlg, IDE_SQL), EM_LIMITTEXT, MAXSQL, 0L);
  1134.             SendMessage(GetDlgItem(hDlg, IDE_PARMS), EM_LIMITTEXT, (MAXNAME*2), 0L);
  1135.             CheckRadioButton(hDlg, IDR_VALUE, IDR_ADDRESS, IDR_VALUE);
  1136.             SendMessage(hDlg, USER_RESETLIST, 0, 0L);
  1137.             SendMessage(hDlg, USER_SETSTATES, 0, 0L);
  1138.             }
  1139.             return TRUE;        
  1140.  
  1141.  
  1142.         // This user message is sent when the list needs to be refreshed
  1143.         case USER_RESETLIST:
  1144.             {
  1145.             LPSTR            str, addstr;
  1146.  
  1147.             addstr = str = (LPSTR)GetMemory(1000);
  1148.             if(!addstr)
  1149.                 return TRUE;
  1150.             cbNames = 0;
  1151.             if(str) {
  1152.                 SendMessage(GetDlgItem(hDlg, IDC_NAME), CB_RESETCONTENT, 0, 0L);
  1153.                 if(GetPrivateProfileString((LPSTR)szPIPES, NULL, NULL,
  1154.                             str, 1000, szLABINI)) 
  1155.                     while(*addstr) {
  1156.                         ++cbNames;
  1157.                         SendMessage(GetDlgItem(hDlg, IDC_NAME),
  1158.                                             CB_ADDSTRING, 0,
  1159.                                             (LPARAM)(LPSTR)addstr);
  1160.                         addstr = addstr + lstrlen(addstr) + 1;
  1161.                         }
  1162.                 }
  1163.             ReleaseMemory(addstr);
  1164.             if(cbNames) 
  1165.                 SendMessage(GetDlgItem(hDlg, IDC_NAME), CB_SETCURSEL, 0, 0L);
  1166.             SendMessage(hDlg, USER_SETDEFAULTS, 0, 0L);
  1167.             SendMessage(hDlg, USER_SETSTATES, 0, 0L);
  1168.             }
  1169.             return TRUE;
  1170.             
  1171.         // This user defined message will set the state of controls
  1172.         case USER_SETSTATES:
  1173.             EnableWindow(GetDlgItem(hDlg, IDB_DELETE), cbNames);
  1174.             EnableWindow(GetDlgItem(hDlg, IDE_SQL), cbNames);
  1175.             EnableWindow(GetDlgItem(hDlg, IDR_VALUE), cbNames);
  1176.             EnableWindow(GetDlgItem(hDlg, IDR_ADDRESS), cbNames);
  1177.             EnableWindow(GetDlgItem(hDlg, IDE_PARMS), cbNames);
  1178.             EnableWindow(GetDlgItem(hDlg, IDOK), cbNames);
  1179.             return TRUE;
  1180.  
  1181.         // This user defined message is for setting default values
  1182.         case USER_SETDEFAULTS: 
  1183.             {
  1184.             char     szParmType[10];
  1185.             char    szSql[MAXSQL];
  1186.             char    szParms[MAXBUFF];
  1187.             
  1188.             HWND    hName = GetDlgItem(hDlg, IDC_NAME);
  1189.             
  1190.             if(cbNames == 0) {                    // No current driver
  1191.                 SetDlgItemText(hDlg, IDE_SQL, "");
  1192.                 SetDlgItemText(hDlg, IDE_PARMS, "");
  1193.                 return TRUE;
  1194.                 }
  1195.             SendMessage(hName, CB_GETLBTEXT,
  1196.                     (WPARAM)SendMessage(hName, CB_GETCURSEL, 0, 0L),
  1197.                     (LPARAM)(LPSTR)szName);
  1198.             if(GetPrivateProfileString(szName, szSQL, NULL, szSql, sizeof(szSql), szLABINI))
  1199.                 SetDlgItemText(hDlg, IDE_SQL, szSql);
  1200.             else
  1201.                 SetDlgItemText(hDlg, IDE_SQL, "");
  1202.             if(GetPrivateProfileString(szName, szPARMS, NULL, szParms, sizeof(szParms), szLABINI))
  1203.                 SetDlgItemText(hDlg, IDE_PARMS, szParms);
  1204.             else
  1205.                 SetDlgItemText(hDlg, IDE_PARMS, "");
  1206.             if(GetPrivateProfileString(szName, szPARMOPT, NULL, szParmType, sizeof(szParmType), szLABINI))
  1207.                 if(lstrcmpi(szVALUE, szParmType) == 0)
  1208.                     CheckRadioButton(hDlg, IDR_VALUE, IDR_ADDRESS, IDR_VALUE);
  1209.                 else
  1210.                     CheckRadioButton(hDlg, IDR_VALUE, IDR_ADDRESS, IDR_ADDRESS);
  1211.             CheckDlgButton(hDlg, IDX_DELETE, GetPrivateProfileInt(szName, szDELETEOPT, 0, szLABINI));
  1212.             }
  1213.             return TRUE;
  1214.             
  1215.         case WM_COMMAND:
  1216.             switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1217.                 case IDB_NEW:
  1218.                     {
  1219.                     NEWPIPE    np;
  1220.                     
  1221.                     np.hwnd = hDlg;
  1222.                     np.hInst = ci->hInst;
  1223.                     NewPipe(&np);
  1224.                     if(np.fSuccess) {
  1225.                         lstrcpy(szName, np.szName);
  1226.                         SendMessage(GetDlgItem(hDlg, IDC_NAME), CB_SETCURSEL,
  1227.                                 (WPARAM)SendMessage(GetDlgItem(hDlg, IDC_NAME), CB_ADDSTRING, 
  1228.                                     0,    (LPARAM)(LPSTR)szName), 0L);
  1229.                         if(cbNames)
  1230.                             SendMessage(hDlg, USER_SETDEFAULTS, 0, 0L);
  1231.                         else
  1232.                             SendMessage(hDlg, USER_RESETLIST, 0, 0L);
  1233.                         }
  1234.                     }                    
  1235.                     return TRUE;
  1236.                     
  1237.                 case IDB_DELETE:
  1238.                     GetText(GetDlgItem(hDlg, IDC_NAME), szName);
  1239.                     wsprintf(OutStr, szDeletePipe, (LPSTR)szName);
  1240.                     if(IDOK == MessageBox(hDlg, OutStr, szEditPipe, MB_OKCANCEL)) {
  1241.                         WritePrivateProfileString(szName, NULL, NULL, szLABINI);
  1242.                         WritePrivateProfileString(szPIPES, szName, NULL, szLABINI);
  1243.                         SendMessage(hDlg, USER_RESETLIST, 0, 0L);
  1244.                         }
  1245.                     return TRUE;
  1246.                     
  1247.                 //
  1248.                 //    Read in the info from the dialog, validate the parms, write to file
  1249.                 //
  1250.                 case IDOK:
  1251.                     {
  1252.                     char    szSql[MAXSQL];
  1253.                     char    szParms[MAXBUFF];
  1254.  
  1255.                     GetDlgItemText(hDlg, IDC_NAME, (LPSTR)szName, sizeof(szName));
  1256.  
  1257.                     GetDlgItemText(hDlg, IDE_PARMS, szParms, sizeof(szParms));
  1258.                     if(IsValidParms(hDlg, szParms)) {
  1259.                         WritePrivateProfileString(szName, szPARMS, szParms, szLABINI);
  1260.                         
  1261.                         GetDlgItemText(hDlg, IDE_SQL, szSql, sizeof(szSql));
  1262.                         WritePrivateProfileString(szName, szSQL, szSql, szLABINI);
  1263.  
  1264.                         if(IsDlgButtonChecked(hDlg, IDR_VALUE))                   
  1265.                             WritePrivateProfileString(szName, szPARMOPT, szVALUE, szLABINI);
  1266.                         else
  1267.                             WritePrivateProfileString(szName, szPARMOPT, szADDRESS, szLABINI);
  1268.  
  1269.                         WritePrivateProfileString(szName, szDELETEOPT, 
  1270.                             (IsDlgButtonChecked(hDlg, IDX_DELETE)) ? (LPSTR)"1" : (LPSTR)"0",
  1271.                             szLABINI);
  1272.                         }
  1273.                     }
  1274.                     return TRUE;
  1275.             
  1276.             case IDCANCEL:
  1277.                     EndDialog(hDlg, IDCANCEL);;
  1278.                     return TRUE;
  1279.                 }
  1280.             // Now check for control notification messages
  1281.             switch(HIWORD(lParam)) {
  1282.                 case CBN_SELENDOK:
  1283.                 case CBN_KILLFOCUS:
  1284.                     SendMessage(hDlg, USER_SETDEFAULTS, TRUE, 0L);
  1285.                     return TRUE;
  1286.                 
  1287.                 default:
  1288.                     break;
  1289.                 }
  1290.             break;
  1291.  
  1292.  
  1293.         default:
  1294.             return FALSE;
  1295.         }
  1296.     return FALSE;
  1297. }
  1298.  
  1299.  
  1300. //*---------------------------------------------------------------------------------
  1301. //| NewPipe:
  1302. //|    This function allows the user to create a new pipe.
  1303. //| Parms:
  1304. //|    in            ci                            CHILDINFO information
  1305. //| Returns:              
  1306. //|    Nothing
  1307. //*---------------------------------------------------------------------------------
  1308. void NewPipe(NEWPIPE FAR * np)
  1309. {
  1310.     DLGPROC  dlgproc;
  1311.     HWND        fHwnd=GetFocus();
  1312.  
  1313.     dlgproc = MakeProcInstance(NewPipeWndProc, np->hInst);
  1314.     if(-1 == DialogBoxParam(np->hInst, 
  1315.             MAKEINTRESOURCE(IDD_NEW_PIPE),
  1316.             np->hwnd, 
  1317.             dlgproc, (LPARAM)np))
  1318.         MessageBox(NULL, "Could not open dialog box.",
  1319.             "Pipe", MB_ICONEXCLAMATION);
  1320.     FreeProcInstance((FARPROC) dlgproc);
  1321.     
  1322.     if(fHwnd)
  1323.         SetFocus(fHwnd);
  1324. }
  1325.  
  1326.  
  1327. //*------------------------------------------------------------------------
  1328. //| NewPipeWndProc:
  1329. //|    Message handler for creating a new pipe.
  1330. //| Parms:
  1331. //|    in            Standard window parms
  1332. //| Returns:              
  1333. //|    Depends on message
  1334. //*------------------------------------------------------------------------
  1335. BOOL EXTFUN NewPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
  1336. {
  1337.     char                                szName[MAXNAME];
  1338.     static NEWPIPE FAR *            np;
  1339.  
  1340.     switch(msg) {
  1341.         case WM_INITDIALOG:
  1342.             {
  1343.             np = (NEWPIPE FAR *)lParam;
  1344.             CenterDialog(hDlg);
  1345.             SendMessage(GetDlgItem(hDlg, IDE_NAME), EM_LIMITTEXT, MAXNAME, 0L);
  1346.             }
  1347.             return TRUE;        
  1348.  
  1349.  
  1350.         case WM_COMMAND:
  1351.             switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1352.                 case IDOK:
  1353.                     {
  1354.                     char szTmp[MAXNAME];
  1355.  
  1356.                     //
  1357.                     // Don't allow names with [,], or = in them, nor any
  1358.                     // reserved section names
  1359.                     //
  1360.                     GetText(GetDlgItem(hDlg, IDE_NAME), (LPSTR)szName);
  1361.                     if(!ValidName((LPSTR)szName) ||
  1362.                         !*szName ||
  1363.                         !lstrcmpi((LPSTR)szName, szSCREEN) ||
  1364.                         !lstrcmpi((LPSTR)szName, szFONT) ||
  1365.                         !lstrcmpi((LPSTR)szName, szCONNECTOPTIONS) ||
  1366.                         !lstrcmpi((LPSTR)szName, szPIPES)) {
  1367.  
  1368.                         szMessageBox(hDlg,
  1369.                                 MB_ICONEXCLAMATION | MB_OK,
  1370.                                 (LPSTR)szErrorMsgTitle,
  1371.                                 iLoadString(idsInvalidName, OutStr, MAXBUFF),
  1372.                                 (LPSTR)szName);
  1373.                         return TRUE;
  1374.                         }
  1375.                     if(GetPrivateProfileString(szPIPES, szName, NULL,
  1376.                             szTmp, sizeof(szTmp), szLABINI)) 
  1377.                         MessageBox(hDlg, szDuplicatePipe, szEditPipe, MB_OK);
  1378.                     else {
  1379.                         lstrcpy(np->szName, szName);
  1380.                         np->fSuccess = TRUE;
  1381.                         WritePrivateProfileString(szPIPES, szName, szInstalled, szLABINI);
  1382.                         EndDialog(hDlg, IDOK);
  1383.                         }
  1384.                     }
  1385.                     return TRUE;
  1386.             
  1387.             case IDCANCEL:
  1388.                     np->fSuccess = FALSE;
  1389.                     EndDialog(hDlg, IDCANCEL);
  1390.                     return TRUE;
  1391.                 }
  1392.             break;
  1393.  
  1394.         default:
  1395.             return FALSE;
  1396.         }
  1397.     return FALSE;
  1398. }
  1399.  
  1400.  
  1401.  
  1402. //*---------------------------------------------------------------------------------
  1403. //| HandlePipe:
  1404. //|    This function will use the active results set and run use pipes against it.
  1405. //| Parms:
  1406. //|    lpci                    Connection window information
  1407. //|    lpri                    Ative results set
  1408. //| Returns:              
  1409. //|    Nothing.
  1410. //*---------------------------------------------------------------------------------
  1411. void INTFUN HandlePipe(lpCHILDINFO lpci, lpRESULTSINFO lpri)
  1412. {
  1413.     DLGPROC                  dlgproc;
  1414.     HWND                        fHwnd=GetFocus();
  1415.  
  1416.     dlgproc = MakeProcInstance(DoPipeWndProc, lpci->hInst);
  1417.     if(-1 == DialogBoxParam(lpci->hInst, 
  1418.             MAKEINTRESOURCE(IDD_DO_PIPE),
  1419.             lpci->hwnd, 
  1420.             dlgproc, (LPARAM)(lpRESULTSINFO)lpri))
  1421.         MessageBox(NULL, "Could not open dialog box.",
  1422.             "HandlePipe", MB_ICONEXCLAMATION);
  1423.     FreeProcInstance((FARPROC) dlgproc);
  1424.     
  1425.     if(fHwnd)
  1426.         SetFocus(fHwnd);
  1427. }
  1428.  
  1429.  
  1430. //*------------------------------------------------------------------------
  1431. //| DoPipeWndProc:
  1432. //|    Handle dialog messages for IDD_DO_PIPE.
  1433. //| Parms:
  1434. //|    in            Standard window parms
  1435. //| Returns:              
  1436. //|    Depends on message
  1437. //*------------------------------------------------------------------------
  1438. BOOL EXTFUN DoPipeWndProc(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
  1439. {
  1440.     static CHILDINFO FAR *         ci;
  1441.     static RESULTSSET FAR *        rs;
  1442.     static SDWORD                    cbPipes;
  1443.  
  1444.     switch(msg) {
  1445.         case WM_INITDIALOG:
  1446.             {
  1447.             lpRESULTSINFO rwi;
  1448.             rwi = (lpRESULTSINFO)lParam;
  1449.             ci = rwi->ci;
  1450.             rs = rwi->rs;
  1451.             CenterDialog(hDlg);
  1452.             cbPipes = RefreshPipeList(GetDlgItem(hDlg, IDL_PIPES));
  1453.             EnableWindow(GetDlgItem(hDlg, IDL_PIPES), (int)(cbPipes));
  1454.             EnableWindow(GetDlgItem(hDlg, IDOK), (int)(cbPipes));
  1455.             }
  1456.             return TRUE;        
  1457.  
  1458.  
  1459.         case WM_COMMAND:
  1460.             switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1461.                 // User has clicked OK.  Retrieve an array of the selected indexes
  1462.                 // and run the current pipe against each.  Finally see if this
  1463.                 // pipe wants to delete items.
  1464.                 case IDOK:
  1465.                     {
  1466.                     int             cbCnt;
  1467.                     int FAR *    xSel;
  1468.                     int            dex;
  1469.                     char            szPipeName[MAXBUFF];
  1470.  
  1471.                     Busy(TRUE);
  1472.                     cbCnt = (int)SendMessage(rs->hwndList, LB_GETSELCOUNT, 0, 0L);
  1473.                     xSel = (int FAR *)GetMemory(sizeof(int) * cbCnt);
  1474.                     if(!xSel) {
  1475.                         Busy(FALSE);
  1476.                         return TRUE;
  1477.                         }
  1478.                     SendMessage(rs->hwndList, LB_GETSELITEMS, cbCnt, (LPARAM)(int FAR *)xSel);
  1479.                     SendMessage(GetDlgItem(hDlg, IDL_PIPES), LB_GETTEXT,
  1480.                                 (WPARAM)SendMessage(GetDlgItem(hDlg, IDL_PIPES), LB_GETCURSEL, 0, 0L),
  1481.                                 (LPARAM)(LPSTR)szPipeName);
  1482.                     DoPipe(rs, ci, (LPSTR)szPipeName, xSel, cbCnt);
  1483.                     if(GetPrivateProfileInt(szPipeName, szDELETEOPT, 0, szLABINI))
  1484.                         for(dex=cbCnt-1;  dex>=0;  dex--)
  1485.                             SendMessage(rs->hwndList, LB_DELETESTRING, xSel[dex], 0L);
  1486.                     Busy(FALSE);
  1487.                     ReleaseMemory(xSel);
  1488.                     }
  1489.                     return TRUE;
  1490.             
  1491.             case IDCANCEL:
  1492.                 EndDialog(hDlg, IDCANCEL);
  1493.                     return TRUE;
  1494.                 }
  1495.             return TRUE;
  1496.  
  1497.         default:
  1498.             return FALSE;
  1499.         }
  1500.     return FALSE;
  1501. }
  1502.  
  1503.  
  1504.  
  1505.  
  1506. //*---------------------------------------------------------------------------------
  1507. //| RefreshPipeList:
  1508. //|    This function will reset the list of pipes based on the values returned
  1509. //|        from GetPipeName.  Having this extra level of abstraction allows us
  1510. //|        to change the location of the pipes without affecting this code.
  1511. //| Parms:
  1512. //|    in            hwnd                        Window handle to list box to fill
  1513. //| Returns:              
  1514. //|    Number of items selected
  1515. //*---------------------------------------------------------------------------------
  1516. SDWORD RefreshPipeList(HWND hDlg)
  1517. {
  1518. #define MAX_PIPE_SIZE 4000
  1519.     LPSTR        szPipes, str;
  1520.     SDWORD count=0;
  1521.     
  1522.     szPipes = (LPSTR)GetMemory(MAX_PIPE_SIZE);
  1523.     if(!szPipes) 
  1524.         return 0;
  1525.     
  1526.     SendMessage(hDlg, LB_RESETCONTENT, 0, 0L);
  1527.     GetPipeNames((LPSTR)szPipes, MAX_PIPE_SIZE);
  1528.     str = szPipes;
  1529.     while(*str) {
  1530.         SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)(LPSTR)str);
  1531.         str += lstrlen(str) + 1;
  1532.         ++count;
  1533.         }
  1534.     if(count)
  1535.         SendMessage(hDlg, LB_SETCURSEL, 0, 0L);
  1536.  
  1537.     ReleaseMemory(szPipes);
  1538.     return count;
  1539. }
  1540.  
  1541.  
  1542. //*---------------------------------------------------------------------------------
  1543. //| DoPipe:
  1544. //|    This function will implement a pipe against the object which is passed in.
  1545. //| Parms:
  1546. //|    in            rs                            Pointer to results set describing data
  1547. //|    in            ci                            Connection window information
  1548. //|    in            szPipeName                Name of pipe to use
  1549. //|    in            xPipes                    Array of items to pipe
  1550. //|    in            cbCnt                        Number of items
  1551. //| Returns:              
  1552. //|    Nothing.
  1553. //*---------------------------------------------------------------------------------
  1554. void DoPipe(RESULTSSET FAR * rs, CHILDINFO FAR * ci, LPSTR szPipeName,
  1555.             int FAR xPipes[], int cbCnt)
  1556. {
  1557.     SDWORD                cbDataAtExec=SQL_DATA_AT_EXEC;
  1558.     int                    dex;
  1559.     int                    cParm;
  1560.     char                    szpsql[200];
  1561.     char                    szparms[35];
  1562.     char                    parmopt[10];
  1563.     UWORD                    cParmCnt=0;
  1564.     LPSTR                    str=szparms;
  1565.     LPSTR                    numstr=szparms;
  1566.     ROWDATA FAR *         rd;
  1567.     RETCODE                retcode;
  1568.  
  1569.     //
  1570.     // Make sure we can retrieve the pipe from the .ini file.  Also get the parameter
  1571.     //        values if they are available.
  1572.     //
  1573.     if(!GetPrivateProfileString(szPipeName, szSQL, NULL, szpsql, sizeof(szpsql), szLABINI)) {
  1574.         szWrite(ci->hwndOut, 
  1575.                     GetidsString(idsPipeNotFound, OutStr, MAXBUFF), 
  1576.                     (LPSTR)szPipeName);
  1577.         return;
  1578.         }
  1579.     GetPrivateProfileString(szPipeName, szPARMS, NULL, szparms, sizeof(szparms), szLABINI);
  1580.     GetPrivateProfileString(szPipeName, szPARMOPT, NULL, parmopt, sizeof(parmopt), szLABINI);
  1581.  
  1582.     //
  1583.     // If there are parameters to set, set each one based on user desription
  1584.     //
  1585.     if(str && *str)
  1586.         PrepareParmList(str);
  1587.     SQLFreeStmt(ci->hstmt, SQL_CLOSE);
  1588.     
  1589.     //
  1590.     // What type of parameter passing to do?  value means substitue text and execute,
  1591.     //        address means use parameter data.  The following will handle the former, the
  1592.     //        next more complicated routine will pass parameters.
  1593.     //
  1594.     if(lstrcmpi(parmopt, szVALUE) == 0) {
  1595.         DoPipeByValue(rs, ci, szpsql, str, xPipes, cbCnt, (LPSTR)szPipeName);
  1596.         return;
  1597.         }
  1598.    
  1599.    //
  1600.    // Now prepare the user's statement, return on error
  1601.    //
  1602.     retcode = SQLPrepare(ci->hstmt, szpsql, SQL_NTS);
  1603.     if(retcode != SQL_SUCCESS) {
  1604.         PrintErrors(ci);
  1605.         return;
  1606.         }
  1607.     
  1608.     //
  1609.     // For each parameter, make sure it's in our range, then see which mode we want,
  1610.     //        address (param data) or value (textual substitution).
  1611.     //
  1612.     while(*str) {
  1613.         ++cParmCnt;
  1614.         cParm = lpatoi(str);
  1615.         if(cParm > rs->cbColumns) 
  1616.             szWrite(ci->hwndOut, 
  1617.                     GetidsString(idsInvalidParamValue, OutStr, MAXBUFF), 
  1618.                     cParm, (LPSTR)szPipeName);
  1619.         else {
  1620.             retcode = SQLBindParameter(ci->hstmt, 
  1621.                     cParmCnt, SQL_PARAM_INPUT,
  1622.                     SQL_C_CHAR, SQL_CHAR, 
  1623.                     rs->md[cParm-1].precision,
  1624.                     rs->md[cParm-1].scale, 
  1625.                     (PTR FAR *)(cParm - 1), 
  1626.                     rs->md[cParm-1].precision,
  1627.                     &cbDataAtExec);
  1628.             if(retcode != SQL_SUCCESS) 
  1629.                 PrintErrors(ci);
  1630.             }
  1631.         str += lstrlen(str) + 1;
  1632.         }    
  1633.  
  1634.  
  1635.     //
  1636.     // For each row selected, retrieve the row data structure associated with it,
  1637.     //        then do an execute.  When prompted for SQL_NEED_DATA, substitute the
  1638.     //        correct parameter address.
  1639.     //
  1640.     for(dex=0;  dex<cbCnt;  dex++) { 
  1641.         int        cNeedParm;
  1642.         rd = (ROWDATA FAR *)SendMessage(rs->hwndList, LB_GETITEMDATA, (WPARAM)xPipes[dex], 0L);
  1643.         retcode = SQLExecute(ci->hstmt);
  1644.         switch(retcode) {
  1645.             //
  1646.             // User had parameter data which we are being prompted for.  Since we
  1647.             //        did the SQLSetParam using the index number, we simply use that
  1648.             //        value to index into our column data and give the driver what
  1649.             //        it requires.
  1650.             //
  1651.             case SQL_NEED_DATA:
  1652.                 retcode = SQLParamData(ci->hstmt, (PTR FAR *)&cNeedParm);
  1653.                 while(retcode == SQL_NEED_DATA) {
  1654.                     retcode = SQLPutData(ci->hstmt, rd->cd[cNeedParm].szCols, SQL_NTS);
  1655.                     retcode = SQLParamData(ci->hstmt, (PTR FAR *)&cNeedParm);
  1656.                     }
  1657.                 break;
  1658.             
  1659.             case SQL_SUCCESS:
  1660.                 CheckForResults(ci);
  1661.                 break;
  1662.                 
  1663.             default:
  1664.                 PrintErrors(ci);
  1665.                 break;
  1666.             }
  1667.         }
  1668.         
  1669.     SQLFreeStmt(ci->hstmt, SQL_CLOSE);
  1670.     return;
  1671. }
  1672.  
  1673.  
  1674.  
  1675. //*---------------------------------------------------------------------------------
  1676. //| PrepareParmList:
  1677. //|    The user will enter a list of numbers separated by columns which will
  1678. //|    designate which parms go for what marker.  We will turn this list into
  1679. //|    a double-null terminated list which can be used later for retrieval.
  1680. //| Parms:
  1681. //|    in            str                        Pointer to string to work on
  1682. //| Returns:              
  1683. //|    Nothing.
  1684. //*---------------------------------------------------------------------------------
  1685. void PrepareParmList(LPSTR str)
  1686. {
  1687.     LPSTR tmpstr=str;
  1688.     LPSTR    lststr=tmpstr;
  1689.  
  1690.     //
  1691.     // Convert parm list into a double-null terminated list
  1692.     //
  1693.     while(tmpstr) {
  1694.         if((tmpstr = _fstrchr(str, ','))) {
  1695.             lststr = tmpstr + 1;
  1696.             *tmpstr++ = '\0';
  1697.             }
  1698.         else {
  1699.             lststr += lstrlen(lststr) + 1;
  1700.             *lststr = '\0';
  1701.             }
  1702.         }
  1703. }            
  1704.  
  1705.  
  1706.  
  1707. //*---------------------------------------------------------------------------------
  1708. //| DoPipeByValue:
  1709. //|    This function will process all of the selcted values by creating a
  1710. //|    statement which has all parameters embedded in it.
  1711. //|
  1712. //|    Note:      There are some servers which use a semi-colon for the name of
  1713. //|                a stored procedure, but which cannot handle doing a drop of the
  1714. //|                object with this name.  If the pipe name is the reserved name
  1715. //|                of "Drop Procedure (with semi-colon)" then we will strip off the
  1716. //|                name since this can't really be done any other way.
  1717. //| Parms:
  1718. //|    in            rs                            Results set pointer
  1719. //|    in            ci                            Child information
  1720. //|    in            szUserSQL                    Statement with parameter markers
  1721. //|    in            szParms                    Parameter list, double null terminated
  1722. //|    in            xPipes                    Array of indexes to use for param data
  1723. //|    in            cbCnt                        Number of records to process
  1724. //|    in            szPipeName                Pipe names
  1725. //| Returns:              
  1726. //|    Nothing.
  1727. //*---------------------------------------------------------------------------------
  1728. void DoPipeByValue(RESULTSSET FAR * rs, CHILDINFO FAR * ci, LPSTR szUserSQL,
  1729.         LPSTR szParms, int FAR xPipes[], int cbCnt, LPSTR szPipeName)
  1730. {
  1731.     char                    szUserSQLCopy[300];
  1732.     char                    sqlstmt[300];
  1733.     LPSTR                    szParmStrOut;
  1734.     LPSTR                    szParmStrIn;
  1735.     LPSTR                    szParmStrLast;
  1736.     LPSTR                    str=szParms;
  1737.     int                    dex;
  1738.     int                    cParm;
  1739.     ROWDATA FAR *        rd;
  1740.     BOOL                    fSemiProc=FALSE;
  1741.     
  1742.     // Handle special case of a procedure name with a semi-colon
  1743.     if(lstrcmp(szPipeName, szDROPPROCSEMI) == 0)
  1744.         fSemiProc = TRUE;
  1745.     
  1746.     //
  1747.     // For each record selected, create a statement which can be executed by finding
  1748.     //        parameter markers and replacing them at run time.
  1749.     //
  1750.     for(dex=0;  dex<cbCnt;  dex++) {
  1751.         _fmemset(sqlstmt, 0, sizeof(sqlstmt));
  1752.         _fmemset(szUserSQLCopy, 0, sizeof(szUserSQLCopy));
  1753.         lstrcpy(szUserSQLCopy, szUserSQL);
  1754.         szParmStrOut = sqlstmt;
  1755.         szParmStrIn = szUserSQLCopy;
  1756.         szParmStrLast = szParmStrIn;
  1757.         str = szParms;
  1758.         rd = (ROWDATA FAR *)SendMessage(rs->hwndList, LB_GETITEMDATA, (WPARAM)xPipes[dex], 0L);
  1759.         while(*str) {
  1760.             cParm = lpatoi(str);
  1761.             if(cParm > rs->cbColumns) 
  1762.                 szWrite(ci->hwndOut, 
  1763.                     GetidsString(idsInvalidParamValue, OutStr, MAXBUFF), 
  1764.                     cParm, (LPSTR)szPipeName);
  1765.             else if(szParmStrIn && *szParmStrIn) {
  1766.                 if((szParmStrIn = _fstrchr(szParmStrIn, '?'))) {
  1767.                     *szParmStrIn++ = '\0';
  1768.                     lstrcpy(szParmStrOut, szParmStrLast);
  1769.                     _fstrcat(szParmStrOut, rd->cd[cParm-1].szCols);
  1770.                     // Remove semi-colon for special case of drop procedure
  1771.                     if(fSemiProc) {
  1772.                         LPSTR        str = _fstrchr(szParmStrOut, ';');
  1773.                         if(str)
  1774.                             *str = '\0';
  1775.                         }
  1776.                     szParmStrLast = szParmStrIn; 
  1777.                     }
  1778.                 else
  1779.                     lstrcpy(szParmStrOut, szParmStrLast);                    // end of list
  1780.                 }
  1781.             str += lstrlen(str) + 1;
  1782.             }
  1783.         if(*szParmStrLast)
  1784.             _fstrcat(szParmStrOut, szParmStrLast);
  1785.         ExecuteCmds(ci, sqlstmt);
  1786.         }
  1787.         
  1788.     return;
  1789. }
  1790.