diff --git a/dlls/setupapi/query.c b/dlls/setupapi/query.c index 932fb988b66..e11ea59da0a 100644 --- a/dlls/setupapi/query.c +++ b/dlls/setupapi/query.c @@ -29,10 +29,32 @@ #include "advpub.h" #include "winnls.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "setupapi_private.h" WINE_DEFAULT_DEBUG_CHANNEL(setupapi); +#ifdef __i386__ +static const WCHAR source_disks_names_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s','.','x','8','6',0}; +static const WCHAR source_disks_files_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s','.','x','8','6',0}; +#elif defined(__x86_64) +static const WCHAR source_disks_names_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s','.','a','m','d','6','4',0}; +static const WCHAR source_disks_files_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s','.','a','m','d','6','4',0}; +#else /* FIXME: other platforms */ +static const WCHAR source_disks_names_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; +static const WCHAR source_disks_files_platform[] = + {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; +#endif +static const WCHAR source_disks_names[] = + {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; +static const WCHAR source_disks_files[] = + {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; + /* fills the PSP_INF_INFORMATION struct fill_info is TRUE * always returns the required size of the information */ @@ -281,3 +303,125 @@ BOOL WINAPI SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation, lstrcpyW(ReturnBuffer, ptr); return TRUE; } + +/*********************************************************************** + * SetupGetSourceFileLocationA (SETUPAPI.@) + */ + +BOOL WINAPI SetupGetSourceFileLocationA( HINF hinf, PINFCONTEXT context, PCSTR filename, + PUINT source_id, PSTR buffer, DWORD buffer_size, + PDWORD required_size ) +{ + BOOL ret = FALSE; + WCHAR *filenameW = NULL, *bufferW = NULL; + DWORD required; + INT size; + + TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_a(filename), source_id, + buffer, buffer_size, required_size); + + if (filename && !(filenameW = strdupAtoW( filename ))) + return FALSE; + + if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, NULL, 0, &required )) + goto done; + + if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) ))) + goto done; + + if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, bufferW, required, NULL )) + goto done; + + size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); + if (required_size) *required_size = size; + + if (buffer) + { + if (buffer_size >= size) + WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL ); + else + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto done; + } + } + ret = TRUE; + + done: + HeapFree( GetProcessHeap(), 0, filenameW ); + HeapFree( GetProcessHeap(), 0, bufferW ); + return ret; +} + +static LPWSTR get_source_id( HINF hinf, PINFCONTEXT context, PCWSTR filename ) +{ + DWORD size; + LPWSTR source_id; + + if (!SetupFindFirstLineW( hinf, source_disks_files_platform, filename, context ) && + !SetupFindFirstLineW( hinf, source_disks_files, filename, context )) + return NULL; + + if (!SetupGetStringFieldW( context, 1, NULL, 0, &size )) + return NULL; + + if (!(source_id = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) + return NULL; + + if (!SetupGetStringFieldW( context, 1, source_id, size, NULL )) + { + HeapFree( GetProcessHeap(), 0, source_id ); + return NULL; + } + + if (!SetupFindFirstLineW( hinf, source_disks_names_platform, source_id, context ) && + !SetupFindFirstLineW( hinf, source_disks_names, source_id, context )) + { + HeapFree( GetProcessHeap(), 0, source_id ); + return NULL; + } + return source_id; +} + +/*********************************************************************** + * SetupGetSourceFileLocationW (SETUPAPI.@) + */ + +BOOL WINAPI SetupGetSourceFileLocationW( HINF hinf, PINFCONTEXT context, PCWSTR filename, + PUINT source_id, PWSTR buffer, DWORD buffer_size, + PDWORD required_size ) +{ + INFCONTEXT ctx; + WCHAR *end, *source_id_str; + + TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_w(filename), source_id, + buffer, buffer_size, required_size); + + if (!context) context = &ctx; + + if (!(source_id_str = get_source_id( hinf, context, filename ))) + return FALSE; + + *source_id = strtolW( source_id_str, &end, 10 ); + if (end == source_id_str || *end) + { + HeapFree( GetProcessHeap(), 0, source_id_str ); + return FALSE; + } + HeapFree( GetProcessHeap(), 0, source_id_str ); + + if (SetupGetStringFieldW( context, 4, buffer, buffer_size, required_size )) + return TRUE; + + if (required_size) *required_size = 1; + if (buffer) + { + if (buffer_size >= 1) buffer[0] = 0; + else + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + } + return TRUE; +} diff --git a/dlls/setupapi/queue.c b/dlls/setupapi/queue.c index 3ddb5521600..26522e68613 100644 --- a/dlls/setupapi/queue.c +++ b/dlls/setupapi/queue.c @@ -84,19 +84,6 @@ inline static WCHAR *strdupW( const WCHAR *str ) return ret; } - -inline static WCHAR *strdupAtoW( const char *str ) -{ - WCHAR *ret = NULL; - if (str) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); - } - return ret; -} - inline static char *strdupWtoA( const WCHAR *str ) { char *ret = NULL; diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index d0a6d228ba8..4ea80f53f90 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -413,8 +413,8 @@ @ stdcall SetupGetLineTextW(ptr long wstr wstr ptr long ptr) @ stdcall SetupGetMultiSzFieldA(ptr long ptr long ptr) @ stdcall SetupGetMultiSzFieldW(ptr long ptr long ptr) -@ stub SetupGetSourceFileLocationA -@ stub SetupGetSourceFileLocationW +@ stdcall SetupGetSourceFileLocationA(ptr ptr str ptr ptr long ptr) +@ stdcall SetupGetSourceFileLocationW(ptr ptr wstr ptr ptr long ptr) @ stub SetupGetSourceFileSizeA @ stub SetupGetSourceFileSizeW @ stdcall SetupGetSourceInfoA(ptr long long str long ptr) diff --git a/dlls/setupapi/setupapi_private.h b/dlls/setupapi/setupapi_private.h index bce05cb7234..ed9a7bfff29 100644 --- a/dlls/setupapi/setupapi_private.h +++ b/dlls/setupapi/setupapi_private.h @@ -29,6 +29,18 @@ #define REGPART_RENAME "\\Rename" #define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager" +inline static WCHAR *strdupAtoW( const char *str ) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + } + return ret; +} + /* string substitutions */ struct inf_file; diff --git a/include/setupapi.h b/include/setupapi.h index 231b30a8bf5..f74bd5baf00 100644 --- a/include/setupapi.h +++ b/include/setupapi.h @@ -814,6 +814,9 @@ BOOL WINAPI SetupGetLineTextW( PINFCONTEXT context, HINF hinf, PCWSTR sectio BOOL WINAPI SetupGetMultiSzFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, LPDWORD required ); BOOL WINAPI SetupGetMultiSzFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, LPDWORD required ); #define SetupGetMultiSzField WINELIB_NAME_AW(SetupGetMultiSzField) +BOOL WINAPI SetupGetSourceFileLocationA( HINF hinf, PINFCONTEXT context, PCSTR filename, PUINT source_id, PSTR buffer, DWORD buffer_size, PDWORD required_size ); +BOOL WINAPI SetupGetSourceFileLocationW( HINF hinf, PINFCONTEXT context, PCWSTR filename, PUINT source_id, PWSTR buffer, DWORD buffer_size, PDWORD required_size ); +#define SetupGetSourceFileLocation WINELIB_NAME_AW(SetupGetSourceFileLocation) BOOL WINAPI SetupGetStringFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required ); BOOL WINAPI SetupGetStringFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, PDWORD required ); #define SetupGetStringField WINELIB_NAME_AW(SetupGetStringField)