home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / odbc / admndemo / admndemo.c next >
Encoding:
C/C++ Source or Header  |  1997-10-08  |  49.7 KB  |  1,561 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:   ADMNDEMO.C
  8. //|      This module contains the main interface modules for SATOOL, including
  9. //|         the MDI client support
  10. //*---------------------------------------------------------------------------------
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <stdlib.h>
  14. #include "admndemo.h"
  15. #include "sql.h"
  16. #include "sqlext.h"
  17. #include "ini.h"
  18. #include "dialogs.h"
  19. #include "odbcinst.h"
  20. #include "errcheck.h"
  21. #include "strings.h"
  22. VSZFile;
  23.  
  24.  
  25.  
  26. //*---------------------------------------------------------------------------------
  27. //|   Defines
  28. //*---------------------------------------------------------------------------------
  29. #define HLP_ADMNDEMO 50
  30.  
  31. typedef struct tagCMDLINE {
  32.    BOOL        fOptions;                     // TRUE if there are options
  33.    BOOL        fExit;                        // TRUE if we should exit when done
  34.    char        szDriverConnect[100];         // String for SQLDriverConnect
  35.    char        szExecuteFile[255];           // File to execute
  36.    BOOL        fTrace;                       // TRUE to trace
  37.    char        szTraceFile[255];             // File to log ODBC calls
  38.    char        szTerm[10];                   // Stmt terminator for file
  39.    int         cbStmt;                       // Maximum statement length
  40.    } CMDLINE;
  41.  
  42.  
  43. //*---------------------------------------------------------------------------------
  44. //|   Global variables
  45. //*---------------------------------------------------------------------------------
  46. HWND              hwndFrame, hwndClient, hwndOutput;
  47. HINSTANCE         hInst;
  48. HENV              henv=NULL;
  49. HMENU             hMenu=NULL, hSubMenu=NULL;
  50. HICON             hIcon=NULL, hResultsIcon=NULL, hConnectIcon=NULL;
  51. HFONT             hSmallEditFont;
  52. RETCODE           retcode;
  53. int               iHelpCnt=0;                // Tracks the
  54. CHILDINFO FAR *   CreateCI=NULL;
  55. char              OutStr[MAXBUFF];
  56. char              szDirName[_MAX_PATH];
  57. char              szDftFileFilter[MAXBUFF];
  58. CMDLINE           cl;
  59.  
  60.  
  61. // Following is an array of connections and a global to track the current
  62. lpCHILDINFO       ConnectStructs[MAXCONNECTS];
  63. lpCHILDINFO       lpActiveConn=NULL;
  64. HWND              hwndCurMDIChild=NULL;
  65.  
  66. extern UWORD            uMenuIDs[NUM_MENU_FLAGS];
  67. extern lpRESULTSINFO    lpActiveResults;
  68.  
  69.  
  70. dCSEG(char) szFrameClass[]                   = "SAMDI:Frame";
  71. dCSEG(char) szChildClass[]                   = "SACLASS:1";
  72. dCSEG(char) szResultsClass[]                 = "SACLASS:2";
  73. dCSEG(char) szWindowTitle[]                  = "ODBC Admin Demo";
  74. dCSEG(char) szHELPFILE[]                     = "..\\doc\\ODBCSMPL.HLP";
  75.  
  76. dCSEG(char) szOPENFILE[]                     = "Open File";
  77. dCSEG(char) szSAVEFILE[]                     = "Save File";
  78. dCSEG(char) szUID[]                          =  "UID=";
  79. dCSEG(char) szDSN[]                          =  "DSN=";
  80. dCSEG(char) szNewLine[]                      =  "\r\n";
  81. dCSEG(char) szComma[]                        =  ", ";
  82.  
  83. dCSEG(char) szUserAt[]                       =  "%s@%s";
  84. dCSEG(char) szUserAtFile[]                   =  "%s@%s   File: %s";
  85.  
  86.  
  87.  
  88. //*---------------------------------------------------------------------------------
  89. //|   Local functions
  90. //*---------------------------------------------------------------------------------
  91. BOOL WINAPI Init(HANDLE hInstance,   HANDLE hPrevInstance,
  92.           LPSTR  lpszCmdLine, int    CmdShow);
  93. BOOL WINAPI SetUp(LPSTR szCmdLine, CMDLINE FAR * cl);
  94. void WINAPI CleanUp(void);
  95. long EXTFUN WndProc(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam);
  96. long EXTFUN PASCAL ChildWndProc(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam);
  97. BOOL EXTFUN PASCAL AboutWndProc(HWND hDlg, unsigned msg, WPARAM wParam, LPARAM lParam);
  98.  
  99. BOOL WINAPI ParseCommandLine(LPSTR szCmdLine, CMDLINE FAR * cl);
  100. BOOL WINAPI ParseOptionsValues(LPSTR instr, LPSTR szTerm, int cbTerm, int FAR * lpMax);
  101. VOID WINAPI DoConnect(HWND hwnd, DWORD dwData);
  102. BOOL WINAPI Connect(CHILDINFO FAR * ci, HWND hwnd, LPSTR szAutoConnect);
  103. VOID WINAPI DoDisconnect(lpCHILDINFO lpci);
  104. BOOL WINAPI Disconnect(CHILDINFO FAR * ci);
  105. void WINAPI DisplayAbout(HWND hwnd, HINSTANCE hInst);
  106. int  WINAPI DoMain(HANDLE hInstance);
  107. HWND INTFUN GetEditWindow(CHILDINFO FAR * ci);
  108.  
  109.  
  110. // File functions
  111. VOID WINAPI DoFileOpen(lpCHILDINFO lpci);
  112. VOID WINAPI DoFileSave(lpCHILDINFO lpci);
  113. VOID WINAPI DoFileSaveAs(lpCHILDINFO lpci);
  114.  
  115.  
  116.  
  117.  
  118. //*------------------------------------------------------------------------
  119. //| WinMain:
  120. //|     Parameters:
  121. //|         hInstance     - Handle to current Data Segment
  122. //|         hPrevInstance - Handle to previous Data Segment (NULL if none)
  123. //|         lpszCmdLine   - Long pointer to command line info
  124. //|         nCmdShow      - Integer value specifying how to start app.,
  125. //|                            (Iconic [7] or Normal [1,5])
  126. //*------------------------------------------------------------------------
  127. int PASCAL WinMain (HINSTANCE hInstance,
  128.                     HINSTANCE hPrevInstance,
  129.                     LPSTR  lpszCmdLine,
  130.                     int    nCmdShow)
  131. {
  132.    int         nReturn;
  133.  
  134.    if (Init(hInstance, hPrevInstance,lpszCmdLine,nCmdShow)) {
  135.       if(!SetUp(lpszCmdLine, &cl))        // Quit on errors
  136.          return 0;
  137.       nReturn = DoMain(hInstance);
  138.       CleanUp();
  139.    }
  140.    return nReturn;
  141. }
  142.  
  143.  
  144. //*---------------------------------------------------------------------------------
  145. //| Init:
  146. //|   This function will take care of initilization for the application.
  147. //| Parms:
  148. //|   in       hInstance            Data segment for this instance
  149. //|   in       hPrevInstance        Data segment for previous instance
  150. //|   in       lpszCmdLine          Command line parameters
  151. //|   in       nCmdShow             Desired display method
  152. //| Returns:
  153. //|   TRUE     if function was successful
  154. //|   FALSE    if there was an error
  155. //*---------------------------------------------------------------------------------
  156. BOOL WINAPI Init(HANDLE hInstance,   HANDLE hPrevInstance,
  157.           LPSTR  lpszCmdLine, int    nCmdShow)
  158. {
  159.    WNDCLASS wc;
  160.  
  161.  
  162.    // Make sure the .ini file is there before creating anything
  163.    ResolveIniFile();
  164.  
  165.    hInst = hInstance;
  166.  
  167.    if(!hPrevInstance) {
  168.       // Register the Frame Window first
  169.       wc.style = CS_HREDRAW | CS_VREDRAW;
  170.       wc.lpfnWndProc = (WNDPROC)WndProc;
  171.       wc.cbClsExtra = 0;
  172.       wc.cbWndExtra = 0;
  173.       wc.hInstance = hInstance;
  174.       hIcon = wc.hIcon = LoadIcon(hInstance, "BASEICON");
  175.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  176.       wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
  177.       wc.lpszMenuName = NULL;
  178.       wc.lpszClassName = szFrameClass;
  179.       if(!RegisterClass(&wc)) {
  180.          PostError((LPSTR)szRegisterClassFailed);
  181.          return FALSE;
  182.       }
  183.  
  184.       // Register the child window class
  185.       wc.style = CS_HREDRAW | CS_VREDRAW;
  186.       wc.lpfnWndProc = (WNDPROC)ChildWndProc;
  187.       wc.cbClsExtra = 0;
  188.       wc.cbWndExtra = sizeof(lpCHILDINFO FAR *);
  189.       wc.hInstance = hInstance;
  190.       hConnectIcon = wc.hIcon = LoadIcon(hInstance, "CONNECTICON");
  191.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  192.       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  193.       wc.lpszMenuName = NULL;
  194.       wc.lpszClassName = szChildClass;
  195.       if(!RegisterClass(&wc)) {
  196.          PostError((LPSTR)szRegisterClassFailed);
  197.          return FALSE;
  198.       }
  199.  
  200.       // Register the results output window class
  201.       wc.style = CS_HREDRAW | CS_VREDRAW;
  202.       wc.lpfnWndProc = (WNDPROC)ResultsWndProc;
  203.       wc.cbClsExtra = 0;
  204.       wc.cbWndExtra = sizeof(lpRESULTSINFO);
  205.       wc.hInstance = hInstance;
  206.       hResultsIcon = wc.hIcon = LoadIcon(hInstance, "RSLTICON");
  207.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  208.       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  209.       wc.lpszMenuName = NULL;
  210.       wc.lpszClassName = szResultsClass;
  211.       if(!RegisterClass(&wc)) {
  212.          PostError((LPSTR)szRegisterClassFailed);
  213.          return FALSE;
  214.       }
  215.    }
  216.  
  217.    hMenu = LoadMenu(hInstance, "BASEMENU");
  218.    hSubMenu = GetSubMenu(hMenu, IDM_WINDOW_POS);
  219.  
  220.    hwndFrame = CreateWindow(szFrameClass,
  221.                             szWindowTitle,
  222.                             WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  223.                             CW_USEDEFAULT,
  224.                             CW_USEDEFAULT,
  225.                             CW_USEDEFAULT,
  226.                             CW_USEDEFAULT,
  227.                             NULL,
  228.                             hMenu,
  229.                             hInstance,
  230.                             NULL);
  231.  
  232.    hwndClient = GetWindow(hwndFrame, GW_CHILD);
  233.    ShowWindow(hwndFrame,
  234.               (GetPrivateProfileInt(szSCREEN, szMAX, 0, szLABINI) == 1)
  235.               ? SW_SHOWMAXIMIZED : nCmdShow);
  236.    UpdateWindow(hwndFrame);
  237.  
  238.    return (BOOL)(hwndFrame!=NULL);
  239. }
  240.  
  241. //*------------------------------------------------------------------------
  242. //| DoMain:
  243. //|     This is the main loop for the application:
  244. //*------------------------------------------------------------------------
  245. int  WINAPI DoMain(HANDLE hInstance)
  246. {
  247.    MSG msg;
  248.    HANDLE hAccel;
  249.  
  250.  
  251.    SendMessage(hwndFrame, USER_INITAPP, 0, 0L);
  252.    hAccel = LoadAccelerators(hInstance,"BASEACCELS");
  253.    while(GetMessage(&msg, NULL, 0, 0)) {
  254.       if(!TranslateAccelerator(hwndFrame,hAccel,&msg) &&
  255.          !TranslateMDISysAccel(hwndClient, &msg)) {
  256.          TranslateMessage(&msg);
  257.          DispatchMessage(&msg);
  258.       }
  259.    }
  260.  
  261.  
  262.    return msg.wParam;
  263. }
  264.  
  265.  
  266. //*---------------------------------------------------------------------------------
  267. //| DoCloseDown:
  268. //|   Clean up all of the global windows, handles, etc...   After this function
  269. //|   is called, the application may be killed off.
  270. //| Parms:
  271. //|   hwnd              The window handle being destoryed, send only on main
  272. //| Returns:
  273. //|   Nothing
  274. //*---------------------------------------------------------------------------------
  275. VOID WINAPI DoCloseDown(HWND hwnd)
  276. {
  277.    char     szTempBuf[10];
  278.  
  279.    // Close all connection windows
  280.    SendMessage(hwnd, WM_COMMAND, IDM_CLOSEALL, 0L);
  281.  
  282.    // Kill off the help file if we opened it.
  283.    if(iHelpCnt)
  284.       WinHelp(hwnd, szHELPFILE, HELP_QUIT, 0L);
  285.  
  286.    // Save our max/min state
  287.    wsprintf(szTempBuf, "%d", IsZoomed(hwnd));
  288.    WritePrivateProfileString(szSCREEN, szMAX, szTempBuf, szLABINI);
  289.  
  290.    // Destroy GDI objects
  291.    DeleteObject(hSmallEditFont);
  292.  
  293.    DestroyWindow(hwnd);
  294. }
  295.  
  296.  
  297. //*------------------------------------------------------------------------
  298. //| WndProc:
  299. //|     Handle requests for action:
  300. //*------------------------------------------------------------------------
  301. long EXTFUN WndProc(HWND      hwnd,
  302.                         unsigned msg,
  303.                         WPARAM     wParam,
  304.                         LPARAM     lParam)
  305. {
  306.    switch(msg) {
  307.      case WM_CREATE:
  308.       {
  309.          LOGFONT                 lf;
  310.          CLIENTCREATESTRUCT         clientcreate;
  311.  
  312.          memset(&lf, 0, sizeof(LOGFONT));
  313.          lf.lfHeight = -10;
  314.          lf.lfWeight = FW_THIN;
  315.          lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  316.          lstrcpy(lf.lfFaceName, szMSSansSerif);
  317.          hSmallEditFont = CreateFontIndirect(&lf);
  318.  
  319.          clientcreate.hWindowMenu = hSubMenu;
  320.          clientcreate.idFirstChild = IDM_FIRSTCHILD;
  321.          hwndClient = CreateWindow("MDICLIENT", NULL,
  322.                                    WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_CLIPSIBLINGS,
  323.                                    0, 0, 0, 0, hwnd,
  324.                                    (HMENU)(1), hInst,
  325.                                    (LPSTR)&clientcreate);
  326.          if(!hwndClient)
  327.             return -1;
  328.       }
  329.       return 0;
  330.  
  331.  
  332.       // This user message is sent to handle any first steps once the
  333.       // application is up and ready for input.  We'll cause a connection
  334.       // to be done.
  335.      case USER_INITAPP:
  336.       SendMessage(hwnd, WM_COMMAND, IDM_CONNECT,
  337.                   (cl.fOptions) ? (LPARAM)(LPSTR)cl.szDriverConnect : 0L);
  338.       if(lpActiveConn &&
  339.          *cl.szExecuteFile)
  340.          ExecuteFile(lpActiveConn, hwnd, cl.szExecuteFile, cl.szTerm, cl.cbStmt);
  341.       if(cl.fExit)
  342.          SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0L);
  343.       return 0;
  344.  
  345.  
  346.       //
  347.       // Hande the WM_INITMENUPOPUP message so that when the user selects
  348.       //    a menu, we enable/disable each item based on our current state.
  349.       //
  350.      case WM_INITMENUPOPUP:
  351.       if(!(BOOL)HIWORD(lParam))        // Not the system menu
  352.          ResetMenu(hMenu, (int)LOWORD(lParam));
  353.       break;
  354.  
  355.      case WM_COMMAND:
  356.       switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  357.          //-------------------------------------------------------------------
  358.          // The F6 key is a virtual key which toggles the cursor
  359.          // location from the input/output window.
  360.          //-------------------------------------------------------------------
  361.         case IDM_MOVE_WINDOW:
  362.          {
  363.             if(lpActiveConn) {
  364.                DWORD    dwActive=SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  365. #ifndef WIN32
  366.                HWND     Active = LOWORD(dwActive);
  367. #else
  368.                HWND     Active = (HWND)(dwActive);
  369. #endif
  370.  
  371.                if(Active != lpActiveConn->hwnd) {
  372.                   SendMessage(hwndClient, WM_MDIACTIVATE,
  373.                               (WPARAM)(HWND)lpActiveConn->hwnd, 0L);
  374.                   return 0;
  375.                }
  376.                if(GetFocus() == lpActiveConn->hwndIn)
  377.                   SetFocus(lpActiveConn->hwndOut);
  378.                else
  379.                   SetFocus(lpActiveConn->hwndIn);
  380.             }
  381.          }
  382.          return 0;
  383.  
  384.  
  385.          //-------------------------------------------------------------------
  386.          // Connect Menu
  387.          //-------------------------------------------------------------------
  388.         case IDM_CONNECT:
  389.          DoConnect(hwnd, lParam);
  390.          return 0;
  391.  
  392.         case IDM_DISCONNECT:
  393.          DoDisconnect(lpActiveConn);
  394.          return 0;
  395.  
  396.         case IDM_EXECUTE_FILE:
  397.          ExecuteFile(lpActiveConn, hwnd, NULL, NULL, 0);
  398.          return 0;
  399.  
  400.         case IDM_OPEN:
  401.          DoFileOpen(lpActiveConn);
  402.          return 0;
  403.  
  404.         case IDM_CLOSE:
  405.          {
  406.             // zzz:  Check for save if modified
  407.             szWrite(lpActiveConn->hwndOut,
  408.                     GetidsString(idsFileClosed, OutStr, sizeof(OutStr)),
  409.                     (LPSTR)lpActiveConn->szFile);
  410.  
  411.             wsprintf((LPSTR)lpActiveConn->szClientTitle, szUserAt,
  412.                      (LPSTR)lpActiveConn->CurrentUser, (LPSTR)lpActiveConn->CurrentServer);
  413.             lpActiveConn->hFile = 0;
  414.             ReleaseMemory(lpActiveConn->szFileBuff);
  415.             SetWindowText(lpActiveConn->hwnd, lpActiveConn->szClientTitle);
  416.          }
  417.          return 0;
  418.  
  419.         case IDM_SAVE:
  420.          DoFileSave(lpActiveConn);
  421.          return 0;
  422.  
  423.         case IDM_SAVEAS:
  424.          DoFileSaveAs(lpActiveConn);
  425.          return 0;
  426.  
  427.         case IDM_EXIT:
  428.          SendMessage(hwnd, WM_CLOSE, 0, 0L);
  429.          return 0;
  430.  
  431.  
  432.          //-------------------------------------------------------------------
  433.          // Edit Menu
  434.          //-------------------------------------------------------------------
  435.         case IDM_UNDO:
  436.         case IDM_CUT:
  437.         case IDM_COPY:
  438.         case IDM_PASTE:
  439.          {
  440.             HWND        fhwnd=GetEditWindow(lpActiveConn);
  441.  
  442.             if(fhwnd)
  443.                SendMessage(fhwnd,
  444.                            (wParam == IDM_CUT) ? WM_CUT :
  445.                            (wParam == IDM_COPY) ? WM_COPY :
  446.                            (wParam == IDM_PASTE) ? WM_PASTE : WM_UNDO,
  447.                            0, 0L);
  448.          }
  449.          return 0;
  450.  
  451.         case IDM_SELECT_ALL:
  452.          {
  453.             HWND              fhwnd;
  454.  
  455.             if(!(fhwnd = GetEditWindow(lpActiveConn)))
  456.                break;
  457.             SetFocus(fhwnd);
  458.             SendMessage(fhwnd, EM_SETSEL, 0, MAKELPARAM(0, -1));
  459.          }
  460.          return 0;
  461.  
  462.  
  463.  
  464.          //-------------------------------------------------------------------
  465.          // Command Menu
  466.          //-------------------------------------------------------------------
  467.         case IDM_EXECUTE_NOW:
  468.          ExecuteCmds(lpActiveConn, NULL);
  469.          return 0;
  470.  
  471.         case IDM_COMMIT:
  472.         case IDM_ROLLBACK:
  473.          DoCommitRollback(lpActiveConn, wParam);
  474.          return 0;
  475.  
  476.  
  477.  
  478.          //-------------------------------------------------------------------
  479.          // Pipe Menu
  480.          //-------------------------------------------------------------------
  481.         case IDM_PIPE_EDIT:
  482.          EditPipe(lpActiveConn);
  483.          return 0;
  484.  
  485.         case IDM_PIPE_DO:
  486.          HandlePipe(lpActiveConn, lpActiveResults);
  487.          return 0;
  488.  
  489.  
  490.  
  491.          //-------------------------------------------------------------------
  492.          // Info Menu
  493.          //-------------------------------------------------------------------
  494.         case IDM_MANAGE_DSNS:
  495.          {
  496.             HWND     fHwnd=GetFocus();
  497.  
  498.             SQLManageDataSources(hwnd);
  499.             if(fHwnd)
  500.                SetFocus(fHwnd);
  501.          }
  502.          return 0;
  503.  
  504.         case IDM_DATA_TYPES:
  505.          DisplayODBCDataTypes(lpActiveConn);
  506.          return 0;
  507.  
  508.         case IDM_FUNCTIONS:
  509.          DisplayODBCFunctions(lpActiveConn);
  510.          return 0;
  511.  
  512.         case IDM_DATA_SOURCES:
  513.          DisplayODBCDataSources(lpActiveConn);
  514.          return 0;
  515.  
  516.         case IDM_ODBC_INFO:
  517.          DisplayGetInfo(lpActiveConn);
  518.          return 0;
  519.  
  520.  
  521.  
  522.          //-------------------------------------------------------------------
  523.          // Lists Menu
  524.          //-------------------------------------------------------------------
  525.         case IDM_TABLES:
  526.         case IDM_COLUMNS:
  527.         case IDM_STATISTICS:
  528.         case IDM_PRIMARY_KEYS:
  529.         case IDM_FOREIGN_KEYS:
  530.         case IDM_TABLE_PRIVS:
  531.         case IDM_COLUMN_PRIVS:
  532.         case IDM_SPECIAL_COLUMNS:
  533.         case IDM_PROCEDURES:
  534.         case IDM_PROC_COLUMNS:
  535.          DoList(lpActiveConn, wParam);
  536.          return 0;
  537.  
  538.  
  539.  
  540.          //-------------------------------------------------------------------
  541.          // Window Menu
  542.          //-------------------------------------------------------------------
  543.         case IDM_FONT:
  544.          PromptForFontName(hwnd);
  545.          return 0;
  546.  
  547.         case IDM_CASCADE:
  548.          SendMessage(hwndClient, WM_MDICASCADE, 0, 0L);
  549.          return 0;
  550.  
  551.         case IDM_TILE:
  552.          SendMessage(hwndClient, WM_MDITILE, 0, 0L);
  553.          return 0;
  554.  
  555.         case IDM_ARRANGE:
  556.          SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0L);
  557.          return 0;
  558.  
  559.         case IDM_CLOSEALL:
  560.          {
  561.             int         idex;
  562.             int         iNum=NumItems(ConnectStructs);
  563.  
  564.             for(idex=0;  idex<iNum;  idex++)
  565.                if(ConnectStructs[idex] != NULL)
  566.                   DoDisconnect(ConnectStructs[idex]);
  567.          }
  568.          return 0;
  569.  
  570.  
  571.  
  572.          //-------------------------------------------------------------------
  573.          // Help Menu
  574.          //-------------------------------------------------------------------
  575.         case IDM_HELP:
  576.          iHelpCnt += WinHelp(hwnd, szHELPFILE, HELP_INDEX, 0L);
  577.          return 0;
  578.  
  579.         case IDM_ABOUT:
  580.          DisplayAbout(hwnd, hInst);
  581.          return 0;
  582.       }
  583.       break;
  584.  
  585.  
  586.  
  587.  
  588.     case WM_CLOSE:
  589.       DoCloseDown(hwnd);
  590.       return 0;
  591.  
  592.      case WM_DESTROY:
  593.       PostQuitMessage(0);
  594.       return 0;
  595.  
  596.  
  597.      default:
  598.       break;
  599.    }
  600.  
  601.    return DefFrameProc(hwnd, hwndClient, msg, wParam, lParam);
  602. }
  603.  
  604.  
  605.  
  606. //*------------------------------------------------------------------------
  607. //| ChildWndProc:
  608. //|     Handle all messages which are received for the MDI child
  609. //|         windows.
  610. //*------------------------------------------------------------------------
  611. long EXTFUN ChildWndProc(HWND    hwnd,
  612.                         unsigned msg,
  613.                         WPARAM     wParam,
  614.                         LPARAM     lParam)
  615. {
  616.    switch(msg) {
  617.       //
  618.       // When a successful connection is made, then we are called to
  619.       //    create a window to handle it.  The CHILDINFO structure has
  620.       //    already been allocated.
  621.       //
  622.      case WM_CREATE:
  623.       {
  624.          CREATESTRUCT FAR *      cs;
  625.          MDICREATESTRUCT FAR *   mdi;
  626.          lpCHILDINFO             lpci;
  627.  
  628.          cs = (CREATESTRUCT FAR *)lParam;
  629.          mdi = (MDICREATESTRUCT FAR *)cs->lpCreateParams;
  630.          lpci = (lpCHILDINFO)mdi->lParam;
  631.  
  632.          SETCIPOINTER(hwnd, lpci);
  633.  
  634.          lpci->hwnd = hwnd;
  635.          lpci->hInst = hInst;
  636.          hwndClient = GetParent(hwnd);
  637.          hwndFrame = GetParent(hwndClient);
  638.          if(!(lpci->hwndIn = CreateWindow("edit", NULL,
  639.                                           WS_CHILD | WS_VISIBLE | WS_VSCROLL |
  640.                                           WS_BORDER | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
  641.                                           0, 0, 0, 0,
  642.                                           hwnd, (HMENU)(3), hInst, NULL)))
  643.             return -1;
  644.          if(!(lpci->hwndOut = CreateWindow("edit", NULL,
  645.                                            WS_CHILD | WS_VISIBLE | WS_VSCROLL |
  646.                                            WS_BORDER | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
  647.                                            0, 0, 0, 0,
  648.                                            hwnd, (HMENU)(4), hInst, NULL)))
  649.             return -1;
  650.  
  651.  
  652.          SendMessage(lpci->hwndIn, WM_SETFONT,
  653.                      (WPARAM)hSmallEditFont, (LPARAM)MAKELONG((WORD)TRUE, 0));
  654.          SendMessage(lpci->hwndOut, WM_SETFONT,
  655.                      (WPARAM)hSmallEditFont, (LPARAM)MAKELONG((WORD)TRUE, 0));
  656.  
  657.          szWrite(lpci->hwndOut,
  658.                  GetidsString(idsSuccessConnect, OutStr, sizeof(OutStr)),
  659.                  (LPSTR)lpci->CurrentUser, (LPSTR)lpci->CurrentServer);
  660.       }
  661.       return 0;
  662.  
  663.       //
  664.       // NOTE:  We must break to return DefMDIWndProc in order for the menu to
  665.       //    be redrawn when we maximize the child window.
  666.       //
  667.      case WM_SIZE:
  668.       {
  669.          lpCHILDINFO       lpci;
  670.          int               di, dot;
  671.  
  672.          lpci = GETCIPOINTER(hwnd);
  673.  
  674.          lpci->dx = LOWORD(lParam);
  675.          lpci->dy = HIWORD(lParam);
  676.          di = lpci->dy * 1 / 2;
  677.          dot = lpci->dy - di;
  678.          MoveWindow(lpci->hwndIn, 0, 0, lpci->dx, di, TRUE);
  679.          MoveWindow(lpci->hwndOut, 0, di, lpci->dx, dot, TRUE);
  680.       }
  681.       break;
  682.  
  683.     
  684.  
  685.  
  686.  
  687.       //
  688.       // Handle the WM_INITMENUPOPUP message so that when the user selects
  689.       //    a menu, we enable/disable each item based on our current state.
  690.       //
  691.      case WM_INITMENUPOPUP:
  692.       if(!(BOOL)HIWORD(lParam))        // Not the system menu
  693.          ResetMenu((HMENU)wParam, (int)LOWORD(lParam));
  694.       break;
  695.  
  696.  
  697.       //
  698.       // All messages are handled in the main wnd proc, so pass them back
  699.       //
  700.      case WM_COMMAND:
  701.       {
  702.          UINT        id=GET_WM_COMMAND_ID(wParam, lParam);
  703.  
  704.          if(id >= IDM_CONNECT &&
  705.             id <= IDM_MOVE_WINDOW)
  706.             SendMessage(hwndFrame, WM_COMMAND, wParam, lParam);
  707.       }
  708.       break;
  709.  
  710.  
  711.       //
  712.       // The WM_MDIACTIVATE message is received first by the child window
  713.       //    which is losing focus, then by the window which is receiving
  714.       //    focus.
  715.       //
  716.      case WM_MDIACTIVATE:
  717.       {
  718. #ifndef WIN32
  719.          if(wParam) {
  720.             lpActiveConn = GETCIPOINTER((HWND)LOWORD(lParam));
  721.          }
  722. #else
  723.          if((HWND)lParam == hwnd) {
  724.             lpActiveConn = GETCIPOINTER((HWND)lParam);
  725.          }
  726. #endif
  727.          else
  728.             lpActiveConn = NULL;
  729.  
  730.          if(lpActiveConn) {
  731.             hwndCurMDIChild = lpActiveConn->hwnd;
  732.             SetFocus(lpActiveConn->hwndIn);
  733.          }
  734.       }
  735.       return 0;
  736.  
  737.  
  738.       //
  739.       // Check for a system close command.  This is the equivalent of a
  740.       //    Disconnect, so process it as such.
  741.       //
  742.      case WM_SYSCOMMAND:
  743.       {
  744.          if(wParam == SC_CLOSE) {
  745.             SendMessage(hwnd, WM_COMMAND, IDM_DISCONNECT, 0L);
  746.             return 0;
  747.          }
  748.       }
  749.       break;
  750.  
  751.      default:
  752.       break;
  753.    }
  754.  
  755.    return DefMDIChildProc(hwnd, msg, wParam, lParam);
  756. }
  757.  
  758.  
  759.  
  760. //*---------------------------------------------------------------------------------
  761. //| SetUp:
  762. //|   This function handles one-time setup operations for the app.  This includes
  763. //|   allocating an environment handle for ODBC, and processing the command
  764. //|   line.
  765. //| Parms:
  766. //|   szCmdLine         Command line arguments
  767. //|   cl                Command line strucutre for return
  768. //| Returns:
  769. //|   FALSE if there was an error
  770. //*---------------------------------------------------------------------------------
  771. BOOL WINAPI SetUp(LPSTR szCmdLine, CMDLINE FAR * cl)
  772. {
  773.    LPSTR str;
  774.  
  775.    // Load default resource strings
  776.    GetidsString(idsDftFileFilter, szDftFileFilter, sizeof(szDftFileFilter));
  777.    str = (LPSTR)szDftFileFilter;
  778.    while((str = strchr(str, '|')))
  779.       *str++ = '\0';
  780.  
  781.    if(SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HENV, &henv)) {
  782.       szMessageBox(GetActiveWindow(),
  783.                    MB_ICONEXCLAMATION,
  784.                    (LPSTR)szErrTitle,
  785.                    GetidsString(idsSQLAllocHandleFailed, OutStr, sizeof(OutStr)));
  786.       return FALSE;
  787.    }
  788.  
  789.    if(SQL_SUCCESS != SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
  790.                                    (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER)) {
  791.       DisplayErrors(NULL, GetidsString(idsSQLSetEnvAttr, OutStr, sizeof(OutStr)),
  792.                     SQL_HANDLE_ENV, henv);
  793.       return FALSE;
  794.    }
  795.  
  796.    if(!ParseCommandLine(szCmdLine, cl))
  797.       return FALSE;
  798.  
  799.    if(cl->fTrace) {
  800.       if(SQL_SUCCESS !=
  801.          (retcode = SQLSetConnectAttr(NULL, SQL_ATTR_TRACEFILE,
  802.                                       (LPSTR)cl->szTraceFile, SQL_NTS)))
  803.          DisplayErrors(NULL, GetidsString(idsSQLSetConnectAttr, OutStr, sizeof(OutStr)),
  804.                        SQL_HANDLE_ENV, henv);
  805.  
  806.       if(SQL_SUCCESS !=
  807.          (retcode = SQLSetConnectAttr(NULL, SQL_ATTR_TRACE,
  808.                                       (SQLPOINTER) SQL_TRUE,
  809.                                       SQL_IS_INTEGER)))
  810.          DisplayErrors(NULL, GetidsString(idsSQLSetConnectAttr, OutStr, sizeof(OutStr)),
  811.                        SQL_HANDLE_ENV, henv);
  812.    }
  813.  
  814.    return TRUE;
  815. }
  816.  
  817.  
  818.  
  819.  
  820. //*------------------------------------------------------------------------
  821. //| CleanUp:
  822. //|     Any last-minute application cleanup activities are done here:
  823. //*------------------------------------------------------------------------
  824. void WINAPI CleanUp(void)
  825. {
  826.    retcode = SQLFreeHandle(SQL_HANDLE_ENV, henv);
  827.  
  828. #ifdef DEBUGGING
  829.    {
  830.       retcode = SQLSetConnectAttr(NULL, SQL_ATTR_TRACE, SQL_FALSE, SQL_IS_INTEGER);
  831.       WinAssert(retcode == SQL_SUCCESS, (LPSTR)"SetConnectAttr: SQL_ATTR_TRACE");
  832.    }
  833. #endif
  834. }
  835.  
  836.  
  837. //*---------------------------------------------------------------------------------
  838. //| ParseCommandLine:
  839. //|   This function will break down the command line and look for common elements.
  840. //| Parms:
  841. //|   instr             The input string to look at
  842. //|   cl                Command line strucutre to store info
  843. //| Returns:
  844. //|   FALSE on error
  845. //*---------------------------------------------------------------------------------
  846. BOOL WINAPI ParseCommandLine(LPSTR instr, CMDLINE FAR * cl)
  847. {
  848.    LPSTR    str=instr;
  849.    LPSTR    endstr=str;
  850.  
  851.    if(!str)
  852.       return TRUE;
  853.  
  854.    // Assume some defaults
  855.    memset(cl, 0, sizeof(CMDLINE));
  856.    cl->cbStmt = 1000;
  857.    lstrcpy(cl->szTerm, (LPSTR)"\r\n");
  858.    cl->fExit = FALSE;
  859.  
  860.    // Look for each / value.  Spaces are allowed.  Any other character
  861.    // at this level is a syntax error
  862.    while(endstr && *str)
  863.       switch(*str) {
  864.          // We have encountered a command line switch.  See which it is
  865.         case '/':
  866.         case '-':
  867.          ++str;
  868.          switch(*str) {
  869.             // /D[] for driver connection string
  870.            case 'D':
  871.            case 'd':
  872.             ++str;
  873.             if(*str != '[' ||
  874.                !(endstr = strchr(str, ']')))
  875.                goto tokenerr;
  876.             *endstr = '\0';
  877.             if(lstrlen(cl->szDriverConnect) > sizeof(cl->szDriverConnect))
  878.                goto toobig;
  879.             lstrcpy(cl->szDriverConnect, str + 1);
  880.             str = endstr + 1;
  881.             cl->fOptions = TRUE;
  882.             break;
  883.  
  884.             // /F for file name to execute
  885.            case 'F':
  886.            case 'f':
  887.             if((endstr = strchr(++str, ' ')))
  888.                *endstr = '\0';
  889.             if(lstrlen(cl->szExecuteFile) > sizeof(cl->szExecuteFile))
  890.                goto toobig;
  891.             lstrcpy(cl->szExecuteFile, str);
  892.             str = endstr + 1;
  893.             break;
  894.  
  895.             // /O for options
  896.            case 'O':
  897.            case 'o':
  898.             if((endstr = strchr(++str, ' ')))
  899.                *endstr = '\0';
  900.             if(!ParseOptionsValues(str, cl->szTerm, sizeof(cl->szTerm), &cl->cbStmt))
  901.                goto tokenerr;
  902.             str = endstr + 1;
  903.             break;
  904.  
  905.             // /T for a trace file name
  906.            case 'T':
  907.            case 't':
  908.             if((endstr = strchr(++str, ' ')))
  909.                *endstr = '\0';
  910.             if(lstrlen(cl->szTraceFile) > sizeof(cl->szTraceFile))
  911.                goto toobig;
  912.             lstrcpy(cl->szTraceFile, str);
  913.             str = endstr + 1;
  914.             cl->fTrace = TRUE;
  915.             break;
  916.  
  917.             // /X for exit option
  918.            case 'X':
  919.            case 'x':
  920.             ++str;
  921.             if(str &&
  922.                (*str == 'Y' || *str == 'y'))
  923.                cl->fExit = TRUE;
  924.             else if(*str == 'N' || *str == 'n')
  925.                cl->fExit = FALSE;
  926.             else
  927.                goto tokenerr;
  928.             ++str;
  929.             break;
  930.  
  931.             // Not a valid argument, error
  932.            default:
  933.             goto tokenerr;
  934.          }
  935.          break;   // End of '/' or '-'
  936.  
  937.         case ' ':
  938.          ++str;
  939.          break;
  940.  
  941.         default:
  942.          goto tokenerr;
  943.       }
  944.    return TRUE;
  945.  
  946.   tokenerr:
  947.    szMessageBox(GetActiveWindow(),
  948.                 MB_ICONEXCLAMATION,
  949.                 (LPSTR)szErrTitle,
  950.                 GetidsString(idsInvalidCmdLine, OutStr, sizeof(OutStr)));
  951.    return FALSE;
  952.  
  953.   toobig:
  954.    szMessageBox(GetActiveWindow(),
  955.                 MB_ICONEXCLAMATION,
  956.                 (LPSTR)szErrTitle,
  957.                 GetidsString(idsCmdLineTooBig, OutStr, sizeof(OutStr)));
  958.    return FALSE;
  959. }
  960.  
  961.  
  962. //*---------------------------------------------------------------------------------
  963. //| ParseOptionsValues:
  964. //|   This function breaks down the /O switch by returning the invidual elements.
  965. //| Parms:
  966. //|   instr             The string to parse
  967. //|   szTerm            Terminator value
  968. //|   cbTerm            Max for terminator value
  969. //|   lpMax             Maximum size for statement execution
  970. //| Returns:
  971. //|   FALSE on error
  972. //*---------------------------------------------------------------------------------
  973. BOOL WINAPI ParseOptionsValues(LPSTR instr, LPSTR szTerm, int cbTerm, int FAR * lpMax)
  974. {
  975.    LPSTR str=instr;
  976.    LPSTR endstr=instr;
  977.    char  cApost = '\'';
  978.  
  979.    // Now look for user specific values
  980.    while(endstr && *str)
  981.       switch(*str) {
  982.          // Found the terminator
  983.         case 'T':
  984.         case 't':
  985.          // Could be a Carriage return or a string
  986.          ++str;
  987.          if(*str == cApost) {
  988.             if(!(endstr = strchr(++str, cApost)))
  989.                return FALSE;
  990.             *endstr = '\0';
  991.             if(lstrlen(str) > cbTerm)
  992.                return FALSE;
  993.             lstrcpy(szTerm, str);
  994.             str = endstr + 1;
  995.          }
  996.          else if(strncmp(str, "CR", 2) != 0)
  997.             return FALSE;
  998.          else {
  999.             lstrcpy(szTerm, (LPSTR)"\r\n");
  1000.             str += 2;
  1001.          }
  1002.          break;
  1003.  
  1004.          // Found the Maximum length value
  1005.         case 'M':
  1006.         case 'm':
  1007.          ++str;
  1008.          if((endstr = strchr(str, ':')))
  1009.             *endstr = '\0';
  1010.          *lpMax = lpatoi(str);
  1011.          if(*lpMax < MINSTMTSIZE ||
  1012.             *lpMax > MAXSTMTSIZE)
  1013.             return FALSE;
  1014.          str = endstr + 1;
  1015.          break;
  1016.  
  1017.          // Ignore delimiter
  1018.         case ':':
  1019.          ++str;
  1020.          break;
  1021.  
  1022.          // This is an error
  1023.         default:
  1024.          return FALSE;
  1025.          break;
  1026.       }
  1027.    return TRUE;
  1028. }
  1029.  
  1030.  
  1031. //*---------------------------------------------------------------------------------
  1032. //| DoConnect:
  1033. //|   Handle the structures involved in creating a connection window.  Invoke the
  1034. //|   Connect function to do the actual ODBC work.
  1035. //| Parms:
  1036. //|   hwnd              The parent window handle for the new child
  1037. //|   dwData            Indicates a start code or string.
  1038. //| Returns:
  1039. //|   Nothing
  1040. //*---------------------------------------------------------------------------------
  1041. VOID WINAPI DoConnect(HWND hwnd, DWORD dwData)
  1042. {
  1043.    lpCHILDINFO       citmp;
  1044.    MDICREATESTRUCT   mdicreate;
  1045.    int               idex;
  1046.  
  1047.    for(idex=0;  idex<MAXCONNECTS;  idex++)
  1048.       if(!ConnectStructs[idex])
  1049.          break;
  1050.  
  1051.    // See if we have exceeded the max connects
  1052.    if(idex >= MAXCONNECTS) {
  1053.       szMessageBox(hwnd,
  1054.                    MB_ICONINFORMATION | MB_OK,
  1055.                    (LPSTR)szErrTitle,
  1056.                    GetidsString(idsTooManyConnects, OutStr, sizeof(OutStr)),
  1057.                    MAXCONNECTS);
  1058.       return;
  1059.    }
  1060.  
  1061.    citmp = (lpCHILDINFO)GetMemory(sizeof(CHILDINFO));
  1062.    if(!citmp)
  1063.       return;
  1064.  
  1065.    memset(citmp, 0, sizeof(CHILDINFO));
  1066.  
  1067.    if(Connect(citmp, hwnd,
  1068.               (HIWORD(dwData) == 1) ? NULL : (LPSTR)dwData)) {  // Pass NULL if accelerator used
  1069.       // We are connected, save the handle
  1070.       ConnectStructs[idex] = citmp;
  1071.  
  1072.       // Now fill out the rest
  1073.       citmp->hwndClient = hwndClient;
  1074.       citmp->henv = henv;                    // Keep local copy of global
  1075.  
  1076.       wsprintf((LPSTR)citmp->szClientTitle, szUserAt, (LPSTR)citmp->CurrentUser,
  1077.                (LPSTR)citmp->CurrentServer);
  1078.       mdicreate.szClass = szChildClass;
  1079.       mdicreate.szTitle = citmp->szClientTitle;
  1080.       mdicreate.hOwner  = hInst;
  1081.       mdicreate.x       = CW_USEDEFAULT;
  1082.       mdicreate.y       = CW_USEDEFAULT;
  1083.       mdicreate.cx      = CW_USEDEFAULT;
  1084.       mdicreate.cy      = CW_USEDEFAULT;
  1085.       mdicreate.style   = (hwndCurMDIChild) ? ((IsZoomed(hwndCurMDIChild)) ? WS_MAXIMIZE : 0) : 0;
  1086.       mdicreate.lParam  = (LPARAM)citmp;
  1087.       SendMessage(hwndClient, WM_MDICREATE, 0,
  1088.                   (LPARAM)(LPMDICREATESTRUCT)&mdicreate);
  1089.    }
  1090.    else {
  1091.       // No connect made, so release all memory
  1092.       retcode = SQLFreeHandle(SQL_HANDLE_DBC, citmp->hdbc);
  1093.       ReleaseMemory(citmp);
  1094.    }
  1095. }
  1096.  
  1097.  
  1098. //*---------------------------------------------------------------------------------
  1099. //| Connect:
  1100. //|   This function attempts to make a connection.  If the user has specified the
  1101. //|   /D command line option, then we will simply use the connection string.
  1102. //| Parms:
  1103. //|   ci                Connection window information
  1104. //|   hwnd              Window handle for any prompting
  1105. //|   szAutoConnect     NULL if prompt, else pointer to szConnStrIn
  1106. //| Returns:
  1107. //|   FALSE on error
  1108. //*---------------------------------------------------------------------------------
  1109. BOOL WINAPI Connect(CHILDINFO FAR * ci, HWND hwnd, LPSTR szAutoConnect)
  1110. {
  1111.    SWORD       cb;
  1112.    RETCODE     rc;
  1113.    UWORD       fExists;
  1114.    int         idex;
  1115.  
  1116.    if(SQL_SUCCESS != (retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &ci->hdbc))) {
  1117.       szMessageBox(GetActiveWindow(),
  1118.                    MB_ICONEXCLAMATION | MB_OK,
  1119.                    (LPSTR)szErrTitle,
  1120.                    GetidsString(idsSQLAllocHandleFailed, OutStr, sizeof(OutStr)));
  1121.       return FALSE;
  1122.    }
  1123.  
  1124.  
  1125.    // Do the connection
  1126.    if(!szAutoConnect)
  1127.       retcode = SQLDriverConnect(ci->hdbc, hwnd, NULL, 0, ci->szConnStrOut,
  1128.                                  MAXBUFF, &cb, SQL_DRIVER_COMPLETE);
  1129.    else
  1130.       retcode = SQLDriverConnect(ci->hdbc, hwnd, szAutoConnect, SQL_NTS,
  1131.                                  ci->szConnStrOut, MAXBUFF, &cb, SQL_DRIVER_NOPROMPT);
  1132.    if(retcode == SQL_NO_DATA)
  1133.       return FALSE;
  1134.    else if(retcode == SQL_ERROR) {
  1135.       PrintErrors(ci, SQL_HANDLE_DBC);
  1136.       return FALSE;
  1137.    }
  1138.  
  1139.    if(RC_SUCCESSFUL(retcode)) {
  1140.       SWORD len;
  1141.  
  1142.       retcode = SQLGetInfo(ci->hdbc, SQL_USER_NAME, ci->CurrentUser,
  1143.                            sizeof(ci->CurrentUser), &len);
  1144.       if(retcode == SQL_ERROR || len == 0)   // Assume driver not capable
  1145.          *ci->CurrentUser = '\0';
  1146.  
  1147.       retcode = SQLGetInfo(ci->hdbc, SQL_DATA_SOURCE_NAME, ci->CurrentServer,
  1148.                            sizeof(ci->CurrentServer), NULL);
  1149.    }
  1150.  
  1151.    if(SQL_SUCCESS != (retcode = SQLAllocHandle(SQL_HANDLE_STMT, ci->hdbc, &ci->hstmt))) {
  1152.       szMessageBox(GetActiveWindow(),
  1153.                    MB_ICONEXCLAMATION,
  1154.                    (LPSTR)szErrTitle,
  1155.                    GetidsString(idsSQLAllocHandleFailed, OutStr, sizeof(OutStr)));
  1156.       return FALSE;
  1157.    }
  1158.  
  1159.    //
  1160.    // Find out what functions are supported and store them in a bitmask
  1161.    //
  1162.    memset(&ci->fFunctions, 0, sizeof(ci->fFunctions));
  1163.    for(idex=0;  idex<NUM_MENU_FLAGS;  idex++) {
  1164.       rc = SQLGetFunctions(ci->hdbc,
  1165.                            uMenuIDs[idex],
  1166.                            &fExists);
  1167.       if(RC_NOTSUCCESSFUL(rc)) {
  1168.          fExists = FALSE;
  1169.          PrintErrors(ci, SQL_HANDLE_DBC);
  1170.       }
  1171.  
  1172.       if(fExists)
  1173.          BitSet(ci->fFunctions, idex);
  1174.    }
  1175.  
  1176.    return TRUE;
  1177. }
  1178.  
  1179.  
  1180. int WINAPI GetConnDex(lpCHILDINFO lpci)
  1181. {
  1182.    int idex;
  1183.  
  1184.    for(idex=0;  idex<MAXCONNECTS;  idex++)
  1185.       if(lpci == ConnectStructs[idex])
  1186.          return idex;
  1187.  
  1188.    return -1;
  1189. }
  1190.  
  1191.  
  1192. //*---------------------------------------------------------------------------------
  1193. //| DoDisconnect:
  1194. //|   Look for the handle passed in and then disconnect it.  The Disconnect function
  1195. //|   is used to do the ODBC portion.
  1196. //| Parms:
  1197. //|   lpci              Connect window to free
  1198. //| Returns:
  1199. //|   Nothing
  1200. //*---------------------------------------------------------------------------------
  1201. VOID WINAPI DoDisconnect(lpCHILDINFO lpci)
  1202. {
  1203.    int         idex;
  1204.  
  1205.    idex = GetConnDex(lpci);
  1206.    if(idex == -1)
  1207.       return;
  1208.  
  1209.    if(Disconnect(lpci)) {
  1210.       FreeConnectWindowResults(lpci);
  1211.       SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)(HWND)lpci->hwnd, 0L);
  1212.       ConnectStructs[idex] = NULL;
  1213.    }
  1214. }
  1215.  
  1216.  
  1217. //*------------------------------------------------------------------------
  1218. //| Disconnect:
  1219. //|     Make a connection to a server.
  1220. //*------------------------------------------------------------------------
  1221. BOOL WINAPI Disconnect(CHILDINFO FAR * ci)
  1222. {
  1223.    if(SQL_SUCCESS != (retcode = SQLFreeHandle(SQL_HANDLE_STMT, ci->hstmt)))
  1224.       DisplayErrors(ci->hwnd, GetidsString(idsSQLFreeHandle, OutStr, sizeof(OutStr)),
  1225.                     SQL_HANDLE_STMT, ci->hstmt);
  1226.    if(SQL_SUCCESS != (retcode = SQLDisconnect(ci->hdbc)))
  1227.       DisplayErrors(ci->hwnd, GetidsString(idsSQLDisconnect, OutStr, sizeof(OutStr)),
  1228.                     SQL_HANDLE_DBC, ci->hdbc);
  1229.    if(SQL_SUCCESS != (retcode = SQLFreeHandle(SQL_HANDLE_DBC, ci->hdbc)))
  1230.       DisplayErrors(ci->hwnd, GetidsString(idsSQLFreeHandle, OutStr, sizeof(OutStr)),
  1231.                     SQL_HANDLE_DBC, ci->hstmt);
  1232.  
  1233.    ci->hstmt = ci->hdbc = NULL;
  1234.    szWrite(ci->hwndOut,
  1235.            GetidsString(idsDisconnectSuccess, OutStr, sizeof(OutStr)));
  1236.  
  1237.    return TRUE;
  1238. }
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246. //*------------------------------------------------------------------------
  1247. //| DisplayAbout:
  1248. //|     Display the about box for this app.
  1249. //*------------------------------------------------------------------------
  1250. void WINAPI DisplayAbout(HWND hwnd, HINSTANCE hInst)
  1251. {
  1252.    HWND     fHwnd=GetFocus();
  1253.  
  1254.    if(-1 == DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, (DLGPROC)AboutWndProc,
  1255.                            (LPARAM)(HINSTANCE FAR * )&hInst))
  1256.       MessageBox(hwnd, "Could not open dialog box.",
  1257.                  "About", MB_ICONEXCLAMATION);
  1258.  
  1259.    if(fHwnd)
  1260.       SetFocus(fHwnd);
  1261. }
  1262.  
  1263.  
  1264.  
  1265. //*------------------------------------------------------------------------
  1266. //| AboutWndProc:
  1267. //|     Handle the About messages
  1268. //*------------------------------------------------------------------------
  1269. BOOL EXTFUN AboutWndProc(HWND    hDlg,
  1270.                               unsigned msg,
  1271.                               WPARAM     wParam,
  1272.                               LPARAM     lParam)
  1273. {
  1274.    int x=10,y=30;
  1275.    static HINSTANCE FAR *  lpHINST;
  1276.  
  1277.    switch(msg) {
  1278.      case WM_INITDIALOG:
  1279.       lpHINST = (HINSTANCE FAR *)lParam;
  1280.       CenterDialog(hDlg);
  1281.       return TRUE;
  1282.  
  1283.      case WM_COMMAND:
  1284.       SendMessage(hDlg, WM_CLOSE, 0, 0L);
  1285.       return TRUE;
  1286.  
  1287.  
  1288.      case WM_CLOSE:
  1289.       EndDialog(hDlg, FALSE);
  1290.       return TRUE;
  1291.  
  1292.  
  1293.      default:
  1294.       return FALSE;
  1295.    }
  1296. }
  1297.  
  1298.  
  1299.  
  1300. //*------------------------------------------------------------------------
  1301. //| Busy:
  1302. //|     Display the hour glass cursor when we are working
  1303. //|         flag = TRUE means we are busy to so display it
  1304. //|         flag = FALSE means go back to old cursor
  1305. //*------------------------------------------------------------------------
  1306. void Busy(int flag)
  1307. {
  1308.    static HCURSOR hCursor;                // Save old cursor handle
  1309.  
  1310.    ShowCursor(FALSE);
  1311.    if(flag)
  1312.       hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1313.    else
  1314.       SetCursor(hCursor);
  1315.    ShowCursor(TRUE);
  1316. }
  1317.  
  1318.  
  1319.  
  1320. //*---------------------------------------------------------------------------------
  1321. //| iLoadString:
  1322. //|   This function will retrieve a string from our resource fork and place it
  1323. //|      in the buffer provided.  If the string is not found, an empty string
  1324. //|      is returned.
  1325. //| Parms:
  1326. //|   in       id                   String number to retrieve
  1327. //|   in       str                  Output string
  1328. //|   in       len                  Lenth of possible output
  1329. //| Returns:
  1330. //|   Pointer to buffer str
  1331. //*---------------------------------------------------------------------------------
  1332. LPSTR iLoadString(int id, LPSTR str, int len)
  1333. {
  1334.    if(!str ||
  1335.       len <= 0)
  1336.       return str;
  1337.  
  1338.    if(!LoadString(hInst, id, str, len))
  1339.       *str = '\0';
  1340.    return str;
  1341. }
  1342.  
  1343.  
  1344. //*---------------------------------------------------------------------------------
  1345. //| GetEditWindow:
  1346. //|   This function will get the current focus window and verify that it is
  1347. //|   an edit window which is valid for one of the Edit menu items.
  1348. //| Parms:
  1349. //|   lpci                 Connection window information
  1350. //| Returns:
  1351. //|   Edit window handle if valid, NULL if not valid
  1352. //*---------------------------------------------------------------------------------
  1353. HWND INTFUN GetEditWindow(lpCHILDINFO lpci)
  1354. {
  1355.    HWND hwnd;
  1356.    hwnd = GetFocus();
  1357.  
  1358.    if(hwnd && lpci) {
  1359.       if(hwnd == lpci->hwndIn ||
  1360.          hwnd == lpci->hwndOut)
  1361.          return hwnd;
  1362.    }
  1363.  
  1364.    return NULL;
  1365. }
  1366.  
  1367.  
  1368. //*------------------------------------------------------------------------
  1369. //| CenterDialog:
  1370. //|      Center the dialog over the parent window.  It is possible that
  1371. //|         their is not a parent window, since the Translate DLL was
  1372. //|         never meant to display data.  For this reason, we may just
  1373. //|         center over the entire screen.
  1374. //*------------------------------------------------------------------------
  1375. void WINAPI  CenterDialog(HWND hdlg)
  1376. {
  1377.    RECT  rcParent;                         // Parent window client rect
  1378.    RECT  rcDlg;                            // Dialog window rect
  1379.    int   nLeft, nTop;                      // Top-left coordinates
  1380.    int   cWidth, cHeight;                  // Width and height
  1381.    HWND  hwnd;
  1382.  
  1383.    // Get frame window client rect in screen coordinates
  1384.    if((hwnd = GetParent(hdlg)) == NULL) {
  1385.       rcParent.top = rcParent.left = 0;
  1386.       rcParent.right = GetSystemMetrics(SM_CXFULLSCREEN);
  1387.       rcParent.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
  1388.    }
  1389.    else
  1390.       GetWindowRect(hwnd, &rcParent);
  1391.  
  1392.    // Determine the top-left point for the dialog to be centered
  1393.    GetWindowRect(hdlg, &rcDlg);
  1394.    cWidth  = rcDlg.right  - rcDlg.left;
  1395.    cHeight = rcDlg.bottom - rcDlg.top;
  1396.    nLeft   = rcParent.left +
  1397.       (((rcParent.right  - rcParent.left) - cWidth ) / 2);
  1398.    nTop    = rcParent.top  +
  1399.       (((rcParent.bottom - rcParent.top ) - cHeight) / 2);
  1400.    if (nLeft < 0) nLeft = 0;
  1401.    if (nTop  < 0) nTop  = 0;
  1402.  
  1403.    // Place the dialog
  1404.    MoveWindow(hdlg, nLeft, nTop, cWidth, cHeight, TRUE);
  1405.    return;
  1406. }
  1407.  
  1408.  
  1409. //*---------------------------------------------------------------------------------
  1410. //| DoFileOpen:
  1411. //|   Use the commond dialog functions to open a file.
  1412. //| Parms:
  1413. //|   lpci                    Connection window information
  1414. //| Returns:
  1415. //|   Nothing
  1416. //*---------------------------------------------------------------------------------
  1417. VOID WINAPI DoFileOpen(lpCHILDINFO lpci)
  1418. {
  1419.    OPENFILENAME      ofn;
  1420.    HWND              fHwnd=GetFocus();
  1421.  
  1422.  
  1423.    // If user has a file open already, verify that we should continue
  1424.    if(lpci->hFile) {
  1425.       if(IDYES == szMessageBox(lpci->hwnd,
  1426.                                MB_YESNO,
  1427.                                (LPSTR)szOPENFILE,
  1428.                                GetidsString(idsCloseFile, OutStr, sizeof(OutStr)),
  1429.                                (LPSTR)lpci->szFile))
  1430.          SendMessage(lpci->hwnd, WM_COMMAND, IDM_CLOSE, 0L);
  1431.       else
  1432.          return;
  1433.    }
  1434.  
  1435.    // Now ask to open a file
  1436.    lpci->szFileBuff = (LPSTR)GetMemory(MAXFILEBUFF);
  1437.    if(!lpci->szFileBuff)
  1438.       return;
  1439.  
  1440.    if(!*szDirName)
  1441.       GetWindowsDirectory(szDirName, sizeof(szDirName));
  1442.  
  1443.    // Fill out the struct
  1444.    memset(&ofn, 0, sizeof(OPENFILENAME));
  1445.    lpci->szFile[0] = '\0';
  1446.    ofn.lStructSize =          sizeof(OPENFILENAME);
  1447.    ofn.hwndOwner =            lpci->hwnd;
  1448.    ofn.lpstrFilter =          szDftFileFilter;
  1449.    ofn.nFilterIndex =         1;
  1450.    ofn.lpstrFile =            lpci->szFile;
  1451.    ofn.nMaxFile =             sizeof(lpci->szFile);
  1452.    ofn.lpstrInitialDir =      szDirName;
  1453.    ofn.Flags =                OFN_HIDEREADONLY |
  1454.       OFN_PATHMUSTEXIST |
  1455.          OFN_FILEMUSTEXIST;
  1456.  
  1457.    // Try to open the file
  1458.    if(GetOpenFileName(&ofn)) {
  1459.       if(fHwnd)
  1460.          SetFocus(fHwnd);
  1461.  
  1462.       if(HFILE_ERROR == (lpci->hFile = _lopen(ofn.lpstrFile, OF_READ))) {
  1463.          szMessageBox(lpci->hwnd,
  1464.                       MB_ICONEXCLAMATION,
  1465.                       (LPSTR)szOPENFILE,
  1466.                       GetidsString(idsOpenFileFailed, OutStr, sizeof(OutStr)),
  1467.                       (LPSTR)ofn.lpstrFile);
  1468.          return;
  1469.       }
  1470.  
  1471.       lpci->cbFileSize = _lread(lpci->hFile,
  1472.                                 (void FAR *)lpci->szFileBuff, MAXFILEBUFF);
  1473.       _lclose(lpci->hFile);
  1474.       szWrite(lpci->hwndIn, (LPSTR)lpci->szFileBuff);
  1475.       SendMessage(lpci->hwndIn, EM_SETMODIFY, FALSE, 0L);
  1476.       wsprintf((LPSTR)lpci->szClientTitle, szUserAtFile,
  1477.                (LPSTR)lpci->CurrentUser, (LPSTR)lpci->CurrentServer,
  1478.                (LPSTR)ofn.lpstrFile);
  1479.       SetWindowText(lpci->hwnd, lpci->szClientTitle);
  1480.       GetNewDirectory(szDirName, ofn.lpstrFile);
  1481.    }
  1482.  
  1483.    if(fHwnd)
  1484.       SetFocus(fHwnd);
  1485. }
  1486.  
  1487.  
  1488. //*---------------------------------------------------------------------------------
  1489. //| DoSave:
  1490. //|   Save the current file.
  1491. //| Parms:
  1492. //|   lpci                    Connection window information
  1493. //| Returns:
  1494. //|   Nothing
  1495. //*---------------------------------------------------------------------------------
  1496. VOID WINAPI DoFileSave(lpCHILDINFO lpci)
  1497. {
  1498.    OFSTRUCT       ofs;
  1499.  
  1500.    ofs.cBytes = sizeof(OFSTRUCT);
  1501.  
  1502.    lpci->cbFileSize = GetWindowText(lpci->hwndIn,
  1503.                                     (LPSTR)lpci->szFileBuff, MAXFILEBUFF);
  1504.    if(HFILE_ERROR == (lpci->hFile =
  1505.                       OpenFile(lpci->szFile, &ofs, OF_CREATE))) {
  1506.       szMessageBox(lpci->hwnd,
  1507.                    MB_ICONEXCLAMATION,
  1508.                    (LPSTR)szSAVEFILE,
  1509.                    GetidsString(idsSaveFileFailed, OutStr, sizeof(OutStr)),
  1510.                    (LPSTR)lpci->szFile);
  1511.       return;
  1512.    }
  1513.  
  1514.    _lwrite(lpci->hFile, (void FAR *)lpci->szFileBuff, lstrlen(lpci->szFileBuff));
  1515.    _lclose(lpci->hFile);
  1516. }
  1517.  
  1518.  
  1519. //*---------------------------------------------------------------------------------
  1520. //| DoFileSaveAs:
  1521. //|   Use the commond dialog functions to save a file.
  1522. //| Parms:
  1523. //|   lpci                    Connection window information
  1524. //| Returns:
  1525. //|   Nothing
  1526. //*---------------------------------------------------------------------------------
  1527. VOID INTFUN DoFileSaveAs(lpCHILDINFO lpci)
  1528. {
  1529.    OPENFILENAME         ofn;
  1530.    HWND                 fHwnd=GetFocus();
  1531.    char                 szSaveFile[_MAX_PATH];
  1532.  
  1533.    // Fill out struct
  1534.    szSaveFile[0] = '\0';
  1535.    memset(&ofn, 0, sizeof(OPENFILENAME));
  1536.    ofn.lStructSize =          sizeof(OPENFILENAME);
  1537.    ofn.hwndOwner =            lpci->hwnd;
  1538.    ofn.lpstrFilter =          szDftFileFilter;
  1539.    ofn.nFilterIndex =         1;
  1540.    ofn.lpstrFile =            szSaveFile;
  1541.    ofn.nMaxFile =             sizeof(lpci->szFile);
  1542.    ofn.lpstrInitialDir =      szDirName;
  1543.    ofn.Flags =                OFN_HIDEREADONLY |
  1544.       OFN_PATHMUSTEXIST |
  1545.          OFN_OVERWRITEPROMPT;
  1546.  
  1547.  
  1548.    // See if user selects a file
  1549.    if(GetSaveFileName(&ofn)) {
  1550.       lstrcpy(lpci->szFile, szSaveFile);
  1551.       wsprintf((LPSTR)lpci->szClientTitle, szUserAtFile,
  1552.                (LPSTR)lpci->CurrentUser, (LPSTR)lpci->CurrentServer,
  1553.                (LPSTR)szSaveFile);
  1554.       SetWindowText(lpci->hwnd, lpci->szClientTitle);
  1555.       DoFileSave(lpci);
  1556.    }
  1557.  
  1558.    if(fHwnd)
  1559.       SetFocus(fHwnd);
  1560. }
  1561.