Disable debug messages.
[reactos.git] / reactos / lib / setupapi / devinst.c
index 7d84bf6..377393b 100644 (file)
 
 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
 #include "wingdi.h"
 #include "winuser.h"
 #include "winnls.h"
-#include "winreg.h"
 #include "setupapi.h"
 #include "wine/debug.h"
 
+#include "rpc.h"
+#include "rpcdce.h"
+
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
+/* Unicode constants */
+static const WCHAR NtExtension[]  = {'.','N','T',0};
+static const WCHAR NtPlatformExtension[]  = {'.','N','T','x','8','6',0};
+static const WCHAR WinExtension[]  = {'.','W','i','n',0};
+static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
+static const WCHAR Class[]  = {'C','l','a','s','s',0};
+
+
 /***********************************************************************
- *             SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
+ *              SetupDiBuildClassInfoList  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
-      HDEVINFO DeviceInfoSet,
-      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
-      PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
-      DWORD DeviceInterfaceDetailDataSize,
-      PDWORD RequiredSize,
-      PSP_DEVINFO_DATA DeviceInfoData )
+BOOL WINAPI SetupDiBuildClassInfoList(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
 {
-    FIXME("\n");
-    return FALSE;
+    TRACE("SetupDiBuildClassInfoList() called\n");
+    return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
+                                        ClassGuidListSize, RequiredSize,
+                                        NULL, NULL);
 }
 
 /***********************************************************************
- *             SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
+ *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
-      HDEVINFO DeviceInfoSet,
-      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
-      PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
-      DWORD DeviceInterfaceDetailDataSize,
-      PDWORD RequiredSize,
-      PSP_DEVINFO_DATA DeviceInfoData )
+BOOL WINAPI SetupDiBuildClassInfoListExA(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCSTR MachineName,
+        PVOID Reserved)
 {
-    FIXME("\n");
+  FIXME("\n");
+  return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiBuildClassInfoListExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiBuildClassInfoListExW(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCWSTR MachineName,
+        PVOID Reserved)
+{
+    WCHAR szKeyName[40];
+    HKEY hClassesKey;
+    HKEY hClassKey;
+    DWORD dwLength;
+    DWORD dwIndex;
+    LONG lError;
+    DWORD dwGuidListIndex = 0;
+
+    TRACE("SetupDiBuildClassInfoListExW() called\n");
+
+    if (RequiredSize != NULL)
+       *RequiredSize = 0;
+
+    hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
+                                            KEY_ALL_ACCESS,
+                                            DIOCR_INSTALLER,
+                                            MachineName,
+                                            Reserved);
+    if (hClassesKey == INVALID_HANDLE_VALUE)
+    {
+       return FALSE;
+    }
+
+    for (dwIndex = 0; ; dwIndex++)
+    {
+       dwLength = 40;
+       lError = RegEnumKeyExW(hClassesKey,
+                              dwIndex,
+                              szKeyName,
+                              &dwLength,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
+       TRACE("RegEnumKeyExW() returns %ld\n", lError);
+       if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+       {
+           TRACE("Key name: %S\n", szKeyName);
+
+           if (RegOpenKeyExW(hClassesKey,
+                             szKeyName,
+                             0,
+                             KEY_ALL_ACCESS,
+                             &hClassKey))
+           {
+               RegCloseKey(hClassesKey);
+               return FALSE;
+           }
+
+           if (!RegQueryValueExW(hClassKey,
+                                L"NoUseClass",
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL))
+           {
+               TRACE("'NoUseClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           if ((Flags & DIBCI_NOINSTALLCLASS) &&
+               (!RegQueryValueExW(hClassKey,
+                                  L"NoInstallClass",
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL)))
+           {
+               TRACE("'NoInstallClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           if ((Flags & DIBCI_NODISPLAYCLASS) &&
+               (!RegQueryValueExW(hClassKey,
+                                  L"NoDisplayClass",
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL)))
+           {
+               TRACE("'NoDisplayClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           RegCloseKey(hClassKey);
+
+           TRACE("Guid: %S\n", szKeyName);
+           if (dwGuidListIndex < ClassGuidListSize)
+           {
+               if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+               {
+                   szKeyName[37] = 0;
+               }
+               TRACE("Guid: %S\n", &szKeyName[1]);
+
+               UuidFromStringW(&szKeyName[1],
+                               &ClassGuidList[dwGuidListIndex]);
+           }
+
+           dwGuidListIndex++;
+       }
+
+       if (lError != ERROR_SUCCESS)
+           break;
+    }
+
+    RegCloseKey(hClassesKey);
+
+    if (RequiredSize != NULL)
+       *RequiredSize = dwGuidListIndex;
+
+    if (ClassGuidListSize < dwGuidListIndex)
+    {
+       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameA(
+        LPCSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
+                                      ClassGuidListSize, RequiredSize,
+                                      NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameW(
+        LPCWSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
+                                      ClassGuidListSize, RequiredSize,
+                                      NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameExA(
+        LPCSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCSTR MachineName,
+        PVOID Reserved)
+{
+  FIXME("\n");
+  return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameExW(
+        LPCWSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCWSTR MachineName,
+        PVOID Reserved)
+{
+    WCHAR szKeyName[40];
+    WCHAR szClassName[256];
+    HKEY hClassesKey;
+    HKEY hClassKey;
+    DWORD dwLength;
+    DWORD dwIndex;
+    LONG lError;
+    DWORD dwGuidListIndex = 0;
+
+    if (RequiredSize != NULL)
+       *RequiredSize = 0;
+
+    hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
+                                            KEY_ALL_ACCESS,
+                                            DIOCR_INSTALLER,
+                                            MachineName,
+                                            Reserved);
+    if (hClassesKey == INVALID_HANDLE_VALUE)
+    {
+       return FALSE;
+    }
+
+    for (dwIndex = 0; ; dwIndex++)
+    {
+       dwLength = 40;
+       lError = RegEnumKeyExW(hClassesKey,
+                              dwIndex,
+                              szKeyName,
+                              &dwLength,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
+       TRACE("RegEnumKeyExW() returns %ld\n", lError);
+       if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+       {
+           TRACE("Key name: %S\n", szKeyName);
+
+           if (RegOpenKeyExW(hClassesKey,
+                             szKeyName,
+                             0,
+                             KEY_ALL_ACCESS,
+                             &hClassKey))
+           {
+               RegCloseKey(hClassesKey);
+               return FALSE;
+           }
+
+           dwLength = 256 * sizeof(WCHAR);
+           if (!RegQueryValueExW(hClassKey,
+                                 Class,
+                                 NULL,
+                                 NULL,
+                                 (LPBYTE)szClassName,
+                                 &dwLength))
+           {
+               TRACE("Class name: %S\n", szClassName);
+
+               if (_wcsicmp(szClassName, ClassName) == 0)
+               {
+                   TRACE("Found matching class name\n");
+
+                   TRACE("Guid: %S\n", szKeyName);
+                   if (dwGuidListIndex < ClassGuidListSize)
+                   {
+                       if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+                       {
+                           szKeyName[37] = 0;
+                       }
+                       TRACE("Guid: %S\n", &szKeyName[1]);
+
+                       UuidFromStringW(&szKeyName[1],
+                                       &ClassGuidList[dwGuidListIndex]);
+                   }
+
+                   dwGuidListIndex++;
+               }
+           }
+
+           RegCloseKey(hClassKey);
+       }
+
+       if (lError != ERROR_SUCCESS)
+           break;
+    }
+
+    RegCloseKey(hClassesKey);
+
+    if (RequiredSize != NULL)
+       *RequiredSize = dwGuidListIndex;
+
+    if (ClassGuidListSize < dwGuidListIndex)
+    {
+       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidA(
+        const GUID* ClassGuid,
+        PSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
+                                     ClassNameSize, RequiredSize,
+                                     NULL, NULL);
+}
+
+/***********************************************************************
+ *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidW(
+        const GUID* ClassGuid,
+        PWSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
+                                     ClassNameSize, RequiredSize,
+                                     NULL, NULL);
+}
+
+/***********************************************************************
+ *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidExA(
+        const GUID* ClassGuid,
+        PSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+  FIXME("\n");
+  return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiClassNameFromGuidExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidExW(
+        const GUID* ClassGuid,
+        PWSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    HKEY hKey;
+    DWORD dwLength;
+
+    hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
+                                     KEY_ALL_ACCESS,
+                                     DIOCR_INSTALLER,
+                                     MachineName,
+                                     Reserved);
+    if (hKey == INVALID_HANDLE_VALUE)
+    {
+       return FALSE;
+    }
+
+    if (RequiredSize != NULL)
+    {
+       dwLength = 0;
+       if (RegQueryValueExW(hKey,
+                            Class,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &dwLength))
+       {
+           RegCloseKey(hKey);
+           return FALSE;
+       }
+
+       *RequiredSize = dwLength / sizeof(WCHAR);
+    }
+
+    dwLength = ClassNameSize * sizeof(WCHAR);
+    if (RegQueryValueExW(hKey,
+                        Class,
+                        NULL,
+                        NULL,
+                        (LPBYTE)ClassName,
+                        &dwLength))
+    {
+       RegCloseKey(hKey);
+       return FALSE;
+    }
+
+    RegCloseKey(hKey);
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInfoList (SETUPAPI.@)
+ */
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
+                           HWND hwndParent)
+{
+  return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
+ */
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
+                              HWND hwndParent,
+                              PCSTR MachineName,
+                              PVOID Reserved)
+{
+  FIXME("\n");
+  return (HDEVINFO)INVALID_HANDLE_VALUE;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
+ */
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
+                              HWND hwndParent,
+                              PCWSTR MachineName,
+                              PVOID Reserved)
+{
+  FIXME("\n");
+  return (HDEVINFO)INVALID_HANDLE_VALUE;
+}
+
+/***********************************************************************
+ *             SetupDiDestroyDeviceInfoList (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
+{
+  FIXME("%04lx\n", (DWORD)devinfo);
+  return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiEnumDeviceInfo (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiEnumDeviceInfo(
+        HDEVINFO  devinfo,
+        DWORD  index,
+        PSP_DEVINFO_DATA info)
+{
+    FIXME("%p %ld %p\n", devinfo, index, info);
+
+    if(info==NULL)
+        return FALSE;
+    if(info->cbSize < sizeof(*info))
+        return FALSE;
+
     return FALSE;
 }
 
@@ -76,6 +540,207 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
     return FALSE;
 }
 
+/***********************************************************************
+ *             SetupDiGetActualSectionToInstallA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetActualSectionToInstallA(
+        HINF InfHandle,
+        PCSTR InfSectionName,
+        PSTR InfSectionWithExt,
+        DWORD InfSectionWithExtSize,
+        PDWORD RequiredSize,
+        PSTR *Extension)
+{
+    FIXME("\n");
+    return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiGetActualSectionToInstallW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetActualSectionToInstallW(
+        HINF InfHandle,
+        PCWSTR InfSectionName,
+        PWSTR InfSectionWithExt,
+        DWORD InfSectionWithExtSize,
+        PDWORD RequiredSize,
+        PWSTR *Extension)
+{
+    WCHAR szBuffer[MAX_PATH];
+    OSVERSIONINFO OsVersionInfo;
+    DWORD dwLength;
+    DWORD dwFullLength;
+    LONG lLineCount = -1;
+
+    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    if (!GetVersionEx(&OsVersionInfo))
+    {
+       return FALSE;
+    }
+
+    lstrcpyW(szBuffer, InfSectionName);
+    dwLength = lstrlenW(szBuffer);
+
+    if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
+    {
+       /* Test section name with '.NTx86' extension */
+       lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
+       lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
+
+       if (lLineCount == -1)
+       {
+           /* Test section name with '.NT' extension */
+           lstrcpyW(&szBuffer[dwLength], NtExtension);
+           lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
+       }
+    }
+    else
+    {
+       /* Test section name with '.Win' extension */
+       lstrcpyW(&szBuffer[dwLength], WinExtension);
+       lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
+    }
+
+    if (lLineCount == -1)
+    {
+       /* Test section name without extension */
+       szBuffer[dwLength] = 0;
+       lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
+    }
+
+    if (lLineCount == -1)
+    {
+       SetLastError(ERROR_INVALID_PARAMETER);
+       return FALSE;
+    }
+
+    dwFullLength = lstrlenW(szBuffer);
+
+    if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
+    {
+       if (InfSectionWithExtSize < (dwFullLength + 1))
+       {
+           SetLastError(ERROR_INSUFFICIENT_BUFFER);
+           return FALSE;
+       }
+
+       lstrcpyW(InfSectionWithExt, szBuffer);
+       if (Extension != NULL)
+       {
+           *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
+       }
+    }
+
+    if (RequiredSize != NULL)
+    {
+       *RequiredSize = dwFullLength + 1;
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionA(
+        const GUID* ClassGuid,
+        PSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
+                                       ClassDescriptionSize,
+                                       RequiredSize, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionW(
+        const GUID* ClassGuid,
+        PWSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
+                                       ClassDescriptionSize,
+                                       RequiredSize, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionExA(
+        const GUID* ClassGuid,
+        PSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+  FIXME("\n");
+  return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionExW(
+        const GUID* ClassGuid,
+        PWSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    HKEY hKey;
+    DWORD dwLength;
+
+    hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
+                                     KEY_ALL_ACCESS,
+                                     DIOCR_INSTALLER,
+                                     MachineName,
+                                     Reserved);
+    if (hKey == INVALID_HANDLE_VALUE)
+    {
+       ERR("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
+       return FALSE;
+    }
+
+    if (RequiredSize != NULL)
+    {
+       dwLength = 0;
+       if (RegQueryValueExW(hKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &dwLength))
+       {
+           RegCloseKey(hKey);
+           return FALSE;
+       }
+
+       *RequiredSize = dwLength / sizeof(WCHAR);
+    }
+
+    dwLength = ClassDescriptionSize * sizeof(WCHAR);
+    if (RegQueryValueExW(hKey,
+                        NULL,
+                        NULL,
+                        NULL,
+                        (LPBYTE)ClassDescription,
+                        &dwLength))
+    {
+       RegCloseKey(hKey);
+       return FALSE;
+    }
+
+    RegCloseKey(hKey);
+
+    return TRUE;
+}
+
 /***********************************************************************
  *             SetupDiGetClassDevsA (SETUPAPI.@)
  */
@@ -103,30 +768,34 @@ HDEVINFO WINAPI SetupDiGetClassDevsW(
 
     return (HDEVINFO) INVALID_HANDLE_VALUE;
 }
+
 /***********************************************************************
- *             SetupDiEnumDeviceInfo (SETUPAPI.@)
+ *             SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiEnumDeviceInfo(
-        HDEVINFO  devinfo,
-        DWORD  index,
-        PSP_DEVINFO_DATA info)
+BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
+      HDEVINFO DeviceInfoSet,
+      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+      PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
+      DWORD DeviceInterfaceDetailDataSize,
+      PDWORD RequiredSize,
+      PSP_DEVINFO_DATA DeviceInfoData)
 {
-    FIXME("%p %ld %p\n", devinfo, index, info );
-
-    if(info==NULL)
-        return FALSE;
-    if(info->cbSize < sizeof(*info))
-        return FALSE;
-
+    FIXME("\n");
     return FALSE;
 }
 
 /***********************************************************************
- *             SetupDiDestroyDeviceInfoList (SETUPAPI.@)
+ *             SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiDestroyDeviceInfoList( HDEVINFO devinfo )
+BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
+      HDEVINFO DeviceInfoSet,
+      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+      PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
+      DWORD DeviceInterfaceDetailDataSize,
+      PDWORD RequiredSize,
+      PSP_DEVINFO_DATA DeviceInfoData)
 {
-    FIXME("%04lx\n", (DWORD)devinfo);
+    FIXME("\n");
     return FALSE;
 }
 
@@ -147,3 +816,291 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
         RequiredSize);
     return FALSE;
 }
+
+/***********************************************************************
+ *             SetupDiInstallClassA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassA(
+        HWND hwndParent,
+        PCSTR InfFileName,
+        DWORD Flags,
+        HSPFILEQ FileQueue)
+{
+    UNICODE_STRING FileNameW;
+    BOOL Result;
+
+    if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
+
+    RtlFreeUnicodeString(&FileNameW);
+
+    return Result;
+}
+
+static HKEY CreateClassKey(HINF hInf)
+{
+    WCHAR FullBuffer[MAX_PATH];
+    WCHAR Buffer[MAX_PATH];
+    DWORD RequiredSize;
+    HKEY hClassKey;
+
+    if (!SetupGetLineTextW(NULL,
+                          hInf,
+                          L"Version",
+                          L"ClassGUID",
+                          Buffer,
+                          MAX_PATH,
+                          &RequiredSize))
+    {
+       return INVALID_HANDLE_VALUE;
+    }
+
+    lstrcpyW(FullBuffer, L"System\\CurrentControlSet\\Control\\Class\\");
+    lstrcatW(FullBuffer, Buffer);
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     FullBuffer,
+                     0,
+                     KEY_ALL_ACCESS,
+                     &hClassKey))
+    {
+       if (!SetupGetLineTextW(NULL,
+                              hInf,
+                              L"Version",
+                              L"Class",
+                              Buffer,
+                              MAX_PATH,
+                              &RequiredSize))
+       {
+           return INVALID_HANDLE_VALUE;
+       }
+
+       if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+                           FullBuffer,
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &hClassKey,
+                           NULL))
+       {
+           return INVALID_HANDLE_VALUE;
+       }
+
+    }
+
+    if (RegSetValueExW(hClassKey,
+                      L"Class",
+                      0,
+                      REG_SZ,
+                      (LPBYTE)Buffer,
+                      RequiredSize * sizeof(WCHAR)))
+    {
+       RegCloseKey(hClassKey);
+       RegDeleteKeyW(HKEY_LOCAL_MACHINE,
+                     FullBuffer);
+       return INVALID_HANDLE_VALUE;
+    }
+
+    return hClassKey;
+}
+
+/***********************************************************************
+ *             SetupDiInstallClassW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassW(
+        HWND hwndParent,
+        PCWSTR InfFileName,
+        DWORD Flags,
+        HSPFILEQ FileQueue)
+{
+    WCHAR SectionName[MAX_PATH];
+    DWORD SectionNameLength = 0;
+    HINF hInf;
+    BOOL bFileQueueCreated = FALSE;
+    HKEY hClassKey;
+
+
+    FIXME("\n");
+
+    if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
+    {
+       SetLastError(ERROR_INVALID_PARAMETER);
+       return FALSE;
+    }
+
+    /* Open the .inf file */
+    hInf = SetupOpenInfFileW(InfFileName,
+                            NULL,
+                            INF_STYLE_WIN4,
+                            NULL);
+    if (hInf == INVALID_HANDLE_VALUE)
+    {
+
+       return FALSE;
+    }
+
+    /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
+    hClassKey = CreateClassKey(hInf);
+    if (hClassKey == INVALID_HANDLE_VALUE)
+    {
+       SetupCloseInfFile(hInf);
+       return FALSE;
+    }
+
+
+    /* Try to append a layout file */
+#if 0
+    SetupOpenAppendInfFileW(NULL, hInf, NULL);
+#endif
+
+    /* Retrieve the actual section name */
+    SetupDiGetActualSectionToInstallW(hInf,
+                                     ClassInstall32,
+                                     SectionName,
+                                     MAX_PATH,
+                                     &SectionNameLength,
+                                     NULL);
+
+#if 0
+    if (!(Flags & DI_NOVCP))
+    {
+       FileQueue = SetupOpenFileQueue();
+       if (FileQueue == INVALID_HANDLE_VALUE)
+       {
+           SetupCloseInfFile(hInf);
+           return FALSE;
+       }
+
+       bFileQueueCreated = TRUE;
+
+    }
+#endif
+
+    SetupInstallFromInfSectionW(NULL,
+                               hInf,
+                               SectionName,
+                               SPINST_REGISTRY,
+                               hClassKey,
+                               NULL,
+                               0,
+                               NULL,
+                               NULL,
+                               INVALID_HANDLE_VALUE,
+                               NULL);
+
+    /* FIXME: More code! */
+
+ByeBye:
+    if (bFileQueueCreated)
+       SetupCloseFileQueue(FileQueue);
+
+    SetupCloseInfFile(hInf);
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKey  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKey(
+        const GUID* ClassGuid,
+        REGSAM samDesired)
+{
+    return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
+                                     DIOCR_INSTALLER, NULL, NULL);
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKeyExA(
+        const GUID* ClassGuid,
+        REGSAM samDesired,
+        DWORD Flags,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+    FIXME("\n");
+    return INVALID_HANDLE_VALUE;
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKeyExW(
+        const GUID* ClassGuid,
+        REGSAM samDesired,
+        DWORD Flags,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    LPWSTR lpGuidString;
+    HKEY hClassesKey;
+    HKEY hClassKey;
+    LPWSTR lpKeyName;
+
+    if (MachineName != NULL)
+    {
+        FIXME("Remote access not supported yet!\n");
+        return INVALID_HANDLE_VALUE;
+    }
+
+    if (Flags == DIOCR_INSTALLER)
+    {
+        lpKeyName = L"SYSTEM\\CurrentControlSet\\Control\\Class";
+    }
+    else if (Flags == DIOCR_INTERFACE)
+    {
+        lpKeyName = L"SYSTEM\\CurrentControlSet\\Control\\DeviceClasses";
+    }
+    else
+    {
+        ERR("Invalid Flags parameter!\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     lpKeyName,
+                     0,
+                     KEY_ALL_ACCESS,
+                     &hClassesKey))
+    {
+       return INVALID_HANDLE_VALUE;
+    }
+
+    if (ClassGuid == NULL)
+        return hClassesKey;
+
+    if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
+    {
+       RegCloseKey(hClassesKey);
+       return FALSE;
+    }
+
+    if (RegOpenKeyExW(hClassesKey,
+                     lpGuidString,
+                     0,
+                     KEY_ALL_ACCESS,
+                     &hClassKey))
+    {
+       RpcStringFreeW(&lpGuidString);
+       RegCloseKey(hClassesKey);
+       return FALSE;
+    }
+
+    RpcStringFreeW(&lpGuidString);
+    RegCloseKey(hClassesKey);
+
+    return hClassKey;
+}