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