1 // Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License, version 2.0, as
5 // published by the Free Software Foundation.
6 //
7 // This program is also distributed with certain software (including
8 // but not limited to OpenSSL) that is licensed under separate terms,
9 // as designated in a particular file or component or in included license
10 // documentation. The authors of MySQL hereby grant you an
11 // additional permission to link the program and your derivative works
12 // with the separately licensed software that they have included with
13 // MySQL.
14 //
15 // Without limiting anything contained in the foregoing, this file,
16 // which is part of MySQL Connector/ODBC, is also subject to the
17 // Universal FOSS Exception, version 1.0, a copy of which can be found at
18 // http://oss.oracle.com/licenses/universal-foss-exception.
19 //
20 // This program is distributed in the hope that it will be useful, but
21 // WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 // See the GNU General Public License, version 2.0, for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software Foundation, Inc.,
27 // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 
29 /**
30  @file  odbcdialogparams.cpp
31  @brief Defines the entry point for the DLL application.
32 */
33 
34 #define WIN32_LEAN_AND_MEAN
35 
36 #include <windows.h>
37 #include <windowsx.h>
38 #include <commctrl.h>
39 #include <stdio.h>
40 #include "resource.h"
41 #include "TabCtrl.h"
42 #include <assert.h>
43 #include <commdlg.h>
44 #include <shlobj.h>
45 #include <xstring>
46 #include <shellapi.h>
47 #include <winsock2.h>
48 
49 #include "../setupgui.h"
50 
51 #include "odbcdialogparams.h"
52 
53 #include "stringutil.h"
54 
55 extern HINSTANCE ghInstance;
56 
57 static DataSource* pParams= NULL;
58 static PWCHAR      pCaption= NULL;
59 static int         OkPressed= 0;
60 
61 static int         mod= 1;
62 static bool        flag= false;
63 static bool        BusyIndicator= false;
64 
65 static TABCTRL     TabCtrl_1;
66 /* Whether we are in SQLDriverConnect() prompt mode (used to disable fields) */
67 static BOOL        g_isPrompt;
68 /* Variable to keep IDC of control where default value were put. It's reset if
69    user changes value. Used to verify if we can reset that control's value.
70    It won't work if for more than 1 field, but we have only one in visible future. */
71 static long        controlWithDefValue= 0;
72 
73 HelpButtonPressedCallbackType* gHelpButtonPressedCallback = NULL;
74 
75 
76 /* Function that enables/disables groups of controls */
77 #define SWITCHED_GROUPS 2
78 #define MAX_GROUP_COTROLS 2
SwitchTcpOrPipe(HWND hwnd,BOOL usePipe)79 void SwitchTcpOrPipe(HWND hwnd, BOOL usePipe)
80 {
81   /* groups of fields to enable/disable*/
82   const int switchedFields[SWITCHED_GROUPS][MAX_GROUP_COTROLS]=
83                                     {{IDC_EDIT_server, IDC_EDIT_port},
84                                      {IDC_EDIT_socket, 0}};
85 
86   /* Default value for enabled empty field */
87   const LPCWSTR defaultValues[SWITCHED_GROUPS][MAX_GROUP_COTROLS]=
88                                     {{NULL, NULL}, {L"MySQL", NULL}};
89   /* Can't be sure that usePipe contains 1 as TRUE*/
90   long activeIndex= usePipe ? 1L : 0L;
91 
92   for (long i= 0; i < SWITCHED_GROUPS; ++i)
93     for (long j= 0; j < MAX_GROUP_COTROLS && switchedFields[i][j] != 0; ++j)
94     {
95       HWND control= GetDlgItem(hwnd, switchedFields[i][j]);
96       EnableWindow(control, i == activeIndex);
97 
98       if (defaultValues[i][j] != NULL)
99       {
100         if (i == activeIndex)
101         {
102           if (Edit_GetTextLength(control) == 0)
103           {
104             /* remember that we set that value */
105             Edit_SetText(control, defaultValues[i][j]);
106             controlWithDefValue= switchedFields[i][j];
107           }
108         }
109         else if (controlWithDefValue == switchedFields[i][j])
110         {
111           /* we don't want to store the value we set instead of user */
112           Edit_SetText(control,L"");
113         }
114       }
115     }
116 }
117 #undef SWITCHED_GROUPS
118 #undef MAX_GROUP_COTROLS
119 
120 
InitStaticValues()121 void InitStaticValues()
122 {
123 	BusyIndicator= true;
124 	pParams      = NULL;
125 	pCaption     = NULL;
126 	OkPressed    = 0;
127 
128 	mod          = 1;
129 	flag         = false;
130 	BusyIndicator= false;
131 
132 	gHelpButtonPressedCallback= NULL;
133 }
134 
135 
136 #define Refresh(A) RedrawWindow(A,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_UPDATENOW);
137 
138 BOOL FormMain_DlgProc (HWND, UINT, WPARAM, LPARAM);
139 
140 
DoEvents(void)141 void DoEvents (void)
142 {
143 	MSG Msg;
144 	while (PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
145 	{
146 		TranslateMessage(&Msg);
147 		DispatchMessage(&Msg);
148 	}
149 }
150 
151 
152 VOID OnWMNotify(WPARAM wParam, LPARAM lParam);
153 
154 
FormMain_OnNotify(HWND hwnd,WPARAM wParam,LPARAM lParam)155 static BOOL FormMain_OnNotify (HWND hwnd, WPARAM wParam, LPARAM lParam)
156 {
157 	OnWMNotify(wParam, lParam);
158 	int id = (int)wParam;
159 
160   switch(id)
161   {
162     case IDC_TAB1:
163     {
164       TabControl_Select(&TabCtrl_1); //update internal "this" pointer
165 
166       LPNMHDR nm = (LPNMHDR)lParam;
167       switch (nm->code)
168       {
169         case TCN_KEYDOWN:
170           TabCtrl_1.OnKeyDown(lParam);
171 
172         case TCN_SELCHANGE:
173           TabCtrl_1.OnSelChanged();
174       }
175     }
176     break;
177   }
178 
179 	return FALSE;
180 }
181 
182 
getStrFieldData(HWND hwnd,SQLWCHAR ** param,int idc)183 void getStrFieldData(HWND hwnd, SQLWCHAR **param, int idc)
184 {
185   x_free(*param);
186   *param= NULL;
187 
188   int len = Edit_GetTextLength(GetDlgItem(hwnd,idc));
189 
190   if (len>0)
191   {
192     *param= (SQLWCHAR *)myodbc_malloc((len + 1) * sizeof(SQLWCHAR), MYF(0));
193     if (*param)
194       Edit_GetText(GetDlgItem(hwnd,idc), *param, len+1);
195   }
196 }
197 
198 
getStrFieldDataTab(SQLWCHAR ** param,unsigned int framenum,int idc)199 void getStrFieldDataTab(SQLWCHAR **param, unsigned int framenum, int idc)
200 {
201   assert(TabCtrl_1.hTabPages);
202   HWND tab = TabCtrl_1.hTabPages[framenum-1];
203 
204   assert(tab);
205 
206   getStrFieldData(tab, param, idc);
207 }
208 
setComboFieldDataTab(SQLWCHAR * param,unsigned int framenum,int idc)209 void setComboFieldDataTab(SQLWCHAR *param, unsigned int framenum, int idc)
210 {
211   if ( TabCtrl_1.hTabPages[framenum-1])
212   {
213     HWND tabHwndMisc = TabCtrl_1.hTabPages[framenum-1];
214     HWND charsetCtrl = GetDlgItem(tabHwndMisc, idc);
215     ComboBox_SetText(charsetCtrl, param);
216   }
217 }
218 
219 
setStrFieldData(HWND hwnd,SQLWCHAR * param,int idc)220 void setStrFieldData(HWND hwnd, SQLWCHAR *param, int idc)
221 {
222   Edit_SetText(GetDlgItem(hwnd, idc), param);
223 }
224 
225 
setStrFieldDataTab(SQLWCHAR * param,unsigned int framenum,int idc)226 void setStrFieldDataTab(SQLWCHAR *param, unsigned int framenum, int idc)
227 {
228   assert(TabCtrl_1.hTabPages);
229   HWND tab = TabCtrl_1.hTabPages[framenum-1];
230 
231   assert(tab);
232 
233   setStrFieldData(tab, param, idc);
234 }
235 
236 
getUnsignedFieldDataTab(unsigned int framenum,unsigned int * param,int idc)237 void getUnsignedFieldDataTab(unsigned int framenum, unsigned int *param, int idc )
238 {
239   getUnsignedFieldData(TabCtrl_1.hTabPages[framenum-1], param, idc);
240 }
241 
242 
getUnsignedFieldData(HWND hwnd,unsigned int * param,int idc)243 void getUnsignedFieldData(HWND hwnd, unsigned int *param, int idc)
244 {
245   *param = 0U;
246   int len = Edit_GetTextLength(GetDlgItem(hwnd,idc));
247 
248   if(len>0)
249   {
250     SQLWCHAR *tmp1= (SQLWCHAR *)myodbc_malloc((len + 1) * sizeof(SQLWCHAR),
251                                          MYF(0));
252     if (tmp1)
253     {
254       Edit_GetText(GetDlgItem(hwnd,idc), tmp1, len+1);
255       *param = _wtol(tmp1);
256       x_free(tmp1);
257     }
258   }
259 }
260 
261 
setUnsignedFieldData(HWND hwnd,const unsigned int param,int idc)262 void setUnsignedFieldData(HWND hwnd, const unsigned int param, int idc)
263 {
264   wchar_t buf[20];
265   _itow( param, (wchar_t*)buf, 10 );
266   Edit_SetText(GetDlgItem(hwnd,idc), buf);
267 }
268 
269 
setUnsignedFieldDataTab(unsigned int framenum,const unsigned int param,int idc)270 void setUnsignedFieldDataTab(unsigned int framenum, const unsigned int param, int idc)
271 {
272   setUnsignedFieldData(TabCtrl_1.hTabPages[framenum-1], param, idc);
273 }
274 
275 
getTabCtrlTab(void)276 HWND getTabCtrlTab(void)
277 {
278   return TabCtrl_1.hTab;
279 }
280 
281 
getTabCtrlTabPages(unsigned int framenum)282 HWND getTabCtrlTabPages(unsigned int framenum)
283 {
284   return TabCtrl_1.hTabPages[framenum];
285 }
286 
287 
getBoolFieldDataTab(unsigned int framenum,int idc)288 my_bool getBoolFieldDataTab(unsigned int framenum, int idc)
289 {
290   assert(TabCtrl_1.hTabPages);
291   HWND checkbox = GetDlgItem(TabCtrl_1.hTabPages[framenum-1], idc);
292 
293   assert(checkbox);
294   if (checkbox)
295       return !!Button_GetCheck(checkbox);
296 
297   return false;
298 }
299 
300 
301 /* this reads non-DSN bool data */
getBoolFieldData(HWND hwnd,int idc)302 my_bool getBoolFieldData(HWND hwnd, int idc)
303 {
304   HWND checkbox = GetDlgItem(hwnd, idc);
305 
306   assert(checkbox);
307   if (checkbox)
308       return !!Button_GetCheck(checkbox);
309 
310   return false;
311 }
312 
313 
setBoolFieldData(HWND hwnd,int idc,my_bool state)314 void setBoolFieldData(HWND hwnd, int idc, my_bool state)
315 {
316   HWND checkbox = GetDlgItem(hwnd, idc);
317   assert(checkbox);
318   if (checkbox)
319   Button_SetCheck(checkbox, state);
320 }
321 
322 
setBoolFieldDataTab(unsigned int framenum,int idc,my_bool state)323 void setBoolFieldDataTab(unsigned int framenum, int idc, my_bool state)
324 {
325   assert(TabCtrl_1.hTabPages);
326   Button_SetCheck(GetDlgItem(TabCtrl_1.hTabPages[framenum-1],idc), state);
327 
328 }
329 
330 
setControlEnabled(unsigned int framenum,int idc,my_bool state)331 void setControlEnabled(unsigned int framenum, int idc, my_bool state)
332 {
333   HWND cursorTab= TabCtrl_1.hTabPages[framenum-1];
334   assert(cursorTab);
335 
336   if (cursorTab)
337   {
338     EnableWindow(GetDlgItem(cursorTab, idc), state);
339   }
340 }
341 
342 
343 void OnDialogClose();
344 
345 
FormMain_OnClose(HWND hwnd)346 void FormMain_OnClose(HWND hwnd)
347 {
348 	//PostQuitMessage(0);// turn off message loop
349     //Unhooks hook(s) :)
350   OnDialogClose();
351 
352 	TabControl_Destroy(&TabCtrl_1);
353   EndDialog(hwnd, NULL);
354 }
355 
356 
357 /****************************************************************************
358  *                                                                          *
359  * Functions: FormMain_OnCommand related event code                         *
360  *                                                                          *
361  * Purpose : Handle WM_COMMAND messages: this is the heart of the app.		*
362  *                                                                          *
363  * History : Date      Reason                                               *
364  *           00/00/00  Created                                              *
365  *                                                                          *
366  ****************************************************************************/
btnDetails_Click(HWND hwnd)367 void btnDetails_Click (HWND hwnd)
368 {
369 	RECT rect;
370 	GetWindowRect( hwnd, &rect );
371 	mod *= -1;
372 	ShowWindow( GetDlgItem(hwnd,IDC_TAB1), mod > 0? SW_SHOW: SW_HIDE );
373 
374 	if(!flag && mod==1)
375 	{
376     static PWSTR tabnames[]= {L"Connection", L"Metadata", L"Cursors/Results", L"Debug", L"SSL", L"Misc", 0};
377 		static PWSTR dlgnames[]= {MAKEINTRESOURCE(IDD_TAB1),
378 							  	  MAKEINTRESOURCE(IDD_TAB2),
379 							  	  MAKEINTRESOURCE(IDD_TAB3),
380 							  	  MAKEINTRESOURCE(IDD_TAB4),
381 								    MAKEINTRESOURCE(IDD_TAB5),
382                     MAKEINTRESOURCE(IDD_TAB6),0};
383 
384 		New_TabControl( &TabCtrl_1,                 // address of TabControl struct
385 					          GetDlgItem(hwnd, IDC_TAB1), // handle to tab control
386 					          tabnames,                   // text for each tab
387 					          dlgnames,                   // dialog id's of each tab page dialog
388 					          &FormMain_DlgProc,          // address of main windows proc
389 					          NULL,                       // address of size function
390 					          TRUE);                      // stretch tab page to fit tab ctrl
391 		flag = true;
392 
393 
394     HWND ssl_tab = TabCtrl_1.hTabPages[4];
395     HWND combo = GetDlgItem(ssl_tab, IDC_EDIT_sslmode);
396 
397     ComboBox_ResetContent(combo);
398 
399     ComboBox_AddString(combo, L"");
400     ComboBox_AddString(combo, LSTR(ODBC_SSL_MODE_DISABLED));
401     ComboBox_AddString(combo, LSTR(ODBC_SSL_MODE_PREFERRED));
402     ComboBox_AddString(combo, LSTR(ODBC_SSL_MODE_REQUIRED));
403     ComboBox_AddString(combo, LSTR(ODBC_SSL_MODE_VERIFY_CA));
404     ComboBox_AddString(combo, LSTR(ODBC_SSL_MODE_VERIFY_IDENTITY));
405 
406     syncTabs(hwnd, pParams);
407 	}
408 	MoveWindow( hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 310*mod, TRUE );
409 }
410 
411 
btnOk_Click(HWND hwnd)412 void btnOk_Click (HWND hwnd)
413 {
414   FillParameters(hwnd, pParams);
415 
416   /* if DS params are valid, close dialog */
417   if (mytestaccept(hwnd, pParams))
418   {
419     OkPressed= 1;
420     PostMessage(hwnd, WM_CLOSE, NULL, NULL);
421   }
422 }
423 
424 
btnCancel_Click(HWND hwnd)425 void btnCancel_Click (HWND hwnd)
426 {
427   PostMessage(hwnd, WM_CLOSE, NULL, NULL);
428 }
429 
430 
btnTest_Click(HWND hwnd)431 void btnTest_Click (HWND hwnd)
432 {
433   FillParameters(hwnd, pParams);
434   wchar_t *testResultMsg= mytest(hwnd, pParams);
435   MessageBoxW(hwnd, testResultMsg, L"Test Result", MB_OK);
436   x_free(testResultMsg);
437 }
438 
439 
btnHelp_Click(HWND hwnd)440 void btnHelp_Click (HWND hwnd)
441 {
442   ShellExecute(NULL, L"open",
443 	       L"http://dev.mysql.com/doc/refman/5.1/en/connector-odbc-configuration-dsn-windows.html",
444 	       NULL, NULL, SW_SHOWNORMAL);
445 }
446 
447 
chooseFile(HWND parent,int hostCtlId)448 void chooseFile( HWND parent, int hostCtlId )
449 {
450 	OPENFILENAMEW	dialog;
451 
452 	HWND			hostControl = GetDlgItem( parent, hostCtlId );
453 
454 	wchar_t			szFile[MAX_PATH];    // buffer for file name
455 
456 	Edit_GetText( hostControl, szFile, sizeof(szFile) );
457 	// Initialize OPENFILENAME
458 	ZeroMemory(&dialog, sizeof(dialog));
459 
460 	dialog.lStructSize			= sizeof(dialog);
461 	dialog.lpstrFile			= szFile;
462 
463 	dialog.lpstrTitle			= L"Select File";
464 	dialog.nMaxFile				= sizeof(szFile);
465 	dialog.lpstrFileTitle		= NULL;
466 	dialog.nMaxFileTitle		= 0;
467 	dialog.lpstrInitialDir		= NULL;
468 	dialog.Flags				= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST ;
469 	dialog.hwndOwner			= parent;
470 	dialog.lpstrCustomFilter	= L"All Files\0*.*\0PEM\0*.pem\0";
471 	dialog.nFilterIndex			= 2;
472 
473 	if ( GetOpenFileNameW( &dialog ) )
474 	{
475 		Edit_SetText( hostControl, dialog.lpstrFile );
476 	}
477 }
478 
479 
choosePath(HWND parent,int hostCtlId)480 void choosePath( HWND parent, int hostCtlId )
481 {
482 	HWND			hostControl = GetDlgItem( parent, hostCtlId );
483 
484 	BROWSEINFOW		dialog;
485 	wchar_t			path[MAX_PATH];    // buffer for file name
486 
487 	Edit_GetText( hostControl, path, sizeof(path) );
488 
489 	ZeroMemory(&dialog,sizeof(dialog));
490 
491 	dialog.lpszTitle		= L"Pick a CA Path";
492 	dialog.hwndOwner		= parent;
493 	dialog.pszDisplayName	= path;
494 
495 	LPITEMIDLIST pidl = SHBrowseForFolder ( &dialog );
496 
497 	if ( pidl )
498 	{
499 		SHGetPathFromIDList ( pidl, path );
500 
501 		Edit_SetText( hostControl, path );
502 
503 		IMalloc * imalloc = 0;
504 		if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
505 		{
506 			imalloc->Free ( pidl );
507 			imalloc->Release ( );
508 		}
509 	}
510 }
511 
512 #ifndef MAX_VISIBLE_CB_ITEMS
513 #define MAX_VISIBLE_CB_ITEMS 20
514 #endif
515 
516 
517 /**
518    Adjusting height of dropped list of cbHwnd combobox to fit
519    itemsCount items, but not more than MAX_VISIBLE_CB_ITEMS
520    ComboBox_SetMinVisible not used because it was introduced in XP.
521 */
adjustDropdownHeight(HWND cbHwnd,unsigned int itemsCount)522 int adjustDropdownHeight(HWND cbHwnd, unsigned int itemsCount)
523 {
524   COMBOBOXINFO  dbcbinfo;
525   RECT          ddRect;
526   int           newHeight = 0;
527 
528   dbcbinfo.cbSize= sizeof(COMBOBOXINFO);
529   ComboBox_GetDroppedControlRect(cbHwnd, &ddRect);
530   newHeight= ddRect.bottom - ddRect.top;
531 
532   if ( GetComboBoxInfo(cbHwnd, &dbcbinfo) )
533   {
534     itemsCount= itemsCount < 1 ? 1 : (itemsCount > MAX_VISIBLE_CB_ITEMS
535                                       ? MAX_VISIBLE_CB_ITEMS
536                                       : itemsCount );
537 
538     /* + (itemsCount - 1) - 1 pixel spaces between list items */
539     newHeight= itemsCount*ComboBox_GetItemHeight(cbHwnd) + (itemsCount - 1);
540     MoveWindow(dbcbinfo.hwndList, ddRect.left, ddRect.top, ddRect.right-ddRect.left, newHeight, FALSE);
541   }
542 
543   return newHeight;
544 }
545 
546 
547 /**
548    Processing commands for dbname combobox (hwndCtl).
549 */
processDbCombobox(HWND hwnd,HWND hwndCtl,UINT codeNotify)550 void processDbCombobox(HWND hwnd, HWND hwndCtl, UINT codeNotify)
551 {
552   switch(codeNotify)
553   {
554     /* Loading list and adjust its height if button clicked and on user input */
555     case(CBN_DROPDOWN):
556     {
557       FillParameters(hwnd, pParams);
558       LIST *dbs= mygetdatabases(hwnd, pParams);
559       LIST *dbtmp= dbs;
560 
561       ComboBox_ResetContent(hwndCtl);
562 
563       adjustDropdownHeight(hwndCtl,list_length(dbs));
564 
565       for (; dbtmp; dbtmp= list_rest(dbtmp))
566         ComboBox_AddString(hwndCtl, (SQLWCHAR *)dbtmp->data);
567 
568       list_free(dbs, 1);
569 
570       ComboBox_SetText(hwndCtl,pParams->database);
571 
572       break;
573     }
574   }
575 }
576 
577 
578 /**
579 Processing commands for charset combobox (hwndCtl).
580 */
processCharsetCombobox(HWND hwnd,HWND hwndCtl,UINT codeNotify)581 void processCharsetCombobox(HWND hwnd, HWND hwndCtl, UINT codeNotify)
582 {
583   switch(codeNotify)
584   {
585     /* Loading list and adjust its height if button clicked and on user input */
586     case(CBN_DROPDOWN):
587     {
588       //FillParameters(hwnd, *pParams);
589       LIST *csl= mygetcharsets(hwnd, pParams);
590       LIST *cstmp= csl;
591 
592       ComboBox_ResetContent(hwndCtl);
593 
594       adjustDropdownHeight(hwndCtl,list_length(csl));
595 
596       for (; cstmp; cstmp= list_rest(cstmp))
597       ComboBox_AddString(hwndCtl, (SQLWCHAR *)cstmp->data);
598 
599       list_free(csl, 1);
600 
601       ComboBox_SetText(hwndCtl,pParams->charset);
602 
603       break;
604     }
605   }
606 }
607 
608 
FormMain_OnCommand(HWND hwnd,int id,HWND hwndCtl,UINT codeNotify)609 void FormMain_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
610 {
611   if (controlWithDefValue != 0 && id == controlWithDefValue
612     && codeNotify==EN_CHANGE)
613     controlWithDefValue= 0;
614 
615   switch (id)
616   {
617     case IDOK:
618       btnOk_Click(hwnd); break;
619     case IDCANCEL:
620       btnCancel_Click(hwnd); break;
621     case IDC_BUTTON_DETAILS:
622       btnDetails_Click(hwnd); break;
623     case IDC_BUTTON_HELP:
624       btnHelp_Click(hwnd); break;
625     case IDC_BUTTON_TEST:
626       btnTest_Click(hwnd); break;
627     case IDC_SSLKEYCHOOSER:
628       chooseFile(hwnd, IDC_EDIT_sslkey); break;
629     case IDC_SSLCERTCHOOSER:
630       chooseFile(hwnd, IDC_EDIT_sslcert); break;
631     case IDC_SSLCACHOOSER:
632       chooseFile(hwnd, IDC_EDIT_sslca); break;
633     case IDC_SSLCAPATHCHOOSER:
634       choosePath(hwnd, IDC_EDIT_sslcapath); break;
635     case IDC_RSAKEYCHOOSER:
636       chooseFile(hwnd, IDC_EDIT_rsakey); break;
637     case IDC_CHOOSER_plugin_dir:
638       choosePath(hwnd, IDC_EDIT_plugin_dir); break;
639     case IDC_RADIO_tcp:
640     case IDC_RADIO_pipe:
641       SwitchTcpOrPipe(hwnd, !!Button_GetCheck(GetDlgItem(hwnd, IDC_RADIO_pipe)));
642       break;
643     case IDC_CHECK_cursor_prefetch_active:
644       {
645         HWND cursorTab= TabCtrl_1.hTabPages[CURSORS_TAB-1];
646         assert(cursorTab);
647         HWND prefetch= GetDlgItem(cursorTab, IDC_EDIT_cursor_prefetch_number);
648         assert(prefetch);
649 
650         EnableWindow(prefetch, !!Button_GetCheck(GetDlgItem(cursorTab,
651                                             IDC_CHECK_cursor_prefetch_active)));
652 
653         if (Edit_GetTextLength(prefetch) == 0)
654         {
655           setUnsignedFieldData(cursorTab, default_cursor_prefetch,
656                               IDC_EDIT_cursor_prefetch_number);
657         }
658       }
659       break;
660     case IDC_EDIT_name:
661     {
662       if (codeNotify==EN_CHANGE)
663       {
664         int len = Edit_GetTextLength(GetDlgItem(hwnd,IDC_EDIT_name));
665         Button_Enable(GetDlgItem(hwnd,IDOK), len > 0);
666         Button_Enable(GetDlgItem(hwnd,IDC_BUTTON_TEST), len > 0);
667         RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE);
668       }
669       break;
670     }
671 
672     case IDC_EDIT_dbname:
673       processDbCombobox(hwnd, hwndCtl, codeNotify);
674     break;
675 
676     case IDC_EDIT_charset:
677       processCharsetCombobox(hwnd, hwndCtl, codeNotify);
678 	}
679 
680 	return;
681 }
682 
683 
684 void AlignWindowToBottom(HWND hwnd, int dY);
685 void AdjustLayout(HWND hwnd);
686 
687 
FormMain_OnSize(HWND hwnd,UINT state,int cx,int cy)688 void FormMain_OnSize(HWND hwnd, UINT state, int cx, int cy)
689 {
690 	AdjustLayout(hwnd);
691 }
692 
693 static int yCurrentScroll = 0;   // current vertical scroll value
694 
FormMain_OnScroll(HWND hwnd,HWND hCtrl,UINT code,int pos)695 void FormMain_OnScroll(HWND hwnd, HWND hCtrl, UINT code, int pos)
696 {
697   SCROLLINFO si;
698   si.cbSize = sizeof(si);
699   si.fMask = SIF_POS;
700   int yNewPos;    // new position
701   switch (code)
702   {
703       // User clicked the scroll bar shaft above the scroll box.
704     case SB_PAGEUP:
705       yNewPos = yCurrentScroll - 50;
706       break;
707 
708       // User clicked the scroll bar shaft below the scroll box.
709     case SB_PAGEDOWN:
710       yNewPos = yCurrentScroll + 50;
711       break;
712 
713       // User clicked the top arrow.
714     case SB_LINEUP:
715       yNewPos = yCurrentScroll - 5;
716       break;
717 
718       // User clicked the bottom arrow.
719     case SB_LINEDOWN:
720       yNewPos = yCurrentScroll + 5;
721       break;
722 
723       // User dragged the scroll box.
724     case SB_THUMBPOSITION:
725       yNewPos = pos;
726       break;
727 
728     default:
729       yNewPos = yCurrentScroll;
730   }
731 
732   si.nPos = yNewPos;
733 
734   ScrollWindowEx(hwnd, 0, -50,
735     NULL, NULL, NULL, NULL, SW_INVALIDATE);
736   UpdateWindow(hwnd);
737 
738   SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
739   yCurrentScroll = yNewPos;
740 }
741 
AdjustLayout(HWND hwnd)742 void AdjustLayout(HWND hwnd)
743 {
744 	RECT  rc;
745    	GetClientRect(hwnd,&rc);
746 
747 	BOOL Visible = (mod==-1)?0:1;
748 
749 	if(TabCtrl_1.hTab)
750 	{
751 		EnableWindow( TabCtrl_1.hTab, Visible );
752 		ShowWindow( TabCtrl_1.hTab, Visible );
753 	}
754 
755 	PWSTR pButtonCaption = Visible? L"Details <<" : L"Details >>";
756 	SetWindowText( GetDlgItem(hwnd,IDC_BUTTON_DETAILS), pButtonCaption );
757 	const int dY = 20;
758 	AlignWindowToBottom( GetDlgItem(hwnd,IDC_BUTTON_DETAILS), dY);
759 	AlignWindowToBottom( GetDlgItem(hwnd,IDOK), dY);
760 	AlignWindowToBottom( GetDlgItem(hwnd,IDCANCEL), dY);
761 	AlignWindowToBottom( GetDlgItem(hwnd,IDC_BUTTON_HELP), dY);
762 
763 	Refresh(hwnd);
764 }
765 
766 
AlignWindowToBottom(HWND hwnd,int dY)767 void AlignWindowToBottom(HWND hwnd, int dY)
768 {
769 	if(!hwnd)
770 		return;
771 	RECT rect;
772 	GetWindowRect( hwnd, &rect );
773 	int h, w;
774 	RECT rc;
775 	GetWindowRect(GetParent(hwnd), &rc);
776 
777 	h=rect.bottom-rect.top;
778 	w=rect.right-rect.left;
779 
780 	rc.top = rc.bottom;
781 	MapWindowPoints(HWND_DESKTOP, GetParent(hwnd), (LPPOINT)&rect, 2);
782 	MapWindowPoints(HWND_DESKTOP, GetParent(hwnd), (LPPOINT)&rc, 2);
783 
784 	MoveWindow(hwnd, rect.left, rc.top -dY-h,w,h,FALSE);
785 }
786 
787 
788 HWND g_hwndDlg;
789 BOOL DoCreateDialogTooltip(void);
790 
791 
FormMain_OnInitDialog(HWND hwnd,HWND hwndFocus,LPARAM lParam)792 BOOL FormMain_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
793 {
794 	g_hwndDlg = hwnd;
795 	SetWindowText(hwnd, pCaption);
796 	//----Everything else must follow the above----//
797 	btnDetails_Click(hwnd);
798 	AdjustLayout(hwnd);
799 	//Get the initial Width and height of the dialog
800 	//in order to fix the minimum size of dialog
801 
802 	syncForm(hwnd, pParams);
803 
804   /* Disable fields if in prompt mode */
805   if (g_isPrompt)
806   {
807     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_name), FALSE);
808     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_description), FALSE);
809   }
810 
811   /* if prompting without DSN, don't disable OK button */
812   /* preserved here old logic + enabled OK if data source
813      name is not NULL when not prompting. I don't know why it should be disabled
814      when prompting and name is not NULL. */
815   if (g_isPrompt == (pParams->name==NULL))
816   {
817     Button_Enable(GetDlgItem(hwnd,IDOK), 1);
818     Button_Enable(GetDlgItem(hwnd,IDC_BUTTON_TEST), 1);
819     RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE);
820   }
821 
822 	BOOL b = DoCreateDialogTooltip();
823 	return 0;
824 }
825 
826 
FormMain_DlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)827 BOOL FormMain_DlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
828 {
829 	switch(msg)
830 	{
831 		HANDLE_MSG (hwndDlg, WM_CLOSE, FormMain_OnClose);
832 		HANDLE_MSG (hwndDlg, WM_COMMAND, FormMain_OnCommand);
833 		HANDLE_MSG (hwndDlg, WM_INITDIALOG, FormMain_OnInitDialog);
834 		HANDLE_MSG (hwndDlg, WM_SIZE, FormMain_OnSize);
835     HANDLE_MSG (hwndDlg, WM_VSCROLL, FormMain_OnScroll);
836 	// There is no message cracker for WM_NOTIFY so redirect manually
837 	case WM_NOTIFY:
838 		return FormMain_OnNotify (hwndDlg,wParam,lParam);
839 
840 	default: return FALSE;
841 	}
842 }
843 
844 
845 /*
846    Display the DSN dialog
847 
848    @param params DataSource struct, should be pre-populated
849    @param ParentWnd Parent window handle
850    @return 1 if the params were correctly populated and OK was pressed
851            0 if the dialog was closed or cancelled
852 */
853 extern "C"
ShowOdbcParamsDialog(DataSource * params,HWND ParentWnd,BOOL isPrompt)854 int ShowOdbcParamsDialog(DataSource* params, HWND ParentWnd, BOOL isPrompt)
855 {
856 	assert(!BusyIndicator);
857 	InitStaticValues();
858 
859 	pParams= params;
860 	pCaption= L"MySQL Connector/ODBC Data Source Configuration";
861   g_isPrompt= isPrompt;
862 
863   /*
864      If prompting (with a DSN name), or not prompting (add/edit DSN),
865      we translate the lib path to the actual driver name.
866   */
867   if (params->name || !isPrompt)
868   {
869     Driver *driver= driver_new();
870     params->driver && memcpy(driver->lib, params->driver,
871            (sqlwcharlen(params->driver) + 1) * sizeof(SQLWCHAR));
872     /* TODO Driver lookup is done in driver too, do we really need it there? */
873     if (!*driver->lib || driver_lookup_name(driver))
874     {
875       wchar_t msg[256];
876       swprintf(msg, 256, L"Failure to lookup driver entry at path '%ls'",
877                driver->lib);
878       MessageBox(ParentWnd, msg, L"Cannot find driver entry", MB_OK);
879       driver_delete(driver);
880       return 0;
881     }
882     ds_set_strattr(&params->driver, driver->name);
883     driver_delete(driver);
884   }
885   DialogBox(ghInstance, MAKEINTRESOURCE(IDD_DIALOG1), ParentWnd,
886             (DLGPROC)FormMain_DlgProc);
887 
888 	BusyIndicator= false;
889 	return OkPressed;
890 }
891