| /* |
| * Directory id handling |
| * |
| * Copyright 2002 Alexandre Julliard for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winternl.h" |
| #include "winerror.h" |
| #include "setupapi.h" |
| #include "wine/unicode.h" |
| #include "setupapi_private.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(setupapi); |
| |
| #define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR |
| |
| struct user_dirid |
| { |
| int id; |
| WCHAR *str; |
| }; |
| |
| static int nb_user_dirids; /* number of user dirids in use */ |
| static int alloc_user_dirids; /* number of allocated user dirids */ |
| static struct user_dirid *user_dirids; |
| static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1]; |
| |
| /* retrieve the string for unknown dirids */ |
| static const WCHAR *get_unknown_dirid(void) |
| { |
| static WCHAR *unknown_dirid; |
| static const WCHAR unknown_str[] = {'\\','u','n','k','n','o','w','n',0}; |
| |
| if (!unknown_dirid) |
| { |
| UINT len = GetSystemDirectoryW( NULL, 0 ) + strlenW(unknown_str); |
| if (!(unknown_dirid = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; |
| GetSystemDirectoryW( unknown_dirid, len ); |
| strcatW( unknown_dirid, unknown_str ); |
| } |
| return unknown_dirid; |
| } |
| |
| /* create the string for a system dirid */ |
| static const WCHAR *create_system_dirid( int dirid ) |
| { |
| static const WCHAR Null[] = {0}; |
| static const WCHAR C_Root[] = {'C',':','\\',0}; |
| static const WCHAR Drivers[] = {'\\','d','r','i','v','e','r','s',0}; |
| static const WCHAR Inf[] = {'\\','i','n','f',0}; |
| static const WCHAR Help[] = {'\\','h','e','l','p',0}; |
| static const WCHAR Fonts[] = {'\\','f','o','n','t','s',0}; |
| static const WCHAR Viewers[] = {'\\','v','i','e','w','e','r','s',0}; |
| static const WCHAR System[] = {'\\','s','y','s','t','e','m',0}; |
| static const WCHAR Spool[] = {'\\','s','p','o','o','l',0}; |
| |
| WCHAR buffer[MAX_PATH+16], *str; |
| int len; |
| |
| switch(dirid) |
| { |
| case DIRID_NULL: |
| return Null; |
| case DIRID_WINDOWS: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| break; |
| case DIRID_SYSTEM: |
| GetSystemDirectoryW( buffer, MAX_PATH ); |
| break; |
| case DIRID_DRIVERS: |
| GetSystemDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Drivers ); |
| break; |
| case DIRID_INF: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Inf ); |
| break; |
| case DIRID_HELP: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Help ); |
| break; |
| case DIRID_FONTS: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Fonts ); |
| break; |
| case DIRID_VIEWERS: |
| GetSystemDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Viewers ); |
| break; |
| case DIRID_APPS: |
| return C_Root; /* FIXME */ |
| case DIRID_SHARED: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| break; |
| case DIRID_BOOT: |
| return C_Root; /* FIXME */ |
| case DIRID_SYSTEM16: |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, System ); |
| break; |
| case DIRID_SPOOL: |
| case DIRID_SPOOLDRIVERS: /* FIXME */ |
| GetWindowsDirectoryW( buffer, MAX_PATH ); |
| strcatW( buffer, Spool ); |
| break; |
| case DIRID_LOADER: |
| return C_Root; /* FIXME */ |
| case DIRID_USERPROFILE: /* FIXME */ |
| case DIRID_COLOR: /* FIXME */ |
| case DIRID_PRINTPROCESSOR: /* FIXME */ |
| default: |
| FIXME( "unknwon dirid %d\n", dirid ); |
| return get_unknown_dirid(); |
| } |
| len = (strlenW(buffer) + 1) * sizeof(WCHAR); |
| if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len ); |
| return str; |
| } |
| |
| /* retrieve the string corresponding to a dirid, or NULL if none */ |
| const WCHAR *DIRID_get_string( HINF hinf, int dirid ) |
| { |
| int i; |
| |
| if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL; |
| |
| if (dirid >= DIRID_USER) |
| { |
| for (i = 0; i < nb_user_dirids; i++) |
| if (user_dirids[i].id == dirid) return user_dirids[i].str; |
| ERR("user id %d not found\n", dirid ); |
| return NULL; |
| } |
| else |
| { |
| if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid(); |
| if (dirid == DIRID_SRCPATH) return PARSER_get_src_root( hinf ); |
| if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid ); |
| return system_dirids[dirid]; |
| } |
| } |
| |
| /* store a user dirid string */ |
| static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str ) |
| { |
| int i; |
| |
| for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break; |
| |
| if (i < nb_user_dirids) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); |
| else |
| { |
| if (nb_user_dirids >= alloc_user_dirids) |
| { |
| int new_size = max( 32, alloc_user_dirids * 2 ); |
| struct user_dirid *new = HeapReAlloc( GetProcessHeap(), 0, user_dirids, |
| new_size * sizeof(*new) ); |
| if (!new) return FALSE; |
| user_dirids = new; |
| alloc_user_dirids = new_size; |
| } |
| nb_user_dirids++; |
| } |
| user_dirids[i].id = id; |
| user_dirids[i].str = str; |
| TRACE("id %d -> %s\n", id, debugstr_w(str) ); |
| return TRUE; |
| } |
| |
| |
| /*********************************************************************** |
| * SetupSetDirectoryIdA (SETUPAPI.@) |
| */ |
| BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir ) |
| { |
| UNICODE_STRING dirW; |
| int i; |
| |
| if (!id) /* clear everything */ |
| { |
| for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); |
| nb_user_dirids = 0; |
| return TRUE; |
| } |
| if (id < DIRID_USER) |
| { |
| SetLastError( ERROR_INVALID_PARAMETER ); |
| return FALSE; |
| } |
| |
| /* duplicate the string */ |
| if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir )) |
| { |
| SetLastError( ERROR_NOT_ENOUGH_MEMORY ); |
| return FALSE; |
| } |
| return store_user_dirid( hinf, id, dirW.Buffer ); |
| } |
| |
| |
| /*********************************************************************** |
| * SetupSetDirectoryIdW (SETUPAPI.@) |
| */ |
| BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir ) |
| { |
| int i, len; |
| WCHAR *str; |
| |
| if (!id) /* clear everything */ |
| { |
| for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); |
| nb_user_dirids = 0; |
| return TRUE; |
| } |
| if (id < DIRID_USER) |
| { |
| SetLastError( ERROR_INVALID_PARAMETER ); |
| return FALSE; |
| } |
| |
| /* duplicate the string */ |
| len = (strlenW(dir)+1) * sizeof(WCHAR); |
| if (!(str = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; |
| memcpy( str, dir, len ); |
| return store_user_dirid( hinf, id, str ); |
| } |