1 | /************************************************* |
2 | * SQLInstallDriverEx |
3 | * |
4 | * pnUsageCount UsageCount is incremented and decremented |
5 | * only in this lib. This is done whenever |
6 | * a request is made to install or remove |
7 | * a driver. |
8 | * This differs slightly from the MS spec. |
9 | * see UsageCount entries in odbcinst.ini |
10 | * |
11 | * pszPathOut This lacks some smarts. I will pass pszPathIn |
12 | * back here or, if pszPathIn=NULL, I will default |
13 | * to /usr/lib |
14 | * |
15 | ************************************************** |
16 | * This code was created by Peter Harvey @ CodeByDesign. |
17 | * Released under LGPL 28.JAN.99 |
18 | * |
19 | * Contributions from... |
20 | * ----------------------------------------------- |
21 | * Peter Harvey - pharvey@codebydesign.com |
22 | **************************************************/ |
23 | #include <config.h> |
24 | #include <odbcinstext.h> |
25 | |
26 | BOOL SQLInstallDriverEx( LPCSTR pszDriver, |
27 | LPCSTR pszPathIn, |
28 | LPSTR pszPathOut, |
29 | WORD nPathOutMax, |
30 | WORD *pnPathOut, |
31 | WORD nRequest, |
32 | LPDWORD pnUsageCount ) |
33 | { |
34 | HINI hIni; |
35 | char szObjectName[INI_MAX_OBJECT_NAME+1]; |
36 | char szNameValue[INI_MAX_PROPERTY_NAME+INI_MAX_PROPERTY_VALUE+3]; |
37 | char szPropertyName[INI_MAX_PROPERTY_NAME+1]; |
38 | char szValue[INI_MAX_PROPERTY_VALUE+1]; |
39 | char szIniName[ ODBC_FILENAME_MAX * 2 + 1 ]; |
40 | |
41 | BOOL bInsertUsageCount; |
42 | int nElement; |
43 | int nUsageCount = 0; /* SHOULD GET THIS FROM SOMEWHERE ? */ |
44 | char b1[ ODBC_FILENAME_MAX + 1 ], b2[ ODBC_FILENAME_MAX + 1 ]; |
45 | |
46 | |
47 | inst_logClear(); |
48 | |
49 | /* SANITY CHECKS */ |
50 | if ( pszDriver == NULL || pszPathOut == NULL ) |
51 | { |
52 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_GENERAL_ERR, "" ); |
53 | return FALSE; |
54 | } |
55 | if ( nRequest != ODBC_INSTALL_INQUIRY && nRequest != ODBC_INSTALL_COMPLETE ) |
56 | { |
57 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_REQUEST_TYPE, "" ); |
58 | return FALSE; |
59 | } |
60 | |
61 | memset( pszPathOut, '\0', nPathOutMax ); |
62 | |
63 | if ( pszPathIn ) |
64 | { |
65 | #ifdef VMS |
66 | snprintf( szIniName, sizeof(szIniName), "%s:%s" , pszPathIn, odbcinst_system_file_name( b2 ) ); |
67 | #else |
68 | snprintf( szIniName, sizeof(szIniName), "%s/%s" , pszPathIn, odbcinst_system_file_name( b2 ) ); |
69 | #endif |
70 | } |
71 | else |
72 | { |
73 | #ifdef VMS |
74 | sprintf( szIniName, "%s:%s" , odbcinst_system_file_path( b1 ), odbcinst_system_file_name( b2 ) ); |
75 | #else |
76 | sprintf( szIniName, "%s/%s" , odbcinst_system_file_path( b1 ), odbcinst_system_file_name( b2 ) ); |
77 | #endif |
78 | } |
79 | |
80 | /* PROCESS ODBC INST INI FILE */ |
81 | |
82 | #ifdef __OS2__ |
83 | if ( iniOpen( &hIni, szIniName, "#;" , '[', ']', '=', TRUE, 1L ) != INI_SUCCESS ) |
84 | #else |
85 | if ( iniOpen( &hIni, szIniName, "#;" , '[', ']', '=', TRUE ) != INI_SUCCESS ) |
86 | #endif |
87 | { |
88 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_COMPONENT_NOT_FOUND, "" ); |
89 | return FALSE; |
90 | } |
91 | |
92 | if ( iniElement( (char *)pszDriver, '\0', '\0', 0, szObjectName, INI_MAX_OBJECT_NAME ) != INI_SUCCESS ) |
93 | { |
94 | iniClose( hIni ); |
95 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_KEYWORD_VALUE, "" ); |
96 | return FALSE; |
97 | } |
98 | |
99 | /* LETS GET ITS FILE USAGE VALUE (if any) */ |
100 | if ( iniPropertySeek( hIni, szObjectName, "UsageCount" , "" ) == INI_SUCCESS ) |
101 | { |
102 | iniValue( hIni, szValue ); |
103 | nUsageCount = atoi( szValue ); |
104 | } |
105 | |
106 | /* DOES THE OBJECT ALREADY EXIST? (also ensures that we have correct current object) */ |
107 | if ( iniObjectSeek( hIni, szObjectName ) == INI_SUCCESS ) |
108 | { |
109 | if ( nUsageCount == 0 ) |
110 | nUsageCount = 1; |
111 | |
112 | if ( nRequest == ODBC_INSTALL_COMPLETE ) |
113 | { |
114 | iniObjectDelete( hIni ); |
115 | } |
116 | } |
117 | |
118 | /* LETS ADD THE SECTION AND ENTRY */ |
119 | nUsageCount++; |
120 | if ( nRequest == ODBC_INSTALL_COMPLETE ) |
121 | { |
122 | bInsertUsageCount = TRUE; |
123 | iniObjectInsert( hIni, szObjectName ); |
124 | for ( nElement=1; |
125 | iniElement( (char *)pszDriver, '\0', '\0', nElement, szNameValue, INI_MAX_PROPERTY_NAME+INI_MAX_PROPERTY_VALUE+3 ) == INI_SUCCESS; |
126 | nElement++ ) |
127 | { |
128 | iniElement( szNameValue, '=', '\0', 0, szPropertyName, INI_MAX_PROPERTY_NAME ); |
129 | iniElementEOL( szNameValue, '=', '\0', 1, szValue, INI_MAX_PROPERTY_VALUE ); |
130 | if ( szPropertyName[0] != '\0' ) |
131 | { |
132 | /* OVERRIDE ANY USAGE COUNT CHANGES */ |
133 | if ( strcasecmp( szPropertyName, "UsageCount" ) == 0 ) |
134 | { |
135 | bInsertUsageCount = FALSE; |
136 | sprintf( szValue, "%d" , nUsageCount ); |
137 | } |
138 | iniPropertyInsert( hIni, szPropertyName, szValue ); |
139 | } |
140 | else |
141 | { |
142 | iniClose( hIni ); |
143 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_KEYWORD_VALUE, "" ); |
144 | return FALSE; |
145 | } |
146 | } /* for */ |
147 | |
148 | if ( bInsertUsageCount ) |
149 | { |
150 | /* LETS INSERT USAGE COUNT */ |
151 | sprintf( szValue, "%d" , nUsageCount ); |
152 | iniPropertyInsert( hIni, "UsageCount" , szValue ); |
153 | } |
154 | |
155 | if ( iniCommit( hIni ) != INI_SUCCESS ) |
156 | { |
157 | inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_PATH, "" ); |
158 | iniClose( hIni ); |
159 | return FALSE; |
160 | } |
161 | } |
162 | iniClose( hIni ); |
163 | |
164 | /* OK, SO WHATS LEFT? */ |
165 | if ( pszPathIn == NULL ) |
166 | { |
167 | if ( pszPathOut ) |
168 | { |
169 | if ( strlen( odbcinst_system_file_path( b1 )) < nPathOutMax ) |
170 | { |
171 | strcpy( pszPathOut, odbcinst_system_file_path( b1 )); |
172 | } |
173 | else |
174 | { |
175 | strncpy( pszPathOut, odbcinst_system_file_path( b1 ), nPathOutMax ); |
176 | pszPathOut[ nPathOutMax - 1 ] = '\0'; |
177 | } |
178 | } |
179 | } |
180 | else |
181 | { |
182 | if ( pszPathOut ) |
183 | { |
184 | if ( strlen( pszPathIn ) < nPathOutMax ) |
185 | { |
186 | strcpy( pszPathOut, pszPathIn ); |
187 | } |
188 | else |
189 | { |
190 | strncpy( pszPathOut, pszPathIn, nPathOutMax ); |
191 | pszPathOut[ nPathOutMax - 1 ] = '\0'; |
192 | } |
193 | } |
194 | } |
195 | |
196 | if ( pnPathOut != NULL ) |
197 | { |
198 | if ( pszPathIn == NULL ) |
199 | { |
200 | *pnPathOut = strlen( odbcinst_system_file_path( b1 )); |
201 | } |
202 | else |
203 | { |
204 | *pnPathOut = strlen( pszPathIn ); |
205 | } |
206 | } |
207 | |
208 | if ( pnUsageCount != NULL ) |
209 | { |
210 | *pnUsageCount = nUsageCount; |
211 | } |
212 | |
213 | return TRUE; |
214 | } |
215 | |
216 | BOOL INSTAPI SQLInstallDriverExW(LPCWSTR lpszDriver, |
217 | LPCWSTR lpszPathIn, |
218 | LPWSTR lpszPathOut, |
219 | WORD cbPathOutMax, |
220 | WORD *pcbPathOut, |
221 | WORD fRequest, |
222 | LPDWORD lpdwUsageCount) |
223 | { |
224 | char *drv; |
225 | char *pth; |
226 | char *pout; |
227 | WORD len; |
228 | BOOL ret; |
229 | |
230 | inst_logClear(); |
231 | |
232 | drv = lpszDriver ? _multi_string_alloc_and_copy( lpszDriver ) : (char*)NULL; |
233 | pth = lpszPathIn ? _single_string_alloc_and_copy( lpszPathIn ) : (char*)NULL; |
234 | |
235 | if ( lpszPathOut ) |
236 | { |
237 | if ( cbPathOutMax > 0 ) |
238 | { |
239 | pout = calloc( cbPathOutMax + 1, 1 ); |
240 | } |
241 | else |
242 | { |
243 | pout = NULL; |
244 | } |
245 | } |
246 | else |
247 | { |
248 | pout = NULL; |
249 | } |
250 | |
251 | ret = SQLInstallDriverEx( drv, pth, pout, cbPathOutMax, &len, fRequest, lpdwUsageCount ); |
252 | |
253 | if ( ret ) |
254 | { |
255 | if ( pout && lpszPathOut ) |
256 | { |
257 | _single_copy_to_wide( lpszPathOut, pout, len + 1 ); |
258 | } |
259 | } |
260 | |
261 | if ( pcbPathOut ) |
262 | { |
263 | *pcbPathOut = len; |
264 | } |
265 | |
266 | if ( drv ) |
267 | free( drv ); |
268 | if ( pth ) |
269 | free( pth ); |
270 | if ( pout ) |
271 | free( pout ); |
272 | |
273 | return ret; |
274 | } |
275 | |