1 /*
2 * info.c
3 *
4 * $Id$
5 *
6 * Information functions
7 *
8 * The iODBC driver manager.
9 *
10 * Copyright (C) 1995 Ke Jin <kejin@empress.com>
11 * Copyright (C) 1996-2021 OpenLink Software <iodbc@openlinksw.com>
12 * All Rights Reserved.
13 *
14 * This software is released under the terms of either of the following
15 * licenses:
16 *
17 * - GNU Library General Public License (see LICENSE.LGPL)
18 * - The BSD License (see LICENSE.BSD).
19 *
20 * Note that the only valid version of the LGPL license as far as this
21 * project is concerned is the original GNU Library General Public License
22 * Version 2, dated June 1991.
23 *
24 * While not mandated by the BSD license, any patches you make to the
25 * iODBC source code may be contributed back into the iODBC project
26 * at your discretion. Contributions will benefit the Open Source and
27 * Data Access community as a whole. Submissions may be made at:
28 *
29 * http://www.iodbc.org
30 *
31 *
32 * GNU Library Generic Public License Version 2
33 * ============================================
34 * This library is free software; you can redistribute it and/or
35 * modify it under the terms of the GNU Library General Public
36 * License as published by the Free Software Foundation; only
37 * Version 2 of the License dated June 1991.
38 *
39 * This library is distributed in the hope that it will be useful,
40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 * Library General Public License for more details.
43 *
44 * You should have received a copy of the GNU Library General Public
45 * License along with this library; if not, write to the Free
46 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
47 *
48 *
49 * The BSD License
50 * ===============
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 *
55 * 1. Redistributions of source code must retain the above copyright
56 * notice, this list of conditions and the following disclaimer.
57 * 2. Redistributions in binary form must reproduce the above copyright
58 * notice, this list of conditions and the following disclaimer in
59 * the documentation and/or other materials provided with the
60 * distribution.
61 * 3. Neither the name of OpenLink Software Inc. nor the names of its
62 * contributors may be used to endorse or promote products derived
63 * from this software without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
66 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
67 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
68 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
69 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
70 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
71 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
72 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
73 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
74 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 */
77
78
79 #include <iodbc.h>
80
81 #include <sql.h>
82 #include <sqlext.h>
83 #include <sqlucode.h>
84 #include <odbcinst.h>
85
86 #include "unicode.h"
87
88 #include "dlproc.h"
89
90 #include "herr.h"
91 #include "henv.h"
92 #include "hdbc.h"
93 #include "hstmt.h"
94
95 #include "itrace.h"
96
97 #include <stdio.h>
98 #include <ctype.h>
99
100 #ifdef WIN32
101 #define SECT1 "ODBC 32 bit Data Sources"
102 #define SECT2 "ODBC 32 bit Drivers"
103 #else
104 #define SECT1 "ODBC Data Sources"
105 #define SECT2 "ODBC Drivers"
106 #endif
107
108 #define MAX_ENTRIES 1024
109
110
111 static int
stricmp(const char * s1,const char * s2)112 stricmp (const char *s1, const char *s2)
113 {
114 int cmp;
115
116 while (*s1)
117 {
118 if ((cmp = toupper (*s1) - toupper (*s2)) != 0)
119 return cmp;
120 s1++;
121 s2++;
122 }
123 return (*s2) ? -1 : 0;
124 }
125
126
127 static int
SectSorter(const void * p1,const void * p2)128 SectSorter (const void *p1, const void *p2)
129 {
130 const char **s1 = (const char **) p1;
131 const char **s2 = (const char **) p2;
132
133 return stricmp (*s1, *s2);
134 }
135
136
137 SQLRETURN SQL_API
SQLDataSources_Internal(SQLHENV henv,SQLUSMALLINT fDir,SQLPOINTER szDSN,SQLSMALLINT cbDSNMax,SQLSMALLINT * pcbDSN,SQLPOINTER szDesc,SQLSMALLINT cbDescMax,SQLSMALLINT * pcbDesc,SQLCHAR waMode)138 SQLDataSources_Internal (
139 SQLHENV henv,
140 SQLUSMALLINT fDir,
141 SQLPOINTER szDSN,
142 SQLSMALLINT cbDSNMax,
143 SQLSMALLINT * pcbDSN,
144 SQLPOINTER szDesc,
145 SQLSMALLINT cbDescMax,
146 SQLSMALLINT * pcbDesc,
147 SQLCHAR waMode)
148 {
149 GENV (genv, henv);
150 char buffer[4096], desc[1024], *ptr;
151 int i, j, usernum = 0;
152 static int cur_entry = -1;
153 static int num_entries = 0;
154 static void **sect = NULL;
155 SQLUSMALLINT fDirOld = fDir;
156
157 waMode = waMode; /*UNUSED*/
158
159 /* check argument */
160 if (cbDSNMax < 0 || cbDescMax < 0)
161 {
162 PUSHSQLERR (genv->herr, en_S1090);
163 return SQL_ERROR;
164 }
165
166 if (fDir != SQL_FETCH_FIRST && fDir != SQL_FETCH_NEXT &&
167 fDir != SQL_FETCH_FIRST_USER && fDir != SQL_FETCH_FIRST_SYSTEM)
168 {
169 PUSHSQLERR (genv->herr, en_S1103);
170 return SQL_ERROR;
171 }
172
173 if (cur_entry < 0 || fDir == SQL_FETCH_FIRST ||
174 fDir == SQL_FETCH_FIRST_USER || fDir == SQL_FETCH_FIRST_SYSTEM)
175 {
176 cur_entry = 0;
177 num_entries = 0;
178
179 /*
180 * Free old section list
181 */
182 if (sect)
183 {
184 for (i = 0; i < MAX_ENTRIES; i++)
185 if (sect[i])
186 free (sect[i]);
187 free (sect);
188 }
189 if ((sect = (void **) calloc (MAX_ENTRIES, sizeof (void *))) == NULL)
190 {
191 PUSHSQLERR (genv->herr, en_S1011);
192 return SQL_ERROR;
193 }
194
195 if (fDirOld == SQL_FETCH_FIRST)
196 fDir = SQL_FETCH_FIRST_USER;
197
198 do {
199 SQLSetConfigMode (fDir == SQL_FETCH_FIRST_SYSTEM ? ODBC_SYSTEM_DSN : ODBC_USER_DSN);
200 SQLGetPrivateProfileString (SECT1, NULL, "", buffer, sizeof(buffer) / sizeof(SQLTCHAR), "odbc.ini");
201
202 /* For each datasources */
203 for(ptr = buffer, i = 1 ; *ptr && i ; ptr += STRLEN(ptr) + 1)
204 {
205 /* Add this section to the datasources list */
206 if (fDirOld == SQL_FETCH_FIRST && fDir == SQL_FETCH_FIRST_SYSTEM)
207 {
208 for(j = 0 ; j<usernum ; j++)
209 {
210 if(STREQ(sect[j<<1], ptr))
211 j = usernum;
212 }
213 if(j == usernum + 1)
214 continue;
215 }
216
217 if ((num_entries << 1) >= MAX_ENTRIES)
218 {
219 i = 0;
220 break;
221 } /* Skip the rest */
222
223 /* Copy the datasource name */
224 sect[num_entries<<1] = STRDUP (ptr);
225
226 /* ... and its description */
227 SQLSetConfigMode (fDir == SQL_FETCH_FIRST_SYSTEM ? ODBC_SYSTEM_DSN : ODBC_USER_DSN);
228 SQLGetPrivateProfileString (SECT1, ptr, "", desc, sizeof(desc) / sizeof(SQLTCHAR), "odbc.ini");
229 sect[(num_entries++<<1) + 1] = STRDUP (desc);
230 }
231
232 switch(fDir)
233 {
234 case SQL_FETCH_FIRST_USER:
235 fDir = SQL_FETCH_FIRST_SYSTEM;
236 usernum = num_entries;
237 break;
238 case SQL_FETCH_FIRST_SYSTEM:
239 fDir = SQL_FETCH_FIRST;
240 break;
241 };
242 } while (fDir!=SQL_FETCH_FIRST && fDirOld==SQL_FETCH_FIRST);
243
244 fDir = fDirOld;
245
246 /*
247 * Sort all entries so we can present a nice list
248 */
249 if (num_entries > 1)
250 {
251 qsort (sect, num_entries, sizeof (char **) + sizeof (char **),
252 SectSorter);
253 }
254 }
255
256 /*
257 * Try to get to the next item
258 */
259 if (cur_entry >= num_entries)
260 {
261 cur_entry = 0; /* Next time, start all over again */
262 return SQL_NO_DATA_FOUND;
263 }
264
265 /*
266 * Copy DSN information
267 */
268 STRNCPY (szDSN, sect[cur_entry << 1], cbDSNMax);
269
270 if (pcbDSN)
271 *pcbDSN = STRLEN (szDSN);
272
273 /*
274 * And find the description that goes with this entry
275 */
276 STRNCPY (szDesc, sect[(cur_entry << 1) + 1], cbDescMax);
277
278 if (pcbDesc)
279 *pcbDesc = STRLEN (szDesc);
280
281 /*
282 * Next record
283 */
284 cur_entry++;
285
286 return SQL_SUCCESS;
287 }
288
289
290 SQLRETURN SQL_API
SQLDataSources(SQLHENV henv,SQLUSMALLINT fDir,SQLCHAR * szDSN,SQLSMALLINT cbDSNMax,SQLSMALLINT * pcbDSN,SQLCHAR * szDesc,SQLSMALLINT cbDescMax,SQLSMALLINT * pcbDesc)291 SQLDataSources (
292 SQLHENV henv,
293 SQLUSMALLINT fDir,
294 SQLCHAR * szDSN,
295 SQLSMALLINT cbDSNMax,
296 SQLSMALLINT * pcbDSN,
297 SQLCHAR * szDesc,
298 SQLSMALLINT cbDescMax,
299 SQLSMALLINT * pcbDesc)
300 {
301 ENTER_HENV (henv,
302 trace_SQLDataSources (TRACE_ENTER,
303 henv,
304 fDir,
305 szDSN, cbDSNMax, pcbDSN,
306 szDesc, cbDescMax, pcbDesc));
307
308 retcode = SQLDataSources_Internal (
309 henv,
310 fDir,
311 szDSN, cbDSNMax, pcbDSN,
312 szDesc, cbDescMax, pcbDesc,
313 'A');
314
315 LEAVE_HENV (henv,
316 trace_SQLDataSources (TRACE_LEAVE,
317 henv,
318 fDir,
319 szDSN, cbDSNMax, pcbDSN,
320 szDesc, cbDescMax, pcbDesc));
321 }
322
323
324 #if ODBCVER >= 0x0300
325 SQLRETURN SQL_API
SQLDataSourcesA(SQLHENV henv,SQLUSMALLINT fDir,SQLCHAR * szDSN,SQLSMALLINT cbDSNMax,SQLSMALLINT * pcbDSN,SQLCHAR * szDesc,SQLSMALLINT cbDescMax,SQLSMALLINT * pcbDesc)326 SQLDataSourcesA (
327 SQLHENV henv,
328 SQLUSMALLINT fDir,
329 SQLCHAR * szDSN,
330 SQLSMALLINT cbDSNMax,
331 SQLSMALLINT * pcbDSN,
332 SQLCHAR * szDesc,
333 SQLSMALLINT cbDescMax,
334 SQLSMALLINT * pcbDesc)
335 {
336 ENTER_HENV (henv,
337 trace_SQLDataSources (TRACE_ENTER,
338 henv,
339 fDir,
340 szDSN, cbDSNMax, pcbDSN,
341 szDesc, cbDescMax, pcbDesc));
342
343 retcode = SQLDataSources_Internal(
344 henv,
345 fDir,
346 szDSN, cbDSNMax, pcbDSN,
347 szDesc, cbDescMax, pcbDesc,
348 'A');
349
350 LEAVE_HENV (henv,
351 trace_SQLDataSources (TRACE_LEAVE,
352 henv,
353 fDir,
354 szDSN, cbDSNMax, pcbDSN,
355 szDesc, cbDescMax, pcbDesc));
356 }
357
358
359 SQLRETURN SQL_API
SQLDataSourcesW(SQLHENV henv,SQLUSMALLINT fDir,SQLWCHAR * szDSN,SQLSMALLINT cbDSNMax,SQLSMALLINT * pcbDSN,SQLWCHAR * szDesc,SQLSMALLINT cbDescMax,SQLSMALLINT * pcbDesc)360 SQLDataSourcesW (
361 SQLHENV henv,
362 SQLUSMALLINT fDir,
363 SQLWCHAR * szDSN,
364 SQLSMALLINT cbDSNMax,
365 SQLSMALLINT * pcbDSN,
366 SQLWCHAR * szDesc,
367 SQLSMALLINT cbDescMax,
368 SQLSMALLINT * pcbDesc)
369 {
370 SQLCHAR *_DSN = NULL;
371 SQLCHAR *_Desc = NULL;
372 GENV (glenv, henv);
373 DM_CONV *conv = &glenv->conv;
374
375 ENTER_HENV (henv,
376 trace_SQLDataSourcesW (TRACE_ENTER,
377 henv,
378 fDir,
379 szDSN, cbDSNMax, pcbDSN,
380 szDesc, cbDescMax, pcbDesc));
381
382 if (cbDSNMax > 0)
383 {
384 if ((_DSN = (SQLCHAR *) malloc (cbDSNMax * UTF8_MAX_CHAR_LEN + 1)) == NULL)
385 {
386 PUSHSQLERR (genv->herr, en_S1001);
387 return SQL_ERROR;
388 }
389 }
390
391 if (cbDescMax > 0)
392 {
393 if ((_Desc = (SQLCHAR *) malloc (cbDescMax * UTF8_MAX_CHAR_LEN + 1)) == NULL)
394 {
395 PUSHSQLERR (genv->herr, en_S1001);
396 return SQL_ERROR;
397 }
398 }
399
400 retcode = SQLDataSources_Internal (
401 henv,
402 fDir,
403 _DSN, cbDSNMax * UTF8_MAX_CHAR_LEN, pcbDSN,
404 _Desc, cbDescMax * UTF8_MAX_CHAR_LEN, pcbDesc,
405 'W');
406
407 if (SQL_SUCCEEDED (retcode))
408 {
409 dm_StrCopyOut2_U8toW_d2m (conv, _DSN, szDSN,
410 cbDSNMax * DM_WCHARSIZE(conv), pcbDSN, NULL);
411 dm_StrCopyOut2_U8toW_d2m (conv, _Desc, szDesc,
412 cbDescMax * DM_WCHARSIZE(conv), pcbDesc, NULL);
413 }
414
415 MEM_FREE (_DSN);
416 MEM_FREE (_Desc);
417
418 LEAVE_HENV (henv,
419 trace_SQLDataSourcesW (TRACE_LEAVE,
420 henv,
421 fDir,
422 szDSN, cbDSNMax, pcbDSN,
423 szDesc, cbDescMax, pcbDesc));
424 }
425 #endif
426
427
428 SQLRETURN SQL_API
SQLDrivers_Internal(SQLHENV henv,SQLUSMALLINT fDir,SQLPOINTER szDrvDesc,SQLSMALLINT cbDrvDescMax,SQLSMALLINT * pcbDrvDesc,SQLPOINTER szDrvAttr,SQLSMALLINT cbDrvAttrMax,SQLSMALLINT * pcbDrvAttr,SQLCHAR waMode)429 SQLDrivers_Internal (
430 SQLHENV henv,
431 SQLUSMALLINT fDir,
432 SQLPOINTER szDrvDesc,
433 SQLSMALLINT cbDrvDescMax,
434 SQLSMALLINT * pcbDrvDesc,
435 SQLPOINTER szDrvAttr,
436 SQLSMALLINT cbDrvAttrMax,
437 SQLSMALLINT * pcbDrvAttr,
438 SQLCHAR waMode)
439 {
440 GENV (genv, henv);
441 char buffer[4096], desc[1024], *ptr;
442 int i, j, usernum = 0;
443 static int cur_entry = -1;
444 static int num_entries = 0;
445 static void **sect = NULL;
446 SQLUSMALLINT fDirOld = fDir;
447
448 waMode = waMode; /*UNUSED*/
449
450 /* check argument */
451 if (cbDrvDescMax < 0 || cbDrvAttrMax < 0)
452 {
453 PUSHSQLERR (genv->herr, en_S1090);
454 return SQL_ERROR;
455 }
456
457 if (fDir != SQL_FETCH_FIRST && fDir != SQL_FETCH_NEXT)
458 {
459 PUSHSQLERR (genv->herr, en_S1103);
460 return SQL_ERROR;
461 }
462
463 if (cur_entry < 0 || fDir == SQL_FETCH_FIRST)
464 {
465 cur_entry = 0;
466 num_entries = 0;
467
468 /*
469 * Free old section list
470 */
471 if (sect)
472 {
473 for (i = 0; i < MAX_ENTRIES; i++)
474 if (sect[i])
475 free (sect[i]);
476 free (sect);
477 }
478 if ((sect = (void **) calloc (MAX_ENTRIES, sizeof (void *))) == NULL)
479 {
480 PUSHSQLERR (genv->herr, en_S1011);
481 return SQL_ERROR;
482 }
483
484 if (fDirOld == SQL_FETCH_FIRST)
485 fDir = SQL_FETCH_FIRST_USER;
486
487 do {
488 SQLSetConfigMode (fDir == SQL_FETCH_FIRST_SYSTEM ? ODBC_SYSTEM_DSN : ODBC_USER_DSN);
489 SQLGetPrivateProfileString (SECT2, NULL, "", buffer, sizeof(buffer) / sizeof(SQLTCHAR), "odbcinst.ini");
490
491 /* For each datasources */
492 for(ptr = buffer, i = 1 ; *ptr && i ; ptr += STRLEN(ptr) + 1)
493 {
494 /* Add this section to the datasources list */
495 if (fDirOld == SQL_FETCH_FIRST && fDir == SQL_FETCH_FIRST_SYSTEM)
496 {
497 for(j = 0 ; j<usernum ; j++)
498 {
499 if(STREQ(sect[j<<1], ptr))
500 j = usernum;
501 }
502 if(j == usernum + 1)
503 continue;
504 }
505
506 if ((num_entries << 1) >= MAX_ENTRIES)
507 {
508 i = 0;
509 break;
510 } /* Skip the rest */
511
512 /* ... and its description */
513 SQLSetConfigMode (fDir == SQL_FETCH_FIRST_SYSTEM ? ODBC_SYSTEM_DSN : ODBC_USER_DSN);
514 SQLGetPrivateProfileString (SECT2, ptr, "", desc, sizeof(desc) / sizeof(SQLTCHAR), "odbcinst.ini");
515
516 /* Check if the driver is installed */
517 if(!STRCASEEQ(desc, "Installed"))
518 continue;
519
520 /* Copy the driver name */
521 sect[num_entries<<1] = STRDUP (ptr);
522 sect[(num_entries++<<1) + 1] = STRDUP (desc);
523 }
524
525 switch(fDir)
526 {
527 case SQL_FETCH_FIRST_USER:
528 fDir = SQL_FETCH_FIRST_SYSTEM;
529 usernum = num_entries;
530 break;
531 case SQL_FETCH_FIRST_SYSTEM:
532 fDir = SQL_FETCH_FIRST;
533 break;
534 };
535 } while (fDir!=SQL_FETCH_FIRST && fDirOld==SQL_FETCH_FIRST);
536
537 fDir = fDirOld;
538
539 /*
540 * Sort all entries so we can present a nice list
541 */
542 if (num_entries > 1)
543 {
544 qsort (sect, num_entries, sizeof (char **) + sizeof (char **),
545 SectSorter);
546 }
547 }
548
549 /*
550 * Try to get to the next item
551 */
552 if (cur_entry >= num_entries)
553 {
554 cur_entry = 0; /* Next time, start all over again */
555 return SQL_NO_DATA_FOUND;
556 }
557
558 /*
559 * Copy Driver information
560 */
561 STRNCPY (szDrvDesc, sect[cur_entry << 1], cbDrvDescMax);
562
563 if (pcbDrvDesc)
564 *pcbDrvDesc = STRLEN (szDrvDesc);
565
566 /*
567 * And find the description that goes with this entry
568 */
569 STRNCPY (szDrvAttr, sect[(cur_entry << 1) + 1], cbDrvAttrMax);
570
571 if (pcbDrvAttr)
572 *pcbDrvAttr = STRLEN (szDrvAttr);
573
574 /*
575 * Next record
576 */
577 cur_entry++;
578
579 return SQL_SUCCESS;
580 }
581
582
583 SQLRETURN SQL_API
SQLDrivers(SQLHENV henv,SQLUSMALLINT fDir,SQLCHAR * szDrvDesc,SQLSMALLINT cbDrvDescMax,SQLSMALLINT * pcbDrvDesc,SQLCHAR * szDrvAttr,SQLSMALLINT cbDrvAttrMax,SQLSMALLINT * pcbDrvAttr)584 SQLDrivers (
585 SQLHENV henv,
586 SQLUSMALLINT fDir,
587 SQLCHAR * szDrvDesc,
588 SQLSMALLINT cbDrvDescMax,
589 SQLSMALLINT * pcbDrvDesc,
590 SQLCHAR * szDrvAttr,
591 SQLSMALLINT cbDrvAttrMax,
592 SQLSMALLINT * pcbDrvAttr)
593 {
594 ENTER_HENV (henv,
595 trace_SQLDrivers (TRACE_ENTER,
596 henv,
597 fDir,
598 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
599 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
600
601 retcode = SQLDrivers_Internal(
602 henv,
603 fDir,
604 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
605 szDrvAttr, cbDrvAttrMax, pcbDrvAttr,
606 'A');
607
608 LEAVE_HENV (henv,
609 trace_SQLDrivers (TRACE_LEAVE,
610 henv,
611 fDir,
612 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
613 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
614 }
615
616
617 #if ODBCVER >= 0x0300
618 SQLRETURN SQL_API
SQLDriversA(SQLHENV henv,SQLUSMALLINT fDir,SQLCHAR * szDrvDesc,SQLSMALLINT cbDrvDescMax,SQLSMALLINT * pcbDrvDesc,SQLCHAR * szDrvAttr,SQLSMALLINT cbDrvAttrMax,SQLSMALLINT * pcbDrvAttr)619 SQLDriversA (
620 SQLHENV henv,
621 SQLUSMALLINT fDir,
622 SQLCHAR * szDrvDesc,
623 SQLSMALLINT cbDrvDescMax,
624 SQLSMALLINT * pcbDrvDesc,
625 SQLCHAR * szDrvAttr,
626 SQLSMALLINT cbDrvAttrMax,
627 SQLSMALLINT * pcbDrvAttr)
628 {
629 ENTER_HENV (henv,
630 trace_SQLDrivers (TRACE_ENTER,
631 henv,
632 fDir,
633 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
634 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
635
636 retcode = SQLDrivers_Internal(
637 henv,
638 fDir,
639 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
640 szDrvAttr, cbDrvAttrMax, pcbDrvAttr,
641 'A');
642
643 LEAVE_HENV (henv,
644 trace_SQLDrivers (TRACE_LEAVE,
645 henv,
646 fDir,
647 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
648 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
649 }
650
651
652 SQLRETURN SQL_API
SQLDriversW(SQLHENV henv,SQLUSMALLINT fDir,SQLWCHAR * szDrvDesc,SQLSMALLINT cbDrvDescMax,SQLSMALLINT * pcbDrvDesc,SQLWCHAR * szDrvAttr,SQLSMALLINT cbDrvAttrMax,SQLSMALLINT * pcbDrvAttr)653 SQLDriversW (SQLHENV henv,
654 SQLUSMALLINT fDir,
655 SQLWCHAR * szDrvDesc,
656 SQLSMALLINT cbDrvDescMax,
657 SQLSMALLINT * pcbDrvDesc,
658 SQLWCHAR * szDrvAttr,
659 SQLSMALLINT cbDrvAttrMax,
660 SQLSMALLINT * pcbDrvAttr)
661 {
662 SQLCHAR *_Driver = NULL;
663 SQLCHAR *_Attrs = NULL;
664 GENV (glenv, henv);
665 DM_CONV *conv = &glenv->conv;
666
667 ENTER_HENV (henv,
668 trace_SQLDriversW (TRACE_ENTER,
669 henv,
670 fDir,
671 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
672 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
673
674 if (cbDrvDescMax > 0)
675 {
676 if ((_Driver = (SQLCHAR *) malloc (cbDrvDescMax * UTF8_MAX_CHAR_LEN + 1)) == NULL)
677 {
678 PUSHSQLERR (genv->herr, en_S1001);
679 return SQL_ERROR;
680 }
681 }
682
683 if (cbDrvAttrMax > 0)
684 {
685 if ((_Attrs = (SQLCHAR *) malloc (cbDrvAttrMax * UTF8_MAX_CHAR_LEN + 1)) == NULL)
686 {
687 PUSHSQLERR (genv->herr, en_S1001);
688 return SQL_ERROR;
689 }
690 }
691
692 retcode = SQLDrivers_Internal (
693 henv,
694 fDir,
695 _Driver, cbDrvDescMax * UTF8_MAX_CHAR_LEN, pcbDrvDesc,
696 _Attrs, cbDrvAttrMax * UTF8_MAX_CHAR_LEN, pcbDrvAttr,
697 'W');
698
699 if (SQL_SUCCEEDED (retcode))
700 {
701 dm_StrCopyOut2_U8toW_d2m (conv, _Driver, szDrvDesc,
702 cbDrvDescMax * DM_WCHARSIZE(conv), pcbDrvDesc, NULL);
703 dm_StrCopyOut2_U8toW_d2m (conv, _Attrs, szDrvAttr,
704 cbDrvAttrMax * DM_WCHARSIZE(conv), pcbDrvAttr, NULL);
705 }
706
707 MEM_FREE (_Driver);
708 MEM_FREE (_Attrs);
709
710 LEAVE_HENV (henv,
711 trace_SQLDriversW (TRACE_LEAVE,
712 henv,
713 fDir,
714 szDrvDesc, cbDrvDescMax, pcbDrvDesc,
715 szDrvAttr, cbDrvAttrMax, pcbDrvAttr));
716 }
717 #endif
718
719
720 SQLRETURN SQL_API
SQLGetInfo_Internal(SQLHDBC hdbc,SQLUSMALLINT fInfoType,SQLPOINTER rgbInfoValue,SQLSMALLINT cbInfoValueMax,SQLSMALLINT * pcbInfoValue,SQLCHAR waMode)721 SQLGetInfo_Internal (
722 SQLHDBC hdbc,
723 SQLUSMALLINT fInfoType,
724 SQLPOINTER rgbInfoValue,
725 SQLSMALLINT cbInfoValueMax,
726 SQLSMALLINT * pcbInfoValue,
727 SQLCHAR waMode)
728 {
729 CONN (pdbc, hdbc);
730 ENVR (penv, pdbc->henv);
731 STMT (pstmt, NULL);
732 STMT (tpstmt, NULL);
733 HPROC hproc = SQL_NULL_HPROC;
734 SQLRETURN retcode = SQL_SUCCESS;
735 void * _InfoValue = NULL;
736 void * infoValueOut = rgbInfoValue;
737 SQLPOINTER ptr = 0;
738 SQLSMALLINT _cbInfoValueMax = cbInfoValueMax;
739 CONV_DIRECT conv_direct = CD_NONE;
740 DM_CONV *conv = &pdbc->conv;
741
742 int size = 0, len = 0, ret = 0;
743 wchar_t buf[20] = {'\0'};
744
745 if (cbInfoValueMax < 0)
746 {
747 PUSHSQLERR (pdbc->herr, en_S1090);
748 return SQL_ERROR;
749 }
750
751 #if (ODBCVER < 0x0300)
752 if ( /* fInfoType < SQL_INFO_FIRST || */
753 (fInfoType > SQL_INFO_LAST
754 && fInfoType < SQL_INFO_DRIVER_START))
755 {
756 PUSHSQLERR (pdbc->herr, en_S1096);
757 return SQL_ERROR;
758 }
759 #endif
760 if (fInfoType == SQL_ODBC_VER
761 #if (ODBCVER >= 0x0300)
762 || fInfoType == SQL_DM_VER
763 #endif
764 )
765 {
766 #if (ODBCVER >= 0x0300)
767 if (fInfoType == SQL_DM_VER)
768 sprintf ((char*)buf, "%02d.%02d.%04d.%04d",
769 SQL_SPEC_MAJOR, SQL_SPEC_MINOR, IODBC_BUILD / 10000, IODBC_BUILD % 10000);
770 else
771 #endif
772 sprintf ((char*)buf, "%02d.%02d.0000", SQL_SPEC_MAJOR, SQL_SPEC_MINOR);
773 if(waMode == 'W')
774 {
775 void *prov = DM_U8toW(conv, (SQLCHAR *)buf, SQL_NTS);
776 if(prov)
777 {
778 DM_WCSNCPY(conv, buf, prov, sizeof(buf)/DM_WCHARSIZE(conv));
779 free(prov);
780 }
781 else
782 DM_SetWCharAt(conv, buf, 0, 0);
783 }
784
785
786 if (rgbInfoValue != NULL && cbInfoValueMax > 0)
787 {
788 len = (waMode != 'W' ? STRLEN (buf) : DM_WCSLEN(conv, buf));
789
790 if (len > cbInfoValueMax - 1)
791 {
792 len = cbInfoValueMax - 1;
793 PUSHSQLERR (pdbc->herr, en_01004);
794
795 retcode = SQL_SUCCESS_WITH_INFO;
796 }
797
798 if (waMode != 'W')
799 {
800 STRNCPY (rgbInfoValue, buf, len);
801 ((char *) rgbInfoValue)[len] = '\0';
802 }
803 else
804 {
805 DM_WCSNCPY (conv, rgbInfoValue, buf, len);
806 DM_SetWCharAt(conv, rgbInfoValue, len, 0);
807 }
808 }
809
810 if (pcbInfoValue != NULL)
811 {
812 *pcbInfoValue = (SWORD) len;
813 }
814
815 return retcode;
816 }
817
818 if (pdbc->state == en_dbc_allocated || pdbc->state == en_dbc_needdata)
819 {
820 PUSHSQLERR (pdbc->herr, en_08003);
821
822 return SQL_ERROR;
823 }
824
825 switch (fInfoType)
826 {
827 case SQL_DRIVER_HDBC:
828 ptr = (SQLPOINTER) (pdbc->dhdbc);
829 size = sizeof (ptr);
830 break;
831
832 case SQL_DRIVER_HENV:
833 penv = (ENV_t *) (pdbc->henv);
834 ptr = (SQLPOINTER) (penv->dhenv);
835 size = sizeof (ptr);
836 break;
837
838 case SQL_DRIVER_HLIB:
839 penv = (ENV_t *) (pdbc->henv);
840 ptr = (SQLPOINTER) (penv->hdll);
841 size = sizeof (ptr);
842 break;
843
844 case SQL_DRIVER_HSTMT:
845 if (rgbInfoValue != NULL)
846 {
847 pstmt = *((STMT_t **) rgbInfoValue);
848 }
849
850 for (tpstmt = (STMT_t *) (pdbc->hstmt);
851 tpstmt != NULL;
852 tpstmt = tpstmt->next)
853 {
854 if (tpstmt == pstmt)
855 {
856 break;
857 }
858 }
859
860 if (tpstmt == NULL)
861 {
862 PUSHSQLERR (pdbc->herr, en_S1009);
863
864 return SQL_ERROR;
865 }
866
867 ptr = (SQLPOINTER) (pstmt->dhstmt);
868 size = sizeof (ptr);
869 break;
870
871 case SQL_DRIVER_NAME:
872 case SQL_DRIVER_ODBC_VER:
873 case SQL_DRIVER_VER:
874 case SQL_ODBC_INTERFACE_CONFORMANCE:
875 break;
876
877 default:
878 /* NOTE : this was before the switch, just move here to let some information going through */
879 if (pdbc->state == en_dbc_allocated || pdbc->state == en_dbc_needdata)
880 {
881 PUSHSQLERR (pdbc->herr, en_08003);
882 return SQL_ERROR;
883 }
884 }
885
886 if (size)
887 {
888 if (rgbInfoValue != NULL)
889 {
890 rgbInfoValue = ptr;
891 }
892
893 if (pcbInfoValue != NULL)
894 {
895 *(pcbInfoValue) = (SWORD) size;
896 }
897
898 return SQL_SUCCESS;
899 }
900
901 #if (ODBCVER >= 0x0300)
902 /*
903 * This was a temp value in ODBC 2
904 */
905 if (((ENV_t *) pdbc->henv)->dodbc_ver == SQL_OV_ODBC2 &&
906 fInfoType == SQL_OJ_CAPABILITIES)
907 fInfoType = 65003;
908 #endif /* ODBCVER >= 0x0300 */
909
910 if (penv->unicode_driver && waMode != 'W')
911 conv_direct = CD_A2W;
912 else if (!penv->unicode_driver && waMode == 'W')
913 conv_direct = CD_W2A;
914 else if (waMode == 'W' && conv && conv->dm_cp!=conv->drv_cp)
915 conv_direct = CD_W2W;
916
917 if (conv_direct != CD_NONE)
918 {
919 switch(fInfoType)
920 {
921 case SQL_ACCESSIBLE_PROCEDURES:
922 case SQL_ACCESSIBLE_TABLES:
923 case SQL_CATALOG_NAME:
924 case SQL_CATALOG_NAME_SEPARATOR:
925 case SQL_CATALOG_TERM:
926 case SQL_COLLATION_SEQ:
927 case SQL_COLUMN_ALIAS:
928 case SQL_DATA_SOURCE_NAME:
929 case SQL_DATA_SOURCE_READ_ONLY:
930 case SQL_DATABASE_NAME:
931 case SQL_DBMS_NAME:
932 case SQL_DBMS_VER:
933 case SQL_DESCRIBE_PARAMETER:
934 case SQL_DRIVER_NAME:
935 case SQL_DRIVER_ODBC_VER:
936 case SQL_DRIVER_VER:
937 case SQL_ODBC_VER:
938 case SQL_EXPRESSIONS_IN_ORDERBY:
939 case SQL_IDENTIFIER_QUOTE_CHAR:
940 case SQL_INTEGRITY:
941 case SQL_KEYWORDS:
942 case SQL_LIKE_ESCAPE_CLAUSE:
943 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
944 case SQL_MULT_RESULT_SETS:
945 case SQL_MULTIPLE_ACTIVE_TXN:
946 case SQL_NEED_LONG_DATA_LEN:
947 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
948 case SQL_PROCEDURE_TERM:
949 case SQL_PROCEDURES:
950 case SQL_ROW_UPDATES:
951 case SQL_SCHEMA_TERM:
952 case SQL_SEARCH_PATTERN_ESCAPE:
953 case SQL_SERVER_NAME:
954 case SQL_SPECIAL_CHARACTERS:
955 case SQL_TABLE_TERM:
956 case SQL_USER_NAME:
957 case SQL_XOPEN_CLI_YEAR:
958 case SQL_OUTER_JOINS:
959 if (conv_direct == CD_A2W || conv_direct == CD_W2W)
960 {
961 /* ansi<=unicode OR unicode<=unicode*/
962 if (conv_direct == CD_W2W)
963 _cbInfoValueMax /= DM_WCHARSIZE(conv);
964
965 if ((_InfoValue = malloc((_cbInfoValueMax + 1) * DRV_WCHARSIZE_ALLOC(conv))) == NULL)
966 {
967 PUSHSQLERR (pdbc->herr, en_HY001);
968 return SQL_ERROR;
969 }
970 _cbInfoValueMax *= DRV_WCHARSIZE_ALLOC(conv);
971 }
972 else if (conv_direct == CD_W2A)
973 {
974 /* unicode<=ansi*/
975 if ((_InfoValue = malloc(_cbInfoValueMax * MB_CUR_MAX + 1)) == NULL)
976 {
977 PUSHSQLERR (pdbc->herr, en_HY001);
978 return SQL_ERROR;
979 }
980 _cbInfoValueMax /= DM_WCHARSIZE(conv);
981 }
982
983 infoValueOut = _InfoValue;
984 break;
985 }
986 }
987
988 CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
989 en_GetInfo, (pdbc->dhdbc, fInfoType, infoValueOut, _cbInfoValueMax,
990 pcbInfoValue));
991
992 if (hproc == SQL_NULL_HPROC)
993 {
994 PUSHSQLERR (pdbc->herr, en_IM001);
995 return SQL_ERROR;
996 }
997
998 if (retcode == SQL_ERROR && fInfoType == SQL_DRIVER_ODBC_VER)
999 {
1000 if (waMode != 'W')
1001 {
1002 STRCPY (buf, "01.00");
1003
1004 if (rgbInfoValue != NULL && cbInfoValueMax > 0)
1005 {
1006 len = STRLEN (buf);
1007
1008 if (len > cbInfoValueMax - 1)
1009 {
1010 len = cbInfoValueMax - 1;
1011 ret = -1;
1012 }
1013 else
1014 {
1015 ret = 0;
1016 }
1017
1018 STRNCPY (rgbInfoValue, buf, len);
1019 ((char *) rgbInfoValue)[len] = '\0';
1020 }
1021
1022 if (pcbInfoValue != NULL)
1023 *pcbInfoValue = (SWORD) len;
1024 }
1025 else
1026 {
1027 int count;
1028 ret = dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *) "01.00",
1029 rgbInfoValue, cbInfoValueMax, NULL, &count);
1030 if (pcbInfoValue)
1031 *pcbInfoValue = (SQLSMALLINT)count;
1032 }
1033
1034 if (ret == -1)
1035 {
1036 PUSHSQLERR (pdbc->herr, en_01004);
1037 retcode = SQL_SUCCESS_WITH_INFO;
1038 }
1039 else
1040 {
1041 retcode = SQL_SUCCESS;
1042 }
1043
1044 }
1045 else if (rgbInfoValue && conv_direct != CD_NONE && SQL_SUCCEEDED (retcode))
1046 {
1047 int count;
1048 switch(fInfoType)
1049 {
1050 case SQL_ACCESSIBLE_PROCEDURES:
1051 case SQL_ACCESSIBLE_TABLES:
1052 case SQL_CATALOG_NAME:
1053 case SQL_CATALOG_NAME_SEPARATOR:
1054 case SQL_CATALOG_TERM:
1055 case SQL_COLLATION_SEQ:
1056 case SQL_COLUMN_ALIAS:
1057 case SQL_DATA_SOURCE_NAME:
1058 case SQL_DATA_SOURCE_READ_ONLY:
1059 case SQL_DATABASE_NAME:
1060 case SQL_DBMS_NAME:
1061 case SQL_DBMS_VER:
1062 case SQL_DESCRIBE_PARAMETER:
1063 case SQL_DRIVER_NAME:
1064 case SQL_DRIVER_ODBC_VER:
1065 case SQL_DRIVER_VER:
1066 case SQL_ODBC_VER:
1067 case SQL_EXPRESSIONS_IN_ORDERBY:
1068 case SQL_IDENTIFIER_QUOTE_CHAR:
1069 case SQL_INTEGRITY:
1070 case SQL_KEYWORDS:
1071 case SQL_LIKE_ESCAPE_CLAUSE:
1072 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
1073 case SQL_MULT_RESULT_SETS:
1074 case SQL_MULTIPLE_ACTIVE_TXN:
1075 case SQL_NEED_LONG_DATA_LEN:
1076 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
1077 case SQL_PROCEDURE_TERM:
1078 case SQL_PROCEDURES:
1079 case SQL_ROW_UPDATES:
1080 case SQL_SCHEMA_TERM:
1081 case SQL_SEARCH_PATTERN_ESCAPE:
1082 case SQL_SERVER_NAME:
1083 case SQL_SPECIAL_CHARACTERS:
1084 case SQL_TABLE_TERM:
1085 case SQL_USER_NAME:
1086 case SQL_XOPEN_CLI_YEAR:
1087 case SQL_OUTER_JOINS:
1088 if (conv_direct == CD_A2W)
1089 {
1090 /* ansi<=unicode*/
1091 ret = dm_StrCopyOut2_W2A_d2m (conv, infoValueOut,
1092 (SQLCHAR *) rgbInfoValue, cbInfoValueMax, NULL, &count);
1093 if (pcbInfoValue)
1094 *pcbInfoValue = (SQLSMALLINT)count;
1095 }
1096 else if (conv_direct == CD_W2A)
1097 {
1098 /* unicode<=ansi*/
1099 ret = dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *) infoValueOut,
1100 rgbInfoValue, cbInfoValueMax, NULL, &count);
1101 if (pcbInfoValue)
1102 *pcbInfoValue = (SQLSMALLINT)count;
1103 }
1104 else if (conv_direct == CD_W2W)
1105 {
1106 /* unicode<=unicode*/
1107 ret = dm_StrCopyOut2_W2W_d2m (conv, infoValueOut,
1108 rgbInfoValue, cbInfoValueMax, NULL, &count);
1109 if (pcbInfoValue)
1110 *pcbInfoValue = (SQLSMALLINT)count;
1111 }
1112
1113 if (ret == -1)
1114 {
1115 PUSHSQLERR (pdbc->herr, en_01004);
1116 retcode = SQL_SUCCESS_WITH_INFO;
1117 }
1118 break;
1119 }
1120 }
1121 MEM_FREE(_InfoValue);
1122
1123 return retcode;
1124 }
1125
1126
1127 SQLRETURN SQL_API
SQLGetInfo(SQLHDBC hdbc,SQLUSMALLINT fInfoType,SQLPOINTER rgbInfoValue,SQLSMALLINT cbInfoValueMax,SQLSMALLINT * pcbInfoValue)1128 SQLGetInfo (SQLHDBC hdbc,
1129 SQLUSMALLINT fInfoType,
1130 SQLPOINTER rgbInfoValue,
1131 SQLSMALLINT cbInfoValueMax,
1132 SQLSMALLINT * pcbInfoValue)
1133 {
1134 ENTER_HDBC (hdbc, 0,
1135 trace_SQLGetInfo (TRACE_ENTER,
1136 hdbc,
1137 fInfoType,
1138 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1139
1140 retcode = SQLGetInfo_Internal(
1141 hdbc,
1142 fInfoType,
1143 rgbInfoValue, cbInfoValueMax, pcbInfoValue,
1144 'A');
1145
1146 LEAVE_HDBC (hdbc, 0,
1147 trace_SQLGetInfo (TRACE_LEAVE,
1148 hdbc,
1149 fInfoType,
1150 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1151 }
1152
1153
1154 #if ODBCVER >= 0x0300
1155 SQLRETURN SQL_API
SQLGetInfoA(SQLHDBC hdbc,SQLUSMALLINT fInfoType,SQLPOINTER rgbInfoValue,SQLSMALLINT cbInfoValueMax,SQLSMALLINT * pcbInfoValue)1156 SQLGetInfoA (SQLHDBC hdbc,
1157 SQLUSMALLINT fInfoType,
1158 SQLPOINTER rgbInfoValue,
1159 SQLSMALLINT cbInfoValueMax,
1160 SQLSMALLINT * pcbInfoValue)
1161 {
1162 ENTER_HDBC (hdbc, 0,
1163 trace_SQLGetInfo (TRACE_ENTER,
1164 hdbc,
1165 fInfoType,
1166 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1167
1168 retcode = SQLGetInfo_Internal(
1169 hdbc,
1170 fInfoType,
1171 rgbInfoValue, cbInfoValueMax, pcbInfoValue,
1172 'A');
1173
1174 LEAVE_HDBC (hdbc, 0,
1175 trace_SQLGetInfo (TRACE_LEAVE,
1176 hdbc,
1177 fInfoType,
1178 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1179 }
1180
1181
1182 SQLRETURN SQL_API
SQLGetInfoW(SQLHDBC hdbc,SQLUSMALLINT fInfoType,SQLPOINTER rgbInfoValue,SQLSMALLINT cbInfoValueMax,SQLSMALLINT * pcbInfoValue)1183 SQLGetInfoW (
1184 SQLHDBC hdbc,
1185 SQLUSMALLINT fInfoType,
1186 SQLPOINTER rgbInfoValue,
1187 SQLSMALLINT cbInfoValueMax,
1188 SQLSMALLINT * pcbInfoValue)
1189 {
1190 ENTER_HDBC (hdbc, 0,
1191 trace_SQLGetInfoW (TRACE_ENTER,
1192 hdbc,
1193 fInfoType,
1194 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1195
1196 retcode = SQLGetInfo_Internal (
1197 hdbc,
1198 fInfoType,
1199 rgbInfoValue, cbInfoValueMax, pcbInfoValue,
1200 'W');
1201
1202 LEAVE_HDBC (hdbc, 0,
1203 trace_SQLGetInfoW (TRACE_LEAVE,
1204 hdbc,
1205 fInfoType,
1206 rgbInfoValue, cbInfoValueMax, pcbInfoValue));
1207 }
1208 #endif
1209
1210
1211 static int FunctionNumbers[] =
1212 {
1213 0
1214 #define FUNCDEF(A,B,C) ,A
1215 #include "henv.ci"
1216 #undef FUNCDEF
1217 };
1218
1219
1220
1221 static SQLRETURN
SQLGetFunctions_Internal(SQLHDBC hdbc,SQLUSMALLINT fFunc,SQLUSMALLINT * pfExists)1222 SQLGetFunctions_Internal (
1223 SQLHDBC hdbc,
1224 SQLUSMALLINT fFunc,
1225 SQLUSMALLINT * pfExists)
1226 {
1227 CONN (pdbc, hdbc);
1228 HPROC hproc;
1229 SQLRETURN retcode;
1230 int i;
1231 UWORD functions2[100];
1232 #if (ODBCVER >= 0x0300)
1233 UWORD functions3[SQL_API_ODBC3_ALL_FUNCTIONS_SIZE];
1234 #endif
1235
1236 if (pdbc->state == en_dbc_allocated
1237 || pdbc->state == en_dbc_needdata)
1238 {
1239 PUSHSQLERR (pdbc->herr, en_S1010);
1240
1241 return SQL_ERROR;
1242 }
1243
1244 if (pfExists == NULL)
1245 {
1246 return SQL_SUCCESS;
1247 }
1248
1249 /*
1250 * These functions are supported by the iODBC driver manager
1251 */
1252 if (fFunc == SQL_API_SQLDATASOURCES
1253 || fFunc == SQL_API_SQLDRIVERS
1254 #if (ODBCVER >= 0x0300)
1255 || fFunc == SQL_API_SQLGETENVATTR
1256 || fFunc == SQL_API_SQLSETENVATTR
1257 #endif
1258 )
1259 {
1260 *pfExists = (UWORD) 1;
1261 return SQL_SUCCESS;
1262 }
1263
1264 /*
1265 * Check if function number is within ODBC version context
1266 */
1267 #if (ODBCVER < 0x0300)
1268 if (fFunc > SQL_EXT_API_LAST)
1269 {
1270 PUSHSQLERR (pdbc->herr, en_S1095);
1271
1272 return SQL_ERROR;
1273 }
1274 #endif
1275
1276 /*
1277 * In a ODBC 2.x driver context, the ODBC 3.x API calls are
1278 * mapped by the driver manager.
1279 */
1280 #if (ODBCVER >= 0x0300)
1281 if (((ENV_t *) pdbc->henv)->dodbc_ver == SQL_OV_ODBC2)
1282 {
1283 switch (fFunc)
1284 {
1285 case SQL_API_ALL_FUNCTIONS:
1286 case SQL_API_ODBC3_ALL_FUNCTIONS:
1287 break;
1288
1289 /* Mapped ODBC3 app -> ODBC2 driver functions */
1290 case SQL_API_SQLALLOCHANDLE:
1291 case SQL_API_SQLFREEHANDLE:
1292 case SQL_API_SQLSETCONNECTATTR:
1293 case SQL_API_SQLGETCONNECTATTR:
1294 case SQL_API_SQLGETSTMTATTR:
1295 case SQL_API_SQLSETSTMTATTR:
1296 case SQL_API_SQLCOLATTRIBUTE:
1297 case SQL_API_SQLENDTRAN:
1298 case SQL_API_SQLBULKOPERATIONS:
1299 case SQL_API_SQLFETCHSCROLL:
1300 case SQL_API_SQLGETDIAGREC:
1301 case SQL_API_SQLGETDIAGFIELD:
1302 *pfExists = SQL_TRUE;
1303 return SQL_SUCCESS;
1304
1305 case SQL_API_SQLBINDPARAM:
1306 fFunc = SQL_API_SQLBINDPARAMETER;
1307 break;
1308
1309 default:
1310 if (fFunc > SQL_API_SQLBINDPARAMETER)
1311 {
1312 *pfExists = SQL_FALSE;
1313
1314 return SQL_SUCCESS;
1315 }
1316 break;
1317 }
1318 }
1319 #endif
1320
1321
1322 /*
1323 * If the driver exports a SQLGetFunctions call, use it
1324 */
1325 hproc = _iodbcdm_getproc (pdbc, en_GetFunctions);
1326
1327 if (hproc != SQL_NULL_HPROC)
1328 {
1329 CALL_DRIVER (hdbc, pdbc, retcode, hproc, (pdbc->dhdbc, fFunc, pfExists));
1330
1331 return retcode;
1332 }
1333
1334 /*
1335 * Map deprecated functions
1336 */
1337 if (fFunc == SQL_API_SQLSETPARAM)
1338 {
1339 fFunc = SQL_API_SQLBINDPARAMETER;
1340 }
1341
1342 /*
1343 * Initialize intermediate result arrays
1344 */
1345 memset (functions2, '\0', sizeof (functions2));
1346 #if (ODBCVER > 0x0300)
1347 memset (functions3, '\0', sizeof (functions3));
1348 #endif
1349
1350 /*
1351 * Build result array by scanning for all API calls
1352 */
1353 for (i = 1; i < __LAST_API_FUNCTION__; i++)
1354 {
1355 int j = FunctionNumbers[i];
1356
1357 hproc = _iodbcdm_getproc (pdbc, i);
1358
1359 if (hproc != SQL_NULL_HPROC)
1360 {
1361 if (j < 100)
1362 functions2[j] = 1;
1363 #if (ODBCVER >= 0x0300)
1364 functions3[j >> 4] |= (1 << (j & 0x000F));
1365 #endif
1366 }
1367 }
1368
1369 /*
1370 * Finally return the information
1371 */
1372 if (fFunc == SQL_API_ALL_FUNCTIONS)
1373 {
1374 memcpy (pfExists, &functions2, sizeof (functions2));
1375 }
1376 #if (ODBCVER < 0x0300)
1377 else
1378 {
1379 *pfExists = functions2[fFunc];
1380 }
1381 #else
1382 else if (fFunc == SQL_API_ODBC3_ALL_FUNCTIONS)
1383 {
1384 memcpy (pfExists, &functions3, sizeof (functions3));
1385 }
1386 else
1387 {
1388 *pfExists = SQL_FUNC_EXISTS (functions3, fFunc);
1389 }
1390 #endif
1391
1392 return SQL_SUCCESS;
1393 }
1394
1395
1396 SQLRETURN SQL_API
SQLGetFunctions(SQLHDBC hdbc,SQLUSMALLINT fFunc,SQLUSMALLINT * pfExists)1397 SQLGetFunctions (
1398 SQLHDBC hdbc,
1399 SQLUSMALLINT fFunc,
1400 SQLUSMALLINT * pfExists)
1401 {
1402 ENTER_HDBC (hdbc, 0,
1403 trace_SQLGetFunctions (TRACE_ENTER,
1404 hdbc,
1405 fFunc,
1406 pfExists));
1407
1408 retcode = SQLGetFunctions_Internal (
1409 hdbc,
1410 fFunc,
1411 pfExists);
1412
1413 LEAVE_HDBC (hdbc, 0,
1414 trace_SQLGetFunctions (TRACE_LEAVE,
1415 hdbc,
1416 fFunc,
1417 pfExists));
1418 }
1419