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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/unicode.h"
34 #include "setupapi_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
39 #define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR
40 #define MIN_CSIDL_DIRID 0x4000
41 #define MAX_CSIDL_DIRID 0x403f
49 static int nb_user_dirids
; /* number of user dirids in use */
50 static int alloc_user_dirids
; /* number of allocated user dirids */
51 static struct user_dirid
*user_dirids
;
52 static const WCHAR
*system_dirids
[MAX_SYSTEM_DIRID
+1];
53 static const WCHAR
*csidl_dirids
[MAX_CSIDL_DIRID
-MIN_CSIDL_DIRID
+1];
55 /* retrieve the string for unknown dirids */
56 static const WCHAR
*get_unknown_dirid(void)
58 static WCHAR
*unknown_dirid
;
59 static const WCHAR unknown_str
[] = {'\\','u','n','k','n','o','w','n',0};
63 UINT len
= GetSystemDirectoryW( NULL
, 0 ) + strlenW(unknown_str
);
64 if (!(unknown_dirid
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
65 GetSystemDirectoryW( unknown_dirid
, len
);
66 strcatW( unknown_dirid
, unknown_str
);
71 /* create the string for a system dirid */
72 static const WCHAR
*create_system_dirid( int dirid
)
74 static const WCHAR Null
[] = {0};
75 static const WCHAR C_Root
[] = {'C',':','\\',0};
76 static const WCHAR Drivers
[] = {'\\','d','r','i','v','e','r','s',0};
77 static const WCHAR Inf
[] = {'\\','i','n','f',0};
78 static const WCHAR Help
[] = {'\\','h','e','l','p',0};
79 static const WCHAR Fonts
[] = {'\\','f','o','n','t','s',0};
80 static const WCHAR Viewers
[] = {'\\','v','i','e','w','e','r','s',0};
81 static const WCHAR System
[] = {'\\','s','y','s','t','e','m',0};
82 static const WCHAR Spool
[] = {'\\','s','p','o','o','l',0};
83 static const WCHAR Profile
[] = {'\\','p','r','o','f','i','l','e','s','\\','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
84 static const WCHAR UserProfile
[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
86 WCHAR buffer
[MAX_PATH
+32], *str
;
94 GetWindowsDirectoryW( buffer
, MAX_PATH
);
97 GetSystemDirectoryW( buffer
, MAX_PATH
);
100 GetSystemDirectoryW( buffer
, MAX_PATH
);
101 strcatW( buffer
, Drivers
);
104 GetWindowsDirectoryW( buffer
, MAX_PATH
);
105 strcatW( buffer
, Inf
);
108 GetWindowsDirectoryW( buffer
, MAX_PATH
);
109 strcatW( buffer
, Help
);
112 GetWindowsDirectoryW( buffer
, MAX_PATH
);
113 strcatW( buffer
, Fonts
);
116 GetSystemDirectoryW( buffer
, MAX_PATH
);
117 strcatW( buffer
, Viewers
);
120 return C_Root
; /* FIXME */
122 GetWindowsDirectoryW( buffer
, MAX_PATH
);
125 return C_Root
; /* FIXME */
127 GetWindowsDirectoryW( buffer
, MAX_PATH
);
128 strcatW( buffer
, System
);
131 case DIRID_SPOOLDRIVERS
: /* FIXME */
132 GetWindowsDirectoryW( buffer
, MAX_PATH
);
133 strcatW( buffer
, Spool
);
135 case DIRID_USERPROFILE
:
136 if (GetEnvironmentVariableW( UserProfile
, buffer
, MAX_PATH
)) break;
137 GetWindowsDirectoryW( buffer
, MAX_PATH
);
138 strcatW( buffer
, Profile
);
141 return C_Root
; /* FIXME */
142 case DIRID_COLOR
: /* FIXME */
143 case DIRID_PRINTPROCESSOR
: /* FIXME */
145 FIXME( "unknown dirid %d\n", dirid
);
146 return get_unknown_dirid();
148 len
= (strlenW(buffer
) + 1) * sizeof(WCHAR
);
149 if ((str
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( str
, buffer
, len
);
153 static const WCHAR
*get_csidl_dir( DWORD csidl
)
155 WCHAR buffer
[MAX_PATH
], *str
;
158 if (!SHGetSpecialFolderPathW( NULL
, buffer
, csidl
, TRUE
))
160 FIXME( "CSIDL %lx not found\n", csidl
);
161 return get_unknown_dirid();
163 len
= (strlenW(buffer
) + 1) * sizeof(WCHAR
);
164 if ((str
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( str
, buffer
, len
);
168 /* retrieve the string corresponding to a dirid, or NULL if none */
169 const WCHAR
*DIRID_get_string( HINF hinf
, int dirid
)
173 if (dirid
== DIRID_ABSOLUTE
|| dirid
== DIRID_ABSOLUTE_16BIT
) dirid
= DIRID_NULL
;
175 if (dirid
>= DIRID_USER
)
177 for (i
= 0; i
< nb_user_dirids
; i
++)
178 if (user_dirids
[i
].id
== dirid
) return user_dirids
[i
].str
;
179 ERR("user id %d not found\n", dirid
);
182 else if (dirid
>= MIN_CSIDL_DIRID
)
184 if (dirid
> MAX_CSIDL_DIRID
) return get_unknown_dirid();
185 dirid
-= MIN_CSIDL_DIRID
;
186 if (!csidl_dirids
[dirid
]) csidl_dirids
[dirid
] = get_csidl_dir( dirid
);
187 return csidl_dirids
[dirid
];
191 if (dirid
> MAX_SYSTEM_DIRID
) return get_unknown_dirid();
192 if (dirid
== DIRID_SRCPATH
) return PARSER_get_src_root( hinf
);
193 if (!system_dirids
[dirid
]) system_dirids
[dirid
] = create_system_dirid( dirid
);
194 return system_dirids
[dirid
];
198 /* store a user dirid string */
199 static BOOL
store_user_dirid( HINF hinf
, int id
, WCHAR
*str
)
203 for (i
= 0; i
< nb_user_dirids
; i
++) if (user_dirids
[i
].id
== id
) break;
205 if (i
< nb_user_dirids
) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
208 if (nb_user_dirids
>= alloc_user_dirids
)
210 int new_size
= max( 32, alloc_user_dirids
* 2 );
212 struct user_dirid
*new;
215 new = HeapReAlloc( GetProcessHeap(), 0, user_dirids
,
216 new_size
* sizeof(*new) );
218 new = HeapAlloc( GetProcessHeap(), 0,
219 new_size
* sizeof(*new) );
221 if (!new) return FALSE
;
223 alloc_user_dirids
= new_size
;
227 user_dirids
[i
].id
= id
;
228 user_dirids
[i
].str
= str
;
229 TRACE("id %d -> %s\n", id
, debugstr_w(str
) );
234 /***********************************************************************
235 * SetupSetDirectoryIdA (SETUPAPI.@)
237 BOOL WINAPI
SetupSetDirectoryIdA( HINF hinf
, DWORD id
, PCSTR dir
)
242 if (!id
) /* clear everything */
244 for (i
= 0; i
< nb_user_dirids
; i
++) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
250 SetLastError( ERROR_INVALID_PARAMETER
);
254 /* duplicate the string */
255 if (!RtlCreateUnicodeStringFromAsciiz( &dirW
, dir
))
257 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
260 return store_user_dirid( hinf
, id
, dirW
.Buffer
);
264 /***********************************************************************
265 * SetupSetDirectoryIdW (SETUPAPI.@)
267 BOOL WINAPI
SetupSetDirectoryIdW( HINF hinf
, DWORD id
, PCWSTR dir
)
272 if (!id
) /* clear everything */
274 for (i
= 0; i
< nb_user_dirids
; i
++) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
280 SetLastError( ERROR_INVALID_PARAMETER
);
284 /* duplicate the string */
285 len
= (strlenW(dir
)+1) * sizeof(WCHAR
);
286 if (!(str
= HeapAlloc( GetProcessHeap(), 0, len
))) return FALSE
;
287 memcpy( str
, dir
, len
);
288 return store_user_dirid( hinf
, id
, str
);