1/* 2 * drvconn.c 3 * 4 * $Id: drvconn.c,v 1.11 2006/07/10 13:46:56 source Exp $ 5 * 6 * The data_sources dialog for SQLDriverConnect 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com> 11 * All Rights Reserved. 12 * 13 * This software is released under the terms of either of the following 14 * licenses: 15 * 16 * - GNU Library General Public License (see LICENSE.LGPL) 17 * - The BSD License (see LICENSE.BSD). 18 * 19 * Note that the only valid version of the LGPL license as far as this 20 * project is concerned is the original GNU Library General Public License 21 * Version 2, dated June 1991. 22 * 23 * While not mandated by the BSD license, any patches you make to the 24 * iODBC source code may be contributed back into the iODBC project 25 * at your discretion. Contributions will benefit the Open Source and 26 * Data Access community as a whole. Submissions may be made at: 27 * 28 * http://www.iodbc.org 29 * 30 * 31 * GNU Library Generic Public License Version 2 32 * ============================================ 33 * This library is free software; you can redistribute it and/or 34 * modify it under the terms of the GNU Library General Public 35 * License as published by the Free Software Foundation; only 36 * Version 2 of the License dated June 1991. 37 * 38 * This library is distributed in the hope that it will be useful, 39 * but WITHOUT ANY WARRANTY; without even the implied warranty of 40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 * Library General Public License for more details. 42 * 43 * You should have received a copy of the GNU Library General Public 44 * License along with this library; if not, write to the Free 45 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 46 * 47 * 48 * The BSD License 49 * =============== 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in 58 * the documentation and/or other materials provided with the 59 * distribution. 60 * 3. Neither the name of OpenLink Software Inc. nor the names of its 61 * contributors may be used to endorse or promote products derived 62 * from this software without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 65 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 66 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 67 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR 68 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 69 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 70 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 71 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 72 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 73 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 74 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 */ 76 77 78#include "gui.h" 79 80#include <herr.h> 81#include <unicode.h> 82#include <dlproc.h> 83 84#ifndef WIN32 85#include <unistd.h> 86 87typedef SQLRETURN SQL_API (*pDriverConnFunc) (HWND hwnd, LPSTR szInOutConnStr, 88 DWORD cbInOutConnStr, int FAR * sqlStat, SQLUSMALLINT fDriverCompletion, UWORD *config); 89typedef SQLRETURN SQL_API (*pDriverConnWFunc) (HWND hwnd, LPWSTR szInOutConnStr, 90 DWORD cbInOutConnStr, int FAR * sqlStat, SQLUSMALLINT fDriverCompletion, UWORD *config); 91 92#define CALL_DRVCONN_DIALBOXW(path, a) \ 93 { \ 94 char *_path_u8 = (a == 'A') ? NULL : dm_SQL_W2A ((wchar_t*)path, SQL_NTS); \ 95 if ((handle = DLL_OPEN((a == 'A') ? (char*)path : _path_u8)) != NULL) \ 96 { \ 97 if ((pDrvConnW = (pDriverConnWFunc)DLL_PROC(handle, "_iodbcdm_drvconn_dialboxw")) != NULL) \ 98 { \ 99 SQLSetConfigMode (*config); \ 100 if (pDrvConnW (hwnd, szInOutConnStr, cbInOutConnStr, sqlStat, fDriverCompletion, config) == SQL_SUCCESS) \ 101 { \ 102 MEM_FREE (_path_u8); \ 103 DLL_CLOSE(handle); \ 104 retcode = SQL_SUCCESS; \ 105 goto quit; \ 106 } \ 107 else \ 108 { \ 109 MEM_FREE (_path_u8); \ 110 DLL_CLOSE(handle); \ 111 retcode = SQL_NO_DATA_FOUND; \ 112 goto quit; \ 113 } \ 114 } \ 115 else \ 116 { \ 117 if ((pDrvConn = (pDriverConnFunc)DLL_PROC(handle, "_iodbcdm_drvconn_dialbox")) != NULL) \ 118 { \ 119 char *_szinoutconstr_u8 = malloc (cbInOutConnStr + 1); \ 120 wchar_t *_prvw; char *_prvu8; \ 121 for (_prvw = szInOutConnStr, _prvu8 = _szinoutconstr_u8 ; \ 122 *_prvw != L'\0' ; _prvw += WCSLEN (_prvw) + 1, \ 123 _prvu8 += STRLEN (_prvu8) + 1) \ 124 dm_StrCopyOut2_W2A (_prvw, _prvu8, cbInOutConnStr, NULL); \ 125 *_prvu8 = '\0'; \ 126 SQLSetConfigMode (*config); \ 127 if (pDrvConn (hwnd, _szinoutconstr_u8, cbInOutConnStr, sqlStat, fDriverCompletion, config) == SQL_SUCCESS) \ 128 { \ 129 dm_StrCopyOut2_A2W (_szinoutconstr_u8, szInOutConnStr, cbInOutConnStr, NULL); \ 130 MEM_FREE (_path_u8); \ 131 MEM_FREE (_szinoutconstr_u8); \ 132 DLL_CLOSE(handle); \ 133 retcode = SQL_SUCCESS; \ 134 goto quit; \ 135 } \ 136 else \ 137 { \ 138 MEM_FREE (_path_u8); \ 139 MEM_FREE (_szinoutconstr_u8); \ 140 DLL_CLOSE(handle); \ 141 retcode = SQL_NO_DATA_FOUND; \ 142 goto quit; \ 143 } \ 144 } \ 145 } \ 146 DLL_CLOSE(handle); \ 147 } \ 148 MEM_FREE (_path_u8); \ 149 } 150#endif 151 152SQLRETURN SQL_API 153iodbcdm_drvconn_dialbox ( 154 HWND hwnd, 155 LPSTR szInOutConnStr, 156 DWORD cbInOutConnStr, 157 int * sqlStat, 158 SQLUSMALLINT fDriverCompletion, 159 UWORD *config) 160{ 161 RETCODE retcode = SQL_ERROR; 162 wchar_t *_string_w = NULL; 163 164 if (cbInOutConnStr > 0) 165 { 166 if ((_string_w = malloc (cbInOutConnStr * sizeof(wchar_t) + 1)) == NULL) 167 goto done; 168 } 169 170 dm_StrCopyOut2_A2W (szInOutConnStr, _string_w, 171 cbInOutConnStr * sizeof(wchar_t), NULL); 172 173 retcode = iodbcdm_drvconn_dialboxw (hwnd, _string_w, 174 cbInOutConnStr, sqlStat, fDriverCompletion, config); 175 176 if (retcode == SQL_SUCCESS) 177 { 178 dm_StrCopyOut2_W2A (_string_w, szInOutConnStr, cbInOutConnStr - 1, NULL); 179 } 180 181done: 182 MEM_FREE (_string_w); 183 184 return retcode; 185} 186 187 188SQLRETURN SQL_API 189iodbcdm_drvconn_dialboxw ( 190 HWND hwnd, 191 LPWSTR szInOutConnStr, 192 DWORD cbInOutConnStr, 193 int * sqlStat, 194 SQLUSMALLINT fDriverCompletion, 195 UWORD *config) 196{ 197 RETCODE retcode = SQL_ERROR; 198 TDSNCHOOSER choose_t; 199 wchar_t *string = NULL, *prov, *prov1, *szDSN = NULL, *szDriver = NULL; 200 wchar_t *szFILEDSN = NULL, *szSAVEFILE = NULL; 201 wchar_t tokenstr[4096]; 202 wchar_t drvbuf[4096] = { L'\0'}; 203 char *_szdriver_u8 = NULL; 204 wchar_t *_szdriver_w = NULL; 205 HDLL handle; 206 pDriverConnFunc pDrvConn; 207 pDriverConnWFunc pDrvConnW; 208 int i, skip; 209#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 210 CFStringRef libname = NULL; 211 CFBundleRef bundle = NULL; 212 CFURLRef liburl = NULL; 213 char name[1024] = { '\0' }; 214#endif 215 216 /* Check input parameters */ 217 if (!szInOutConnStr || cbInOutConnStr < 1) 218 goto quit; 219 220 /* Transform the string connection to list of key pairs */ 221 string = (wchar_t*) malloc((cbInOutConnStr + 1) * sizeof(wchar_t)); 222 if (string == NULL) 223 { 224 if (sqlStat) 225#if (ODBCVER>=0x3000) 226 *sqlStat = en_HY092; 227#else 228 *sqlStat = en_S1000; 229#endif 230 retcode = SQL_ERROR; 231 goto quit; 232 } 233 234 /* Conversion to the list of key pairs */ 235 wcsncpy (string, szInOutConnStr, cbInOutConnStr); 236 string[WCSLEN (string) + 1] = L'\0'; 237 skip = 0; 238 for (i = WCSLEN (string) - 1 ; i >= 0 ; i--) 239 { 240 if (string[i] == L'}') 241 skip = 1; 242 else if (string[i] == L'{') 243 skip = 0; 244 else if (skip == 0 && string[i] == L';') string[i] = L'\0'; 245 } 246 247 /* Look for the DSN and DRIVER keyword */ 248 for (prov = string ; *prov != L'\0' ; prov += WCSLEN (prov) + 1) 249 { 250 if (!wcsncasecmp (prov, L"DSN=", WCSLEN (L"DSN="))) 251 { 252 szDSN = prov + WCSLEN (L"DSN="); 253 continue; 254 } 255 if (!wcsncasecmp (prov, L"DRIVER=", WCSLEN (L"DRIVER="))) 256 { 257 szDriver = prov + WCSLEN (L"DRIVER="); 258 continue; 259 } 260 if (!wcsncasecmp (prov, L"FILEDSN=", WCSLEN (L"FILEDSN="))) 261 { 262 szFILEDSN = prov + WCSLEN (L"FILEDSN="); 263 continue; 264 } 265 if (!wcsncasecmp (prov, L"SAVEFILE=", WCSLEN (L"SAVEFILE="))) 266 { 267 szSAVEFILE = prov + WCSLEN (L"SAVEFILE="); 268 continue; 269 } 270 } 271 272 if (!szDSN && !szDriver) 273 { 274 /* Display the DSN chooser dialog box */ 275 create_dsnchooser (hwnd, &choose_t); 276 277 /* Check output parameters */ 278 if (choose_t.dsn || choose_t.fdsn) 279 { 280#if (ODBCVER>=0x3000) 281 int errSqlStat = en_HY092; 282#else 283 int errSqlStat = en_HY092; 284#endif 285 /* Change the config mode */ 286 switch (choose_t.type_dsn) 287 { 288 case USER_DSN: 289 *config = ODBC_USER_DSN; 290 break; 291 case SYSTEM_DSN: 292 *config = ODBC_SYSTEM_DSN; 293 break; 294 }; 295 296 if (choose_t.dsn && (choose_t.type_dsn == USER_DSN || choose_t.type_dsn == SYSTEM_DSN)) 297 { 298 /* Try to copy the DSN */ 299 if (cbInOutConnStr > WCSLEN (choose_t.dsn) + WCSLEN (L"DSN=") + 2) 300 { 301 WCSCPY (string, L"DSN="); 302 WCSCAT (string, choose_t.dsn); 303 string[WCSLEN (string) + 1] = L'\0'; 304 szDSN = string + WCSLEN (L"DSN="); 305 retcode = SQL_SUCCESS; 306 } 307 else 308 { 309 if (sqlStat) 310 *sqlStat = errSqlStat; 311 } 312 } 313 else if (choose_t.fdsn && choose_t.type_dsn == FILE_DSN) 314 { 315 DWORD sz, sz_entry; 316 wchar_t entries[4096]; 317 WORD read_len; 318 wchar_t *p, *p_next; 319 320 sz = WCSLEN(choose_t.fdsn) + WCSLEN(L"FILEDSN=") + 2; 321 if (cbInOutConnStr > sz) 322 { 323 WCSCPY (string, L"FILEDSN="); 324 WCSCAT (string, choose_t.fdsn); 325 WCSCAT (string, L";"); 326 retcode = SQL_SUCCESS; 327 } 328 329 /* Get list of entries in .dsn file */ 330 if (retcode == SQL_SUCCESS 331 && SQLReadFileDSNW (choose_t.fdsn, L"ODBC", NULL, 332 entries, sizeof (entries)/sizeof(wchar_t), &read_len)) 333 { 334 /* add params from the .dsn file */ 335 for (p = entries; *p != '\0'; p = p_next) 336 { 337 wchar_t value[1024]; 338 339 /* get next entry */ 340 p_next = wcschr (p, L';'); 341 if (p_next) 342 *p_next++ = L'\0'; 343 344 if (!SQLReadFileDSNW (choose_t.fdsn, L"ODBC", p, value, 345 sizeof(value)/sizeof(wchar_t), &read_len)) 346 { 347 retcode = SQL_ERROR; 348 break; 349 } 350 351 if (!wcsncasecmp (p, L"DRIVER", WCSLEN(L"DRIVER"))) 352 { 353 szDriver = _szdriver_w = (wchar_t*) malloc((WCSLEN(value) + 1) * sizeof(wchar_t)); 354 if (szDriver) 355 WCSCPY(szDriver, value); 356 } 357 358 sz_entry = WCSLEN(p) + 1 + WCSLEN(value) + 2; 359 if (cbInOutConnStr > sz + sz_entry) 360 { 361 WCSCAT (string, p); 362 WCSCAT (string, L"="); 363 WCSCAT (string, value); 364 WCSCAT (string, L";"); 365 sz += sz_entry; 366 } 367 else 368 { 369 retcode = SQL_ERROR; 370 } 371 } 372 } 373 if (retcode == SQL_SUCCESS) 374 { 375 string[WCSLEN (string) + 1] = L'\0'; 376 for (i = WCSLEN (string) - 1 ; i >= 0 ; i--) 377 if (string[i] == L';') string[i] = L'\0'; 378 } 379 else if (sqlStat) 380 *sqlStat = errSqlStat; 381 } 382 else 383 { 384 if (sqlStat) 385 *sqlStat = errSqlStat; 386 } 387 } 388 else 389 retcode = SQL_NO_DATA_FOUND; 390 391 if (choose_t.dsn) 392 free (choose_t.dsn); 393 if (choose_t.fdsn) 394 free (choose_t.fdsn); 395 396 if (retcode != SQL_SUCCESS) 397 goto quit; 398 } 399 400 401 /* Constitute the string connection */ 402 for (prov = szInOutConnStr, prov1 = string, i = 0 ; *prov1 != L'\0' ; 403 prov1 += WCSLEN (prov) + 1, i += WCSLEN (prov) + 1, prov += WCSLEN (prov) + 1) 404 WCSCPY (prov, prov1); 405 *prov = L'\0'; 406 407 /* Check if the driver is provided */ 408 if (szDriver == NULL) 409 { 410 SQLSetConfigMode (ODBC_BOTH_DSN); 411 SQLGetPrivateProfileStringW (L"ODBC Data Sources", 412 szDSN && szDSN[0] != L'\0' ? szDSN : L"default", 413 L"", tokenstr, sizeof (tokenstr)/sizeof(wchar_t), NULL); 414 szDriver = tokenstr; 415 } 416 417 /* Call the iodbcdm_drvconn_dialbox */ 418 _szdriver_u8 = dm_SQL_W2A (szDriver, SQL_NTS); 419 420 SQLSetConfigMode (ODBC_USER_DSN); 421 if (!access (_szdriver_u8, X_OK)) 422 { CALL_DRVCONN_DIALBOXW (_szdriver_u8, 'A'); } 423 if (SQLGetPrivateProfileStringW (szDriver, L"Driver", L"", drvbuf, 424 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 425 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 426 if (SQLGetPrivateProfileStringW (szDriver, L"Setup", L"", drvbuf, 427 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 428 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 429 if (SQLGetPrivateProfileStringW (L"Default", L"Driver", L"", drvbuf, 430 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 431 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 432 if (SQLGetPrivateProfileStringW (L"Default", L"Setup", L"", drvbuf, 433 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 434 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 435 436 SQLSetConfigMode (ODBC_SYSTEM_DSN); 437 if (!access (_szdriver_u8, X_OK)) 438 { CALL_DRVCONN_DIALBOXW (_szdriver_u8, 'A'); } 439 if (SQLGetPrivateProfileStringW (szDriver, L"Driver", L"", drvbuf, 440 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 441 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 442 if (SQLGetPrivateProfileStringW (szDriver, L"Setup", L"", drvbuf, 443 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 444 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 445 if (SQLGetPrivateProfileStringW (L"Default", L"Driver", L"", drvbuf, 446 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 447 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 448 if (SQLGetPrivateProfileStringW (L"Default", L"Setup", L"", drvbuf, 449 sizeof (drvbuf) / sizeof(wchar_t), L"odbcinst.ini")) 450 { CALL_DRVCONN_DIALBOXW (drvbuf, 'W'); } 451 452 /* The last ressort, a proxy driver */ 453#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 454 bundle = CFBundleGetBundleWithIdentifier (CFSTR ("org.iodbc.core")); 455 if (!bundle) 456 bundle = CFBundleGetBundleWithIdentifier (CFSTR ("org.iodbc.inst")); 457 if (bundle) 458 { 459 /* Search for the drvproxy library */ 460 liburl = 461 CFBundleCopyResourceURL (bundle, CFSTR ("iODBCdrvproxy.bundle"), 462 NULL, NULL); 463 if (liburl && (libname = 464 CFURLCopyFileSystemPath (liburl, kCFURLPOSIXPathStyle))) 465 { 466 CFStringGetCString (libname, name, sizeof (name), 467 kCFStringEncodingASCII); 468 STRCAT (name, "/Contents/MacOS/iODBCdrvproxy"); 469 CALL_DRVCONN_DIALBOXW (name, 'A'); 470 } 471 } 472#else 473 CALL_DRVCONN_DIALBOXW ("libdrvproxy.so", 'A'); 474#endif /* __APPLE__ */ 475 476 if (sqlStat) 477 *sqlStat = en_IM003; 478 479quit: 480#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 481 if (liburl) CFRelease (liburl); 482 if (libname) CFRelease (libname); 483#endif 484 485 MEM_FREE (string); 486 MEM_FREE (_szdriver_u8); 487 MEM_FREE (_szdriver_w); 488 489 return retcode; 490} 491 492 493SQLRETURN SQL_API 494_iodbcdm_drvchoose_dialbox ( 495 HWND hwnd, 496 LPSTR szInOutConnStr, 497 DWORD cbInOutConnStr, 498 int * sqlStat) 499{ 500 RETCODE retcode = SQL_ERROR; 501 wchar_t *_string_w = NULL; 502 WORD len; 503 504 if (cbInOutConnStr > 0) 505 { 506 if ((_string_w = malloc (cbInOutConnStr * sizeof(wchar_t) + 1)) == NULL) 507 goto done; 508 } 509 510 retcode = _iodbcdm_drvchoose_dialboxw (hwnd, _string_w, 511 cbInOutConnStr * sizeof(wchar_t), sqlStat); 512 513 if (retcode == SQL_SUCCESS) 514 { 515 dm_StrCopyOut2_W2A (_string_w, szInOutConnStr, cbInOutConnStr - 1, &len); 516 } 517 518done: 519 MEM_FREE (_string_w); 520 521 return retcode; 522} 523 524 525SQLRETURN SQL_API 526_iodbcdm_drvchoose_dialboxw (HWND hwnd, 527 LPWSTR szInOutConnStr, 528 DWORD cbInOutConnStr, 529 int FAR * sqlStat) 530{ 531 RETCODE retcode = SQL_ERROR; 532 TDRIVERCHOOSER choose_t; 533 534 /* Check input parameters */ 535 if (!hwnd || !szInOutConnStr || cbInOutConnStr < 1) 536 goto quit; 537 538 create_driverchooser (hwnd, &choose_t); 539 540 /* Check output parameters */ 541 if (choose_t.driver) 542 { 543 if (cbInOutConnStr > WCSLEN (choose_t.driver) + WCSLEN (L"DRIVER=")) 544 { 545 WCSCPY (szInOutConnStr, L"DRIVER="); 546 WCSCAT (szInOutConnStr, choose_t.driver); 547 retcode = SQL_SUCCESS; 548 } 549 else 550 { 551 if (sqlStat) 552#if (ODBCVER>=0x3000) 553 *sqlStat = en_HY092; 554#else 555 *sqlStat = en_S1000; 556#endif 557 retcode = SQL_ERROR; 558 } 559 } 560 else 561 retcode = SQL_NO_DATA; 562 563 if (choose_t.driver) 564 free (choose_t.driver); 565 566quit: 567 return retcode; 568} 569 570 571SQLRETURN SQL_API 572_iodbcdm_admin_dialbox (HWND hwnd) 573{ 574 RETCODE retcode = SQL_ERROR; 575 576 /* Check input parameters */ 577 if (!hwnd) 578 goto quit; 579 580 create_administrator (hwnd); 581 retcode = SQL_SUCCESS; 582 583quit: 584 return retcode; 585} 586 587 588SQLRETURN SQL_API 589_iodbcdm_trschoose_dialbox ( 590 HWND hwnd, 591 LPSTR szInOutConnStr, 592 DWORD cbInOutConnStr, 593 int FAR * sqlStat) 594{ 595 RETCODE retcode = SQL_ERROR; 596 wchar_t *_string_w = NULL; 597 WORD len; 598 599 if (cbInOutConnStr > 0) 600 { 601 if ((_string_w = malloc (cbInOutConnStr * sizeof(wchar_t) + 1)) == NULL) 602 goto done; 603 } 604 605 retcode = _iodbcdm_trschoose_dialboxw (hwnd, _string_w, 606 cbInOutConnStr * sizeof(wchar_t), sqlStat); 607 608 if (retcode == SQL_SUCCESS) 609 { 610 dm_StrCopyOut2_W2A (_string_w, szInOutConnStr, cbInOutConnStr - 1, &len); 611 } 612 613done: 614 MEM_FREE (_string_w); 615 616 return retcode; 617} 618 619 620SQLRETURN SQL_API 621_iodbcdm_trschoose_dialboxw ( 622 HWND hwnd, 623 LPWSTR szInOutConnStr, 624 DWORD cbInOutConnStr, 625 int * sqlStat) 626{ 627 RETCODE retcode = SQL_ERROR; 628 TTRANSLATORCHOOSER choose_t; 629 630 /* Check input parameters */ 631 if (!hwnd || !szInOutConnStr || cbInOutConnStr < 1) 632 goto quit; 633 634 create_translatorchooser (hwnd, &choose_t); 635 636 /* Check output parameters */ 637 if (choose_t.translator) 638 { 639 if (cbInOutConnStr > 640 WCSLEN (choose_t.translator) + WCSLEN (L"TranslationName=")) 641 { 642 WCSCPY (szInOutConnStr, L"TranslationName"); 643 WCSCAT (szInOutConnStr, choose_t.translator); 644 retcode = SQL_SUCCESS; 645 } 646 else 647 { 648 if (sqlStat) 649#if (ODBCVER>=0x3000) 650 *sqlStat = en_HY092; 651#else 652 *sqlStat = en_S1000; 653#endif 654 retcode = SQL_ERROR; 655 } 656 } 657 else 658 retcode = SQL_NO_DATA; 659 660 if (choose_t.translator) 661 free (choose_t.translator); 662 663quit: 664 return retcode; 665} 666 667 668