Merge SetupGetFileCompressionInfo[Ex]A/W, SetupDecompressOrCopyFileA/W, SetupGetSourc...
authorHervé Poussineau <hpoussin@reactos.org>
Fri, 27 Jul 2007 09:02:18 +0000 (09:02 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Fri, 27 Jul 2007 09:02:18 +0000 (09:02 +0000)
Misc fixes by me and Wine team

svn path=/trunk/; revision=27896

13 files changed:
reactos/dll/win32/setupapi/cfgmgr.c
reactos/dll/win32/setupapi/devclass.c
reactos/dll/win32/setupapi/devinst.c
reactos/dll/win32/setupapi/install.c
reactos/dll/win32/setupapi/misc.c
reactos/dll/win32/setupapi/parser.c
reactos/dll/win32/setupapi/query.c
reactos/dll/win32/setupapi/queue.c
reactos/dll/win32/setupapi/setupapi.rbuild
reactos/dll/win32/setupapi/setupapi.spec
reactos/dll/win32/setupapi/setupapi_private.h
reactos/dll/win32/setupapi/stubs.c
reactos/include/psdk/setupapi.h

index 1fffe5b..afc2d83 100644 (file)
@@ -66,9 +66,9 @@ static BOOL GuidToString(LPGUID Guid, LPWSTR String)
 
     lstrcpyW(&String[1], lpString);
 
-    String[0] = L'{';
-    String[MAX_GUID_STRING_LEN - 2] = L'}';
-    String[MAX_GUID_STRING_LEN - 1] = 0;
+    String[0] = '{';
+    String[MAX_GUID_STRING_LEN - 2] = '}';
+    String[MAX_GUID_STRING_LEN - 1] = UNICODE_NULL;
 
     RpcStringFreeW(&lpString);
 
index 6121512..36890a9 100644 (file)
@@ -276,7 +276,7 @@ SetupDiBuildClassInfoListExW(
             TRACE("Guid: %s\n", debugstr_w(szKeyName));
             if (dwGuidListIndex < ClassGuidListSize)
             {
-                if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+                if (szKeyName[0] == '{' && szKeyName[37] == '}')
                     szKeyName[37] = 0;
 
                 UuidFromStringW(&szKeyName[1],
@@ -472,7 +472,7 @@ SetupDiClassGuidsFromNameExW(
                     TRACE("Guid: %s\n", debugstr_w(szKeyName));
                     if (dwGuidListIndex < ClassGuidListSize)
                     {
-                        if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+                        if (szKeyName[0] == '{' && szKeyName[37] == '}')
                             szKeyName[37] = 0;
 
                         UuidFromStringW(&szKeyName[1],
index 36b3f87..2b5ab05 100644 (file)
@@ -172,7 +172,7 @@ SetupDiCreateDeviceInfoListExW(
     IN PCWSTR MachineName OPTIONAL,
     IN PVOID Reserved)
 {
-    struct DeviceInfoSet *list;
+    struct DeviceInfoSet *list = NULL;
     DWORD size;
     DWORD rc;
     CONFIGRET cr;
@@ -181,6 +181,12 @@ SetupDiCreateDeviceInfoListExW(
     TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
         debugstr_w(MachineName), Reserved);
 
+    if (Reserved != NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        goto cleanup;
+    }
+
     size = FIELD_OFFSET(struct DeviceInfoSet, szData);
     if (MachineName)
         size += (strlenW(MachineName) + 3) * sizeof(WCHAR);
@@ -205,7 +211,7 @@ SetupDiCreateDeviceInfoListExW(
         rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
         if (rc != ERROR_SUCCESS)
         {
-            SetLastError(rc);
+            SetLastError(ERROR_INVALID_MACHINENAME);
             goto cleanup;
         }
 
@@ -493,7 +499,7 @@ CheckSectionValid(
         if (Fields[i])
         {
             Fields[i]++;
-            *(Fields[i] - 1) = L'\0';
+            *(Fields[i] - 1) = UNICODE_NULL;
         }
     }
     /* Take care of first 2 fields */
@@ -3422,7 +3428,7 @@ SetupDiInstallDevice(
     TRACE("Write information to driver key\n");
     TRACE("DriverDate      : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
     TRACE("DriverDesc      : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
-    TRACE("DriverVersion   : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
+    TRACE("DriverVersion   : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
     TRACE("InfPath         : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
     TRACE("InfSection      : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
     TRACE("InfSectionExt   : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
index 498a6c3..ddf83de 100644 (file)
@@ -981,7 +981,7 @@ static BOOL needs_callback( HINF hinf, PCWSTR field, void *arg )
             return SetupInstallServicesFromInfSectionExW(*(HINF*)hinf, field, info->flags,
                 info->devinfo, info->devinfo_data, info->reserved1, info->reserved2);
         default:
-            ERR("Unknown info type %ld\n", info->type);
+            ERR("Unknown info type %u\n", info->type);
             return FALSE;
     }
 }
@@ -1689,7 +1689,7 @@ BOOL WINAPI SetupCopyOEMInfA(
         SetLastError(ERROR_INVALID_PARAMETER);
     else if (!(SourceInfFileNameW = MultiByteToUnicode(SourceInfFileName, CP_ACP)))
         SetLastError(ERROR_INVALID_PARAMETER);
-    else if (!(OEMSourceMediaLocationW = MultiByteToUnicode(OEMSourceMediaLocation, CP_ACP)))
+    else if (OEMSourceMediaType != SPOST_NONE && !(OEMSourceMediaLocationW = MultiByteToUnicode(OEMSourceMediaLocation, CP_ACP)))
         SetLastError(ERROR_INVALID_PARAMETER);
     else
     {
@@ -1743,6 +1743,29 @@ cleanup:
     return ret;
 }
 
+static int compare_files( HANDLE file1, HANDLE file2 )
+{
+    char buffer1[2048];
+    char buffer2[2048];
+    DWORD size1;
+    DWORD size2;
+
+    while( ReadFile(file1, buffer1, sizeof(buffer1), &size1, NULL) &&
+           ReadFile(file2, buffer2, sizeof(buffer2), &size2, NULL) )
+    {
+        int ret;
+        if (size1 != size2)
+            return size1 > size2 ? 1 : -1;
+        if (!size1)
+            return 0;
+        ret = memcmp( buffer1, buffer2, size1 );
+        if (ret)
+            return ret;
+    }
+
+    return 0;
+}
+
 /***********************************************************************
  *             SetupCopyOEMInfW  (SETUPAPI.@)
  */
@@ -1767,6 +1790,8 @@ BOOL WINAPI SetupCopyOEMInfW(
         SetLastError(ERROR_INVALID_PARAMETER);
     else if (OEMSourceMediaType != SPOST_NONE && OEMSourceMediaType != SPOST_PATH && OEMSourceMediaType != SPOST_URL)
         SetLastError(ERROR_INVALID_PARAMETER);
+    else if (OEMSourceMediaType != SPOST_NONE && !OEMSourceMediaLocation)
+        SetLastError(ERROR_INVALID_PARAMETER);
     else if (CopyStyle & ~(SP_COPY_DELETESOURCE | SP_COPY_REPLACEONLY | SP_COPY_NOOVERWRITE | SP_COPY_OEMINF_CATALOG_ONLY))
     {
         TRACE("Unknown flags: 0x%08lx\n", CopyStyle & ~(SP_COPY_DELETESOURCE | SP_COPY_REPLACEONLY | SP_COPY_NOOVERWRITE | SP_COPY_OEMINF_CATALOG_ONLY));
@@ -1776,7 +1801,7 @@ BOOL WINAPI SetupCopyOEMInfW(
         SetLastError(ERROR_INVALID_PARAMETER);
     else if (CopyStyle & SP_COPY_OEMINF_CATALOG_ONLY)
     {
-        FIXME("CopyStyle 0x%lx not supported\n", SP_COPY_OEMINF_CATALOG_ONLY);
+        FIXME("CopyStyle 0x%x not supported\n", SP_COPY_OEMINF_CATALOG_ONLY);
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     }
     else
@@ -1788,29 +1813,68 @@ BOOL WINAPI SetupCopyOEMInfW(
         SIZE_T len;
         LPWSTR pFullFileName = NULL;
         LPWSTR pFileName; /* Pointer into pFullFileName buffer */
+        HANDLE hSourceFile = INVALID_HANDLE_VALUE;
 
         if (OEMSourceMediaType == SPOST_PATH || OEMSourceMediaType == SPOST_URL)
             FIXME("OEMSourceMediaType 0x%lx ignored\n", OEMSourceMediaType);
 
-        /* Search if the specified .inf file already exists in %WINDIR%\Inf */
-        AlreadyExists = FALSE; /* FIXME */
+        /* Check if source file exists, and open it */
+        if (strchrW(SourceInfFileName, '\\' ) || strchrW(SourceInfFileName, '/' ))
+        {
+            WCHAR *path;
 
-        if (!AlreadyExists && CopyStyle & SP_COPY_REPLACEONLY)
+            if (!(len = GetFullPathNameW(SourceInfFileName, 0, NULL, NULL)))
+                return FALSE;
+            if (!(path = MyMalloc(len * sizeof(WCHAR))))
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+            GetFullPathNameW(SourceInfFileName, len, path, NULL);
+            hSourceFile = CreateFileW(
+                path, FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                NULL, OPEN_EXISTING, 0, NULL);
+            MyFree(path);
+        }
+        else  /* try Windows directory */
         {
-            /* FIXME: set DestinationInfFileName, RequiredSize, DestinationInfFileNameComponent */
-            SetLastError(ERROR_FILE_NOT_FOUND);
-            goto cleanup;
+            WCHAR *path, *p;
+            static const WCHAR Inf[]      = {'\\','i','n','f','\\',0};
+            static const WCHAR System32[] = {'\\','s','y','s','t','e','m','3','2','\\',0};
+
+            len = GetWindowsDirectoryW(NULL, 0) + strlenW(SourceInfFileName) + 12;
+            if (!(path = MyMalloc(len * sizeof(WCHAR))))
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+            GetWindowsDirectoryW(path, len);
+            p = path + strlenW(path);
+            strcpyW(p, Inf);
+            strcatW(p, SourceInfFileName);
+            hSourceFile = CreateFileW(
+                path, FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                NULL, OPEN_EXISTING, 0, NULL);
+            if (hSourceFile == INVALID_HANDLE_VALUE)
+            {
+                strcpyW(p, System32);
+                strcatW(p, SourceInfFileName);
+                hSourceFile = CreateFileW(
+                    path, FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                    NULL, OPEN_EXISTING, 0, NULL);
+            }
+            MyFree(path);
         }
-        else if (AlreadyExists && (CopyStyle & SP_COPY_NOOVERWRITE))
+        if (hSourceFile == INVALID_HANDLE_VALUE)
         {
-            //SetLastError(ERROR_FILE_EXISTS);
-            /* FIXME: set return fields */
-            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-            FIXME("File already exists. Need to return its name!\n");
+            SetLastError(ERROR_FILE_NOT_FOUND);
             goto cleanup;
         }
 
-        /* Search the number to give to OEM??.INF */
+        /* Prepare .inf file specification */
         len = MAX_PATH + 1 + strlenW(InfDirectory) + 13;
         pFullFileName = MyMalloc(len * sizeof(WCHAR));
         if (!pFullFileName)
@@ -1825,7 +1889,70 @@ BOOL WINAPI SetupCopyOEMInfW(
             strcatW(pFullFileName, BackSlash);
         strcatW(pFullFileName, InfDirectory);
         pFileName = &pFullFileName[strlenW(pFullFileName)];
-        sprintfW(pFileName, OemFileMask, NextFreeNumber);
+
+        /* Search if the specified .inf file already exists in %WINDIR%\Inf */
+        AlreadyExists = FALSE;
+        strcpyW(pFileName, OemFileMask);
+        hSearch = FindFirstFileW(pFullFileName, &FindFileData);
+        if (hSearch != INVALID_HANDLE_VALUE)
+        {
+            LARGE_INTEGER SourceFileSize;
+
+            if (GetFileSizeEx(hSourceFile, &SourceFileSize))
+            {
+                do
+                {
+                    LARGE_INTEGER DestFileSize;
+                    HANDLE hDestFile;
+
+                    strcpyW(pFileName, FindFileData.cFileName);
+                    hDestFile = CreateFileW(
+                        pFullFileName, FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        NULL, OPEN_EXISTING, 0, NULL);
+                    if (hDestFile != INVALID_HANDLE_VALUE)
+                    {
+                        if (GetFileSizeEx(hDestFile, &DestFileSize)
+                         && DestFileSize.QuadPart == SourceFileSize.QuadPart
+                         && compare_files(hSourceFile, hDestFile))
+                        {
+                            TRACE("%s already exists as %s\n",
+                                debugstr_w(SourceInfFileName), debugstr_w(pFileName));
+                            AlreadyExists = TRUE;
+                        }
+                    }
+                } while (!AlreadyExists && FindNextFileW(hSearch, &FindFileData));
+            }
+            FindClose(hSearch);
+            hSearch = INVALID_HANDLE_VALUE;
+        }
+
+        if (!AlreadyExists && CopyStyle & SP_COPY_REPLACEONLY)
+        {
+            /* FIXME: set DestinationInfFileName, RequiredSize, DestinationInfFileNameComponent */
+            SetLastError(ERROR_FILE_NOT_FOUND);
+            goto cleanup;
+        }
+        else if (AlreadyExists && (CopyStyle & SP_COPY_NOOVERWRITE))
+        {
+            DWORD Size = strlenW(pFileName) + 1;
+
+            if (RequiredSize)
+                *RequiredSize = Size;
+            if (DestinationInfFileNameSize == 0)
+                SetLastError(ERROR_FILE_EXISTS);
+            else if (DestinationInfFileNameSize < Size)
+                SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            else
+            {
+                SetLastError(ERROR_FILE_EXISTS);
+                strcpyW(DestinationInfFileName, pFileName);
+            }
+            goto cleanup;
+        }
+
+        /* Search the number to give to OEM??.INF */
+        strcpyW(pFileName, OemFileMask);
         hSearch = FindFirstFileW(pFullFileName, &FindFileData);
         if (hSearch == INVALID_HANDLE_VALUE)
         {
@@ -1840,7 +1967,8 @@ BOOL WINAPI SetupCopyOEMInfW(
                 if (swscanf(FindFileData.cFileName, OemFileSpecification, &CurrentNumber) == 1
                     && CurrentNumber <= 99999)
                 {
-                    NextFreeNumber = CurrentNumber + 1;
+                    if (CurrentNumber >= NextFreeNumber)
+                        NextFreeNumber = CurrentNumber + 1;
                 }
             } while (FindNextFileW(hSearch, &FindFileData));
         }
@@ -1856,24 +1984,28 @@ BOOL WINAPI SetupCopyOEMInfW(
         sprintfW(pFileName, OemFileSpecification, NextFreeNumber);
         TRACE("Next available file is %s\n", debugstr_w(pFileName));
 
+        if (!CopyFileW(SourceInfFileName, pFullFileName, TRUE))
+        {
+            TRACE("CopyFileW() failed with error 0x%lx\n", GetLastError());
+            goto cleanup;
+        }
+
+        len = strlenW(pFullFileName) + 1;
         if (RequiredSize)
             *RequiredSize = len;
         if (DestinationInfFileName)
         {
-            if (DestinationInfFileNameSize < len)
+            if (DestinationInfFileNameSize >= len)
+            {
+                strcpyW(DestinationInfFileName, pFullFileName);
+                if (DestinationInfFileNameComponent)
+                    *DestinationInfFileNameComponent = &DestinationInfFileName[pFileName - pFullFileName];
+            }
+            else
             {
                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
                 goto cleanup;
             }
-            strcpyW(DestinationInfFileName, pFullFileName);
-            if (DestinationInfFileNameComponent)
-                *DestinationInfFileNameComponent = &DestinationInfFileName[pFileName - pFullFileName];
-        }
-
-        if (!CopyFileW(SourceInfFileName, pFullFileName, TRUE))
-        {
-            TRACE("CopyFileW() failed with error 0x%lx\n", GetLastError());
-            goto cleanup;
         }
 
         if (CopyStyle & SP_COPY_DELETESOURCE)
@@ -1888,6 +2020,8 @@ BOOL WINAPI SetupCopyOEMInfW(
         ret = TRUE;
 
 cleanup:
+        if (hSourceFile != INVALID_HANDLE_VALUE)
+            CloseHandle(hSourceFile);
         if (hSearch != INVALID_HANDLE_VALUE)
             FindClose(hSearch);
         MyFree(pFullFileName);
index 7a4c6e6..40e0f47 100644 (file)
@@ -2,6 +2,7 @@
  * Setupapi miscellaneous functions
  *
  * Copyright 2005 Eric Kohl
+ * Copyright 2007 Hans Leidekker
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1221,3 +1222,437 @@ GetVersionInfoFromImage(LPWSTR lpFileName,
 
     return TRUE;
 }
+
+/***********************************************************************
+ *      InstallCatalog  (SETUPAPI.@)
+ */
+DWORD WINAPI InstallCatalog( LPCSTR catalog, LPCSTR basename, LPSTR fullname )
+{
+    FIXME("%s, %s, %p\n", debugstr_a(catalog), debugstr_a(basename), fullname);
+    return 0;
+}
+
+static UINT detect_compression_type( LPCWSTR file )
+{
+    DWORD size;
+    HANDLE handle;
+    UINT type = FILE_COMPRESSION_NONE;
+    static const BYTE LZ_MAGIC[] = { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33 };
+    static const BYTE MSZIP_MAGIC[] = { 0x4b, 0x57, 0x41, 0x4a };
+    static const BYTE NTCAB_MAGIC[] = { 0x4d, 0x53, 0x43, 0x46 };
+    BYTE buffer[8];
+
+    handle = CreateFileW( file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
+    if (handle == INVALID_HANDLE_VALUE)
+    {
+        ERR("cannot open file %s\n", debugstr_w(file));
+        return FILE_COMPRESSION_NONE;
+    }
+    if (!ReadFile( handle, buffer, sizeof(buffer), &size, NULL ) || size != sizeof(buffer))
+    {
+        CloseHandle( handle );
+        return FILE_COMPRESSION_NONE;
+    }
+    if (!memcmp( buffer, LZ_MAGIC, sizeof(LZ_MAGIC) )) type = FILE_COMPRESSION_WINLZA;
+    else if (!memcmp( buffer, MSZIP_MAGIC, sizeof(MSZIP_MAGIC) )) type = FILE_COMPRESSION_MSZIP;
+    else if (!memcmp( buffer, NTCAB_MAGIC, sizeof(NTCAB_MAGIC) )) type = FILE_COMPRESSION_MSZIP; /* not a typo */
+
+    CloseHandle( handle );
+    return type;
+}
+
+static BOOL get_file_size( LPCWSTR file, DWORD *size )
+{
+    HANDLE handle;
+
+    handle = CreateFileW( file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
+    if (handle == INVALID_HANDLE_VALUE)
+    {
+        ERR("cannot open file %s\n", debugstr_w(file));
+        return FALSE;
+    }
+    *size = GetFileSize( handle, NULL );
+    CloseHandle( handle );
+    return TRUE;
+}
+
+static BOOL get_file_sizes_none( LPCWSTR source, DWORD *source_size, DWORD *target_size )
+{
+    DWORD size;
+
+    if (!get_file_size( source, &size )) return FALSE;
+    if (source_size) *source_size = size;
+    if (target_size) *target_size = size;
+    return TRUE;
+}
+
+static BOOL get_file_sizes_lz( LPCWSTR source, DWORD *source_size, DWORD *target_size )
+{
+    DWORD size;
+    BOOL ret = TRUE;
+
+    if (source_size)
+    {
+        if (!get_file_size( source, &size )) ret = FALSE;
+        else *source_size = size;
+    }
+    if (target_size)
+    {
+        INT file;
+        OFSTRUCT of;
+
+        if ((file = LZOpenFileW( (LPWSTR)source, &of, OF_READ )) < 0)
+        {
+            ERR("cannot open source file for reading\n");
+            return FALSE;
+        }
+        *target_size = LZSeek( file, 0, 2 );
+        LZClose( file );
+    }
+    return ret;
+}
+
+static UINT CALLBACK file_compression_info_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 )
+{
+    DWORD *size = context;
+    FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
+
+    switch (notification)
+    {
+    case SPFILENOTIFY_FILEINCABINET:
+    {
+        *size = info->FileSize;
+        return FILEOP_SKIP;
+    }
+    default: return NO_ERROR;
+    }
+}
+
+static BOOL get_file_sizes_cab( LPCWSTR source, DWORD *source_size, DWORD *target_size )
+{
+    DWORD size;
+    BOOL ret = TRUE;
+
+    if (source_size)
+    {
+        if (!get_file_size( source, &size )) ret = FALSE;
+        else *source_size = size;
+    }
+    if (target_size)
+    {
+        ret = SetupIterateCabinetW( source, 0, file_compression_info_callback, target_size );
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *      SetupGetFileCompressionInfoExA  (SETUPAPI.@)
+ *
+ * See SetupGetFileCompressionInfoExW.
+ */
+BOOL WINAPI SetupGetFileCompressionInfoExA( PCSTR source, PSTR name, DWORD len, PDWORD required,
+                                            PDWORD source_size, PDWORD target_size, PUINT type )
+{
+    BOOL ret;
+    WCHAR *nameW = NULL, *sourceW = NULL;
+    DWORD nb_chars = 0;
+    LPSTR nameA;
+
+    TRACE("%s, %p, %lu, %p, %p, %p, %p\n", debugstr_a(source), name, len, required,
+          source_size, target_size, type);
+
+    if (!source || !(sourceW = MultiByteToUnicode( source, CP_ACP ))) return FALSE;
+
+    if (name)
+    {
+        ret = SetupGetFileCompressionInfoExW( sourceW, NULL, 0, &nb_chars, NULL, NULL, NULL );
+        if (!(nameW = HeapAlloc( GetProcessHeap(), 0, nb_chars * sizeof(WCHAR) )))
+        {
+            MyFree( sourceW );
+            return FALSE;
+        }
+    }
+    ret = SetupGetFileCompressionInfoExW( sourceW, nameW, nb_chars, &nb_chars, source_size, target_size, type );
+    if (ret)
+    {
+        if ((nameA = UnicodeToMultiByte( nameW, CP_ACP )))
+        {
+            if (name && len >= nb_chars) lstrcpyA( name, nameA );
+            else
+            {
+                SetLastError( ERROR_INSUFFICIENT_BUFFER );
+                ret = FALSE;
+            }
+            MyFree( nameA );
+        }
+    }
+    if (required) *required = nb_chars;
+    HeapFree( GetProcessHeap(), 0, nameW );
+    MyFree( sourceW );
+
+    return ret;
+}
+
+/***********************************************************************
+ *      SetupGetFileCompressionInfoExW  (SETUPAPI.@)
+ *
+ * Get compression type and compressed/uncompressed sizes of a given file.
+ *
+ * PARAMS
+ *  source      [I] File to examine.
+ *  name        [O] Actual filename used.
+ *  len         [I] Length in characters of 'name' buffer.
+ *  required    [O] Number of characters written to 'name'.
+ *  source_size [O] Size of compressed file.
+ *  target_size [O] Size of uncompressed file.
+ *  type        [O] Compression type.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI SetupGetFileCompressionInfoExW( PCWSTR source, PWSTR name, DWORD len, PDWORD required,
+                                            PDWORD source_size, PDWORD target_size, PUINT type )
+{
+    UINT comp;
+    BOOL ret = FALSE;
+    DWORD source_len;
+
+    TRACE("%s, %p, %lu, %p, %p, %p, %p\n", debugstr_w(source), name, len, required,
+          source_size, target_size, type);
+
+    if (!source) return FALSE;
+
+    source_len = lstrlenW( source ) + 1;
+    if (required) *required = source_len;
+    if (name && len >= source_len)
+    {
+        lstrcpyW( name, source );
+        ret = TRUE;
+    }
+    else return FALSE;
+
+    comp = detect_compression_type( source );
+    if (type) *type = comp;
+
+    switch (comp)
+    {
+    case FILE_COMPRESSION_MSZIP:
+    case FILE_COMPRESSION_NTCAB:  ret = get_file_sizes_cab( source, source_size, target_size ); break;
+    case FILE_COMPRESSION_NONE:   ret = get_file_sizes_none( source, source_size, target_size ); break;
+    case FILE_COMPRESSION_WINLZA: ret = get_file_sizes_lz( source, source_size, target_size ); break;
+    default: break;
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *      SetupGetFileCompressionInfoA  (SETUPAPI.@)
+ *
+ * See SetupGetFileCompressionInfoW.
+ */
+DWORD WINAPI SetupGetFileCompressionInfoA( PCSTR source, PSTR *name, PDWORD source_size,
+                                           PDWORD target_size, PUINT type )
+{
+    BOOL ret;
+    DWORD error, required;
+    LPSTR actual_name;
+
+    TRACE("%s, %p, %p, %p, %p\n", debugstr_a(source), name, source_size, target_size, type);
+
+    if (!source || !name || !source_size || !target_size || !type)
+        return ERROR_INVALID_PARAMETER;
+
+    ret = SetupGetFileCompressionInfoExA( source, NULL, 0, &required, NULL, NULL, NULL );
+    if (!(actual_name = MyMalloc( required ))) return ERROR_NOT_ENOUGH_MEMORY;
+
+    ret = SetupGetFileCompressionInfoExA( source, actual_name, required, &required,
+                                          source_size, target_size, type );
+    if (!ret)
+    {
+        error = GetLastError();
+        MyFree( actual_name );
+        return error;
+    }
+    *name = actual_name;
+    return ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ *      SetupGetFileCompressionInfoW  (SETUPAPI.@)
+ *
+ * Get compression type and compressed/uncompressed sizes of a given file.
+ *
+ * PARAMS
+ *  source      [I] File to examine.
+ *  name        [O] Actual filename used.
+ *  source_size [O] Size of compressed file.
+ *  target_size [O] Size of uncompressed file.
+ *  type        [O] Compression type.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Win32 error code.
+ */
+DWORD WINAPI SetupGetFileCompressionInfoW( PCWSTR source, PWSTR *name, PDWORD source_size,
+                                           PDWORD target_size, PUINT type )
+{
+    BOOL ret;
+    DWORD error, required;
+    LPWSTR actual_name;
+
+    TRACE("%s, %p, %p, %p, %p\n", debugstr_w(source), name, source_size, target_size, type);
+
+    if (!source || !name || !source_size || !target_size || !type)
+        return ERROR_INVALID_PARAMETER;
+
+    ret = SetupGetFileCompressionInfoExW( source, NULL, 0, &required, NULL, NULL, NULL );
+    if (!(actual_name = MyMalloc( required ))) return ERROR_NOT_ENOUGH_MEMORY;
+
+    ret = SetupGetFileCompressionInfoExW( source, actual_name, required, &required,
+                                          source_size, target_size, type );
+    if (!ret)
+    {
+        error = GetLastError();
+        MyFree( actual_name );
+        return error;
+    }
+    *name = actual_name;
+    return ERROR_SUCCESS;
+}
+
+static DWORD decompress_file_lz( LPCWSTR source, LPCWSTR target )
+{
+    DWORD ret;
+    LONG error;
+    INT src, dst;
+    OFSTRUCT sof, dof;
+
+    if ((src = LZOpenFileW( (LPWSTR)source, &sof, OF_READ )) < 0)
+    {
+        ERR("cannot open source file for reading\n");
+        return ERROR_FILE_NOT_FOUND;
+    }
+    if ((dst = LZOpenFileW( (LPWSTR)target, &dof, OF_CREATE )) < 0)
+    {
+        ERR("cannot open target file for writing\n");
+        LZClose( src );
+        return ERROR_FILE_NOT_FOUND;
+    }
+    if ((error = LZCopy( src, dst )) >= 0) ret = ERROR_SUCCESS;
+    else
+    {
+        WARN("failed to decompress file %ld\n", error);
+        ret = ERROR_INVALID_DATA;
+    }
+
+    LZClose( src );
+    LZClose( dst );
+    return ret;
+}
+
+static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 )
+{
+    FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
+
+    switch (notification)
+    {
+    case SPFILENOTIFY_FILEINCABINET:
+    {
+        LPCWSTR filename, targetname = context;
+        WCHAR *p;
+
+        if ((p = strrchrW( targetname, '\\' ))) filename = p + 1;
+        else filename = targetname;
+
+        if (!lstrcmpiW( filename, info->NameInCabinet ))
+        {
+            strcpyW( info->FullTargetName, targetname );
+            return FILEOP_DOIT;
+        }
+        return FILEOP_SKIP;
+    }
+    default: return NO_ERROR;
+    }
+}
+
+static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target )
+{
+    BOOL ret;
+
+    ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, (PVOID)target );
+
+    if (ret) return ERROR_SUCCESS;
+    else return GetLastError();
+}
+
+/***********************************************************************
+ *      SetupDecompressOrCopyFileA  (SETUPAPI.@)
+ *
+ * See SetupDecompressOrCopyFileW.
+ */
+DWORD WINAPI SetupDecompressOrCopyFileA( PCSTR source, PCSTR target, PUINT type )
+{
+    DWORD ret = FALSE;
+    WCHAR *sourceW = NULL, *targetW = NULL;
+
+    if (source && !(sourceW = MultiByteToUnicode( source, CP_ACP ))) return FALSE;
+    if (target && !(targetW = MultiByteToUnicode( target, CP_ACP )))
+    {
+        MyFree( sourceW );
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    ret = SetupDecompressOrCopyFileW( sourceW, targetW, type );
+
+    MyFree( sourceW );
+    MyFree( targetW );
+
+    return ret;
+}
+
+/***********************************************************************
+ *      SetupDecompressOrCopyFileW  (SETUPAPI.@)
+ *
+ * Copy a file and decompress it if needed.
+ *
+ * PARAMS
+ *  source [I] File to copy.
+ *  target [I] Filename of the copy.
+ *  type   [I] Compression type.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Win32 error code.
+ */
+DWORD WINAPI SetupDecompressOrCopyFileW( PCWSTR source, PCWSTR target, PUINT type )
+{
+    UINT comp;
+    DWORD ret = ERROR_INVALID_PARAMETER;
+
+    if (!source || !target) return ERROR_INVALID_PARAMETER;
+
+    if (!type) comp = detect_compression_type( source );
+    else comp = *type;
+
+    switch (comp)
+    {
+    case FILE_COMPRESSION_NONE:
+        if (CopyFileW( source, target, FALSE )) ret = ERROR_SUCCESS;
+        else ret = GetLastError();
+        break;
+    case FILE_COMPRESSION_WINLZA:
+        ret = decompress_file_lz( source, target );
+        break;
+    case FILE_COMPRESSION_NTCAB:
+    case FILE_COMPRESSION_MSZIP:
+        ret = decompress_file_cab( source, target );
+        break;
+    default:
+        WARN("unknown compression type %d\n", comp);
+        break;
+    }
+
+    TRACE("%s -> %s %d\n", debugstr_w(source), debugstr_w(target), comp);
+    return ret;
+}
index b4b3f10..957c0aa 100644 (file)
@@ -944,10 +944,21 @@ static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style
 
     if (!RtlIsTextUnicode( buffer, size, NULL ))
     {
-        WCHAR *new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
-        if (new_buff)
+        static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
+        WCHAR *new_buff;
+        UINT codepage = CP_ACP;
+        UINT offset = 0;
+
+        if (size > sizeof(utf8_bom) && !memcmp( buffer, utf8_bom, sizeof(utf8_bom) ))
         {
-            DWORD len = MultiByteToWideChar( CP_ACP, 0, buffer, size, new_buff, size );
+            codepage = CP_UTF8;
+            offset = sizeof(utf8_bom);
+        }
+
+        if ((new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
+        {
+            DWORD len = MultiByteToWideChar( codepage, 0, (char *)buffer + offset,
+                                             size - offset, new_buff, size );
             err = parse_buffer( file, new_buff, new_buff + len, error_line );
             HeapFree( GetProcessHeap(), 0, new_buff );
         }
@@ -964,8 +975,6 @@ static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style
     if (!err)  /* now check signature */
     {
         int version_index = find_section( file, Version );
-        if (version_index == -1 && (style & INF_STYLE_OLDNT))
-            goto done;
         if (version_index != -1)
         {
             struct line *line = find_line( file, version_index, Signature );
@@ -978,7 +987,7 @@ static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style
             }
         }
         if (error_line) *error_line = 0;
-        err = ERROR_WRONG_INF_STYLE;
+        if (style & INF_STYLE_WIN4) err = ERROR_WRONG_INF_STYLE;
     }
 
  done:
@@ -1215,7 +1224,7 @@ HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *err
             /* Not enough memory */
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             SetupCloseInfFile((HINF)file);
-            return NULL;
+            return (HINF)INVALID_HANDLE_VALUE;
         }
         else if (!PARSER_GetInfClassW((HINF)file, &ClassGuid, ClassName, strlenW(class) + 1, NULL))
         {
@@ -1223,7 +1232,7 @@ HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *err
             HeapFree(GetProcessHeap(), 0, ClassName);
             SetLastError(ERROR_CLASS_MISMATCH);
             SetupCloseInfFile((HINF)file);
-            return NULL;
+            return (HINF)INVALID_HANDLE_VALUE;
         }
         else if (strcmpW(class, ClassName) != 0)
         {
@@ -1231,7 +1240,7 @@ HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *err
             HeapFree(GetProcessHeap(), 0, ClassName);
             SetLastError(ERROR_CLASS_MISMATCH);
             SetupCloseInfFile((HINF)file);
-            return NULL;
+            return (HINF)INVALID_HANDLE_VALUE;
         }
         HeapFree(GetProcessHeap(), 0, ClassName);
     }
@@ -1312,9 +1321,10 @@ void WINAPI SetupCloseInfFile( HINF hinf )
     struct inf_file *file = hinf;
     unsigned int i;
 
-    if (file != NULL)
+    if (file != NULL && file != INVALID_HANDLE_VALUE)
     {
-        for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] );
+        for (i = 0; i < file->nb_sections; i++)
+            HeapFree( GetProcessHeap(), 0, file->sections[i] );
         HeapFree( GetProcessHeap(), 0, file->filename );
         HeapFree( GetProcessHeap(), 0, file->sections );
         HeapFree( GetProcessHeap(), 0, file->fields );
index 5df1157..9082071 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
+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
  */
@@ -270,3 +275,414 @@ 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%08lx, %p\n", hinf, context, debugstr_a(filename), source_id,
+          buffer, buffer_size, required_size);
+
+    if (filename && *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 )
+{
+    WCHAR Section[MAX_PATH];
+    DWORD size;
+    LPWSTR source_id;
+    BOOL ret;
+
+    ret = SetupDiGetActualSectionToInstallW(hinf, source_disks_files, Section, MAX_PATH, NULL, NULL);
+    if (!ret)
+        return NULL;
+
+    if (!SetupFindFirstLineW( hinf, Section, 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;
+    }
+
+    ret = SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL);
+    if (!ret)
+        return NULL;
+
+    if (!SetupFindFirstLineW( hinf, Section, 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%08lx, %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;
+}
+
+/***********************************************************************
+ *            SetupGetSourceInfoA  (SETUPAPI.@)
+ */
+
+BOOL WINAPI SetupGetSourceInfoA( HINF hinf, UINT source_id, UINT info,
+                                 PSTR buffer, DWORD buffer_size, LPDWORD required_size )
+{
+    BOOL ret = FALSE;
+    WCHAR *bufferW = NULL;
+    DWORD required;
+    INT size;
+
+    TRACE("%p, %d, %d, %p, %lu, %p\n", hinf, source_id, info, buffer, buffer_size,
+          required_size);
+
+    if (!SetupGetSourceInfoW( hinf, source_id, info, NULL, 0, &required ))
+        return FALSE;
+
+    if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) )))
+        return FALSE;
+
+    if (!SetupGetSourceInfoW( hinf, source_id, info, 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, bufferW );
+    return ret;
+}
+
+/***********************************************************************
+ *            SetupGetSourceInfoW  (SETUPAPI.@)
+ */
+
+BOOL WINAPI SetupGetSourceInfoW( HINF hinf, UINT source_id, UINT info,
+                                 PWSTR buffer, DWORD buffer_size, LPDWORD required_size )
+{
+    WCHAR Section[MAX_PATH];
+    INFCONTEXT ctx;
+    WCHAR source_id_str[11];
+    static const WCHAR fmt[] = {'%','d',0};
+    DWORD index;
+    BOOL ret;
+
+    TRACE("%p, %d, %d, %p, %lu, %p\n", hinf, source_id, info, buffer, buffer_size,
+          required_size);
+
+    sprintfW( source_id_str, fmt, source_id );
+
+    ret = SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL);
+    if (!ret)
+        return FALSE;
+
+    if (!SetupFindFirstLineW( hinf, Section, source_id_str, &ctx ) &&
+        !SetupFindFirstLineW( hinf, source_disks_names, source_id_str, &ctx ))
+        return FALSE;
+
+    switch (info)
+    {
+    case SRCINFO_PATH:          index = 4; break;
+    case SRCINFO_TAGFILE:       index = 2; break;
+    case SRCINFO_DESCRIPTION:   index = 1; break;
+    default:
+        WARN("unknown info level: %d\n", info);
+        return FALSE;
+    }
+
+    if (SetupGetStringFieldW( &ctx, index, 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;
+}
+
+/***********************************************************************
+ *            SetupGetTargetPathA   (SETUPAPI.@)
+ */
+
+BOOL WINAPI SetupGetTargetPathA( HINF hinf, PINFCONTEXT context, PCSTR section, PSTR buffer,
+                                 DWORD buffer_size, PDWORD required_size )
+{
+    BOOL ret = FALSE;
+    WCHAR *sectionW = NULL, *bufferW = NULL;
+    DWORD required;
+    INT size;
+
+    TRACE("%p, %p, %s, %p, 0x%08lx, %p\n", hinf, context, debugstr_a(section), buffer,
+          buffer_size, required_size);
+
+    if (section && !(sectionW = strdupAtoW( section )))
+        return FALSE;
+
+    if (!SetupGetTargetPathW( hinf, context, sectionW, NULL, 0, &required ))
+        goto done;
+
+    if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) )))
+        goto done;
+
+    if (!SetupGetTargetPathW( hinf, context, sectionW, 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, sectionW );
+    HeapFree( GetProcessHeap(), 0, bufferW );
+    return ret;
+}
+
+/***********************************************************************
+ *            SetupGetTargetPathW   (SETUPAPI.@)
+ */
+
+BOOL WINAPI SetupGetTargetPathW( HINF hinf, PINFCONTEXT context, PCWSTR section, PWSTR buffer,
+                                 DWORD buffer_size, PDWORD required_size )
+{
+    static const WCHAR destination_dirs[] =
+        {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
+    static const WCHAR default_dest_dir[]  =
+        {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
+
+    INFCONTEXT ctx;
+    WCHAR *dir;
+    INT size;
+
+    TRACE("%p, %p, %s, %p, 0x%08lx, %p\n", hinf, context, debugstr_w(section), buffer,
+          buffer_size, required_size);
+
+    if (context && !SetupFindFirstLineW( hinf, destination_dirs, NULL, context )) return FALSE;
+    else if (section && !SetupFindFirstLineW( hinf, section, NULL, &ctx )) return FALSE;
+    else if (!SetupFindFirstLineW( hinf, destination_dirs, default_dest_dir, &ctx )) return FALSE;
+
+    if (!(dir = PARSER_get_dest_dir( context ? context : &ctx ))) return FALSE;
+
+    size = lstrlenW( dir ) + 1;
+    if (required_size) *required_size = size;
+
+    if (buffer)
+    {
+        if (buffer_size >= size)
+            lstrcpyW( buffer, dir );
+        else
+        {
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
+            HeapFree( GetProcessHeap(), 0, dir );
+            return FALSE;
+        }
+    }
+    HeapFree( GetProcessHeap(), 0, dir );
+    return TRUE;
+}
+
+/***********************************************************************
+ *            SetupQueryInfOriginalFileInformationA   (SETUPAPI.@)
+ */
+BOOL WINAPI SetupQueryInfOriginalFileInformationA(
+    PSP_INF_INFORMATION InfInformation, UINT InfIndex,
+    PSP_ALTPLATFORM_INFO AlternativePlatformInfo,
+    PSP_ORIGINAL_FILE_INFO_A OriginalFileInfo)
+{
+    BOOL ret;
+    SP_ORIGINAL_FILE_INFO_W OriginalFileInfoW;
+
+    TRACE("(%p, %d, %p, %p)\n", InfInformation, InfIndex,
+        AlternativePlatformInfo, OriginalFileInfo);
+
+    if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo))
+    {
+        ERR("incorrect OriginalFileInfo->cbSize of %lu\n", OriginalFileInfo->cbSize);
+        SetLastError( ERROR_INVALID_USER_BUFFER );
+        return FALSE;
+    }
+
+    OriginalFileInfoW.cbSize = sizeof(OriginalFileInfoW);
+    ret = SetupQueryInfOriginalFileInformationW(InfInformation, InfIndex,
+        AlternativePlatformInfo, &OriginalFileInfoW);
+    if (ret)
+    {
+        WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalInfName, MAX_PATH,
+            OriginalFileInfo->OriginalInfName, MAX_PATH, NULL, NULL);
+        WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalCatalogName, MAX_PATH,
+            OriginalFileInfo->OriginalCatalogName, MAX_PATH, NULL, NULL);
+    }
+
+    return ret;
+}
+
+/***********************************************************************
+ *            SetupQueryInfOriginalFileInformationW   (SETUPAPI.@)
+ */
+BOOL WINAPI SetupQueryInfOriginalFileInformationW(
+    PSP_INF_INFORMATION InfInformation, UINT InfIndex,
+    PSP_ALTPLATFORM_INFO AlternativePlatformInfo,
+    PSP_ORIGINAL_FILE_INFO_W OriginalFileInfo)
+{
+    LPCWSTR inf_name;
+    LPCWSTR inf_path;
+    HINF hinf;
+    static const WCHAR wszVersion[] = { 'V','e','r','s','i','o','n',0 };
+    static const WCHAR wszCatalogFile[] = { 'C','a','t','a','l','o','g','F','i','l','e',0 };
+
+    //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    //return FALSE;
+
+    FIXME("(%p, %d, %p, %p): semi-stub\n", InfInformation, InfIndex,
+        AlternativePlatformInfo, OriginalFileInfo);
+
+    if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo))
+    {
+        ERR("incorrect OriginalFileInfo->cbSize of %lu\n", OriginalFileInfo->cbSize);
+        return ERROR_INVALID_USER_BUFFER;
+    }
+
+    inf_path = (LPWSTR)&InfInformation->VersionData[0];
+
+    /* FIXME: we should get OriginalCatalogName from CatalogFile line in
+     * the original inf file and cache it, but that would require building a
+     * .pnf file. */
+    hinf = SetupOpenInfFileW(inf_path, NULL, INF_STYLE_WIN4, NULL);
+    if (hinf == INVALID_HANDLE_VALUE) return FALSE;
+
+    if (!SetupGetLineTextW(NULL, hinf, wszVersion, wszCatalogFile,
+                           OriginalFileInfo->OriginalCatalogName,
+                           sizeof(OriginalFileInfo->OriginalCatalogName)/sizeof(OriginalFileInfo->OriginalCatalogName[0]),
+                           NULL))
+    {
+        OriginalFileInfo->OriginalCatalogName[0] = '\0';
+    }
+    SetupCloseInfFile(hinf);
+
+    /* FIXME: not quite correct as we just return the same file name as
+     * destination (copied) inf file, not the source (original) inf file.
+     * to fix it properly would require building a .pnf file */
+    /* file name is stored in VersionData field of InfInformation */
+    inf_name = strrchrW(inf_path, '\\');
+    if (inf_name) inf_name++;
+    else inf_name = inf_path;
+
+    strcpyW(OriginalFileInfo->OriginalInfName, inf_name);
+
+    return TRUE;
+}
index b283040..60d8d5a 100644 (file)
@@ -74,19 +74,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;
index 40c88d6..ac05b30 100644 (file)
@@ -1,4 +1,4 @@
-<module name="setupapi" type="win32dll" baseaddress="${BASEADDRESS_SETUPAPI}" installbase="system32" installname="setupapi.dll">
+<module name="setupapi" type="win32dll" baseaddress="${BASEADDRESS_SETUPAPI}" installbase="system32" installname="setupapi.dll" allowwarnings="true">
        <importlibrary definition="setupapi.spec.def" />
        <include base="setupapi">.</include>
        <include base="ReactOS">include/reactos/wine</include>
index a80fc0a..d02ce8a 100644 (file)
 @ stdcall GetSetFileTimestamp(wstr ptr ptr ptr long)
 @ stdcall GetVersionInfoFromImage(wstr ptr ptr)
 @ stub InfIsFromOemLocation
-@ stub InstallCatalog
+@ stdcall InstallCatalog(str str ptr)
 @ stdcall InstallHinfSection(long long str long) InstallHinfSectionA
 @ stdcall InstallHinfSectionA(long long str long)
 @ stdcall InstallHinfSectionW(long long wstr long)
 @ stub QueryMultiSzValueToArray
 @ stdcall QueryRegistryValue(long wstr ptr ptr ptr)
 @ stub ReadAsciiOrUnicodeTextFile
-@ stub RegistryDelnode
+@ stdcall RegistryDelnode(long long)
+# Yes, Microsoft really misspelled this one!
 @ stdcall RetreiveFileSecurity(wstr ptr)
 @ stub RetrieveServiceConfig
 @ stub SearchForInfFile
 @ stdcall SetupCopyOEMInfW(wstr wstr long long ptr long ptr ptr)
 @ stdcall SetupCreateDiskSpaceListA(ptr long long)
 @ stdcall SetupCreateDiskSpaceListW(ptr long long)
-@ stub SetupDecompressOrCopyFileA
-@ stub SetupDecompressOrCopyFileW
+@ stdcall SetupDecompressOrCopyFileA(str str ptr)
+@ stdcall SetupDecompressOrCopyFileW(wstr wstr ptr)
 @ stub SetupDefaultQueueCallback
 @ stdcall SetupDefaultQueueCallbackA(ptr long long long)
 @ stdcall SetupDefaultQueueCallbackW(ptr long long long)
 @ stub SetupGetBackupInformationW
 @ stdcall SetupGetBinaryField(ptr long ptr long ptr)
 @ stdcall SetupGetFieldCount(ptr)
-@ stub SetupGetFileCompressionInfoA
-@ stub SetupGetFileCompressionInfoW
+@ stdcall SetupGetFileCompressionInfoA(str ptr ptr ptr ptr)
+@ stdcall SetupGetFileCompressionInfoExA(str ptr long ptr ptr ptr ptr)
+@ stdcall SetupGetFileCompressionInfoExW(wstr ptr long ptr ptr ptr ptr)
+@ stdcall SetupGetFileCompressionInfoW(wstr ptr ptr ptr ptr)
 @ stdcall SetupGetFileQueueCount(long long ptr)
 @ stdcall SetupGetFileQueueFlags(long ptr)
 @ stdcall SetupGetInfFileListA(str long str long ptr)
 @ 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
-@ stub SetupGetSourceInfoA
-@ stub SetupGetSourceInfoW
+@ stdcall SetupGetSourceInfoA(ptr long long ptr long ptr)
+@ stdcall SetupGetSourceInfoW(ptr long long ptr long ptr)
 @ stdcall SetupGetStringFieldA(ptr long ptr long ptr)
 @ stdcall SetupGetStringFieldW(ptr long ptr long ptr)
-@ stub SetupGetTargetPathA
-@ stub SetupGetTargetPathW
+@ stdcall SetupGetTargetPathA(ptr ptr str ptr long ptr)
+@ stdcall SetupGetTargetPathW(ptr ptr wstr ptr long ptr)
 @ stdcall SetupInitDefaultQueueCallback(long)
 @ stdcall SetupInitDefaultQueueCallbackEx(long long long long ptr)
 @ stdcall SetupInitializeFileLogA(str long)
 @ stub SetupQueryFileLogW
 @ stdcall SetupQueryInfFileInformationA(ptr long str long ptr)
 @ stdcall SetupQueryInfFileInformationW(ptr long wstr long ptr)
-@ stub SetupQueryInfOriginalFileInformationA
-@ stub SetupQueryInfOriginalFileInformationW
+@ stdcall SetupQueryInfOriginalFileInformationA(ptr long ptr ptr)
+@ stdcall SetupQueryInfOriginalFileInformationW(ptr long ptr ptr)
 @ stub SetupQueryInfVersionInformationA
 @ stub SetupQueryInfVersionInformationW
 @ stub SetupQuerySourceListA
 @ stdcall SetupSetFileQueueFlags(long long long)
 @ stub SetupSetPlatformPathOverrideA
 @ stub SetupSetPlatformPathOverrideW
-@ stub SetupSetSourceListA
-@ stub SetupSetSourceListW
+@ stdcall SetupSetSourceListA(long ptr long)
+@ stdcall SetupSetSourceListW(long ptr long)
 @ stdcall SetupTermDefaultQueueCallback(ptr)
 @ stdcall SetupTerminateFileLog(long)
 @ stub ShouldDeviceBeExcluded
index 5e37cc9..4fd617e 100644 (file)
@@ -221,6 +221,18 @@ extern HINSTANCE hInstance;
 #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;
index d2617fd..589ea5c 100644 (file)
@@ -118,6 +118,23 @@ INT WINAPI SetupPromptReboot(HSPFILEQ FileQueue, HWND Owner, BOOL ScanOnly)
     return -1;
 }
 
+/***********************************************************************
+ *      SetupSetSourceListA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupSetSourceListA(DWORD flags, PCSTR *list, UINT count)
+{
+    FIXME("0x%08lx %p %d\n", flags, list, count);
+    return FALSE;
+}
+
+/***********************************************************************
+ *      SetupSetSourceListW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupSetSourceListW(DWORD flags, PCWSTR *list, UINT count)
+{
+    FIXME("0x%08lx %p %d\n", flags, list, count);
+    return FALSE;
+}
 
 /***********************************************************************
  *             SetupTerminateFileLog(SETUPAPI.@)
@@ -128,6 +145,14 @@ BOOL WINAPI SetupTerminateFileLog(HANDLE FileLogHandle)
     return TRUE;
 }
 
+/***********************************************************************
+ *             RegistryDelnode(SETUPAPI.@)
+ */
+BOOL WINAPI RegistryDelnode(DWORD x, DWORD y)
+{
+    FIXME("%08lx %08lx: stub\n", x, y);
+    return FALSE;
+}
 
 /***********************************************************************
  *      SetupCloseLog(SETUPAPI.@)
index 281e082..710a7ad 100644 (file)
@@ -1312,6 +1312,8 @@ WINSETUPAPI BOOL WINAPI SetupGetBinaryField(PINFCONTEXT,DWORD,PBYTE,DWORD,LPDWOR
 WINSETUPAPI DWORD WINAPI SetupGetFieldCount(PINFCONTEXT);
 WINSETUPAPI DWORD WINAPI SetupGetFileCompressionInfoA(PCSTR,PSTR*,PDWORD,PDWORD,PUINT);
 WINSETUPAPI DWORD WINAPI SetupGetFileCompressionInfoW(PCWSTR,PWSTR*,PDWORD,PDWORD,PUINT);
+WINSETUPAPI BOOL WINAPI SetupGetFileCompressionInfoExA(PCSTR,PSTR,DWORD,PDWORD,PDWORD,PDWORD,PUINT);
+WINSETUPAPI BOOL WINAPI SetupGetFileCompressionInfoExW(PCWSTR,PWSTR,DWORD,PDWORD,PDWORD,PDWORD,PUINT);
 WINSETUPAPI BOOL WINAPI SetupGetInfFileListA(PCSTR,DWORD,PSTR,DWORD,PDWORD);
 WINSETUPAPI BOOL WINAPI SetupGetInfFileListW(PCWSTR,DWORD,PWSTR,DWORD,PDWORD);
 WINSETUPAPI BOOL WINAPI SetupGetInfInformationA(LPCVOID,DWORD,PSP_INF_INFORMATION,DWORD,PDWORD);
@@ -1524,6 +1526,7 @@ WINSETUPAPI BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);
 #define SetupFreeSourceList    SetupFreeSourceListW
 #define SetupGetBackupInformation      SetupGetBackupInformationW
 #define SetupGetFileCompressionInfo    SetupGetFileCompressionInfoW
+#define SetupGetFileCompressionInfoEx  SetupGetFileCompressionInfoExW
 #define SetupGetInfFileList    SetupGetInfFileListW
 #define SetupGetInfInformation SetupGetInfInformationW
 #define SetupGetLineByIndex    SetupGetLineByIndexW
@@ -1645,6 +1648,7 @@ WINSETUPAPI BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);
 #define SetupFreeSourceList    SetupFreeSourceListA
 #define SetupGetBackupInformation      SetupGetBackupInformationA
 #define SetupGetFileCompressionInfo    SetupGetFileCompressionInfoA
+#define SetupGetFileCompressionInfoEx  SetupGetFileCompressionInfoExA
 #define SetupGetInfFileList    SetupGetInfFileListA
 #define SetupGetInfInformation SetupGetInfInformationA
 #define SetupGetLineByIndex    SetupGetLineByIndexA