setupapi: Test SetupDiInstallClass.
[wine] / dlls / setupapi / infparse.c
1 /*
2  * SetupX .inf file parsing functions
3  *
4  * Copyright 2000 Andreas Mohr for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * FIXME:
21  * - return values ???
22  * - this should be reimplemented at some point to have its own
23  *   file parsing instead of using profile functions,
24  *   as some SETUPX exports probably demand that
25  *   (IpSaveRestorePosition, IpFindNextMatchLine, ...).
26  */
27
28 #include <stdarg.h>
29 #include <string.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winreg.h"
34 #include "winternl.h"
35 #include "wingdi.h"
36 #include "winuser.h"
37 #include "winnls.h"
38 #include "setupapi.h"
39 #include "setupx16.h"
40 #include "setupapi_private.h"
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
44
45 #define MAX_HANDLES 16384
46 #define FIRST_HANDLE 32
47
48 static HINF handles[MAX_HANDLES];
49
50
51 static RETERR16 alloc_hinf16( HINF hinf, HINF16 *hinf16 )
52 {
53     int i;
54     for (i = 0; i < MAX_HANDLES; i++)
55     {
56         if (!handles[i])
57         {
58             handles[i] = hinf;
59             *hinf16 = i + FIRST_HANDLE;
60             return OK;
61         }
62     }
63     return ERR_IP_OUT_OF_HANDLES;
64 }
65
66 static HINF get_hinf( HINF16 hinf16 )
67 {
68     int idx = hinf16 - FIRST_HANDLE;
69     if (idx < 0 || idx >= MAX_HANDLES) return 0;
70     return handles[idx];
71 }
72
73
74 static HINF free_hinf16( HINF16 hinf16 )
75 {
76     HINF ret;
77     int idx = hinf16 - FIRST_HANDLE;
78
79     if (idx < 0 || idx >= MAX_HANDLES) return 0;
80     ret = handles[idx];
81     handles[idx] = 0;
82     return ret;
83 }
84
85 /* convert last error code to a RETERR16 value */
86 static RETERR16 get_last_error(void)
87 {
88     switch(GetLastError())
89     {
90     case ERROR_EXPECTED_SECTION_NAME:
91     case ERROR_BAD_SECTION_NAME_LINE:
92     case ERROR_SECTION_NAME_TOO_LONG: return ERR_IP_INVALID_SECT_NAME;
93     case ERROR_SECTION_NOT_FOUND: return ERR_IP_SECT_NOT_FOUND;
94     case ERROR_LINE_NOT_FOUND: return ERR_IP_LINE_NOT_FOUND;
95     default: return IP_ERROR;  /* FIXME */
96     }
97 }
98
99
100 /***********************************************************************
101  *              IpOpen (SETUPX.2)
102  *
103  */
104 RETERR16 WINAPI IpOpen16( LPCSTR filename, HINF16 *hinf16 )
105 {
106     HINF hinf = SetupOpenInfFileA( filename, NULL, INF_STYLE_WIN4, NULL );
107     if (hinf == (HINF)INVALID_HANDLE_VALUE) return get_last_error();
108     return alloc_hinf16( hinf, hinf16 );
109 }
110
111
112 /***********************************************************************
113  *              IpClose (SETUPX.4)
114  */
115 RETERR16 WINAPI IpClose16( HINF16 hinf16 )
116 {
117     HINF hinf = free_hinf16( hinf16 );
118     if (!hinf) return ERR_IP_INVALID_HINF;
119     SetupCloseInfFile( hinf );
120     return OK;
121 }
122
123
124 /***********************************************************************
125  *              IpGetProfileString (SETUPX.210)
126  */
127 RETERR16 WINAPI IpGetProfileString16( HINF16 hinf16, LPCSTR section, LPCSTR entry,
128                                       LPSTR buffer, WORD buflen )
129 {
130     DWORD required_size;
131     HINF hinf = get_hinf( hinf16 );
132
133     if (!hinf) return ERR_IP_INVALID_HINF;
134     if (!SetupGetLineTextA( NULL, hinf, section, entry, buffer, buflen, &required_size ))
135         return get_last_error();
136     TRACE("%p: section %s entry %s ret %s\n",
137           hinf, debugstr_a(section), debugstr_a(entry), debugstr_a(buffer) );
138     return OK;
139 }
140
141
142 /***********************************************************************
143  *              GenFormStrWithoutPlaceHolders (SETUPX.103)
144  *
145  * ought to be pretty much implemented, I guess...
146  */
147 void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR dst, LPCSTR src, HINF16 hinf16 )
148 {
149     UNICODE_STRING srcW;
150     HINF hinf = get_hinf( hinf16 );
151
152     if (!hinf) return;
153
154     if (!RtlCreateUnicodeStringFromAsciiz( &srcW, src )) return;
155     PARSER_string_substA( hinf, srcW.Buffer, dst, MAX_INF_STRING_LENGTH );
156     RtlFreeUnicodeString( &srcW );
157     TRACE( "%s -> %s\n", debugstr_a(src), debugstr_a(dst) );
158 }
159
160 /***********************************************************************
161  *              GenInstall (SETUPX.101)
162  *
163  * generic installer function for .INF file sections
164  *
165  * This is not perfect - patch whenever you can !
166  *
167  * wFlags == GENINSTALL_DO_xxx
168  * e.g. NetMeeting:
169  * first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES,
170  * second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI
171  */
172 RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags )
173 {
174     UINT flags = 0;
175     HINF hinf = get_hinf( hinf16 );
176     RETERR16 ret = OK;
177     void *context;
178
179     if (!hinf) return ERR_IP_INVALID_HINF;
180
181     if (genflags & GENINSTALL_DO_FILES) flags |= SPINST_FILES;
182     if (genflags & GENINSTALL_DO_INI) flags |= SPINST_INIFILES;
183     if (genflags & GENINSTALL_DO_REG) flags |= SPINST_REGISTRY;
184     if (genflags & GENINSTALL_DO_INI2REG) flags |= SPINST_INI2REG;
185     if (genflags & GENINSTALL_DO_LOGCONFIG) flags |= SPINST_LOGCONFIG;
186     if (genflags & GENINSTALL_DO_REGSRCPATH) FIXME( "unsupported flag: GENINSTALL_DO_REGSRCPATH\n" );
187     if (genflags & GENINSTALL_DO_CFGAUTO) FIXME( "unsupported flag: GENINSTALL_DO_CFGAUTO\n" );
188     if (genflags & GENINSTALL_DO_PERUSER) FIXME( "unsupported flag: GENINSTALL_DO_PERUSER\n" );
189
190     context = SetupInitDefaultQueueCallback( 0 );
191     if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL,
192                                       SP_COPY_NEWER_OR_SAME, SetupDefaultQueueCallbackA,
193                                       context, 0, 0 ))
194         ret = get_last_error();
195
196     SetupTermDefaultQueueCallback( context );
197     return ret;
198 }