[CLT2012]
[reactos.git] / dll / win32 / setupapi / dirid.c
1 /*
2 * Directory id handling
3 *
4 * Copyright 2002 Alexandre Julliard 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
21 #include "setupapi_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
24
25 #define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR
26 #define MIN_CSIDL_DIRID 0x4000
27 #define MAX_CSIDL_DIRID 0x403f
28
29 struct user_dirid
30 {
31 int id;
32 WCHAR *str;
33 };
34
35 static int nb_user_dirids; /* number of user dirids in use */
36 static int alloc_user_dirids; /* number of allocated user dirids */
37 static struct user_dirid *user_dirids;
38 static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1];
39 static const WCHAR *csidl_dirids[MAX_CSIDL_DIRID-MIN_CSIDL_DIRID+1];
40
41 /* retrieve the string for unknown dirids */
42 static const WCHAR *get_unknown_dirid(void)
43 {
44 static WCHAR *unknown_dirid;
45 static const WCHAR unknown_str[] = {'\\','u','n','k','n','o','w','n',0};
46
47 if (!unknown_dirid)
48 {
49 UINT len = GetSystemDirectoryW( NULL, 0 ) + strlenW(unknown_str);
50 if (!(unknown_dirid = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
51 GetSystemDirectoryW( unknown_dirid, len );
52 strcatW( unknown_dirid, unknown_str );
53 }
54 return unknown_dirid;
55 }
56
57 static const WCHAR *get_csidl_dir(DWORD csidl);
58
59 /* create the string for a system dirid */
60 static const WCHAR *create_system_dirid( int dirid )
61 {
62 static const WCHAR Null[] = {0};
63 static const WCHAR C_Root[] = {'C',':','\\',0};
64 static const WCHAR Drivers[] = {'\\','d','r','i','v','e','r','s',0};
65 static const WCHAR Inf[] = {'\\','i','n','f',0};
66 static const WCHAR Help[] = {'\\','h','e','l','p',0};
67 static const WCHAR Fonts[] = {'\\','f','o','n','t','s',0};
68 static const WCHAR Viewers[] = {'\\','v','i','e','w','e','r','s',0};
69 static const WCHAR System[] = {'\\','s','y','s','t','e','m',0};
70 static const WCHAR Spool[] = {'\\','s','p','o','o','l',0};
71 static const WCHAR UserProfile[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
72
73 WCHAR buffer[MAX_PATH+32], *str;
74 int len;
75
76 switch(dirid)
77 {
78 case DIRID_NULL:
79 return Null;
80 case DIRID_WINDOWS:
81 GetWindowsDirectoryW( buffer, MAX_PATH );
82 break;
83 case DIRID_SYSTEM:
84 GetSystemDirectoryW( buffer, MAX_PATH );
85 break;
86 case DIRID_DRIVERS:
87 GetSystemDirectoryW( buffer, MAX_PATH );
88 strcatW( buffer, Drivers );
89 break;
90 case DIRID_INF:
91 GetWindowsDirectoryW( buffer, MAX_PATH );
92 strcatW( buffer, Inf );
93 break;
94 case DIRID_HELP:
95 GetWindowsDirectoryW( buffer, MAX_PATH );
96 strcatW( buffer, Help );
97 break;
98 case DIRID_FONTS:
99 GetWindowsDirectoryW( buffer, MAX_PATH );
100 strcatW( buffer, Fonts );
101 break;
102 case DIRID_VIEWERS:
103 GetSystemDirectoryW( buffer, MAX_PATH );
104 strcatW( buffer, Viewers );
105 break;
106 case DIRID_APPS:
107 return C_Root; /* FIXME */
108 case DIRID_SHARED:
109 GetWindowsDirectoryW( buffer, MAX_PATH );
110 break;
111 case DIRID_BOOT:
112 return C_Root; /* FIXME */
113 case DIRID_SYSTEM16:
114 GetWindowsDirectoryW( buffer, MAX_PATH );
115 strcatW( buffer, System );
116 break;
117 case DIRID_SPOOL:
118 case DIRID_SPOOLDRIVERS: /* FIXME */
119 GetWindowsDirectoryW( buffer, MAX_PATH );
120 strcatW( buffer, Spool );
121 break;
122 case DIRID_USERPROFILE:
123 if (GetEnvironmentVariableW( UserProfile, buffer, MAX_PATH )) break;
124 return get_csidl_dir(CSIDL_PROFILE);
125 case DIRID_LOADER:
126 return C_Root; /* FIXME */
127 case DIRID_COLOR: /* FIXME */
128 case DIRID_PRINTPROCESSOR: /* FIXME */
129 default:
130 FIXME( "unknown dirid %d\n", dirid );
131 return get_unknown_dirid();
132 }
133 len = (strlenW(buffer) + 1) * sizeof(WCHAR);
134 if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len );
135 return str;
136 }
137
138 static const WCHAR *get_csidl_dir( DWORD csidl )
139 {
140 WCHAR buffer[MAX_PATH], *str;
141 int len;
142
143 if (!SHGetSpecialFolderPathW( NULL, buffer, csidl, TRUE ))
144 {
145 FIXME( "CSIDL %x not found\n", csidl );
146 return get_unknown_dirid();
147 }
148 len = (strlenW(buffer) + 1) * sizeof(WCHAR);
149 if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len );
150 return str;
151 }
152
153 /* retrieve the string corresponding to a dirid, or NULL if none */
154 const WCHAR *DIRID_get_string( int dirid )
155 {
156 int i;
157
158 if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL;
159
160 if (dirid >= DIRID_USER)
161 {
162 for (i = 0; i < nb_user_dirids; i++)
163 if (user_dirids[i].id == dirid) return user_dirids[i].str;
164 WARN("user id %d not found\n", dirid );
165 return NULL;
166 }
167 else if (dirid >= MIN_CSIDL_DIRID)
168 {
169 if (dirid > MAX_CSIDL_DIRID) return get_unknown_dirid();
170 dirid -= MIN_CSIDL_DIRID;
171 if (!csidl_dirids[dirid]) csidl_dirids[dirid] = get_csidl_dir( dirid );
172 return csidl_dirids[dirid];
173 }
174 else
175 {
176 if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid();
177 if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid );
178 return system_dirids[dirid];
179 }
180 }
181
182 /* store a user dirid string */
183 static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str )
184 {
185 int i;
186
187 for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break;
188
189 if (i < nb_user_dirids) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
190 else
191 {
192 if (nb_user_dirids >= alloc_user_dirids)
193 {
194 int new_size = max( 32, alloc_user_dirids * 2 );
195
196 struct user_dirid *new;
197
198 if (user_dirids)
199 new = HeapReAlloc( GetProcessHeap(), 0, user_dirids,
200 new_size * sizeof(*new) );
201 else
202 new = HeapAlloc( GetProcessHeap(), 0,
203 new_size * sizeof(*new) );
204
205 if (!new) return FALSE;
206 user_dirids = new;
207 alloc_user_dirids = new_size;
208 }
209 nb_user_dirids++;
210 }
211 user_dirids[i].id = id;
212 user_dirids[i].str = str;
213 TRACE("id %d -> %s\n", id, debugstr_w(str) );
214 return TRUE;
215 }
216
217
218 /***********************************************************************
219 * SetupSetDirectoryIdA (SETUPAPI.@)
220 */
221 BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir )
222 {
223 UNICODE_STRING dirW;
224 int i;
225
226 if (!id) /* clear everything */
227 {
228 for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
229 nb_user_dirids = 0;
230 return TRUE;
231 }
232 if (id < DIRID_USER)
233 {
234 SetLastError( ERROR_INVALID_PARAMETER );
235 return FALSE;
236 }
237
238 /* duplicate the string */
239 if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir ))
240 {
241 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
242 return FALSE;
243 }
244 return store_user_dirid( hinf, id, dirW.Buffer );
245 }
246
247
248 /***********************************************************************
249 * SetupSetDirectoryIdW (SETUPAPI.@)
250 */
251 BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir )
252 {
253 int i, len;
254 WCHAR *str;
255
256 if (!id) /* clear everything */
257 {
258 for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
259 nb_user_dirids = 0;
260 return TRUE;
261 }
262 if (id < DIRID_USER)
263 {
264 SetLastError( ERROR_INVALID_PARAMETER );
265 return FALSE;
266 }
267
268 /* duplicate the string */
269 len = (strlenW(dir)+1) * sizeof(WCHAR);
270 if (!(str = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
271 memcpy( str, dir, len );
272 return store_user_dirid( hinf, id, str );
273 }