[SETUPAPI] Adopt SetupGetInfFileListW() from Wine Staging 1.7.37. Based on the work...
[reactos.git] / reactos / dll / win32 / setupapi / parser.c
index f3bfc59..16429ec 100644 (file)
@@ -2120,137 +2120,143 @@ LPCWSTR WINAPI pSetupGetField( PINFCONTEXT context, DWORD index )
     return field->text;
 }
 
+
 /***********************************************************************
- *             SetupGetInfFileListW    (SETUPAPI.@)
+ *              SetupGetInfFileListW  (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupGetInfFileListW(
-    IN PCWSTR DirectoryPath OPTIONAL,
-    IN DWORD InfStyle,
-    IN OUT PWSTR ReturnBuffer OPTIONAL,
-    IN DWORD ReturnBufferSize OPTIONAL,
-    OUT PDWORD RequiredSize OPTIONAL)
-{
-    HANDLE hSearch;
-    LPWSTR pFullFileName = NULL;
-    LPWSTR pFileName; /* Pointer into pFullFileName buffer */
-    LPWSTR pBuffer = ReturnBuffer;
-    WIN32_FIND_DATAW wfdFileInfo;
-    size_t len;
-    DWORD requiredSize = 0;
-    BOOL ret = FALSE;
-
-    TRACE("%s %lx %p %ld %p\n", debugstr_w(DirectoryPath), InfStyle,
-        ReturnBuffer, ReturnBufferSize, RequiredSize);
-
-    if (InfStyle & ~(INF_STYLE_OLDNT | INF_STYLE_WIN4))
-    {
-        TRACE("Unknown flags: 0x%08lx\n", InfStyle & ~(INF_STYLE_OLDNT  | INF_STYLE_WIN4));
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto cleanup;
-    }
-    else if (ReturnBufferSize == 0 && ReturnBuffer != NULL)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto cleanup;
+BOOL WINAPI SetupGetInfFileListW(PCWSTR dir, DWORD style, PWSTR buffer,
+                                 DWORD insize, PDWORD outsize)
+{
+    static const WCHAR inf[] = {'\\','*','.','i','n','f',0 };
+    WCHAR *filter, *fullname = NULL, *ptr = buffer;
+    DWORD dir_len, name_len = 20, size ;
+    WIN32_FIND_DATAW finddata;
+    HANDLE hdl;
+    if (style & ~( INF_STYLE_OLDNT | INF_STYLE_WIN4 |
+                   INF_STYLE_CACHE_ENABLE | INF_STYLE_CACHE_DISABLE ))
+    {
+        FIXME( "unknown inf_style(s) 0x%x\n",
+               style & ~( INF_STYLE_OLDNT | INF_STYLE_WIN4 |
+                         INF_STYLE_CACHE_ENABLE | INF_STYLE_CACHE_DISABLE ));
+        if( outsize ) *outsize = 1;
+        return TRUE;
     }
-    else if (ReturnBufferSize > 0 && ReturnBuffer == NULL)
+    if ((style & ( INF_STYLE_OLDNT | INF_STYLE_WIN4 )) == INF_STYLE_NONE)
     {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto cleanup;
-    }
-
-    /* Allocate memory for file filter */
-    if (DirectoryPath != NULL)
-        /* "DirectoryPath\" form */
-        len = strlenW(DirectoryPath) + 1 + 1;
-    else
-        /* "%SYSTEMROOT%\Inf\" form */
-        len = MAX_PATH + 1 + strlenW(InfDirectory) + 1;
-    len += MAX_PATH; /* To contain file name or "*.inf" string */
-    pFullFileName = MyMalloc(len * sizeof(WCHAR));
-    if (pFullFileName == NULL)
-    {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        goto cleanup;
+        FIXME( "inf_style INF_STYLE_NONE not handled\n" );
+        if( outsize ) *outsize = 1;
+        return TRUE;
     }
+    if (style & ( INF_STYLE_CACHE_ENABLE | INF_STYLE_CACHE_DISABLE ))
+        FIXME("ignored inf_style(s) %s %s\n",
+              ( style & INF_STYLE_CACHE_ENABLE  ) ? "INF_STYLE_CACHE_ENABLE"  : "",
+              ( style & INF_STYLE_CACHE_DISABLE ) ? "INF_STYLE_CACHE_DISABLE" : "");
+    if( dir )
+    {
+        DWORD att;
+        DWORD msize;
+        dir_len = strlenW( dir );
+        if ( !dir_len ) return FALSE;
+        msize = ( 7 + dir_len )  * sizeof( WCHAR ); /* \\*.inf\0 */
+        filter = HeapAlloc( GetProcessHeap(), 0, msize );
+        if( !filter )
+        {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+            return FALSE;
+        }
+        strcpyW( filter, dir );
+        if ( '\\' == filter[dir_len - 1] )
+            filter[--dir_len] = 0;
 
-    /* Fill file filter buffer */
-    if (DirectoryPath)
-    {
-        strcpyW(pFullFileName, DirectoryPath);
-        if (*pFullFileName && pFullFileName[strlenW(pFullFileName) - 1] != '\\')
-            strcatW(pFullFileName, BackSlash);
+        att = GetFileAttributesW( filter );
+        if (att != INVALID_FILE_ATTRIBUTES && !(att & FILE_ATTRIBUTE_DIRECTORY))
+        {
+            HeapFree( GetProcessHeap(), 0, filter );
+            SetLastError( ERROR_DIRECTORY );
+            return FALSE;
+        }
     }
     else
     {
-        len = GetSystemWindowsDirectoryW(pFullFileName, MAX_PATH);
-        if (len == 0 || len > MAX_PATH)
-            goto cleanup;
-        if (pFullFileName[strlenW(pFullFileName) - 1] != '\\')
-            strcatW(pFullFileName, BackSlash);
-        strcatW(pFullFileName, InfDirectory);
+        WCHAR infdir[] = {'\\','i','n','f',0 };
+        DWORD msize;
+        dir_len = GetWindowsDirectoryW( NULL, 0 );
+        msize = ( 7 + 4 + dir_len ) * sizeof( WCHAR );
+        filter = HeapAlloc( GetProcessHeap(), 0, msize );
+        if( !filter )
+        {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+            return FALSE;
+        }
+        GetWindowsDirectoryW( filter, msize );
+        strcatW( filter, infdir );
     }
-    pFileName = &pFullFileName[strlenW(pFullFileName)];
+    strcatW( filter, inf );
 
-    /* Search for the first file */
-    strcpyW(pFileName, InfFileSpecification);
-    hSearch = FindFirstFileW(pFullFileName, &wfdFileInfo);
-    if (hSearch == INVALID_HANDLE_VALUE)
+    hdl = FindFirstFileW( filter , &finddata );
+    if ( hdl == INVALID_HANDLE_VALUE )
     {
-        TRACE("No file returned by %s\n", debugstr_w(pFullFileName));
-        goto cleanup;
+        if( outsize ) *outsize = 1;
+        HeapFree( GetProcessHeap(), 0, filter );
+        return TRUE;
     }
-
+    size = 1;
     do
     {
-        HINF hInf;
-
-        strcpyW(pFileName, wfdFileInfo.cFileName);
-        hInf = SetupOpenInfFileW(
-            pFullFileName,
-            NULL, /* Inf class */
-            InfStyle,
-            NULL /* Error line */);
-        if (hInf == INVALID_HANDLE_VALUE)
+        static const WCHAR key[] =
+               {'S','i','g','n','a','t','u','r','e',0 };
+        static const WCHAR section[] =
+               {'V','e','r','s','i','o','n',0 };
+        static const WCHAR sig_win4_1[] =
+               {'$','C','h','i','c','a','g','o','$',0 };
+        static const WCHAR sig_win4_2[] =
+               {'$','W','I','N','D','O','W','S',' ','N','T','$',0 };
+        WCHAR signature[ MAX_PATH ];
+        BOOL valid = FALSE;
+        DWORD len = strlenW( finddata.cFileName );
+        if (!fullname || ( name_len < len ))
         {
-            if (GetLastError() == ERROR_CLASS_MISMATCH)
+            name_len = ( name_len < len ) ? len : name_len;
+            HeapFree( GetProcessHeap(), 0, fullname );
+            fullname = HeapAlloc( GetProcessHeap(), 0,
+                                  ( 2 + dir_len + name_len) * sizeof( WCHAR ));
+            if( !fullname )
             {
-                /* InfStyle was not correct. Skip this file */
-                continue;
+                FindClose( hdl );
+                HeapFree( GetProcessHeap(), 0, filter );
+                SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+                return FALSE;
             }
-            TRACE("Invalid .inf file %s\n", debugstr_w(pFullFileName));
-            continue;
+            strcpyW( fullname, filter );
         }
-
-        len = strlenW(wfdFileInfo.cFileName) + 1;
-        requiredSize += (DWORD)(len * sizeof(WCHAR));
-        if (requiredSize <= ReturnBufferSize)
+        fullname[ dir_len + 1] = 0; /* keep '\\' */
+        strcatW( fullname, finddata.cFileName );
+        if (!GetPrivateProfileStringW( section, key, NULL, signature, MAX_PATH, fullname ))
+            signature[0] = 0;
+        if( INF_STYLE_OLDNT & style )
+            valid = strcmpiW( sig_win4_1, signature ) &&
+                    strcmpiW( sig_win4_2, signature );
+        if( INF_STYLE_WIN4 & style )
+            valid = valid || !strcmpiW( sig_win4_1, signature ) ||
+                    !strcmpiW( sig_win4_2, signature );
+        if( valid )
         {
-            strcpyW(pBuffer, wfdFileInfo.cFileName);
-            pBuffer = &pBuffer[len];
+            size += 1 + strlenW( finddata.cFileName );
+            if( ptr && insize >= size )
+            {
+                strcpyW( ptr, finddata.cFileName );
+                ptr += 1 + strlenW( finddata.cFileName );
+                *ptr = 0;
+            }
         }
-        SetupCloseInfFile(hInf);
-    } while (FindNextFileW(hSearch, &wfdFileInfo));
-    FindClose(hSearch);
-
-    requiredSize += sizeof(WCHAR); /* Final NULL char */
-    if (requiredSize <= ReturnBufferSize)
-    {
-        *pBuffer = '\0';
-        ret = TRUE;
-    }
-    else
-    {
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        ret = FALSE;
     }
-    if (RequiredSize)
-        *RequiredSize = requiredSize;
+    while( FindNextFileW( hdl, &finddata ));
+    FindClose( hdl );
 
-cleanup:
-    MyFree(pFullFileName);
-    return ret;
+    HeapFree( GetProcessHeap(), 0, fullname );
+    HeapFree( GetProcessHeap(), 0, filter );
+    if( outsize ) *outsize = size;
+    return TRUE;
 }
 
 /***********************************************************************