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
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
49 static const WCHAR printer_env
[] = L
"w32x86";
50 #elif defined __x86_64__
51 static const WCHAR printer_env
[] = L
"x64";
53 static const WCHAR printer_env
[] = L
"arm";
54 #elif defined __aarch64__
55 static const WCHAR printer_env
[] = L
"arm64";
57 #error not defined for this cpu
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
;
74 UINT len
= GetSystemDirectoryW( NULL
, 0 ) + lstrlenW(L
"\\unknown");
75 if (!(unknown_dirid
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
76 GetSystemDirectoryW( unknown_dirid
, len
);
77 lstrcatW( unknown_dirid
, L
"\\unknown" );
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
;
95 GetWindowsDirectoryW( buffer
, MAX_PATH
);
98 GetSystemDirectoryW( buffer
, MAX_PATH
);
101 GetSystemDirectoryW( buffer
, MAX_PATH
);
102 lstrcatW( buffer
, L
"\\drivers" );
105 GetWindowsDirectoryW( buffer
, MAX_PATH
);
106 lstrcatW( buffer
, L
"\\inf" );
109 GetWindowsDirectoryW( buffer
, MAX_PATH
);
110 lstrcatW( buffer
, L
"\\help" );
113 GetWindowsDirectoryW( buffer
, MAX_PATH
);
114 lstrcatW( buffer
, L
"\\fonts" );
117 GetSystemDirectoryW( buffer
, MAX_PATH
);
118 lstrcatW( buffer
, L
"\\viewers" );
121 GetSystemDirectoryW( buffer
, MAX_PATH
);
122 lstrcatW( buffer
, L
"\\spool\\drivers\\color" );
125 return L
"C:\\"; /* FIXME */
127 GetWindowsDirectoryW( buffer
, MAX_PATH
);
130 return L
"C:\\"; /* FIXME */
132 GetWindowsDirectoryW( buffer
, MAX_PATH
);
133 lstrcatW( buffer
, L
"\\system" );
136 GetSystemDirectoryW( buffer
, MAX_PATH
);
137 lstrcatW( buffer
, L
"\\spool" );
139 case DIRID_SPOOLDRIVERS
:
140 GetSystemDirectoryW( buffer
, MAX_PATH
);
141 lstrcatW( buffer
, L
"\\spool\\drivers" );
143 case DIRID_USERPROFILE
:
144 if (GetEnvironmentVariableW( L
"USERPROFILE", buffer
, MAX_PATH
)) break;
145 return get_csidl_dir(CSIDL_PROFILE
);
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
);
154 FIXME( "unknown dirid %d\n", dirid
);
155 return get_unknown_dirid();
157 len
= (lstrlenW(buffer
) + 1) * sizeof(WCHAR
);
158 if ((str
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( str
, buffer
, len
);
162 static const WCHAR
*create_printer_dirid( DWORD dirid
)
164 WCHAR buffer
[MAX_PATH
+32], *str
;
169 case 66000: /* printer driver */
170 GetSystemDirectoryW( buffer
, MAX_PATH
);
171 lstrcatW( buffer
, L
"\\spool\\drivers\\" );
172 lstrcatW( buffer
, printer_env
);
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
);
179 case 66003: /* color directory */
180 return create_system_dirid( DIRID_COLOR
);
181 case 66004: /* asp files directory */
183 FIXME( "unsupported dirid %d\n", dirid
);
184 return get_unknown_dirid();
186 len
= (lstrlenW(buffer
) + 1) * sizeof(WCHAR
);
187 if ((str
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( str
, buffer
, len
);
191 static const WCHAR
*get_csidl_dir( DWORD csidl
)
193 WCHAR buffer
[MAX_PATH
], *str
;
196 if (!SHGetSpecialFolderPathW( NULL
, buffer
, csidl
, TRUE
))
198 FIXME( "CSIDL %x not found\n", csidl
);
199 return get_unknown_dirid();
201 len
= (lstrlenW(buffer
) + 1) * sizeof(WCHAR
);
202 if ((str
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( str
, buffer
, len
);
206 /* retrieve the string corresponding to a dirid, or NULL if none */
207 const WCHAR
*DIRID_get_string( int dirid
)
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
);
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
];
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
)
245 for (i
= 0; i
< nb_user_dirids
; i
++) if (user_dirids
[i
].id
== id
) break;
247 if (i
< nb_user_dirids
) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
250 if (nb_user_dirids
>= alloc_user_dirids
)
252 int new_size
= max( 32, alloc_user_dirids
* 2 );
254 struct user_dirid
*new;
257 new = HeapReAlloc( GetProcessHeap(), 0, user_dirids
,
258 new_size
* sizeof(*new) );
260 new = HeapAlloc( GetProcessHeap(), 0,
261 new_size
* sizeof(*new) );
263 if (!new) return FALSE
;
265 alloc_user_dirids
= new_size
;
269 user_dirids
[i
].id
= id
;
270 user_dirids
[i
].str
= str
;
271 TRACE("id %d -> %s\n", id
, debugstr_w(str
) );
276 /***********************************************************************
277 * SetupSetDirectoryIdA (SETUPAPI.@)
279 BOOL WINAPI
SetupSetDirectoryIdA( HINF hinf
, DWORD id
, PCSTR dir
)
284 if (!id
) /* clear everything */
286 for (i
= 0; i
< nb_user_dirids
; i
++) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
292 SetLastError( ERROR_INVALID_PARAMETER
);
296 /* duplicate the string */
297 if (!RtlCreateUnicodeStringFromAsciiz( &dirW
, dir
))
299 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
302 return store_user_dirid( hinf
, id
, dirW
.Buffer
);
306 /***********************************************************************
307 * SetupSetDirectoryIdW (SETUPAPI.@)
309 BOOL WINAPI
SetupSetDirectoryIdW( HINF hinf
, DWORD id
, PCWSTR dir
)
314 if (!id
) /* clear everything */
316 for (i
= 0; i
< nb_user_dirids
; i
++) HeapFree( GetProcessHeap(), 0, user_dirids
[i
].str
);
322 SetLastError( ERROR_INVALID_PARAMETER
);
326 /* duplicate the string */
327 len
= (lstrlenW(dir
)+1) * sizeof(WCHAR
);
328 if (!(str
= HeapAlloc( GetProcessHeap(), 0, len
))) return FALSE
;
329 memcpy( str
, dir
, len
);
330 return store_user_dirid( hinf
, id
, str
);