shcore: Use CRT allocation functions.
[wine.git] / dlls / setupapi / dirid.c
blob1de0c5f6c42d63accec993e06991b0c714463c9d
1 /*
2 * Directory id handling
4 * Copyright 2002 Alexandre Julliard for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "winternl.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "setupapi.h"
32 #include "shlobj.h"
33 #include "setupapi_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
38 #define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR
39 #define MIN_CSIDL_DIRID 0x4000
40 #define MAX_CSIDL_DIRID 0x403f
42 struct user_dirid
44 int id;
45 WCHAR *str;
48 #ifdef __i386__
49 static const WCHAR printer_env[] = L"w32x86";
50 #elif defined __x86_64__
51 static const WCHAR printer_env[] = L"x64";
52 #elif defined __arm__
53 static const WCHAR printer_env[] = L"arm";
54 #elif defined __aarch64__
55 static const WCHAR printer_env[] = L"arm64";
56 #else
57 #error not defined for this cpu
58 #endif
60 static int nb_user_dirids; /* number of user dirids in use */
61 static int alloc_user_dirids; /* number of allocated user dirids */
62 static struct user_dirid *user_dirids;
63 static const WCHAR *printer_dirids[5]; /* 66000..66004 */
64 static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1];
65 static const WCHAR *csidl_dirids[MAX_CSIDL_DIRID-MIN_CSIDL_DIRID+1];
67 /* retrieve the string for unknown dirids */
68 static const WCHAR *get_unknown_dirid(void)
70 static WCHAR *unknown_dirid;
72 if (!unknown_dirid)
74 UINT len = GetSystemDirectoryW( NULL, 0 ) + lstrlenW(L"\\unknown");
75 if (!(unknown_dirid = malloc( len * sizeof(WCHAR) ))) return NULL;
76 GetSystemDirectoryW( unknown_dirid, len );
77 lstrcatW( unknown_dirid, L"\\unknown" );
79 return unknown_dirid;
82 static const WCHAR *get_csidl_dir(DWORD csidl);
84 /* create the string for a system dirid */
85 static const WCHAR *create_system_dirid( int dirid )
87 WCHAR buffer[MAX_PATH+32], *str;
88 int len;
90 switch(dirid)
92 case DIRID_NULL:
93 return L"";
94 case DIRID_WINDOWS:
95 GetWindowsDirectoryW( buffer, MAX_PATH );
96 break;
97 case DIRID_SYSTEM:
98 GetSystemDirectoryW( buffer, MAX_PATH );
99 break;
100 case DIRID_DRIVERS:
101 GetSystemDirectoryW( buffer, MAX_PATH );
102 lstrcatW( buffer, L"\\drivers" );
103 break;
104 case DIRID_INF:
105 GetWindowsDirectoryW( buffer, MAX_PATH );
106 lstrcatW( buffer, L"\\inf" );
107 break;
108 case DIRID_HELP:
109 GetWindowsDirectoryW( buffer, MAX_PATH );
110 lstrcatW( buffer, L"\\help" );
111 break;
112 case DIRID_FONTS:
113 GetWindowsDirectoryW( buffer, MAX_PATH );
114 lstrcatW( buffer, L"\\fonts" );
115 break;
116 case DIRID_VIEWERS:
117 GetSystemDirectoryW( buffer, MAX_PATH );
118 lstrcatW( buffer, L"\\viewers" );
119 break;
120 case DIRID_COLOR:
121 GetSystemDirectoryW( buffer, MAX_PATH );
122 lstrcatW( buffer, L"\\spool\\drivers\\color" );
123 break;
124 case DIRID_APPS:
125 return L"C:\\"; /* FIXME */
126 case DIRID_SHARED:
127 GetWindowsDirectoryW( buffer, MAX_PATH );
128 break;
129 case DIRID_BOOT:
130 return L"C:\\"; /* FIXME */
131 case DIRID_SYSTEM16:
132 GetWindowsDirectoryW( buffer, MAX_PATH );
133 lstrcatW( buffer, L"\\system" );
134 break;
135 case DIRID_SPOOL:
136 GetSystemDirectoryW( buffer, MAX_PATH );
137 lstrcatW( buffer, L"\\spool" );
138 break;
139 case DIRID_SPOOLDRIVERS:
140 GetSystemDirectoryW( buffer, MAX_PATH );
141 lstrcatW( buffer, L"\\spool\\drivers" );
142 break;
143 case DIRID_USERPROFILE:
144 if (GetEnvironmentVariableW( L"USERPROFILE", buffer, MAX_PATH )) break;
145 return get_csidl_dir(CSIDL_PROFILE);
146 case DIRID_LOADER:
147 return L"C:\\"; /* FIXME */
148 case DIRID_PRINTPROCESSOR:
149 GetSystemDirectoryW( buffer, MAX_PATH );
150 lstrcatW( buffer, L"\\spool\\prtprocs\\" );
151 lstrcatW( buffer, printer_env );
152 break;
153 default:
154 FIXME( "unknown dirid %d\n", dirid );
155 return get_unknown_dirid();
157 len = (lstrlenW(buffer) + 1) * sizeof(WCHAR);
158 if ((str = malloc( len ))) memcpy( str, buffer, len );
159 return str;
162 static const WCHAR *create_printer_dirid( DWORD dirid )
164 WCHAR buffer[MAX_PATH+32], *str;
165 int len;
167 switch (dirid)
169 case 66000: /* printer driver */
170 GetSystemDirectoryW( buffer, MAX_PATH );
171 lstrcatW( buffer, L"\\spool\\drivers\\" );
172 lstrcatW( buffer, printer_env );
173 break;
174 case 66001: /* print processor */
175 return create_system_dirid( DIRID_PRINTPROCESSOR );
176 case 66002: /* system directory (FIXME: only for native architecture) */
177 GetSystemDirectoryW( buffer, MAX_PATH );
178 break;
179 case 66003: /* color directory */
180 return create_system_dirid( DIRID_COLOR );
181 case 66004: /* asp files directory */
182 default:
183 FIXME( "unsupported dirid %ld\n", dirid );
184 return get_unknown_dirid();
186 len = (lstrlenW(buffer) + 1) * sizeof(WCHAR);
187 if ((str = malloc( len ))) memcpy( str, buffer, len );
188 return str;
191 static const WCHAR *get_csidl_dir( DWORD csidl )
193 WCHAR buffer[MAX_PATH], *str;
194 int len;
196 if (!SHGetSpecialFolderPathW( NULL, buffer, csidl, TRUE ))
198 FIXME( "CSIDL %lx not found\n", csidl );
199 return get_unknown_dirid();
201 len = (lstrlenW(buffer) + 1) * sizeof(WCHAR);
202 if ((str = malloc( len ))) memcpy( str, buffer, len );
203 return str;
206 /* retrieve the string corresponding to a dirid, or NULL if none */
207 const WCHAR *DIRID_get_string( int dirid )
209 int i;
211 if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL;
213 if (dirid >= 66000 && dirid <= 66004)
215 if (!printer_dirids[dirid - 66000]) printer_dirids[dirid - 66000] = create_printer_dirid( dirid );
216 return printer_dirids[dirid - 66000];
218 else if (dirid >= DIRID_USER)
220 for (i = 0; i < nb_user_dirids; i++)
221 if (user_dirids[i].id == dirid) return user_dirids[i].str;
222 WARN("user id %d not found\n", dirid );
223 return NULL;
225 else if (dirid >= MIN_CSIDL_DIRID)
227 if (dirid > MAX_CSIDL_DIRID) return get_unknown_dirid();
228 dirid -= MIN_CSIDL_DIRID;
229 if (!csidl_dirids[dirid]) csidl_dirids[dirid] = get_csidl_dir( dirid );
230 return csidl_dirids[dirid];
232 else
234 if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid();
235 if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid );
236 return system_dirids[dirid];
240 /* store a user dirid string */
241 static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str )
243 int i;
245 for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break;
247 if (i < nb_user_dirids) free( user_dirids[i].str );
248 else
250 if (nb_user_dirids >= alloc_user_dirids)
252 int new_size = max( 32, alloc_user_dirids * 2 );
253 struct user_dirid *new = realloc( user_dirids, new_size * sizeof(*new) );
254 if (!new) return FALSE;
255 user_dirids = new;
256 alloc_user_dirids = new_size;
258 nb_user_dirids++;
260 user_dirids[i].id = id;
261 user_dirids[i].str = str;
262 TRACE("id %d -> %s\n", id, debugstr_w(str) );
263 return TRUE;
267 /***********************************************************************
268 * SetupSetDirectoryIdA (SETUPAPI.@)
270 BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir )
272 UNICODE_STRING dirW;
273 int i;
275 if (!id) /* clear everything */
277 for (i = 0; i < nb_user_dirids; i++) free( user_dirids[i].str );
278 nb_user_dirids = 0;
279 return TRUE;
281 if (id < DIRID_USER)
283 SetLastError( ERROR_INVALID_PARAMETER );
284 return FALSE;
287 /* duplicate the string */
288 if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir ))
290 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
291 return FALSE;
293 return store_user_dirid( hinf, id, dirW.Buffer );
297 /***********************************************************************
298 * SetupSetDirectoryIdW (SETUPAPI.@)
300 BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir )
302 int i, len;
303 WCHAR *str;
305 if (!id) /* clear everything */
307 for (i = 0; i < nb_user_dirids; i++) free( user_dirids[i].str );
308 nb_user_dirids = 0;
309 return TRUE;
311 if (id < DIRID_USER)
313 SetLastError( ERROR_INVALID_PARAMETER );
314 return FALSE;
317 /* duplicate the string */
318 len = (lstrlenW(dir)+1) * sizeof(WCHAR);
319 if (!(str = malloc( len ))) return FALSE;
320 memcpy( str, dir, len );
321 return store_user_dirid( hinf, id, str );