Logo Search packages:      
Sourcecode: wine version File versions

devinst.c

/*
 * SetupAPI device installer
 *
 * Copyright 2000 Andreas Mohr for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"
#include "wine/port.h"
 
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "setupapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "initguid.h"
#include "winioctl.h"
#include "rpc.h"
#include "rpcdce.h"

#include "setupapi_private.h"


WINE_DEFAULT_DEBUG_CHANNEL(setupapi);

/* Unicode constants */
static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
static const WCHAR Class[]  = {'C','l','a','s','s',0};
static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
static const WCHAR NoDisplayClass[]  = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
static const WCHAR NoInstallClass[]  = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
static const WCHAR NoUseClass[]  = {'N','o','U','s','e','C','l','a','s','s',0};
static const WCHAR NtExtension[]  = {'.','N','T',0};
static const WCHAR NtPlatformExtension[]  = {'.','N','T','x','8','6',0};
static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
static const WCHAR WinExtension[]  = {'.','W','i','n',0};

/* Registry key and value names */
static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
                                  'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
                                  'C','o','n','t','r','o','l','\\',
                                  'C','l','a','s','s',0};

static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
                                  'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
                                  'C','o','n','t','r','o','l','\\',
                                  'D','e','v','i','c','e','C','l','a','s','s','e','s',0};

/***********************************************************************
 *              SetupDiBuildClassInfoList  (SETUPAPI.@)
 */
BOOL WINAPI SetupDiBuildClassInfoList(
        DWORD Flags,
        LPGUID ClassGuidList,
        DWORD ClassGuidListSize,
        PDWORD RequiredSize)
{
    TRACE("\n");
    return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
                                        ClassGuidListSize, RequiredSize,
                                        NULL, NULL);
}

/***********************************************************************
 *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
 */
BOOL WINAPI SetupDiBuildClassInfoListExA(
        DWORD Flags,
        LPGUID ClassGuidList,
        DWORD ClassGuidListSize,
        PDWORD RequiredSize,
        LPCSTR MachineName,
        PVOID Reserved)
{
    LPWSTR MachineNameW = NULL;
    BOOL bResult;

    TRACE("\n");

    if (MachineName)
    {
        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
        if (MachineNameW == NULL) return FALSE;
    }

    bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
                                           ClassGuidListSize, RequiredSize,
                                           MachineNameW, Reserved);

    if (MachineNameW)
        MyFree(MachineNameW);

    return bResult;
}

/***********************************************************************
 *          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("\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: %p\n", szKeyName);

          if (RegOpenKeyExW(hClassesKey,
                        szKeyName,
                        0,
                        KEY_ALL_ACCESS,
                        &hClassKey))
          {
            RegCloseKey(hClassesKey);
            return FALSE;
          }

          if (!RegQueryValueExW(hClassKey,
                          NoUseClass,
                          NULL,
                          NULL,
                          NULL,
                          NULL))
          {
            TRACE("'NoUseClass' value found!\n");
            RegCloseKey(hClassKey);
            continue;
          }

          if ((Flags & DIBCI_NOINSTALLCLASS) &&
            (!RegQueryValueExW(hClassKey,
                           NoInstallClass,
                           NULL,
                           NULL,
                           NULL,
                           NULL)))
          {
            TRACE("'NoInstallClass' value found!\n");
            RegCloseKey(hClassKey);
            continue;
          }

          if ((Flags & DIBCI_NODISPLAYCLASS) &&
            (!RegQueryValueExW(hClassKey,
                           NoDisplayClass,
                           NULL,
                           NULL,
                           NULL,
                           NULL)))
          {
            TRACE("'NoDisplayClass' value found!\n");
            RegCloseKey(hClassKey);
            continue;
          }

          RegCloseKey(hClassKey);

          TRACE("Guid: %p\n", szKeyName);
          if (dwGuidListIndex < ClassGuidListSize)
          {
            if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
            {
                szKeyName[37] = 0;
            }
            TRACE("Guid: %p\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)
{
    LPWSTR ClassNameW = NULL;
    LPWSTR MachineNameW = NULL;
    BOOL bResult;

    FIXME("\n");

    ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
    if (ClassNameW == NULL)
        return FALSE;

    if (MachineNameW)
    {
        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
        if (MachineNameW == NULL)
        {
            MyFree(ClassNameW);
            return FALSE;
        }
    }

    bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
                                           ClassGuidListSize, RequiredSize,
                                           MachineNameW, Reserved);

    if (MachineNameW)
        MyFree(MachineNameW);

    MyFree(ClassNameW);

    return bResult;
}

/***********************************************************************
 *          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: %p\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: %p\n", szClassName);

            if (strcmpiW(szClassName, ClassName) == 0)
            {
                TRACE("Found matching class name\n");

                TRACE("Guid: %p\n", szKeyName);
                if (dwGuidListIndex < ClassGuidListSize)
                {
                  if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
                  {
                      szKeyName[37] = 0;
                  }
                  TRACE("Guid: %p\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)
{
    LPWSTR MachineNameW = NULL;
    HDEVINFO hDevInfo;

    TRACE("\n");

    if (MachineName)
    {
        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
        if (MachineNameW == NULL)
            return (HDEVINFO)INVALID_HANDLE_VALUE;
    }

    hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
                                              MachineNameW, Reserved);

    if (MachineNameW)
        MyFree(MachineNameW);

    return hDevInfo;
}

/***********************************************************************
 *          SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
 */
HDEVINFO WINAPI
SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
                         HWND hwndParent,
                         PCWSTR MachineName,
                         PVOID Reserved)
{
  FIXME("\n");
  return (HDEVINFO)INVALID_HANDLE_VALUE;
}

/***********************************************************************
 *          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;
}

/***********************************************************************
 *          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];
    DWORD dwLength;
    DWORD dwFullLength;
    LONG lLineCount = -1;

    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)
    {
      WARN("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.@)
 */
HDEVINFO WINAPI SetupDiGetClassDevsA(
       CONST GUID *class,
       LPCSTR enumstr,
       HWND parent,
       DWORD flags)
{
    HDEVINFO ret;
    LPWSTR enumstrW = NULL;

    if (enumstr)
    {
        int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
        enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
        if (!enumstrW)
        {
            ret = (HDEVINFO)INVALID_HANDLE_VALUE;
            goto end;
        }
        MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
    }
    ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
    HeapFree(GetProcessHeap(), 0, enumstrW);

end:
    return ret;
}

#define SETUP_SERIAL_PORT_MAGIC 0xd00ff055

typedef struct _SerialPortName
{
    WCHAR name[5];
} SerialPortName;

typedef struct _SerialPortList
{
    DWORD magic;
    UINT  numPorts;
    SerialPortName names[1];
} SerialPortList;

static HDEVINFO SETUP_CreateSerialDeviceList(void)
{
    static const size_t initialSize = 100;
    size_t size;
    WCHAR buf[initialSize];
    LPWSTR devices;
    HDEVINFO ret;
    BOOL failed = FALSE;

    devices = buf;
    size = initialSize;
    do {
        if (QueryDosDeviceW(NULL, devices, size) == 0)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                size *= 2;
                if (devices != buf)
                    HeapFree(GetProcessHeap(), 0, devices);
                devices = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
                 size * sizeof(WCHAR));
                if (!devices)
                    failed = TRUE;
                else
                    *devices = 0;
            }
            else
                failed = TRUE;
        }
    } while (!*devices && !failed);
    if (!failed)
    {
        static const WCHAR comW[] = { 'C','O','M',0 };
        LPWSTR ptr;
        UINT numSerialPorts = 0;
        SerialPortList *list;

        for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
        {
            if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
                numSerialPorts++;
        }
        list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) +
         numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0);
        if (list)
        {
            list->magic = SETUP_SERIAL_PORT_MAGIC;
            list->numPorts = 0;
            for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
            {
                if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
                {
                    strncpyW(list->names[list->numPorts].name, ptr,
                     sizeof(list->names[list->numPorts].name) /
                     sizeof(list->names[list->numPorts].name[0]));
                    TRACE("Adding %s to list\n",
                     debugstr_w(list->names[list->numPorts].name));
                    list->numPorts++;
                }
            }
            TRACE("list->numPorts is %d\n", list->numPorts);
        }
        ret = (HDEVINFO)list;
    }
    else
        ret = (HDEVINFO)INVALID_HANDLE_VALUE;
    if (devices != buf)
        HeapFree(GetProcessHeap(), 0, devices);
    TRACE("returning %p\n", ret);
    return ret;
}

/***********************************************************************
 *          SetupDiGetClassDevsW (SETUPAPI.@)
 */
HDEVINFO WINAPI SetupDiGetClassDevsW(
       CONST GUID *class,
       LPCWSTR enumstr,
       HWND parent,
       DWORD flags)
{
    HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;

    TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr),
     parent, flags);

    if (enumstr)
        FIXME(": unimplemented for enumerator strings (%s)\n",
         debugstr_w(enumstr));
    else if (flags & DIGCF_ALLCLASSES)
        FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
    else
    {
        if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
            ret = SETUP_CreateSerialDeviceList();
        else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
            ret = SETUP_CreateSerialDeviceList();
        else
            FIXME("(%s): stub\n", debugstr_guid(class));
    }
    return ret;
}

/***********************************************************************
 *          SetupDiEnumDeviceInterfaces (SETUPAPI.@)
 */
BOOL WINAPI SetupDiEnumDeviceInterfaces(
       HDEVINFO DeviceInfoSet,
       PSP_DEVINFO_DATA DeviceInfoData,
       CONST GUID * InterfaceClassGuid,
       DWORD MemberIndex,
       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
    BOOL ret = FALSE;

    TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
     debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
    if (!DeviceInterfaceData)
        SetLastError(ERROR_INVALID_PARAMETER);
    else if (DeviceInfoData)
        FIXME(": unimplemented with PSP_DEVINFO_DATA set\n");
    else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
    {
        /* FIXME: this assumes the only possible enumeration is of serial
         * ports.
         */
        SerialPortList *list = (SerialPortList *)DeviceInfoSet;

        if (list->magic == SETUP_SERIAL_PORT_MAGIC)
        {
            if (MemberIndex >= list->numPorts)
                SetLastError(ERROR_NO_MORE_ITEMS);
            else
            {
                DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                memcpy(&DeviceInterfaceData->InterfaceClassGuid,
                 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
                 sizeof(DeviceInterfaceData->InterfaceClassGuid));
                DeviceInterfaceData->Flags = 0;
                /* Note: this appears to be dangerous, passing a private
                 * pointer a heap-allocated datum to the caller.  However, the
                 * expected lifetime of the device data is the same as the
                 * HDEVINFO; once that is closed, the data are no longer valid.
                 */
                DeviceInterfaceData->Reserved =
                 (ULONG_PTR)&list->names[MemberIndex].name;
                ret = TRUE;
            }
        }
        else
            SetLastError(ERROR_INVALID_HANDLE);
    }
    else
        SetLastError(ERROR_INVALID_HANDLE);
    return ret;
}

/***********************************************************************
 *          SetupDiDestroyDeviceInfoList (SETUPAPI.@)
 */
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
{
    BOOL ret = FALSE;

    TRACE("%p\n", devinfo);
    if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
    {
        /* FIXME: this assumes the only possible enumeration is of serial
         * ports.
         */
        SerialPortList *list = (SerialPortList *)devinfo;

        if (list->magic == SETUP_SERIAL_PORT_MAGIC)
        {
            HeapFree(GetProcessHeap(), 0, list);
            ret = TRUE;
        }
        else
            SetLastError(ERROR_INVALID_HANDLE);
    }
    else
        SetLastError(ERROR_INVALID_HANDLE);
    return ret;
}

/***********************************************************************
 *          SetupDiGetDeviceInterfaceDetailA (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 ret = FALSE;

    TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
     DeviceInterfaceData, DeviceInterfaceDetailData,
     DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
    if (!DeviceInterfaceData)
        SetLastError(ERROR_INVALID_PARAMETER);
    else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) ||
     (DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize))
        SetLastError(ERROR_INVALID_PARAMETER);
    else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
    {
        /* FIXME: this assumes the only possible enumeration is of serial
         * ports.
         */
        SerialPortList *list = (SerialPortList *)DeviceInfoSet;

        if (list->magic == SETUP_SERIAL_PORT_MAGIC)
        {
            LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved;
            DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) +
             lstrlenW(devName);

            if (sizeRequired > DeviceInterfaceDetailDataSize)
            {
                SetLastError(ERROR_INSUFFICIENT_BUFFER);
                if (RequiredSize)
                    *RequiredSize = sizeRequired;
            }
            else
            {
                LPSTR dst = DeviceInterfaceDetailData->DevicePath;
                LPCWSTR src = devName;

                /* MSDN claims cbSize must be set by the caller, but it lies */
                DeviceInterfaceDetailData->cbSize =
                 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
                for ( ; *src; src++, dst++)
                    *dst = *src;
                *dst = '\0';
                TRACE("DevicePath is %s\n",
                 debugstr_a(DeviceInterfaceDetailData->DevicePath));
                if (DeviceInfoData)
                {
                    DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
                    memcpy(&DeviceInfoData->ClassGuid,
                     &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
                     sizeof(DeviceInfoData->ClassGuid));
                    DeviceInfoData->DevInst = 0;
                    DeviceInfoData->Reserved = (ULONG_PTR)devName;
                }
                ret = TRUE;
            }
        }
        else
            SetLastError(ERROR_INVALID_HANDLE);
    }
    else
        SetLastError(ERROR_INVALID_HANDLE);
    TRACE("Returning %d\n", ret);
    return ret;
}

/***********************************************************************
 *          SetupDiGetDeviceInterfaceDetailW (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)
{
    FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
     DeviceInterfaceData, DeviceInterfaceDetailData,
     DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
    return FALSE;
}

/***********************************************************************
 *          SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
 */
BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
        HDEVINFO  devinfo,
        PSP_DEVINFO_DATA  DeviceInfoData,
        DWORD   Property,
        PDWORD  PropertyRegDataType,
        PBYTE   PropertyBuffer,
        DWORD   PropertyBufferSize,
        PDWORD  RequiredSize)
{
    FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
        Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
        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,
                     Version,
                     ClassGUID,
                     Buffer,
                     MAX_PATH,
                     &RequiredSize))
    {
      return INVALID_HANDLE_VALUE;
    }

    lstrcpyW(FullBuffer, ControlClass);
    lstrcatW(FullBuffer, Buffer);

    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                  FullBuffer,
                  0,
                  KEY_ALL_ACCESS,
                  &hClassKey))
    {
      if (!SetupGetLineTextW(NULL,
                         hInf,
                         Version,
                         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,
                   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! */

    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)
{
    PWSTR MachineNameW = NULL;
    HKEY hKey;

    TRACE("\n");

    if (MachineName)
    {
        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
        if (MachineNameW == NULL)
            return INVALID_HANDLE_VALUE;
    }

    hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
                                     Flags, MachineNameW, Reserved);

    if (MachineNameW)
        MyFree(MachineNameW);

    return hKey;
}


/***********************************************************************
 *          SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
 */
HKEY WINAPI SetupDiOpenClassRegKeyExW(
        const GUID* ClassGuid,
        REGSAM samDesired,
        DWORD Flags,
        PCWSTR MachineName,
        PVOID Reserved)
{
    LPWSTR lpGuidString;
    HKEY hClassesKey;
    HKEY hClassKey;
    LPCWSTR lpKeyName;

    if (MachineName != NULL)
    {
        FIXME("Remote access not supported yet!\n");
        return INVALID_HANDLE_VALUE;
    }

    if (Flags == DIOCR_INSTALLER)
    {
        lpKeyName = ControlClass;
    }
    else if (Flags == DIOCR_INTERFACE)
    {
        lpKeyName = 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;
}

/***********************************************************************
 *          SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
 */
BOOL WINAPI SetupDiOpenDeviceInterfaceW(
       HDEVINFO DeviceInfoSet,
       PCWSTR DevicePath,
       DWORD OpenFlags,
       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
    FIXME("%p %s %08lx %p\n",
        DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
    return FALSE;
}

/***********************************************************************
 *          SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
 */
BOOL WINAPI SetupDiOpenDeviceInterfaceA(
       HDEVINFO DeviceInfoSet,
       PCSTR DevicePath,
       DWORD OpenFlags,
       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
    FIXME("%p %s %08lx %p\n", DeviceInfoSet,
        debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
    return FALSE;
}

/***********************************************************************
 *          SetupDiSetClassInstallParamsA (SETUPAPI.@)
 */
BOOL WINAPI SetupDiSetClassInstallParamsA(
       HDEVINFO  DeviceInfoSet,
       PSP_DEVINFO_DATA DeviceInfoData,
       PSP_CLASSINSTALL_HEADER ClassInstallParams,
       DWORD ClassInstallParamsSize)
{
    FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
          ClassInstallParams->InstallFunction, ClassInstallParamsSize);
    return FALSE;
}

/***********************************************************************
 *          SetupDiCallClassInstaller (SETUPAPI.@)
 */
BOOL WINAPI SetupDiCallClassInstaller(
       DWORD InstallFunction,
       HDEVINFO DeviceInfoSet,
       PSP_DEVINFO_DATA DeviceInfoData)
{
    FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
    return FALSE;
}

/***********************************************************************
 *          SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
 */
BOOL WINAPI SetupDiGetDeviceInstallParamsA(
       HDEVINFO DeviceInfoSet,
       PSP_DEVINFO_DATA DeviceInfoData,
       PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
{
    FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
    return FALSE;
}

/***********************************************************************
 *          SetupDiOpenDevRegKey (SETUPAPI.@)
 */
HKEY WINAPI SetupDiOpenDevRegKey(
       HDEVINFO DeviceInfoSet,
       PSP_DEVINFO_DATA DeviceInfoData,
       DWORD Scope,
       DWORD HwProfile,
       DWORD KeyType,
       REGSAM samDesired)
{
    FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
          Scope, HwProfile, KeyType, samDesired);
    return INVALID_HANDLE_VALUE;
}

Generated by  Doxygen 1.6.0   Back to index