[CMAKE]
authorSylvain Petreolle <spetreolle@yahoo.fr>
Wed, 26 Jan 2011 22:19:12 +0000 (22:19 +0000)
committerSylvain Petreolle <spetreolle@yahoo.fr>
Wed, 26 Jan 2011 22:19:12 +0000 (22:19 +0000)
Sync trunk up to r50477.

svn path=/branches/cmake-bringup/; revision=50504

157 files changed:
1  2  3 
base/applications/network/ping/CMakeLists.txt
base/applications/network/ping/lang/de-DE.rc
base/applications/network/ping/lang/en-US.rc
base/applications/network/ping/lang/fr-FR.rc
base/applications/network/ping/lang/it-IT.rc
base/applications/network/ping/lang/pl-PL.rc
base/applications/network/ping/ping.c
base/applications/network/ping/ping.rc
base/applications/network/ping/resource.h
base/applications/rapps/rapps/kdewin.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/mono2.txt
base/applications/rapps/rapps/python.txt
base/applications/rapps/rapps/sbforvmware.txt
base/applications/rapps/rapps/tuxpaint.txt
base/applications/shutdown/lang/fr-FR.rc
base/shell/explorer-new/CMakeLists.txt
base/shell/explorer-new/explorer.c
base/shell/explorer-new/taskswnd.c
base/shell/explorer/utility/utility.h
base/system/winlogon/wlx.c
boot/freeldr/freeldr/arch/i386/machpc.c
boot/freeldr/freeldr/windows/winldr.c
dll/win32/cryptui/main.c
dll/win32/gdi32/CMakeLists.txt
dll/win32/gdi32/gdi32.spec
dll/win32/gdi32/include/gdi32p.h
dll/win32/gdi32/objects/coord.c
dll/win32/gdi32/objects/efloat.c
dll/win32/iphlpapi/iphlpapi_private.h
dll/win32/iphlpapi/resinfo_reactos.c
dll/win32/kernel32/file/cnotify.c
dll/win32/setupapi/cfgmgr.c
dll/win32/setupapi/devinst.c
dll/win32/setupapi/setupapi.spec
dll/win32/user32/CMakeLists.txt
dll/win32/user32/controls/icontitle.c
dll/win32/user32/controls/listbox.c
dll/win32/user32/controls/static.c
dll/win32/user32/include/controls.h
dll/win32/user32/include/cursor.h
dll/win32/user32/include/message.h
dll/win32/user32/include/regcontrol.h
dll/win32/user32/include/user32.h
dll/win32/user32/include/user32p.h
dll/win32/user32/include/window.h
dll/win32/user32/misc/desktop.c
dll/win32/user32/windows/class.c
dll/win32/user32/windows/cursoricon.c
dll/win32/user32/windows/defwnd.c
dll/win32/user32/windows/dialog.c
dll/win32/user32/windows/menu.c
dll/win32/user32/windows/window.c
drivers/filesystems/npfs/dirctl.c
drivers/usb/usbehci/fdo.c
drivers/usb/usbehci/irp.c
drivers/usb/usbehci/physmem.c
drivers/usb/usbehci/physmem.h
drivers/usb/usbehci/transfer.c
drivers/usb/usbehci/usbehci.h
drivers/usb/usbehci/usbiffn.c
include/crt/mingw32/intrin_x86.h
include/ndk/ketypes.h
include/psdk/cfgmgr32.h
include/psdk/windowsx.h
include/psdk/winuser.h
include/reactos/asm.inc
include/reactos/ksamd64.inc
include/reactos/undocuser.h
include/reactos/win32k/ntuser.h
lib/rtl/CMakeLists.txt
lib/rtl/heap.c
lib/rtl/srw.c
lib/sdk/crt/CMakeLists.txt
lib/sdk/crt/printf/_snprintf.c
lib/sdk/crt/printf/_snwprintf.c
lib/sdk/crt/printf/_sxprintf.c
lib/sdk/crt/printf/_vsnprintf.c
lib/sdk/crt/printf/_vsnwprintf.c
lib/sdk/crt/printf/printf.c
lib/sdk/crt/printf/sprintf.c
lib/sdk/crt/printf/streamout.c
lib/sdk/crt/printf/swprintf.c
lib/sdk/crt/printf/vsprintf.c
lib/sdk/crt/printf/vswprintf.c
lib/sdk/crt/printf/wsprintfA.c
lib/sdk/crt/printf/wsprintfW.c
lib/sdk/crt/printf/wvsnprintfA.c
lib/sdk/crt/printf/wvsnprintfW.c
lib/sdk/crt/printf/wvsprintfA.c
lib/sdk/crt/printf/wvsprintfW.c
lib/sdk/crt/stdio/_flsbuf.c
lib/sdk/crt/stdio/_flswbuf.c
lib/sdk/crt/stdio/file.c
lib/sdk/crt/stdlib/ecvt.c
lib/sdk/crt/string/strtoull.c
lib/sdk/crt/string/wcs.c
ntoskrnl/include/internal/i386/mm.h
ntoskrnl/mm/ARM3/pagfault.c
ntoskrnl/mm/ARM3/pool.c
ntoskrnl/mm/ARM3/syspte.c
ntoskrnl/mm/ARM3/virtual.c
ntoskrnl/ps/process.c
ntoskrnl/ps/psmgr.c
ntoskrnl/se/priv.c
subsystems/win32/win32k/eng/clip.c
subsystems/win32/win32k/eng/engevent.c
subsystems/win32/win32k/eng/engwindow.c
subsystems/win32/win32k/eng/i386/floatobj.S
subsystems/win32/win32k/eng/semaphor.c
subsystems/win32/win32k/eng/surface.c
subsystems/win32/win32k/eng/xlate.c
subsystems/win32/win32k/include/bitmaps.h
subsystems/win32/win32k/include/caret.h
subsystems/win32/win32k/include/coord.h
subsystems/win32/win32k/include/dc.h
subsystems/win32/win32k/include/gdifloat.h
subsystems/win32/win32k/include/monitor.h
subsystems/win32/win32k/include/msgqueue.h
subsystems/win32/win32k/include/object.h
subsystems/win32/win32k/include/surface.h
subsystems/win32/win32k/include/tags.h
subsystems/win32/win32k/include/xformobj.h
subsystems/win32/win32k/ntuser/accelerator.c
subsystems/win32/win32k/ntuser/callback.c
subsystems/win32/win32k/ntuser/cursoricon.c
subsystems/win32/win32k/ntuser/display.c
subsystems/win32/win32k/ntuser/hotkey.c
subsystems/win32/win32k/ntuser/input.c
subsystems/win32/win32k/ntuser/kbdlayout.c
subsystems/win32/win32k/ntuser/message.c
subsystems/win32/win32k/ntuser/monitor.c
subsystems/win32/win32k/ntuser/msgqueue.c
subsystems/win32/win32k/ntuser/windc.c
subsystems/win32/win32k/ntuser/window.c
subsystems/win32/win32k/objects/bitblt.c
subsystems/win32/win32k/objects/bitmaps.c
subsystems/win32/win32k/objects/cliprgn.c
subsystems/win32/win32k/objects/coord.c
subsystems/win32/win32k/objects/dcobjs.c
subsystems/win32/win32k/objects/dcutil.c
subsystems/win32/win32k/objects/dibobj.c
subsystems/win32/win32k/objects/font.c
subsystems/win32/win32k/objects/freetype.c
subsystems/win32/win32k/objects/icm.c
subsystems/win32/win32k/objects/line.c
subsystems/win32/win32k/objects/metafile.c
subsystems/win32/win32k/objects/path.c
subsystems/win32/win32k/objects/pen.c
subsystems/win32/win32k/objects/print.c
subsystems/win32/win32k/objects/region.c
subsystems/win32/win32k/objects/text.c
subsystems/win32/win32k/objects/xformobj.c
subsystems/win32/win32k/pch.h
subsystems/win32/win32k/stubs/stubs.c
subsystems/win32/win32k/stubs/umpdstubs.c
subsystems/win32/win32k/win32k.spec

index 9146b26,0000000,0000000..8cb9b9f
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,13 -1,0 -1,0 +1,14 @@@@
 ++
+++set_unicode()
 ++add_definitions(-D__USE_W32_SOCKETS)
 ++
 ++add_executable(ping ping.c ping.rc)
 ++
 ++set_module_type(ping win32cui)
 ++
 ++add_importlibs(ping ws2_32 msvcrt kernel32)
 ++if(MSVC)
 ++add_importlibs(ping ntdll)
 ++endif()
 ++
 ++add_cab_target(ping 1)
index 19aa099,0000000,0000000..616498d
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,670 -1,0 -1,0 +1,751 @@@@
-  CHAR                TargetName[256];
 ++/*
 ++ * COPYRIGHT:   See COPYING in the top level directory
 ++ * PROJECT:     ReactOS ping utility
 ++ * FILE:        base/applications/network/ping/ping.c
 ++ * PURPOSE:     Network test utility
 ++ * PROGRAMMERS:
 ++ */
 ++
 ++#include <winsock2.h>
 ++#include <ws2tcpip.h>
 ++#include <tchar.h>
 ++#include <stdarg.h>
 ++#include <string.h>
 ++#include <stdio.h>
+++#include "resource.h"
 ++
 ++#define NDEBUG
 ++
 ++/* General ICMP constants */
 ++#define ICMP_MINSIZE        8     /* Minimum ICMP packet size */
 ++#define ICMP_MAXSIZE        65535 /* Maximum ICMP packet size */
 ++
 ++/* ICMP message types */
 ++#define ICMPMSG_ECHOREQUEST 8     /* ICMP ECHO request message */
 ++#define ICMPMSG_ECHOREPLY   0     /* ICMP ECHO reply message */
 ++
 ++#pragma pack(4)
 ++
 ++/* IPv4 header structure */
 ++typedef struct _IPv4_HEADER
 ++{
 ++    unsigned char IHL:4;
 ++    unsigned char Version:4;
 ++    unsigned char TOS;
 ++    unsigned short Length;
 ++    unsigned short Id;
 ++    unsigned short FragFlags;
 ++    unsigned char TTL;
 ++    unsigned char Protocol;
 ++    unsigned short Checksum;
 ++    unsigned int SrcAddress;
 ++    unsigned int DstAddress;
 ++} IPv4_HEADER, *PIPv4_HEADER;
 ++
 ++/* ICMP echo request/reply header structure */
 ++typedef struct _ICMP_HEADER
 ++{
 ++    unsigned char Type;
 ++    unsigned char Code;
 ++    unsigned short Checksum;
 ++    unsigned short Id;
 ++    unsigned short SeqNum;
 ++} ICMP_HEADER, *PICMP_HEADER;
 ++
 ++typedef struct _ICMP_ECHO_PACKET
 ++{
 ++    ICMP_HEADER Icmp;
 ++} ICMP_ECHO_PACKET, *PICMP_ECHO_PACKET;
 ++
 ++#pragma pack(1)
 ++
 ++BOOL                InvalidOption;
 ++BOOL                NeverStop;
 ++BOOL                ResolveAddresses;
 ++UINT                PingCount;
 ++UINT                DataSize;   /* ICMP echo request data size */
 ++BOOL                DontFragment;
 ++ULONG               TTLValue;
 ++ULONG               TOSValue;
 ++ULONG               Timeout;
-  LPSTR               TargetIP;
+++WCHAR               TargetName[256];
 ++SOCKET              IcmpSock;
 ++SOCKADDR_IN         Target;
-      printf("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] destination-host\n\n");
-      printf("Options:\n");
-      printf("    -t             Ping the specified host until stopped.\n");
-      printf("                   To stop - type Control-C.\n");
-      printf("    -n count       Number of echo requests to send.\n");
-      printf("    -l size        Send buffer size.\n");
-      printf("    -w timeout     Timeout in milliseconds to wait for each reply.\n\n");
+++WCHAR               TargetIP[16];
 ++FD_SET              Fds;
 ++TIMEVAL             Timeval;
 ++UINT                CurrentSeqNum;
 ++UINT                SentCount;
 ++UINT                LostCount;
 ++BOOL                MinRTTSet;
 ++LARGE_INTEGER       MinRTT;     /* Minimum round trip time in microseconds */
 ++LARGE_INTEGER       MaxRTT;
 ++LARGE_INTEGER       SumRTT;
 ++LARGE_INTEGER       AvgRTT;
 ++LARGE_INTEGER       TicksPerMs; /* Ticks per millisecond */
 ++LARGE_INTEGER       TicksPerUs; /* Ticks per microsecond */
 ++LARGE_INTEGER       SentTime;
 ++BOOL                UsePerformanceCounter;
+++HANDLE              hStdOutput;
 ++
 ++#ifndef NDEBUG
 ++/* Display the contents of a buffer */
 ++static VOID DisplayBuffer(
 ++    PVOID Buffer,
 ++    DWORD Size)
 ++{
 ++    UINT i;
 ++    PCHAR p;
 ++
 ++    printf("Buffer (0x%p)  Size (0x%lX).\n", Buffer, Size);
 ++
 ++    p = (PCHAR)Buffer;
 ++    for (i = 0; i < Size; i++)
 ++    {
 ++        if (i % 16 == 0)
 ++            printf("\n");
 ++        printf("%02X ", (p[i]) & 0xFF);
 ++    }
 ++}
 ++#endif /* !NDEBUG */
 ++
+++LPWSTR
+++MyLoadString(UINT uID)
+++{
+++    HRSRC hres;
+++    HGLOBAL hResData;
+++    WCHAR *pwsz;
+++    UINT string_num, i;
+++
+++    hres = FindResourceW(NULL, MAKEINTRESOURCEW((LOWORD(uID) >> 4) + 1), RT_STRING);
+++    if (!hres) return NULL;
+++
+++    hResData = LoadResource(NULL, hres);
+++    if (!hResData) return NULL;
+++
+++    pwsz = LockResource(hResData);
+++    if (!pwsz) return NULL;
+++    
+++    string_num = uID & 15;
+++    for (i = 0; i < string_num; i++)
+++        pwsz += *pwsz + 1;
+++
+++    return pwsz + 1;
+++}
+++
+++void FormatOutput(UINT uID, ...)
+++{
+++    va_list valist;
+++
+++    WCHAR Buf[1024];
+++    LPWSTR pBuf = Buf;
+++    LPWSTR Format;
+++    DWORD written;
+++    UINT DataLength;
+++
+++    va_start(valist, uID);
+++
+++    Format = MyLoadString(uID);
+++    if (!Format) return;
+++
+++    DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\
+++                  sizeof(Buf) / sizeof(WCHAR), &valist);
+++
+++    if(!DataLength)
+++    {
+++        if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+++            return;
+++
+++        DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING |\
+++                                    FORMAT_MESSAGE_ALLOCATE_BUFFER,\
+++                                    Format, 0, 0, (LPWSTR)&pBuf, 0, &valist);
+++
+++        if(!DataLength)
+++            return;
+++    }
+++
+++    WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL);
+++
+++    if(pBuf != Buf)
+++        LocalFree(pBuf);
+++}
+++
 ++/* Display usage information on screen */
 ++static VOID Usage(VOID)
 ++{
-  static ULONG GetULONG(LPSTR String)
+++    FormatOutput(IDS_USAGE);
 ++}
 ++
 ++/* Reset configuration to default values */
 ++static VOID Reset(VOID)
 ++{
 ++    LARGE_INTEGER PerformanceCounterFrequency;
 ++
 ++    NeverStop             = FALSE;
 ++    ResolveAddresses      = FALSE;
 ++    PingCount             = 4;
 ++    DataSize              = 32;
 ++    DontFragment          = FALSE;
 ++    TTLValue              = 128;
 ++    TOSValue              = 0;
 ++    Timeout               = 1000;
 ++    UsePerformanceCounter = QueryPerformanceFrequency(&PerformanceCounterFrequency);
 ++
 ++    if (UsePerformanceCounter)
 ++    {
 ++        /* Performance counters may return incorrect results on some multiprocessor
 ++           platforms so we restrict execution on the first processor. This may fail
 ++           on Windows NT so we fall back to GetCurrentTick() for timing */
 ++        if (SetThreadAffinityMask (GetCurrentThread(), 1) == 0)
 ++            UsePerformanceCounter = FALSE;
 ++
 ++        /* Convert frequency to ticks per millisecond */
 ++        TicksPerMs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000;
 ++        /* And to ticks per microsecond */
 ++        TicksPerUs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000000;
 ++    }
 ++    if (!UsePerformanceCounter)
 ++    {
 ++        /* 1 tick per millisecond for GetCurrentTick() */
 ++        TicksPerMs.QuadPart = 1;
 ++        /* GetCurrentTick() cannot handle microseconds */
 ++        TicksPerUs.QuadPart = 1;
 ++    }
 ++}
 ++
 ++/* Return ULONG in a string */
-      LPSTR StopString;
+++static ULONG GetULONG(LPWSTR String)
 ++{
 ++    UINT i, Length;
 ++    ULONG Value;
-      Length = (UINT)_tcslen(String);
-      while ((i < Length) && ((String[i] < '0') || (String[i] > '9'))) i++;
-      if ((i >= Length) || ((String[i] < '0') || (String[i] > '9')))
+++    LPWSTR StopString;
 ++    i = 0;
-      Value = strtoul(&String[i], &StopString, 10);
+++    Length = (UINT)wcslen(String);
+++    while ((i < Length) && ((String[i] < L'0') || (String[i] > L'9'))) i++;
+++    if ((i >= Length) || ((String[i] < L'0') || (String[i] > L'9')))
 ++    {
 ++        InvalidOption = TRUE;
 ++        return 0;
 ++    }
-  static ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i)
+++    Value = wcstoul(&String[i], &StopString, 10);
 ++
 ++    return Value;
 ++}
 ++
 ++/* Return ULONG in a string. Try next paramter if not successful */
-          if (String2[0] != '-')
+++static ULONG GetULONG2(LPWSTR String1, LPWSTR String2, PINT i)
 ++{
 ++    ULONG Value;
 ++
 ++    Value = GetULONG(String1);
 ++    if (InvalidOption)
 ++    {
 ++        InvalidOption = FALSE;
-  static BOOL ParseCmdline(int argc, char* argv[])
+++        if (String2[0] != L'-')
 ++        {
 ++            Value = GetULONG(String2);
 ++            if (!InvalidOption)
 ++                *i += 1;
 ++        }
 ++    }
 ++
 ++    return Value;
 ++}
 ++
 ++/* Parse command line parameters */
-          if (argv[i][0] == '-')
+++static BOOL ParseCmdline(int argc, LPWSTR argv[])
 ++{
 ++    INT i;
 ++    BOOL ShowUsage;
 ++    BOOL FoundTarget;
 ++    if (argc < 2)
 ++        ShowUsage = TRUE;
 ++    else
 ++        ShowUsage = FALSE;
 ++    FoundTarget = FALSE;
 ++    InvalidOption = FALSE;
 ++
 ++    for (i = 1; i < argc; i++)
 ++    {
-                  case 't': NeverStop = TRUE; break;
-                  case 'a': ResolveAddresses = TRUE; break;
-                  case 'n': PingCount = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
-                  case 'l':
+++        if (argv[i][0] == L'-')
 ++        {
 ++            switch (argv[i][1])
 ++            {
-                          printf("Bad value for option -l, valid range is from 0 to %d.\n",
-                              ICMP_MAXSIZE - (int)sizeof(ICMP_ECHO_PACKET) - (int)sizeof(IPv4_HEADER));
+++                case L't': NeverStop = TRUE; break;
+++                case L'a': ResolveAddresses = TRUE; break;
+++                case L'n': PingCount = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
+++                case L'l':
 ++                    DataSize = GetULONG2(&argv[i][2], argv[i + 1], &i);
 ++                    if (DataSize > ICMP_MAXSIZE - sizeof(ICMP_ECHO_PACKET) - sizeof(IPv4_HEADER))
 ++                    {
-                  case 'f': DontFragment = TRUE; break;
-                  case 'i': TTLValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
-                  case 'v': TOSValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
-                  case 'w': Timeout  = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
+++                        FormatOutput(IDS_BAD_VALUE_OPTION_L, ICMP_MAXSIZE - \
+++                                     (int)sizeof(ICMP_ECHO_PACKET) - \
+++                                     (int)sizeof(IPv4_HEADER));
 ++                        return FALSE;
 ++                   }
 ++                    break;
-                      printf("Bad option %s.\n", argv[i]);
+++                case L'f': DontFragment = TRUE; break;
+++                case L'i': TTLValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
+++                case L'v': TOSValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
+++                case L'w': Timeout  = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
 ++                default:
-                  printf("Bad option format %s.\n", argv[i]);
+++                    FormatOutput(IDS_BAD_OPTION, argv[i]);
 ++                    Usage();
 ++                    return FALSE;
 ++            }
 ++            if (InvalidOption)
 ++            {
-                  printf("Bad parameter %s.\n", argv[i]);
+++                FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]);
 ++                return FALSE;
 ++            }
 ++        }
 ++        else
 ++        {
 ++            if (FoundTarget)
 ++            {
-                  lstrcpy(TargetName, argv[i]);
+++                FormatOutput(IDS_BAD_PARAMETER, argv[i]);
 ++                return FALSE;
 ++            }
 ++            else
 ++            {
-          printf("Name or IP address of destination host must be specified.\n");
+++                wcscpy(TargetName, argv[i]);
 ++                FoundTarget = TRUE;
 ++            }
 ++        }
 ++    }
 ++
 ++    if ((!ShowUsage) && (!FoundTarget))
 ++    {
-          printf("Could not initialize winsock dll.\n");
+++        FormatOutput(IDS_DEST_MUST_BE_SPECIFIED);
 ++        return FALSE;
 ++    }
 ++
 ++    if (ShowUsage)
 ++    {
 ++        Usage();
 ++        return FALSE;
 ++    }
 ++    return TRUE;
 ++}
 ++
 ++/* Calculate checksum of data */
 ++static WORD Checksum(PUSHORT data, UINT size)
 ++{
 ++    ULONG sum = 0;
 ++
 ++    while (size > 1)
 ++    {
 ++        sum  += *data++;
 ++        size -= sizeof(USHORT);
 ++    }
 ++
 ++    if (size)
 ++        sum += *(UCHAR*)data;
 ++
 ++    sum = (sum >> 16) + (sum & 0xFFFF);
 ++    sum += (sum >> 16);
 ++
 ++    return (USHORT)(~sum);
 ++}
 ++
 ++/* Prepare to ping target */
 ++static BOOL Setup(VOID)
 ++{
 ++    WORD     wVersionRequested;
 ++    WSADATA  WsaData;
 ++    INT      Status;
 ++    ULONG    Addr;
 ++    PHOSTENT phe;
+++    CHAR     aTargetName[256];
 ++
 ++    wVersionRequested = MAKEWORD(2, 2);
 ++
 ++    Status = WSAStartup(wVersionRequested, &WsaData);
 ++    if (Status != 0)
 ++    {
-          printf("Could not create socket (#%d).\n", WSAGetLastError());
+++        FormatOutput(IDS_COULD_NOT_INIT_WINSOCK);
 ++        return FALSE;
 ++    }
 ++
 ++    IcmpSock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);
 ++    if (IcmpSock == INVALID_SOCKET)
 ++    {
-           printf("setsockopt failed (%d).\n", WSAGetLastError());
+++        FormatOutput(IDS_COULD_NOT_CREATE_SOCKET, WSAGetLastError());
 ++        return FALSE;
 ++    }
 ++
 ++    if (setsockopt(IcmpSock,
 ++                   IPPROTO_IP,
 ++                   IP_DONTFRAGMENT,
 ++                   (const char *)&DontFragment,
 ++                   sizeof(DontFragment)) == SOCKET_ERROR)
 ++    {
-           printf("setsockopt failed (%d).\n", WSAGetLastError());
+++        FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError());
 ++         return FALSE;
 ++    }
 ++
 ++    if (setsockopt(IcmpSock,
 ++                   IPPROTO_IP,
 ++                   IP_TTL,
 ++                   (const char *)&TTLValue,
 ++                   sizeof(TTLValue)) == SOCKET_ERROR)
 ++    {
-      Addr = inet_addr(TargetName);
+++        FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError());
 ++         return FALSE;
 ++    }
 ++
 ++
+++    if(!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,\
+++                            sizeof(aTargetName), NULL, NULL))
+++    {
+++        FormatOutput(IDS_UNKNOWN_HOST, TargetName);
+++        return FALSE;
+++    }
+++
 ++    ZeroMemory(&Target, sizeof(Target));
 ++    phe = NULL;
-          phe = gethostbyname(TargetName);
+++    Addr = inet_addr(aTargetName);
 ++    if (Addr == INADDR_NONE)
 ++    {
-              printf("Unknown host %s.\n", TargetName);
+++        phe = gethostbyname(aTargetName);
 ++        if (phe == NULL)
 ++        {
-      }
+++            FormatOutput(IDS_UNKNOWN_HOST, TargetName);
 ++            return FALSE;
 ++        }
-      if (phe != NULL)
 ++
-      else
-          Target.sin_addr.s_addr = Addr;
-  
-      if (phe != NULL)
 ++        CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length);
-      TargetIP = inet_ntoa(Target.sin_addr);
 ++        Target.sin_family = phe->h_addrtype;
+++    }
 ++    else
+++    {
+++        Target.sin_addr.s_addr = Addr;
 ++        Target.sin_family = AF_INET;
+++    }
+++
 ++
-  static VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time)
+++    swprintf(TargetIP, L"%d.%d.%d.%d", Target.sin_addr.S_un.S_un_b.s_b1,\
+++                                       Target.sin_addr.S_un.S_un_b.s_b2,\
+++                                       Target.sin_addr.S_un.S_un_b.s_b3,\
+++                                       Target.sin_addr.S_un.S_un_b.s_b4);
 ++    CurrentSeqNum = 1;
 ++    SentCount = 0;
 ++    LostCount = 0;
 ++    MinRTT.QuadPart = 0;
 ++    MaxRTT.QuadPart = 0;
 ++    SumRTT.QuadPart = 0;
 ++    MinRTTSet       = FALSE;
 ++    return TRUE;
 ++}
 ++
 ++/* Close socket */
 ++static VOID Cleanup(VOID)
 ++{
 ++    if (IcmpSock != INVALID_SOCKET)
 ++        closesocket(IcmpSock);
 ++
 ++    WSACleanup();
 ++}
 ++
 ++static VOID QueryTime(PLARGE_INTEGER Time)
 ++{
 ++    if (UsePerformanceCounter)
 ++    {
 ++        if (QueryPerformanceCounter(Time) == 0)
 ++        {
 ++            /* This should not happen, but we fall
 ++               back to GetCurrentTick() if it does */
 ++            Time->u.LowPart  = (ULONG)GetTickCount();
 ++            Time->u.HighPart = 0;
 ++
 ++            /* 1 tick per millisecond for GetCurrentTick() */
 ++            TicksPerMs.QuadPart = 1;
 ++            /* GetCurrentTick() cannot handle microseconds */
 ++            TicksPerUs.QuadPart = 1;
 ++
 ++            UsePerformanceCounter = FALSE;
 ++        }
 ++    }
 ++    else
 ++    {
 ++        Time->u.LowPart  = (ULONG)GetTickCount();
 ++        Time->u.HighPart = 0;
 ++    }
 ++}
 ++
-      CHAR          Convstr[40];
+++static VOID TimeToMsString(LPWSTR String, LARGE_INTEGER Time)
 ++{
-      _i64toa(LargeTime.QuadPart, Convstr, 10);
-      strcpy(String, Convstr);
-      strcat(String, "ms");
+++    WCHAR         Convstr[40];
 ++    LARGE_INTEGER LargeTime;
+++    LPWSTR ms;
 ++
 ++    LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
 ++
-      CHAR              Time[100];
+++    _i64tow(LargeTime.QuadPart, Convstr, 10);
+++    wcscpy(String, Convstr);
+++    ms = MyLoadString(IDS_MS);
+++    wcscat(String, ms);
 ++}
 ++
 ++/* Locate the ICMP data and print it. Returns TRUE if the packet was good,
 ++   FALSE if not */
 ++static BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from)
 ++{
 ++    PIPv4_HEADER      IpHeader;
 ++    PICMP_ECHO_PACKET Icmp;
 ++    UINT              IphLength;
-      CHAR              Sign[2];
+++    WCHAR             Time[100];
 ++    LARGE_INTEGER     RelativeTime;
 ++    LARGE_INTEGER     LargeTime;
-          strcpy(Sign, "<");
-          strcpy(Time, "1ms");
+++    WCHAR             Sign[2];
+++    WCHAR wfromIP[16];
 ++
 ++    IpHeader = (PIPv4_HEADER)buffer;
 ++
 ++    IphLength = IpHeader->IHL * 4;
 ++
 ++    if (size  < IphLength + ICMP_MINSIZE)
 ++    {
 ++#ifndef NDEBUG
 ++        printf("Bad size (0x%X < 0x%X)\n", size, IphLength + ICMP_MINSIZE);
 ++#endif /* !NDEBUG */
 ++        return FALSE;
 ++    }
 ++
 ++    Icmp = (PICMP_ECHO_PACKET)(buffer + IphLength);
 ++
 ++    if (Icmp->Icmp.Type != ICMPMSG_ECHOREPLY)
 ++    {
 ++#ifndef NDEBUG
 ++        printf("Bad ICMP type (0x%X should be 0x%X)\n", Icmp->Icmp.Type, ICMPMSG_ECHOREPLY);
 ++#endif /* !NDEBUG */
 ++        return FALSE;
 ++    }
 ++
 ++    if (Icmp->Icmp.Id != (USHORT)GetCurrentProcessId())
 ++    {
 ++#ifndef NDEBUG
 ++        printf("Bad ICMP id (0x%X should be 0x%X)\n", Icmp->Icmp.Id, (USHORT)GetCurrentProcessId());
 ++#endif /* !NDEBUG */
 ++        return FALSE;
 ++    }
 ++
 ++    if (from->sin_addr.s_addr != Target.sin_addr.s_addr)
 ++    {
 ++#ifndef NDEBUG
 ++        printf("Bad source address (%s should be %s)\n", inet_ntoa(from->sin_addr), inet_ntoa(Target.sin_addr));
 ++#endif /* !NDEBUG */
 ++        return FALSE;
 ++    }
 ++
 ++    QueryTime(&LargeTime);
 ++
 ++    RelativeTime.QuadPart = (LargeTime.QuadPart - SentTime.QuadPart);
 ++
 ++    if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1)
 ++    {
-          strcpy(Sign, "=");
+++        LPWSTR ms1;
+++
+++        wcscpy(Sign, L"<");
+++        ms1 = MyLoadString(IDS_1MS);
+++        wcscpy(Time, ms1);
 ++    }
 ++    else
 ++    {
-      printf("Reply from %s: bytes=%d time%s%s TTL=%d\n", inet_ntoa(from->sin_addr),
-        size - IphLength - (int)sizeof(ICMP_ECHO_PACKET), Sign, Time, IpHeader->TTL);
+++        wcscpy(Sign, L"=");
 ++        TimeToMsString(Time, RelativeTime);
 ++    }
 ++
 ++
-          printf("Not enough free resources available.\n");
+++    swprintf(wfromIP, L"%d.%d.%d.%d", from->sin_addr.S_un.S_un_b.s_b1,\
+++                                      from->sin_addr.S_un.S_un_b.s_b2,\
+++                                      from->sin_addr.S_un.S_un_b.s_b3,\
+++                                      from->sin_addr.S_un.S_un_b.s_b4);
+++    FormatOutput(IDS_REPLY_FROM, wfromIP,\
+++                 size - IphLength - (int)sizeof(ICMP_ECHO_PACKET),\
+++                 Sign, Time, IpHeader->TTL);
+++
 ++    if (RelativeTime.QuadPart < MinRTT.QuadPart || !MinRTTSet)
 ++    {
 ++        MinRTT.QuadPart = RelativeTime.QuadPart;
 ++        MinRTTSet = TRUE;
 ++    }
 ++    if (RelativeTime.QuadPart > MaxRTT.QuadPart)
 ++        MaxRTT.QuadPart = RelativeTime.QuadPart;
 ++
 ++    SumRTT.QuadPart += RelativeTime.QuadPart;
 ++
 ++    return TRUE;
 ++}
 ++
 ++/* Send and receive one ping */
 ++static BOOL Ping(VOID)
 ++{
 ++    INT                 Status;
 ++    SOCKADDR            From;
 ++    INT                 Length;
 ++    PVOID               Buffer;
 ++    UINT                Size;
 ++    PICMP_ECHO_PACKET   Packet;
 ++
 ++    /* Account for extra space for IP header when packet is received */
 ++    Size   = DataSize + 128;
 ++    Buffer = GlobalAlloc(0, Size);
 ++    if (!Buffer)
 ++    {
-              printf("Destination host unreachable.\n");
+++        FormatOutput(IDS_NOT_ENOUGH_RESOURCES);
 ++        return FALSE;
 ++    }
 ++
 ++    ZeroMemory(Buffer, Size);
 ++    Packet = (PICMP_ECHO_PACKET)Buffer;
 ++
 ++    /* Assemble ICMP echo request packet */
 ++    Packet->Icmp.Type     = ICMPMSG_ECHOREQUEST;
 ++    Packet->Icmp.Code     = 0;
 ++    Packet->Icmp.Id       = (USHORT)GetCurrentProcessId();
 ++    Packet->Icmp.SeqNum   = htons((USHORT)CurrentSeqNum);
 ++    Packet->Icmp.Checksum = 0;
 ++
 ++    /* Calculate checksum for ICMP header and data area */
 ++    Packet->Icmp.Checksum = Checksum((PUSHORT)&Packet->Icmp, sizeof(ICMP_ECHO_PACKET) + DataSize);
 ++
 ++    CurrentSeqNum++;
 ++
 ++    /* Send ICMP echo request */
 ++
 ++    FD_ZERO(&Fds);
 ++    FD_SET(IcmpSock, &Fds);
 ++    Timeval.tv_sec  = Timeout / 1000;
 ++    Timeval.tv_usec = Timeout % 1000;
 ++    Status = select(0, NULL, &Fds, NULL, &Timeval);
 ++    if ((Status != SOCKET_ERROR) && (Status != 0))
 ++    {
 ++
 ++#ifndef NDEBUG
 ++        printf("Sending packet\n");
 ++        DisplayBuffer(Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize);
 ++        printf("\n");
 ++#endif /* !NDEBUG */
 ++
 ++        Status = sendto(IcmpSock, Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize,
 ++            0, (SOCKADDR*)&Target, sizeof(Target));
 ++        QueryTime(&SentTime);
 ++        SentCount++;
 ++    }
 ++    if (Status == SOCKET_ERROR)
 ++    {
 ++        if (WSAGetLastError() == WSAEHOSTUNREACH)
-              printf("Could not transmit data (%d).\n", WSAGetLastError());
+++            FormatOutput(IDS_DEST_UNREACHABLE);
 ++        else
-                  printf("Could not receive data (%d).\n", WSAGetLastError());
+++            FormatOutput(IDS_COULD_NOT_TRANSMIT, WSAGetLastError());
 ++        GlobalFree(Buffer);
 ++        return FALSE;
 ++    }
 ++
 ++    /* Expect to receive ICMP echo reply */
 ++    FD_ZERO(&Fds);
 ++    FD_SET(IcmpSock, &Fds);
 ++    Timeval.tv_sec  = Timeout / 1000;
 ++    Timeval.tv_usec = Timeout % 1000;
 ++
 ++    do {
 ++        Status = select(0, &Fds, NULL, NULL, &Timeval);
 ++        if ((Status != SOCKET_ERROR) && (Status != 0))
 ++        {
 ++            Length = sizeof(From);
 ++            Status = recvfrom(IcmpSock, Buffer, Size, 0, &From, &Length);
 ++
 ++#ifndef NDEBUG
 ++            printf("Received packet\n");
 ++            DisplayBuffer(Buffer, Status);
 ++            printf("\n");
 ++#endif /* !NDEBUG */
 ++        }
 ++        else
 ++            LostCount++;
 ++        if (Status == SOCKET_ERROR)
 ++        {
 ++            if (WSAGetLastError() != WSAETIMEDOUT)
 ++            {
-              printf("Request timed out.\n");
+++                FormatOutput(IDS_COULD_NOT_RECV, WSAGetLastError());
 ++                GlobalFree(Buffer);
 ++                return FALSE;
 ++            }
 ++            Status = 0;
 ++        }
 ++
 ++        if (Status == 0)
 ++        {
-  int main(int argc, char* argv[])
+++            FormatOutput(IDS_REQUEST_TIMEOUT);
 ++            GlobalFree(Buffer);
 ++            return TRUE;
 ++        }
 ++
 ++    } while (!DecodeResponse(Buffer, Status, (PSOCKADDR_IN)&From));
 ++
 ++    GlobalFree(Buffer);
 ++    return TRUE;
 ++}
 ++
 ++
 ++/* Program entry point */
-      CHAR MinTime[20];
-      CHAR MaxTime[20];
-      CHAR AvgTime[20];
+++int wmain(int argc, LPWSTR argv[])
 ++{
 ++    UINT Count;
-          printf("\nPinging %s [%s] with %d bytes of data:\n\n",
-              TargetName, TargetIP, DataSize);
+++    WCHAR MinTime[20];
+++    WCHAR MaxTime[20];
+++    WCHAR AvgTime[20];
+++
+++    hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 ++
 ++    Reset();
 ++
 ++    if ((ParseCmdline(argc, argv)) && (Setup()))
 ++    {
 ++
-          printf("\nPing statistics for %s:\n", TargetIP);
-          printf("    Packets: Sent = %d, Received = %d, Lost = %d (%d%% loss),\n",
+++        FormatOutput(IDS_PING_WITH_BYTES, TargetName, TargetIP, DataSize);
 ++
 ++        Count = 0;
 ++        while ((NeverStop) || (Count < PingCount))
 ++        {
 ++            Ping();
 ++            Count++;
 ++            if((NeverStop) || (Count < PingCount))
 ++                Sleep(Timeout);
 ++        };
 ++
 ++        Cleanup();
 ++
 ++        /* Calculate avarage round trip time */
 ++        if ((SentCount - LostCount) > 0)
 ++            AvgRTT.QuadPart = SumRTT.QuadPart / (SentCount - LostCount);
 ++        else
 ++            AvgRTT.QuadPart = 0;
 ++
 ++        /* Calculate loss percent */
 ++        Count = SentCount ? (LostCount * 100) / SentCount : 0;
 ++
 ++        if (!MinRTTSet)
 ++            MinRTT = MaxRTT;
 ++
 ++        TimeToMsString(MinTime, MinRTT);
 ++        TimeToMsString(MaxTime, MaxRTT);
 ++        TimeToMsString(AvgTime, AvgRTT);
 ++
 ++        /* Print statistics */
-              printf("Approximate round trip times in milli-seconds:\n");
-              printf("    Minimum = %s, Maximum = %s, Average = %s\n",
-                  MinTime, MaxTime, AvgTime);
+++        FormatOutput(IDS_PING_STATISTICS, TargetIP);
+++        FormatOutput(IDS_PACKETS_SENT_RECEIVED_LOST,\
 ++            SentCount, SentCount - LostCount, LostCount, Count);
+++
 ++        /* Print approximate times or NO approximate times if 100% loss */
 ++        if ((SentCount - LostCount) > 0)
 ++        {
+++            FormatOutput(IDS_APPROXIMATE_ROUND_TRIP);
+++            FormatOutput(IDS_MIN_MAX_AVERAGE, MinTime, MaxTime, AvgTime);
 ++        }
 ++    }
 ++    return 0;
 ++}
 ++
 ++/* EOF */
index e856080,0000000,0000000..e138e7c
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,7 -1,0 -1,0 +1,15 @@@@
 ++/* $Id$ */
+++#include <windows.h>
+++#include "resource.h"
 ++
 ++#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 Ping\0"
 ++#define REACTOS_STR_INTERNAL_NAME    "ping\0"
 ++#define REACTOS_STR_ORIGINAL_FILENAME        "ping.exe\0"
 ++#define REACTOS_STR_ORIGINAL_COPYRIGHT       "Casper S. Hornstrup (chorns@users.sourceforge.net)\0"
 ++#include <reactos/version.rc>
+++
+++#include "lang/de-DE.rc"
+++#include "lang/en-US.rc"
+++#include "lang/fr-FR.rc"
+++#include "lang/pl-PL.rc"
+++#include "lang/it-IT.rc"
index 4c47525,0000000,ced1b4a..ced1b4a
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,21 -1,0 -1,21 +1,21 @@@@
-  Version = 0.9.7-0
 + ; UTF-8
 + 
 + [Section]
 + Name = K Desktop Environment
-  URLDownload = http://www.winkde.org/pub/kde/ports/win32/installer/kdewin-installer-gui-0.9.7-0.exe
++ Version = 0.9.8-1
 + Licence = GPL
 + Description = KDE for Windows.
 + Size = 2.0MB
 + Category = 15
 + URLSite = http://www.winkde.org/
++ URLDownload = http://www.winkde.org/pub/kde/ports/win32/installer/kdewin-installer-gui-0.9.8-1.exe
 + CDPath = none
 + 
 + [Section.0407]
 + Description = KDE für Windows.
 + 
 + [Section.0415]
 + Description = KDE dla Windows.
 + 
 + [Section.0422]
 + Description = KDE для Windows.
index 2fd0d9d,0000000,60c99c5..60c99c5
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,24 -1,0 -1,24 +1,24 @@@@
-  Version = 3.3.0 RC2
 + ; UTF-8
 + 
 + [Section]
 + Name = LibreOffice
-  Size = 206.0MB
++ Version = 3.3.0 RC3
 + Licence = LGPL
 + Description = Former called OpenOffice. Open Source Office Suite.
-  URLDownload = http://download.documentfoundation.org/libreoffice/testing/3.3.0-rc2/win/x86/LibO_3.3.0rc2_Win_x86_install_multi.exe
++ Size = 209.0MB
 + Category = 6
 + URLSite = http://www.documentfoundation.org/
++ URLDownload = http://download.documentfoundation.org/libreoffice/testing/3.3.0-rc3/win/x86/LibO_3.3.0rc3_Win_x86_install_multi.exe
 + CDPath = none
 + 
 + [Section.0407]
 + Description = Vorher bekannt als OpenOffice. Open Source Office Suite.
 + 
 + [Section.040a]
 + Description = La suite de ofimática de código abierto.
 + 
 + [Section.0415]
 + Description = Otwarty pakiet biurowy.
 + 
 + [Section.0422]
 + Description = Відкритий офісний пакет.
index 0000000,0000000,4b73234..4b73234
mode 000000,000000,100644..100644
--- /dev/null
--- /dev/null
index deb41dc,0000000,e50c5e9..e50c5e9
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,14 -1,0 -1,14 +1,14 @@@@
-    Aucun argument ou -?\tAffichent ce message\n\
 + LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
 + 
 + STRINGTABLE DISCARDABLE
 + BEGIN
 + 
 + IDS_USAGE, "Utilisation: shutdown [-?] [-l | -s | -r] [-f]\n\n\
++   Aucun argument ou -?\tAffiche ce message\n\
 +   -l\t\t\tSe déconnecter\n\
 +   -s\t\t\tÉteindre l'ordinateur\n\
 +   -r\t\t\tÉteindre et redémarrer l'ordinateur\n\
 +   -f\t\t\tForce les applications en cours de fonctionnement à se fermer sans avertissements\n\
 +     \t\t\tSi vous ne spécifiez aucun autre paramètre, cette option\n\
 +     \t\t\tprovoquera aussi une déconnexion"
 + END
index 4b62255,0000000,0000000..2ac2ed9
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,38 -1,0 -1,0 +1,39 @@@@
 ++
 ++set_unicode()
 ++
 ++add_definitions(-DWIN32)
 ++
 ++list(APPEND SOURCE
 ++    desktop.c
 ++    dragdrop.c
 ++    explorer.c
 ++    startmnu.c
 ++    taskband.c
 ++    taskswnd.c
 ++    tbsite.c
 ++    trayntfy.c
 ++    trayprop.c
 ++    traywnd.c
 ++    explorer.rc)
 ++
 ++add_executable(explorer_new ${CMAKE_CURRENT_BINARY_DIR}/explorer_new_precomp.h.gch ${SOURCE})
 ++
 ++target_link_libraries(explorer_new uuid)
 ++
 ++add_pch(explorer_new ${CMAKE_CURRENT_SOURCE_DIR}/precomp.h ${SOURCE})
 ++set_module_type(explorer_new win32gui)
 ++add_importlibs(explorer_new
 ++    advapi32
 ++    gdi32
 ++    user32
 ++    comctl32
 ++    ole32
 ++    oleaut32
 ++    shell32
 ++    shlwapi
+++    version
 ++    msvcrt
 ++    kernel32
 ++    ntdll)
 ++
 ++add_cab_target(explorer_new 4)
Simple merge
Simple merge
Simple merge
index 7dcb9bc,0000000,3258c19..3258c19
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,1141 -1,0 -1,1175 +1,1175 @@@@
-       DefaultSecurity.lpSecurityDescriptor = pDefaultAcl;
 + /*
 +  * COPYRIGHT:       See COPYING in the top level directory
 +  * PROJECT:         ReactOS Winlogon
 +  * FILE:            base/system/winlogon/wlx.c
 +  * PURPOSE:         Logon
 +  * PROGRAMMERS:     Thomas Weidenmueller (w3seek@users.sourceforge.net)
 +  *                  Ge van Geldorp (gvg@reactos.com)
 +  *                  Hervé Poussineau (hpoussin@reactos.org)
 +  */
 + 
 + /* INCLUDES *****************************************************************/
 + 
 + #include "winlogon.h"
 + 
 + #include <wine/debug.h>
 + 
 + WINE_DEFAULT_DEBUG_CHANNEL(winlogon);
 + 
 + #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
 +      DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
 +      DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
 +      DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
 + 
 + #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
 +      WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
 +      WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
 +      WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
 +      STANDARD_RIGHTS_REQUIRED)
 + 
 + #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
 +      GENERIC_EXECUTE | GENERIC_ALL)
 + 
 + /* GLOBALS ******************************************************************/
 + 
 + static DLGPROC PreviousWindowProc;
 + static UINT_PTR IdTimer;
 + 
 + /* FUNCTIONS ****************************************************************/
 + 
 + static INT_PTR CALLBACK
 + DefaultWlxWindowProc(
 +      IN HWND hwndDlg,
 +      IN UINT uMsg,
 +      IN WPARAM wParam,
 +      IN LPARAM lParam)
 + {
 +      if (uMsg == WM_TIMER && (UINT_PTR)wParam == IdTimer)
 +      {
 +              EndDialog(hwndDlg, -1);
 +              KillTimer(hwndDlg, IdTimer);
 +              return TRUE;
 +      }
 +      else if (uMsg == WM_INITDIALOG)
 +      {
 +              IdTimer = SetTimer(hwndDlg, 0, WLSession->DialogTimeout * 1000, NULL);
 +              return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
 +      }
 +      else if (uMsg == WM_NCDESTROY)
 +      {
 +              BOOL ret;
 +              ret = PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
 +              PreviousWindowProc = NULL;
 +              return ret;
 +      }
 +      else
 +      {
 +              return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
 +      }
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + VOID WINAPI
 + WlxUseCtrlAltDel(
 +      HANDLE hWlx)
 + {
 +      ULONG_PTR OldValue;
 + 
 +      TRACE("WlxUseCtrlAltDel()\n");
 + 
 +      WlxSetOption(hWlx, WLX_OPTION_USE_CTRL_ALT_DEL, TRUE, &OldValue);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + VOID WINAPI
 + WlxSetContextPointer(
 +      HANDLE hWlx,
 +      PVOID pWlxContext)
 + {
 +      ULONG_PTR OldValue;
 + 
 +      TRACE("WlxSetContextPointer(%p)\n", pWlxContext);
 + 
 +      WlxSetOption(hWlx, WLX_OPTION_CONTEXT_POINTER, (ULONG_PTR)pWlxContext, &OldValue);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + VOID WINAPI
 + WlxSasNotify(
 +      HANDLE hWlx,
 +      DWORD dwSasType)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxSasNotify(0x%lx)\n", dwSasType);
 + 
 +      if (dwSasType == WLX_SAS_TYPE_CTRL_ALT_DEL || dwSasType > WLX_SAS_TYPE_MAX_MSFT_VALUE)
 +              PostMessageW(Session->SASWindow, WLX_WM_SAS, dwSasType, 0);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + BOOL WINAPI
 + WlxSetTimeout(
 +      HANDLE hWlx,
 +      DWORD Timeout)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxSetTimeout(%lu)\n", Timeout);
 + 
 +      Session->DialogTimeout = Timeout;
 +      return TRUE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + int WINAPI
 + WlxAssignShellProtection(
 +      HANDLE hWlx,
 +      HANDLE hToken,
 +      HANDLE hProcess,
 +      HANDLE hThread)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(hToken);
 +      UNREFERENCED_PARAMETER(hProcess);
 +      UNREFERENCED_PARAMETER(hThread);
 + 
 +      UNIMPLEMENTED;
 +      return 0;
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxMessageBox(
 +      HANDLE hWlx,
 +      HWND hwndOwner,
 +      LPWSTR lpszText,
 +      LPWSTR lpszTitle,
 +      UINT fuStyle)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      TRACE("WlxMessageBox()\n");
 +      /* FIXME: Provide a custom window proc to be able to handle timeout */
 +      return MessageBoxW(hwndOwner, lpszText, lpszTitle, fuStyle);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxDialogBox(
 +      HANDLE hWlx,
 +      HANDLE hInst,
 +      LPWSTR lpszTemplate,
 +      HWND hwndOwner,
 +      DLGPROC dlgprc)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      TRACE("WlxDialogBox()\n");
 + 
 +      if (PreviousWindowProc != NULL)
 +              return -1;
 +      PreviousWindowProc = dlgprc;
 +      return (int)DialogBoxW((HINSTANCE) hInst, lpszTemplate, hwndOwner, DefaultWlxWindowProc);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxDialogBoxParam(
 +      HANDLE hWlx,
 +      HANDLE hInst,
 +      LPWSTR lpszTemplate,
 +      HWND hwndOwner,
 +      DLGPROC dlgprc,
 +      LPARAM dwInitParam)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      TRACE("WlxDialogBoxParam()\n");
 + 
 +      if (PreviousWindowProc != NULL)
 +              return -1;
 +      PreviousWindowProc = dlgprc;
 +      return (int)DialogBoxParamW(hInst, lpszTemplate, hwndOwner, DefaultWlxWindowProc, dwInitParam);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxDialogBoxIndirect(
 +      HANDLE hWlx,
 +      HANDLE hInst,
 +      LPCDLGTEMPLATE hDialogTemplate,
 +      HWND hwndOwner,
 +      DLGPROC dlgprc)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      TRACE("WlxDialogBoxIndirect()\n");
 + 
 +      if (PreviousWindowProc != NULL)
 +              return -1;
 +      PreviousWindowProc = dlgprc;
 +      return (int)DialogBoxIndirectW(hInst, hDialogTemplate, hwndOwner, DefaultWlxWindowProc);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxDialogBoxIndirectParam(
 +      HANDLE hWlx,
 +      HANDLE hInst,
 +      LPCDLGTEMPLATE hDialogTemplate,
 +      HWND hwndOwner,
 +      DLGPROC dlgprc,
 +      LPARAM dwInitParam)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      TRACE("WlxDialogBoxIndirectParam()\n");
 + 
 +      if (PreviousWindowProc != NULL)
 +              return -1;
 +      PreviousWindowProc = dlgprc;
 +      return (int)DialogBoxIndirectParamW(hInst, hDialogTemplate, hwndOwner, DefaultWlxWindowProc, dwInitParam);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxSwitchDesktopToUser(
 +      HANDLE hWlx)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxSwitchDesktopToUser()\n");
 + 
 +      return (int)SwitchDesktop(Session->ApplicationDesktop);
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + int WINAPI
 + WlxSwitchDesktopToWinlogon(
 +      HANDLE hWlx)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxSwitchDesktopToWinlogon()\n");
 + 
 +      return (int)SwitchDesktop(Session->WinlogonDesktop);
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + int WINAPI
 + WlxChangePasswordNotify(
 +      HANDLE hWlx,
 +      PWLX_MPR_NOTIFY_INFO pMprInfo,
 +      DWORD dwChangeInfo)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(pMprInfo);
 +      UNREFERENCED_PARAMETER(dwChangeInfo);
 + 
 +      UNIMPLEMENTED;
 +      return 0;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxGetSourceDesktop(
 +      HANDLE hWlx,
 +      PWLX_DESKTOP* ppDesktop)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(ppDesktop);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxSetReturnDesktop(
 +      HANDLE hWlx,
 +      PWLX_DESKTOP pDesktop)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(pDesktop);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxCreateUserDesktop(
 +      HANDLE hWlx,
 +      HANDLE hToken,
 +      DWORD Flags,
 +      PWSTR pszDesktopName,
 +      PWLX_DESKTOP* ppDesktop)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(hToken);
 +      UNREFERENCED_PARAMETER(Flags);
 +      UNREFERENCED_PARAMETER(pszDesktopName);
 +      UNREFERENCED_PARAMETER(ppDesktop);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + int WINAPI
 + WlxChangePasswordNotifyEx(
 +      HANDLE hWlx,
 +      PWLX_MPR_NOTIFY_INFO pMprInfo,
 +      DWORD dwChangeInfo,
 +      PWSTR ProviderName,
 +      PVOID Reserved)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(pMprInfo);
 +      UNREFERENCED_PARAMETER(dwChangeInfo);
 +      UNREFERENCED_PARAMETER(ProviderName);
 +      UNREFERENCED_PARAMETER(Reserved);
 + 
 +      UNIMPLEMENTED;
 +      return 0;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxCloseUserDesktop(
 +      HANDLE hWlx,
 +      PWLX_DESKTOP pDesktop,
 +      HANDLE hToken)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(pDesktop);
 +      UNREFERENCED_PARAMETER(hToken);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + BOOL WINAPI
 + WlxSetOption(
 +      HANDLE hWlx,
 +      DWORD Option,
 +      ULONG_PTR Value,
 +      ULONG_PTR* OldValue)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxSetOption(%lu)\n", Option);
 + 
 +      switch (Option)
 +      {
 +              case WLX_OPTION_USE_CTRL_ALT_DEL:
 +                      *OldValue = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
 +                      Session->Gina.UseCtrlAltDelete = (BOOL)Value;
 +                      return TRUE;
 +              case WLX_OPTION_CONTEXT_POINTER:
 +                      *OldValue = (ULONG_PTR)Session->Gina.Context;
 +                      Session->Gina.Context = (PVOID)Value;
 +                      return TRUE;
 +              case WLX_OPTION_USE_SMART_CARD:
 +                      UNIMPLEMENTED;
 +                      return FALSE;
 +      }
 + 
 +      return FALSE;
 + }
 + 
 + /*
 +  * @implemented
 +  */
 + BOOL WINAPI
 + WlxGetOption(
 +      HANDLE hWlx,
 +      DWORD Option,
 +      ULONG_PTR* Value)
 + {
 +      PWLSESSION Session = (PWLSESSION)hWlx;
 + 
 +      TRACE("WlxGetOption(%lu)\n", Option);
 + 
 +      switch (Option)
 +      {
 +              case WLX_OPTION_USE_CTRL_ALT_DEL:
 +                      *Value = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
 +                      return TRUE;
 +              case WLX_OPTION_CONTEXT_POINTER:
 +              {
 +                      *Value = (ULONG_PTR)Session->Gina.Context;
 +                      return TRUE;
 +              }
 +              case WLX_OPTION_USE_SMART_CARD:
 +              case WLX_OPTION_SMART_CARD_PRESENT:
 +              case WLX_OPTION_SMART_CARD_INFO:
 +                      UNIMPLEMENTED;
 +                      return FALSE;
 +              case WLX_OPTION_DISPATCH_TABLE_SIZE:
 +              {
 +                      switch (Session->Gina.Version)
 +                      {
 +                              case WLX_VERSION_1_0:
 +                                      *Value = sizeof(WLX_DISPATCH_VERSION_1_0);
 +                                      break;
 +                              case WLX_VERSION_1_1:
 +                                      *Value = sizeof(WLX_DISPATCH_VERSION_1_1);
 +                                      break;
 +                              case WLX_VERSION_1_2:
 +                                      *Value = sizeof(WLX_DISPATCH_VERSION_1_2);
 +                                      break;
 +                              case WLX_VERSION_1_3:
 +                                      *Value = sizeof(WLX_DISPATCH_VERSION_1_3);
 +                                      break;
 +                              case WLX_VERSION_1_4:
 +                                      *Value = sizeof(WLX_DISPATCH_VERSION_1_4);
 +                                      break;
 +                              default:
 +                                      return FALSE;
 +                      }
 +                      return TRUE;
 +              }
 +      }
 + 
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + VOID WINAPI
 + WlxWin31Migrate(
 +      HANDLE hWlx)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 + 
 +      UNIMPLEMENTED;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxQueryClientCredentials(
 +      PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
 + {
 +      UNREFERENCED_PARAMETER(pCred);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxQueryInetConnectorCredentials(
 +      PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
 + {
 +      UNREFERENCED_PARAMETER(pCred);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxDisconnect(VOID)
 + {
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + DWORD WINAPI
 + WlxQueryTerminalServicesData(
 +      HANDLE hWlx,
 +      PWLX_TERMINAL_SERVICES_DATA pTSData,
 +      WCHAR* UserName,
 +      WCHAR* Domain)
 + {
 +      UNREFERENCED_PARAMETER(hWlx);
 +      UNREFERENCED_PARAMETER(pTSData);
 +      UNREFERENCED_PARAMETER(UserName);
 +      UNREFERENCED_PARAMETER(Domain);
 + 
 +      UNIMPLEMENTED;
 +      return 0;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + DWORD WINAPI
 + WlxQueryConsoleSwitchCredentials(
 +      PWLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0 pCred)
 + {
 +      UNREFERENCED_PARAMETER(pCred);
 + 
 +      UNIMPLEMENTED;
 +      return 0;
 + }
 + 
 + /*
 +  * @unimplemented
 +  */
 + BOOL WINAPI
 + WlxQueryTsLogonCredentials(
 +      PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pCred)
 + {
 +      UNREFERENCED_PARAMETER(pCred);
 + 
 +      UNIMPLEMENTED;
 +      return FALSE;
 + }
 + 
 + static
 + WLX_DISPATCH_VERSION_1_4 FunctionTable = {
 +      WlxUseCtrlAltDel,
 +      WlxSetContextPointer,
 +      WlxSasNotify,
 +      WlxSetTimeout,
 +      WlxAssignShellProtection,
 +      WlxMessageBox,
 +      WlxDialogBox,
 +      WlxDialogBoxParam,
 +      WlxDialogBoxIndirect,
 +      WlxDialogBoxIndirectParam,
 +      WlxSwitchDesktopToUser,
 +      WlxSwitchDesktopToWinlogon,
 +      WlxChangePasswordNotify,
 +      WlxGetSourceDesktop,
 +      WlxSetReturnDesktop,
 +      WlxCreateUserDesktop,
 +      WlxChangePasswordNotifyEx,
 +      WlxCloseUserDesktop,
 +      WlxSetOption,
 +      WlxGetOption,
 +      WlxWin31Migrate,
 +      WlxQueryClientCredentials,
 +      WlxQueryInetConnectorCredentials,
 +      WlxDisconnect,
 +      WlxQueryTerminalServicesData,
 +      WlxQueryConsoleSwitchCredentials,
 +      WlxQueryTsLogonCredentials
 + };
 + 
 + /******************************************************************************/
 + 
 + static BOOL
 + GetGinaPath(
 +      OUT LPWSTR Path,
 +      IN DWORD Len)
 + {
 +      LONG Status;
 +      DWORD Type, Size;
 +      HKEY hKey;
 + 
 +      Status = RegOpenKeyExW(
 +              HKEY_LOCAL_MACHINE,
 +              L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
 +              0,
 +              KEY_QUERY_VALUE,
 +              &hKey);
 +      if (Status != ERROR_SUCCESS)
 +      {
 +              /* Default value */
 +              wcsncpy(Path, L"msgina.dll", Len);
 +              return TRUE;
 +      }
 + 
 +      Size = Len * sizeof(WCHAR);
 +      Status = RegQueryValueExW(
 +              hKey,
 +              L"GinaDLL",
 +              NULL,
 +              &Type,
 +              (LPBYTE)Path,
 +              &Size);
 +      if (Status != ERROR_SUCCESS || Type != REG_SZ || Size == 0)
 +              wcsncpy(Path, L"msgina.dll", Len);
 +      RegCloseKey(hKey);
 +      return TRUE;
 + }
 + 
 + static BOOL WINAPI
 + DefaultWlxScreenSaverNotify(
 +      IN PVOID pWlxContext,
 +      IN OUT BOOL *pSecure)
 + {
 +      if (*pSecure)
 +              *pSecure = WLSession->Gina.Functions.WlxIsLogoffOk(pWlxContext);
 +      return TRUE;
 + }
 + 
 + static BOOL
 + LoadGina(
 +      IN OUT PGINAFUNCTIONS Functions,
 +      OUT DWORD *DllVersion,
 +      OUT HMODULE *GinaInstance)
 + {
 +      HMODULE hGina = NULL;
 +      WCHAR GinaDll[MAX_PATH + 1];
 +      BOOL ret = FALSE;
 + 
 +      GinaDll[0] = '\0';
 +      if (!GetGinaPath(GinaDll, MAX_PATH))
 +              goto cleanup;
 +      /* Terminate string */
 +      GinaDll[MAX_PATH] = '\0';
 + 
 +      hGina = LoadLibraryW(GinaDll);
 +      if (!hGina)
 +              goto cleanup;
 + 
 +      Functions->WlxNegotiate = (PFWLXNEGOTIATE)GetProcAddress(hGina, "WlxNegotiate");
 +      Functions->WlxInitialize = (PFWLXINITIALIZE)GetProcAddress(hGina, "WlxInitialize");
 + 
 +      if (!Functions->WlxInitialize)
 +              goto cleanup;
 + 
 +      if (!Functions->WlxNegotiate)
 +      {
 +              /* Assume current version */
 +              *DllVersion = WLX_CURRENT_VERSION;
 +      }
 +      else
 +      {
 +              TRACE("About to negociate with Gina %S. Winlogon uses version %x\n",
 +                      GinaDll, WLX_CURRENT_VERSION);
 +              if (!Functions->WlxNegotiate(WLX_CURRENT_VERSION, DllVersion))
 +                      goto cleanup;
 +      }
 + 
 +      TRACE("Gina uses WLX_VERSION %lx\n", *DllVersion);
 + 
 +      if (*DllVersion >= WLX_VERSION_1_0)
 +      {
 +              Functions->WlxActivateUserShell = (PFWLXACTIVATEUSERSHELL)GetProcAddress(hGina, "WlxActivateUserShell");
 +              if (!Functions->WlxActivateUserShell) goto cleanup;
 +              Functions->WlxDisplayLockedNotice = (PFWLXDISPLAYLOCKEDNOTICE)GetProcAddress(hGina, "WlxDisplayLockedNotice");
 +              if (!Functions->WlxDisplayLockedNotice) goto cleanup;
 +              Functions->WlxDisplaySASNotice = (PFWLXDISPLAYSASNOTICE)GetProcAddress(hGina, "WlxDisplaySASNotice");
 +              if (!Functions->WlxDisplaySASNotice) goto cleanup;
 +              Functions->WlxIsLockOk = (PFWLXISLOCKOK)GetProcAddress(hGina, "WlxIsLockOk");
 +              if (!Functions->WlxIsLockOk) goto cleanup;
 +              Functions->WlxIsLogoffOk = (PFWLXISLOGOFFOK)GetProcAddress(hGina, "WlxIsLogoffOk");
 +              if (!Functions->WlxIsLogoffOk) goto cleanup;
 +              Functions->WlxLoggedOnSAS = (PFWLXLOGGEDONSAS)GetProcAddress(hGina, "WlxLoggedOnSAS");
 +              if (!Functions->WlxLoggedOnSAS) goto cleanup;
 +              Functions->WlxLoggedOutSAS = (PFWLXLOGGEDOUTSAS)GetProcAddress(hGina, "WlxLoggedOutSAS");
 +              if (!Functions->WlxLoggedOutSAS) goto cleanup;
 +              Functions->WlxLogoff = (PFWLXLOGOFF)GetProcAddress(hGina, "WlxLogoff");
 +              if (!Functions->WlxLogoff) goto cleanup;
 +              Functions->WlxShutdown = (PFWLXSHUTDOWN)GetProcAddress(hGina, "WlxShutdown");
 +              if (!Functions->WlxShutdown) goto cleanup;
 +              Functions->WlxWkstaLockedSAS = (PFWLXWKSTALOCKEDSAS)GetProcAddress(hGina, "WlxWkstaLockedSAS");
 +              if (!Functions->WlxWkstaLockedSAS) goto cleanup;
 +      }
 + 
 +      if (*DllVersion >= WLX_VERSION_1_1)
 +      {
 +              Functions->WlxScreenSaverNotify = (PFWLXSCREENSAVERNOTIFY)GetProcAddress(hGina, "WlxScreenSaverNotify");
 +              Functions->WlxStartApplication = (PFWLXSTARTAPPLICATION)GetProcAddress(hGina, "WlxStartApplication");
 +      }
 + 
 +      if (*DllVersion >= WLX_VERSION_1_3)
 +      {
 +              Functions->WlxDisplayStatusMessage = (PFWLXDISPLAYSTATUSMESSAGE)GetProcAddress(hGina, "WlxDisplayStatusMessage");
 +              if (!Functions->WlxDisplayStatusMessage) goto cleanup;
 +              Functions->WlxGetStatusMessage = (PFWLXGETSTATUSMESSAGE)GetProcAddress(hGina, "WlxGetStatusMessage");
 +              if (!Functions->WlxGetStatusMessage) goto cleanup;
 +              Functions->WlxNetworkProviderLoad = (PFWLXNETWORKPROVIDERLOAD)GetProcAddress(hGina, "WlxNetworkProviderLoad");
 +              if (!Functions->WlxNetworkProviderLoad) goto cleanup;
 +              Functions->WlxRemoveStatusMessage = (PFWLXREMOVESTATUSMESSAGE)GetProcAddress(hGina, "WlxRemoveStatusMessage");
 +              if (!Functions->WlxRemoveStatusMessage) goto cleanup;
 +      }
 + 
 +      /* Provide some default functions */
 +      if (!Functions->WlxScreenSaverNotify)
 +              Functions->WlxScreenSaverNotify = DefaultWlxScreenSaverNotify;
 + 
 +      ret = TRUE;
 + 
 + cleanup:
 +      if (!ret)
 +      {
 +              if (hGina)
 +                      FreeLibrary(hGina);
 +      }
 +      else
 +              *GinaInstance = hGina;
 +      return ret;
 + }
 + 
 + BOOL
 + GinaInit(
 +      IN OUT PWLSESSION Session)
 + {
 +      DWORD GinaDllVersion;
 + 
 +      if (!LoadGina(&Session->Gina.Functions, &GinaDllVersion, &Session->Gina.hDllInstance))
 +              return FALSE;
 + 
 +      Session->Gina.Context = NULL;
 +      Session->Gina.Version = GinaDllVersion;
 +      Session->Gina.UseCtrlAltDelete = FALSE;
 +      Session->SuppressStatus = FALSE;
 +      PreviousWindowProc = NULL;
 + 
 +      TRACE("Calling WlxInitialize(\"%S\")\n", Session->InteractiveWindowStationName);
 +      return Session->Gina.Functions.WlxInitialize(
 +              Session->InteractiveWindowStationName,
 +              (HANDLE)Session,
 +              NULL,
 +              (PVOID)&FunctionTable,
 +              &Session->Gina.Context);
 + }
 + 
 + BOOL
 + AddAceToWindowStation(
 +      IN HWINSTA WinSta,
 +      IN PSID Sid)
 + {
 +      DWORD AclSize;
 +      SECURITY_INFORMATION SecurityInformation;
 +      PACL pDefaultAcl = NULL;
 +      PSECURITY_DESCRIPTOR WinstaSd = NULL;
 +      PACCESS_ALLOWED_ACE Ace = NULL;
 +      BOOL Ret = FALSE;
 + 
 +      /* Allocate space for an ACL */
 +      AclSize = sizeof(ACL)
 +              + 2 * (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(Sid));
 +      pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
 +      if (!pDefaultAcl)
 +      {
 +              ERR("WL: HeapAlloc() failed\n");
 +              goto cleanup;
 +      }
 + 
 +      /* Initialize it */
 +      if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION))
 +      {
 +              ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Initialize new security descriptor */
 +      WinstaSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
 +      if (!InitializeSecurityDescriptor(WinstaSd, SECURITY_DESCRIPTOR_REVISION))
 +      {
 +              ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Allocate memory for access allowed ACE */
 +      Ace = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE)+
 +              GetLengthSid(Sid) - sizeof(DWORD));
 + 
 +      /* Create the first ACE for the window station */
 +      Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
 +      Ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
 +      Ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(Sid) - sizeof(DWORD);
 +      Ace->Mask = GENERIC_ACCESS;
 + 
 +      /* Copy the sid */
 +      if (!CopySid(GetLengthSid(Sid), &Ace->SidStart, Sid))
 +      {
 +              ERR("WL: CopySid() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add the first ACE */
 +      if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
 +      {
 +              ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add the second ACE to the end of ACL */
 +      Ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
 +      Ace->Mask = WINSTA_ALL;
 +      if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
 +      {
 +              ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add ACL to winsta's security descriptor */
 +      if (!SetSecurityDescriptorDacl(WinstaSd, TRUE, pDefaultAcl, FALSE))
 +      {
 +              ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Apply security to the window station */
 +      SecurityInformation = DACL_SECURITY_INFORMATION;
 +      if (!SetUserObjectSecurity(WinSta, &SecurityInformation, WinstaSd))
 +      {
 +              ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Indicate success */
 +      Ret = TRUE;
 + 
 + cleanup:
 +      /* Free allocated stuff */
 +      if (pDefaultAcl) HeapFree(GetProcessHeap(), 0, pDefaultAcl);
 +      if (WinstaSd) HeapFree(GetProcessHeap(), 0, WinstaSd);
 +      if (Ace) HeapFree(GetProcessHeap(), 0, Ace);
 + 
 +      return Ret;
 + }
 + 
 + BOOL
 + AddAceToDesktop(
 +      IN HDESK Desktop,
 +      IN PSID WinlogonSid,
 +      IN PSID UserSid)
 + {
 +      DWORD AclSize;
 +      SECURITY_INFORMATION SecurityInformation;
 +      PACL Acl = NULL;
 +      PSECURITY_DESCRIPTOR DesktopSd = NULL;
 +      BOOL Ret = FALSE;
 + 
 +      /* Allocate ACL */
 +      AclSize = sizeof(ACL)
 +              + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(WinlogonSid);
 + 
 +      /* Take user's sid into account */
 +      if (UserSid)
 +              AclSize += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(UserSid);
 + 
 +      Acl = HeapAlloc(GetProcessHeap(), 0, AclSize);
 +      if (!Acl)
 +      {
 +              ERR("WL: HeapAlloc() failed\n");
 +              goto cleanup;
 +      }
 + 
 +      /* Initialize ACL */
 +      if (!InitializeAcl(Acl, AclSize, ACL_REVISION))
 +      {
 +              ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add full desktop access ACE for winlogon */
 +      if (!AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, WinlogonSid))
 +      {
 +              ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add full desktop access ACE for a user (if provided) */
 +      if (UserSid && !AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, UserSid))
 +      {
 +              ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Initialize new security descriptor */
 +      DesktopSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
 +      if (!InitializeSecurityDescriptor(DesktopSd, SECURITY_DESCRIPTOR_REVISION))
 +      {
 +              ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Add ACL to the security descriptor */
 +      if (!SetSecurityDescriptorDacl(DesktopSd, TRUE, Acl, FALSE))
 +      {
 +              ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Apply security to the window station */
 +      SecurityInformation = DACL_SECURITY_INFORMATION;
 +      if (!SetUserObjectSecurity(Desktop, &SecurityInformation, DesktopSd))
 +      {
 +              ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* Indicate success */
 +      Ret = TRUE;
 + 
 + cleanup:
 +      /* Free allocated stuff */
 +      if (Acl) HeapFree(GetProcessHeap(), 0, Acl);
 +      if (DesktopSd) HeapFree(GetProcessHeap(), 0, DesktopSd);
 + 
 +      return Ret;
 + }
 + 
 + BOOL
 + CreateWindowStationAndDesktops(
 +      IN OUT PWLSESSION Session)
 + {
 +      BYTE LocalSystemBuffer[SECURITY_MAX_SID_SIZE];
 +      BYTE InteractiveBuffer[SECURITY_MAX_SID_SIZE];
 +      PSID pLocalSystemSid = (PSID)&LocalSystemBuffer;
 +      PSID pInteractiveSid = (PSID)InteractiveBuffer;
 +      DWORD SidSize, AclSize;
 +      PACL pDefaultAcl = NULL;
 +      PACL pUserDesktopAcl = NULL;
++      SECURITY_DESCRIPTOR DefaultSecurityDescriptor;
 +      SECURITY_ATTRIBUTES DefaultSecurity;
++      SECURITY_DESCRIPTOR UserDesktopSecurityDescriptor;
 +      SECURITY_ATTRIBUTES UserDesktopSecurity;
 +      BOOL ret = FALSE;
 + 
 +      /*
 +       * Prepare information for ACLs we will apply
 +       */
 +      SidSize = SECURITY_MAX_SID_SIZE;
 +      if (!CreateWellKnownSid(WinLocalSystemSid, NULL, pLocalSystemSid, &SidSize))
 +      {
 +              ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 +      SidSize = SECURITY_MAX_SID_SIZE;
 +      if (!CreateWellKnownSid(WinInteractiveSid, NULL, pInteractiveSid, &SidSize))
 +      {
 +              ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      AclSize = sizeof(ACL)
 +              + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pLocalSystemSid)
 +              + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pInteractiveSid);
 +      pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
 +      pUserDesktopAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
 +      if (!pDefaultAcl || !pUserDesktopAcl)
 +      {
 +              ERR("WL: HeapAlloc() failed\n");
 +              goto cleanup;
 +      }
 + 
 +      if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION)
 +       || !InitializeAcl(pUserDesktopAcl, AclSize, ACL_REVISION))
 +      {
 +              ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /*
 +       * Create default ACL (window station, winlogon desktop, screen saver desktop)
 +       */
 +      if (!AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
 +       || !AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_READ, pInteractiveSid))
 +      {
 +              ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
++ 
++      /*
++       * Create the default security descriptor
++       */
++      if (!InitializeSecurityDescriptor(&DefaultSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
++      {
++              ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
++              goto cleanup;
++      }
++ 
++      if (!SetSecurityDescriptorDacl(&DefaultSecurityDescriptor, TRUE, pDefaultAcl, FALSE))
++      {
++              ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
++              goto cleanup;
++      }
++ 
 +      DefaultSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
-       UserDesktopSecurity.lpSecurityDescriptor = pUserDesktopAcl;
++      DefaultSecurity.lpSecurityDescriptor = &DefaultSecurityDescriptor;
 +      DefaultSecurity.bInheritHandle = TRUE;
 + 
 +      /*
 +       * Create user desktop ACL
 +       */
 +      if (!AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
 +       || !AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pInteractiveSid))
 +      {
 +              ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
++ 
++      /*
++       * Create the user desktop security descriptor
++       */
++      if (!InitializeSecurityDescriptor(&UserDesktopSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
++      {
++              ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
++              goto cleanup;
++      }
++ 
++      if (!SetSecurityDescriptorDacl(&UserDesktopSecurityDescriptor, TRUE, pUserDesktopAcl, FALSE))
++      {
++              ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
++              goto cleanup;
++      }
++ 
 +      UserDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
++      UserDesktopSecurity.lpSecurityDescriptor = &UserDesktopSecurityDescriptor;
 +      UserDesktopSecurity.bInheritHandle = TRUE;
 + 
 +      /*
 +       * Create the interactive window station
 +       */
 +      Session->InteractiveWindowStationName = L"WinSta0";
 +      Session->InteractiveWindowStation = CreateWindowStationW(
 +              Session->InteractiveWindowStationName,
 +              0,
 +              GENERIC_ALL,
 +              &DefaultSecurity);
 +      if (!Session->InteractiveWindowStation)
 +      {
 +              ERR("WL: Failed to create window station (%lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 +      if (!SetProcessWindowStation(Session->InteractiveWindowStation))
 +      {
 +              ERR("WL: SetProcessWindowStation() failed (error %lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /*
 +       * Create the application desktop
 +       */
 +      Session->ApplicationDesktop = CreateDesktopW(
 +              L"Default",
 +              NULL,
 +              NULL,
 +              0, /* FIXME: Add DF_ALLOWOTHERACCOUNTHOOK flag? */
 +              GENERIC_ALL,
 +              &UserDesktopSecurity);
 +      if (!Session->ApplicationDesktop)
 +      {
 +              ERR("WL: Failed to create Default desktop (%lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /*
 +       * Create the winlogon desktop
 +       */
 +      Session->WinlogonDesktop = CreateDesktopW(
 +              L"Winlogon",
 +              NULL,
 +              NULL,
 +              0,
 +              GENERIC_ALL,
 +              &DefaultSecurity);
 +      if (!Session->WinlogonDesktop)
 +      {
 +              ERR("WL: Failed to create Winlogon desktop (%lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /*
 +       * Create the screen saver desktop
 +       */
 +      Session->ScreenSaverDesktop = CreateDesktopW(
 +              L"Screen-Saver",
 +              NULL,
 +              NULL,
 +              0,
 +              GENERIC_ALL,
 +              &DefaultSecurity);
 +      if(!Session->ScreenSaverDesktop)
 +      {
 +              ERR("WL: Failed to create Screen-Saver desktop (%lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      /* FIXME: big HACK */
 +      CloseDesktop(Session->WinlogonDesktop);
 +      CloseDesktop(Session->ScreenSaverDesktop);
 +      Session->WinlogonDesktop = OpenDesktopW(L"Default", 0, FALSE, GENERIC_ALL);
 +      Session->ScreenSaverDesktop = OpenDesktopW(L"Default", 0, FALSE, GENERIC_ALL);
 + 
 +      /*
 +       * Switch to winlogon desktop
 +      */
 +      if (!SetThreadDesktop(Session->WinlogonDesktop) ||
 +          !SwitchDesktop(Session->WinlogonDesktop))
 +      {
 +              ERR("WL: Cannot switch to Winlogon desktop (%lu)\n", GetLastError());
 +              goto cleanup;
 +      }
 + 
 +      ret = TRUE;
 + 
 + cleanup:
 +      if (!ret)
 +      {
 +              if (Session->ApplicationDesktop)
 +              {
 +                      CloseDesktop(Session->ApplicationDesktop);
 +                      Session->ApplicationDesktop = NULL;
 +              }
 +              if (Session->WinlogonDesktop)
 +              {
 +                      CloseDesktop(Session->WinlogonDesktop);
 +                      Session->WinlogonDesktop = NULL;
 +              }
 +              if (Session->ScreenSaverDesktop)
 +              {
 +                      CloseDesktop(Session->ScreenSaverDesktop);
 +                      Session->ScreenSaverDesktop = NULL;
 +              }
 +              if (Session->InteractiveWindowStation)
 +              {
 +                      CloseWindowStation(Session->InteractiveWindowStation);
 +                      Session->InteractiveWindowStation = NULL;
 +              }
 +      }
 +      HeapFree(GetProcessHeap(), 0, pDefaultAcl);
 +      HeapFree(GetProcessHeap(), 0, pUserDesktopAcl);
 +      return ret;
 + }
index d4e6f11,0000000,0000000..a8c91fe
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,703 -1,0 -1,0 +1,703 @@@@
-  #ifndef _M_ARM
 ++/*
 ++ *  FreeLoader
 ++ *
 ++ *  Copyright (C) 1998-2003  Brian Palmer    <brianp@sginet.com>
 ++ *  Copyright (C) 2006       Aleksey Bragin  <aleksey@reactos.org>
 ++ *
 ++ *  This program is free software; you can redistribute it and/or modify
 ++ *  it under the terms of the GNU General Public License as published by
 ++ *  the Free Software Foundation; either version 2 of the License, or
 ++ *  (at your option) any later version.
 ++ *
 ++ *  This program 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 General Public License for more details.
 ++ *
 ++ *  You should have received a copy of the GNU General Public License along
 ++ *  with this program; if not, write to the Free Software Foundation, Inc.,
 ++ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 ++ */
 ++
 ++#include <freeldr.h>
 ++
 ++#include <ndk/ldrtypes.h>
 ++#include <debug.h>
 ++
 ++// TODO: Move to .h
 ++void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
 ++                      PVOID *GdtIdt,
 ++                      ULONG *PcrBasePage,
 ++                      ULONG *TssBasePage);
 ++
 ++//FIXME: Do a better way to retrieve Arc disk information
 ++extern ULONG reactos_disk_count;
 ++extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
 ++extern char reactos_arc_strings[32][256];
 ++
 ++extern BOOLEAN UseRealHeap;
 ++extern ULONG LoaderPagesSpanned;
 ++extern BOOLEAN AcpiPresent;
 ++
 ++extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
 ++extern BOOLEAN WinLdrTerminalConnected;
 ++extern void WinLdrSetupEms(IN PCHAR BootOptions);
 ++
 ++BOOLEAN
 ++WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
 ++                        IN PCH DllName,
 ++                        OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);
 ++
 ++// debug stuff
 ++VOID DumpMemoryAllocMap(VOID);
 ++VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
 ++VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);
 ++VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock);
 ++
 ++
 ++// Init "phase 0"
 ++VOID
 ++AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
 ++{
 ++     PLOADER_PARAMETER_BLOCK LoaderBlock;
 ++
 ++     /* Allocate and zero-init the LPB */
 ++     LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK));
 ++     RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
 ++
 ++     /* Init three critical lists, used right away */
 ++     InitializeListHead(&LoaderBlock->LoadOrderListHead);
 ++     InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
 ++     InitializeListHead(&LoaderBlock->BootDriverListHead);
 ++
 ++     /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */
 ++     LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK));
 ++     if (LoaderBlock->NlsData == NULL)
 ++     {
 ++             UiMessageBox("Failed to allocate memory for NLS table data!");
 ++             return;
 ++     }
 ++     RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));
 ++
 ++     *OutLoaderBlock = LoaderBlock;
 ++}
 ++
 ++// Init "phase 1"
 ++VOID
 ++WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 ++                       PCHAR Options,
 ++                       PCHAR SystemRoot,
 ++                       PCHAR BootPath,
 ++                       USHORT VersionToBoot)
 ++{
 ++     /* Examples of correct options and paths */
 ++     //CHAR  Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";
 ++     //CHAR  Options[] = "/NODEBUG";
 ++     //CHAR  SystemRoot[] = "\\WINNT\\";
 ++     //CHAR  ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
 ++
 ++     CHAR    HalPath[] = "\\";
 ++     CHAR    ArcBoot[256];
 ++     CHAR    MiscFiles[256];
 ++     ULONG i, PathSeparator;
 ++     PLOADER_PARAMETER_EXTENSION Extension;
 ++
 ++     /* Construct SystemRoot and ArcBoot from SystemPath */
 ++     PathSeparator = strstr(BootPath, "\\") - BootPath;
 ++     strncpy(ArcBoot, BootPath, PathSeparator);
 ++     ArcBoot[PathSeparator] = 0;
 ++
 ++     DPRINTM(DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot);
 ++     DPRINTM(DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot);
 ++     DPRINTM(DPRINT_WINDOWS, "Options: %s\n", Options);
 ++
 ++     /* Fill Arc BootDevice */
 ++     LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
 ++     strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);
 ++     LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
 ++
 ++     /* Fill Arc HalDevice, it matches ArcBoot path */
 ++     LoaderBlock->ArcHalDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
 ++     strcpy(LoaderBlock->ArcHalDeviceName, ArcBoot);
 ++     LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);
 ++
 ++     /* Fill SystemRoot */
 ++     LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1);
 ++     strcpy(LoaderBlock->NtBootPathName, SystemRoot);
 ++     LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
 ++
 ++     /* Fill NtHalPathName */
 ++     LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1);
 ++     strcpy(LoaderBlock->NtHalPathName, HalPath);
 ++     LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
 ++
 ++     /* Fill load options */
 ++     LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1);
 ++     strcpy(LoaderBlock->LoadOptions, Options);
 ++     LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
 ++
 ++     /* Arc devices */
 ++     LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION));
 ++     InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
 ++
 ++     /* Convert ARC disk information from freeldr to a correct format */
 ++     for (i = 0; i < reactos_disk_count; i++)
 ++     {
 ++             PARC_DISK_SIGNATURE ArcDiskInfo;
 ++
 ++             /* Get the ARC structure */
 ++             ArcDiskInfo = (PARC_DISK_SIGNATURE)MmHeapAlloc(sizeof(ARC_DISK_SIGNATURE));
 ++             RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE));
 ++
 ++             /* Copy the data over */
 ++             ArcDiskInfo->Signature = reactos_arc_disk_info[i].Signature;
 ++             ArcDiskInfo->CheckSum = reactos_arc_disk_info[i].CheckSum;
 ++
 ++             /* Copy the ARC Name */
 ++             ArcDiskInfo->ArcName = (PCHAR)MmHeapAlloc(sizeof(CHAR)*256);
 ++             strcpy(ArcDiskInfo->ArcName, reactos_arc_disk_info[i].ArcName);
 ++             ArcDiskInfo->ArcName = (PCHAR)PaToVa(ArcDiskInfo->ArcName);
 ++
 ++             /* Mark partition table as valid */
 ++             ArcDiskInfo->ValidPartitionTable = TRUE;
 ++
 ++             /* Insert into the list */
 ++             InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
 ++                     &ArcDiskInfo->ListEntry);
 ++     }
 ++
 ++     /* Convert all list's to Virtual address */
 ++
 ++     /* Convert the ArcDisks list to virtual address */
 ++     List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
 ++     LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);
 ++
 ++     /* Convert configuration entries to VA */
 ++     ConvertConfigToVA(LoaderBlock->ConfigurationRoot);
 ++     LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);
 ++
 ++     /* Convert all DTE into virtual addresses */
 ++     List_PaToVa(&LoaderBlock->LoadOrderListHead);
 ++
 ++     /* this one will be converted right before switching to
 ++        virtual paging mode */
 ++     //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
 ++
 ++     /* Convert list of boot drivers */
 ++     List_PaToVa(&LoaderBlock->BootDriverListHead);
 ++
 ++     /* Initialize Extension now */
 ++     Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION));
 ++     if (Extension == NULL)
 ++     {
 ++             UiMessageBox("Failed to allocate LPB Extension!");
 ++             return;
 ++     }
 ++     RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));
 ++
 ++     /* Fill LPB extension */
 ++     Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
 ++     Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;
 ++     Extension->MinorVersion = VersionToBoot & 0xFF;
 ++     Extension->Profile.Status = 2;
 ++
 ++     /* Check if ACPI is present */
 ++     if (AcpiPresent)
 ++     {
 ++             /* See KiRosFrldrLpbToNtLpb for details */
 ++             Extension->AcpiTable = (PVOID)1;
 ++     }
 ++
-  #ifndef _M_ARM
+++#ifdef _M_IX86
 ++    /* Set headless block pointer */
 ++    if (WinLdrTerminalConnected)
 ++    {
 ++        Extension->HeadlessLoaderBlock = MmHeapAlloc(sizeof(HEADLESS_LOADER_BLOCK));
 ++        if (Extension->HeadlessLoaderBlock == NULL)
 ++        {
 ++            UiMessageBox("Failed to allocate HLB Extension!");
 ++            while (TRUE);
 ++            return;
 ++        }
 ++        RtlCopyMemory(
 ++            Extension->HeadlessLoaderBlock,
 ++            &LoaderRedirectionInformation,
 ++            sizeof(HEADLESS_LOADER_BLOCK));
 ++        Extension->HeadlessLoaderBlock = PaToVa(Extension->HeadlessLoaderBlock);
 ++    }
 ++#endif
 ++     /* Load drivers database */
 ++     strcpy(MiscFiles, BootPath);
 ++     strcat(MiscFiles, "AppPatch\\drvmain.sdb");
 ++     Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles,
 ++             &Extension->DrvDBSize, LoaderRegistryData));
 ++
 ++     /* Convert extension and setup block pointers */
 ++     LoaderBlock->Extension = PaToVa(Extension);
 ++
 ++     if (LoaderBlock->SetupLdrBlock)
 ++             LoaderBlock->SetupLdrBlock = PaToVa(LoaderBlock->SetupLdrBlock);
 ++
 ++}
 ++
 ++BOOLEAN
 ++WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
 ++                       LPSTR BootPath,
 ++                       PUNICODE_STRING FilePath,
 ++                       ULONG Flags,
 ++                       PLDR_DATA_TABLE_ENTRY *DriverDTE)
 ++{
 ++     CHAR FullPath[1024];
 ++     CHAR DriverPath[1024];
 ++     CHAR DllName[1024];
 ++     PCHAR DriverNamePos;
 ++     BOOLEAN Status;
 ++     PVOID DriverBase;
 ++
 ++     // Separate the path to file name and directory path
 ++     _snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
 ++     DriverNamePos = strrchr(DriverPath, '\\');
 ++     if (DriverNamePos != NULL)
 ++     {
 ++             // Copy the name
 ++             strcpy(DllName, DriverNamePos+1);
 ++
 ++             // Cut out the name from the path
 ++             *(DriverNamePos+1) = 0;
 ++     }
 ++     else
 ++     {
 ++             // There is no directory in the path
 ++             strcpy(DllName, DriverPath);
 ++             DriverPath[0] = 0;
 ++     }
 ++
 ++     DPRINTM(DPRINT_WINDOWS, "DriverPath: %s, DllName: %s, LPB %p\n", DriverPath, DllName, LoaderBlock);
 ++
 ++
 ++     // Check if driver is already loaded
 ++     Status = WinLdrCheckForLoadedDll(LoaderBlock, DllName, DriverDTE);
 ++     if (Status)
 ++     {
 ++             // We've got the pointer to its DTE, just return success
 ++             return TRUE;
 ++     }
 ++
 ++     // It's not loaded, we have to load it
 ++     strcpy(FullPath, "\\ArcName\\");
 ++     _snprintf(FullPath+strlen("\\ArcName\\"), sizeof(FullPath), "%s%wZ", BootPath, FilePath);
 ++     Status = WinLdrLoadImage(FullPath+strlen("\\ArcName\\"), LoaderBootDriver, &DriverBase);
 ++     if (!Status)
 ++             return FALSE;
 ++
 ++     // Allocate a DTE for it
 ++     Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, FullPath, DriverBase, DriverDTE);
 ++     if (!Status)
 ++     {
 ++             DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
 ++             return FALSE;
 ++     }
 ++
 ++     // Modify any flags, if needed
 ++     (*DriverDTE)->Flags |= Flags;
 ++
 ++     // Look for any dependencies it may have, and load them too
 ++     sprintf(FullPath,"%s%s", BootPath, DriverPath);
 ++     Status = WinLdrScanImportDescriptorTable(LoaderBlock, FullPath, *DriverDTE);
 ++     if (!Status)
 ++     {
 ++             DPRINTM(DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable() failed for %s\n",
 ++                     FullPath);
 ++             return FALSE;
 ++     }
 ++
 ++     return TRUE;
 ++}
 ++
 ++BOOLEAN
 ++WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
 ++                      LPSTR BootPath)
 ++{
 ++     PLIST_ENTRY NextBd;
 ++     PBOOT_DRIVER_LIST_ENTRY BootDriver;
 ++     BOOLEAN Status;
 ++
 ++     // Walk through the boot drivers list
 ++     NextBd = LoaderBlock->BootDriverListHead.Flink;
 ++
 ++     while (NextBd != &LoaderBlock->BootDriverListHead)
 ++     {
 ++             BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link);
 ++
 ++             DPRINTM(DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
 ++                     BootDriver->LdrEntry, &BootDriver->RegistryPath);
 ++
 ++             // Paths are relative (FIXME: Are they always relative?)
 ++
 ++             // Load it
 ++             Status = WinLdrLoadDeviceDriver(LoaderBlock, BootPath, &BootDriver->FilePath,
 ++                     0, &BootDriver->LdrEntry);
 ++
 ++             // If loading failed - cry loudly
 ++             //FIXME: Maybe remove it from the list and try to continue?
 ++             if (!Status)
 ++             {
 ++                     UiMessageBox("Can't load boot driver!");
 ++                     return FALSE;
 ++             }
 ++
 ++             // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore
 ++             BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer);
 ++             BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer);
 ++             BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry);
 ++
 ++             NextBd = BootDriver->Link.Flink;
 ++     }
 ++
 ++     return TRUE;
 ++}
 ++
 ++PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
 ++                                        TYPE_OF_MEMORY MemoryType)
 ++{
 ++     ULONG FileId;
 ++     PVOID PhysicalBase;
 ++     FILEINFORMATION FileInfo;
 ++     ULONG FileSize;
 ++     ULONG Status;
 ++     ULONG BytesRead;
 ++
 ++     //CHAR ProgressString[256];
 ++
 ++     /* Inform user we are loading files */
 ++     //sprintf(ProgressString, "Loading %s...", FileName);
 ++     //UiDrawProgressBarCenter(1, 100, ProgressString);
 ++
 ++     DPRINTM(DPRINT_WINDOWS, "Loading module %s\n", ModuleName);
 ++     *Size = 0;
 ++
 ++     /* Open the image file */
 ++     Status = ArcOpen((PCHAR)ModuleName, OpenReadOnly, &FileId);
 ++     if (Status != ESUCCESS)
 ++     {
 ++             /* In case of errors, we just return, without complaining to the user */
 ++             return NULL;
 ++     }
 ++
 ++     /* Get this file's size */
 ++     Status = ArcGetFileInformation(FileId, &FileInfo);
 ++     if (Status != ESUCCESS)
 ++     {
 ++             ArcClose(FileId);
 ++             return NULL;
 ++     }
 ++     FileSize = FileInfo.EndingAddress.LowPart;
 ++     *Size = FileSize;
 ++
 ++     /* Allocate memory */
 ++     PhysicalBase = MmAllocateMemoryWithType(FileSize, MemoryType);
 ++     if (PhysicalBase == NULL)
 ++     {
 ++             ArcClose(FileId);
 ++             return NULL;
 ++     }
 ++
 ++     /* Load whole file */
 ++     Status = ArcRead(FileId, PhysicalBase, FileSize, &BytesRead);
 ++     ArcClose(FileId);
 ++     if (Status != ESUCCESS)
 ++     {
 ++             return NULL;
 ++     }
 ++
 ++     DPRINTM(DPRINT_WINDOWS, "Loaded %s at 0x%x with size 0x%x\n", ModuleName, PhysicalBase, FileSize);
 ++
 ++     return PhysicalBase;
 ++}
 ++
 ++
 ++USHORT
 ++WinLdrDetectVersion()
 ++{
 ++     LONG rc;
 ++     FRLDRHKEY hKey;
 ++
 ++     rc = RegOpenKey(
 ++             NULL,
 ++             L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
 ++             &hKey);
 ++     if (rc != ERROR_SUCCESS)
 ++     {
 ++             // Key doesn't exist; assume NT 4.0
 ++             return _WIN32_WINNT_NT4;
 ++     }
 ++
 ++     // We may here want to read the value of ProductVersion
 ++     return _WIN32_WINNT_WS03;
 ++}
 ++
 ++
 ++VOID
 ++LoadAndBootWindows(PCSTR OperatingSystemName,
 ++                   PSTR SettingsValue,
 ++                   USHORT OperatingSystemVersion)
 ++{
 ++     BOOLEAN HasSection;
 ++     char  FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
 ++     CHAR  FileName[MAX_PATH];
 ++     CHAR  BootOptions[256];
 ++     PCHAR File;
 ++     PCHAR PathSeparator;
 ++     PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
 ++     BOOLEAN Status;
 ++     ULONG_PTR SectionId;
 ++     PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
 ++     KERNEL_ENTRY_POINT KiSystemStartup;
 ++     PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
 ++     // Mm-related things
 ++     PVOID GdtIdt;
 ++     ULONG PcrBasePage=0;
 ++     ULONG TssBasePage=0;
 ++
 ++     // Open the operating system section
 ++     // specified in the .ini file
 ++     HasSection = IniOpenSection(OperatingSystemName, &SectionId);
 ++
 ++     UiDrawBackdrop();
 ++     UiDrawStatusText("Detecting Hardware...");
 ++     UiDrawProgressBarCenter(1, 100, "Loading NT...");
 ++
 ++     /* Read the system path is set in the .ini file */
 ++     if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", FullPath, sizeof(FullPath)))
 ++     {
 ++             strcpy(FullPath, OperatingSystemName);
 ++     }
 ++
 ++     /* Special case for LiveCD */
 ++     if (!_strnicmp(FullPath, "LiveCD", strlen("LiveCD")))
 ++     {
 ++             strcpy(BootPath, FullPath + strlen("LiveCD"));
 ++             MachDiskGetBootPath(FullPath, sizeof(FullPath));
 ++             strcat(FullPath, BootPath);
 ++     }
 ++
 ++     /* Convert FullPath to SystemRoot */
 ++     PathSeparator = strstr(FullPath, "\\");
 ++     strcpy(SystemRoot, PathSeparator);
 ++     strcat(SystemRoot, "\\");
 ++
 ++     /* Read booting options */
 ++     if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
 ++     {
 ++             /* Get options after the title */
 ++             const CHAR*p = SettingsValue;
 ++             while (*p == ' ' || *p == '"')
 ++                     p++;
 ++             while (*p != '\0' && *p != '"')
 ++                     p++;
 ++             strcpy(BootOptions, p);
 ++             DPRINTM(DPRINT_WINDOWS,"BootOptions: '%s'\n", BootOptions);
 ++     }
 ++
 ++     /* Append boot-time options */
 ++     AppendBootTimeOptions(BootOptions);
 ++
 ++     //
 ++     // Check if a ramdisk file was given
 ++     //
 ++     File = strstr(BootOptions, "/RDPATH=");
 ++     if (File)
 ++     {
 ++             //
 ++             // Copy the file name and everything else after it
 ++             //
 ++             strcpy(FileName, File + 8);
 ++
 ++             //
 ++             // Null-terminate
 ++             //
 ++             *strstr(FileName, " ") = ANSI_NULL;
 ++
 ++             //
 ++             // Load the ramdisk
 ++             //
 ++             RamDiskLoadVirtualFile(FileName);
 ++     }
 ++
 ++     /* Let user know we started loading */
 ++     UiDrawStatusText("Loading...");
 ++
 ++     /* append a backslash */
 ++     strcpy(BootPath, FullPath);
 ++     if ((strlen(BootPath)==0) ||
 ++         BootPath[strlen(BootPath)] != '\\')
 ++             strcat(BootPath, "\\");
 ++
 ++     DPRINTM(DPRINT_WINDOWS,"BootPath: '%s'\n", BootPath);
 ++
 ++     /* Allocate and minimalistic-initialize LPB */
 ++     AllocateAndInitLPB(&LoaderBlock);
 ++
+++#ifdef _M_IX86
 ++     /* Setup redirection support */
 ++     WinLdrSetupEms(BootOptions);
 ++#endif
 ++     /* Detect hardware */
 ++     UseRealHeap = TRUE;
 ++     LoaderBlock->ConfigurationRoot = MachHwDetect();
 ++
 ++     /* Load Hive */
 ++     Status = WinLdrInitSystemHive(LoaderBlock, BootPath);
 ++     DPRINTM(DPRINT_WINDOWS, "SYSTEM hive loaded with status %d\n", Status);
 ++
 ++     if (OperatingSystemVersion == 0)
 ++             OperatingSystemVersion = WinLdrDetectVersion();
 ++
 ++     strcpy(FileName, "\\ArcName\\");
 ++
 ++     /* Load kernel */
 ++     strcpy(FileName+strlen("\\ArcName\\"), BootPath);
 ++     strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
 ++     Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderSystemCode, &NtosBase);
 ++     DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
 ++     WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
 ++             FileName, NtosBase, &KernelDTE);
 ++
 ++     /* Load HAL */
 ++     strcpy(FileName+strlen("\\ArcName\\"), BootPath);
 ++     strcat(FileName, "SYSTEM32\\HAL.DLL");
 ++     Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderHalCode, &HalBase);
 ++     DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
 ++     WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
 ++             FileName, HalBase, &HalDTE);
 ++
 ++     /* Load kernel-debugger support dll */
 ++     if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
 ++     {
 ++             strcpy(FileName+strlen("\\ArcName\\"), BootPath);
 ++             strcat(FileName, "SYSTEM32\\KDCOM.DLL");
 ++             Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderBootDriver, &KdComBase);
 ++             DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
 ++             WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
 ++                     FileName, KdComBase, &KdComDTE);
 ++     }
 ++
 ++     /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
 ++     strcpy(FileName, BootPath);
 ++     strcat(FileName, "SYSTEM32\\");
 ++     WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KernelDTE);
 ++     WinLdrScanImportDescriptorTable(LoaderBlock, FileName, HalDTE);
 ++     if (KdComDTE)
 ++             WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KdComDTE);
 ++
 ++     /* Load NLS data, OEM font, and prepare boot drivers list */
 ++     Status = WinLdrScanSystemHive(LoaderBlock, BootPath);
 ++     DPRINTM(DPRINT_WINDOWS, "SYSTEM hive scanned with status %d\n", Status);
 ++
 ++     /* Load boot drivers */
 ++     Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
 ++     DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
 ++
 ++     /* Alloc PCR, TSS, do magic things with the GDT/IDT */
 ++     WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
 ++
 ++     /* Initialize Phase 1 - no drivers loading anymore */
 ++     WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemRoot, BootPath, OperatingSystemVersion);
 ++
 ++     /* Save entry-point pointer and Loader block VAs */
 ++     KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
 ++     LoaderBlockVA = PaToVa(LoaderBlock);
 ++
 ++     /* "Stop all motors", change videomode */
 ++     if (OperatingSystemVersion < _WIN32_WINNT_WIN2K)
 ++             MachPrepareForReactOS(TRUE);
 ++     else
 ++             MachPrepareForReactOS(FALSE);
 ++
 ++     /* Debugging... */
 ++     //DumpMemoryAllocMap();
 ++
 ++     /* Turn on paging mode of CPU*/
 ++     WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
 ++
 ++     /* Save final value of LoaderPagesSpanned */
 ++     LoaderBlockVA->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
 ++
 ++     DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
 ++             KiSystemStartup, LoaderBlockVA);
 ++
 ++     WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
 ++     WinLdrpDumpBootDriver(LoaderBlockVA);
 ++     WinLdrpDumpArcDisks(LoaderBlockVA);
 ++
 ++     //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below
 ++     //while (1) {};
 ++     /*asm(".intel_syntax noprefix\n");
 ++             asm("test1:\n");
 ++             asm("jmp test1\n");
 ++     asm(".att_syntax\n");*/
 ++
 ++     /* Pass control */
 ++     (*KiSystemStartup)(LoaderBlockVA);
 ++
 ++     return;
 ++}
 ++
 ++VOID
 ++WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
 ++{
 ++     PLIST_ENTRY NextMd;
 ++     PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
 ++
 ++     NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
 ++
 ++     while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
 ++     {
 ++             MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
 ++
 ++             DPRINTM(DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,
 ++                     MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType);
 ++
 ++             NextMd = MemoryDescriptor->ListEntry.Flink;
 ++     }
 ++}
 ++
 ++VOID
 ++WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock)
 ++{
 ++     PLIST_ENTRY NextBd;
 ++     PBOOT_DRIVER_LIST_ENTRY BootDriver;
 ++
 ++     NextBd = LoaderBlock->BootDriverListHead.Flink;
 ++
 ++     while (NextBd != &LoaderBlock->BootDriverListHead)
 ++     {
 ++             BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link);
 ++
 ++             DPRINTM(DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
 ++                     BootDriver->LdrEntry, &BootDriver->RegistryPath);
 ++
 ++             NextBd = BootDriver->Link.Flink;
 ++     }
 ++}
 ++
 ++VOID
 ++WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock)
 ++{
 ++     PLIST_ENTRY NextBd;
 ++     PARC_DISK_SIGNATURE ArcDisk;
 ++
 ++     NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink;
 ++
 ++     while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead)
 ++     {
 ++             ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry);
 ++
 ++             DPRINTM(DPRINT_WINDOWS, "ArcDisk %s checksum: 0x%X, signature: 0x%X\n",
 ++                     ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature);
 ++
 ++             NextBd = ArcDisk->ListEntry.Flink;
 ++     }
 ++}
 ++
 ++
Simple merge
index 9baa9f9,0000000,0000000..d5409c6
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,59 -1,0 -1,0 +1,64 @@@@
 ++
 ++set_unicode()
 ++
 ++add_definitions(
 ++    -D_DLL -D__USE_CRTIMP
 ++    -DLANGPACK)
 ++
 ++include_directories(include)
 ++
 ++spec2def(gdi32.dll gdi32.spec)
 ++
+++if(ARCH MATCHES i386)
+++list(APPEND SOURCE
+++    objects/efloat.c)
+++endif()
+++
 ++list(APPEND SOURCE
 ++    main/dllmain.c
 ++    misc/heap.c
 ++    misc/gdientry.c
 ++    misc/hacks.c
 ++    misc/historic.c
 ++    misc/misc.c
 ++    misc/stubs.c
 ++    misc/stubsa.c
 ++    misc/stubsw.c
 ++    misc/wingl.c
 ++    objects/arc.c
 ++    objects/bitmap.c
 ++    objects/brush.c
 ++    objects/coord.c
 ++    objects/dc.c
 ++    objects/eng.c
 ++    objects/enhmfile.c
 ++    objects/font.c
 ++    objects/icm.c
 ++    objects/linedda.c
 ++    objects/metafile.c
 ++    objects/painting.c
 ++    objects/printdrv.c
 ++    objects/palette.c
 ++    objects/pen.c
 ++    objects/region.c
 ++    objects/text.c
 ++    objects/utils.c
 ++    objects/path.c
 ++    gdi32.rc
 ++    ${CMAKE_CURRENT_BINARY_DIR}/gdi32.def)
 ++
 ++add_library(gdi32 SHARED
 ++    ${CMAKE_CURRENT_BINARY_DIR}/gdi32_precomp.h.gch
 ++    ${SOURCE})
 ++
 ++set_module_type(gdi32 win32dll)
 ++
 ++target_link_libraries(gdi32
 ++    win32ksys
 ++    dxguid
 ++    ${PSEH_LIB})
 ++
 ++add_importlibs(gdi32 user32 advapi32 msvcrt kernel32 ntdll)
 ++add_pch(gdi32 ${CMAKE_CURRENT_SOURCE_DIR}/include/precomp.h ${SOURCE})
 ++add_cab_target(gdi32 1)
 ++add_importlib_target(gdi32.spec)
index cfe82e3,0000000,0000000..b3b0fdd
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,613 -1,0 -1,0 +1,613 @@@@
-  @ stdcall CombineTransform(ptr ptr ptr) NtGdiCombineTransform
 ++@ stdcall AbortDoc(ptr)
 ++@ stdcall AbortPath(ptr)
 ++@ stdcall AddFontMemResourceEx(ptr long ptr ptr)
 ++@ stdcall AddFontResourceA(str)
 ++@ stdcall AddFontResourceExA(str long ptr)
 ++@ stdcall AddFontResourceExW(wstr long ptr)
 ++@ stdcall AddFontResourceTracking(str long)
 ++@ stdcall AddFontResourceW(wstr)
 ++@ stdcall AngleArc(ptr long long long long long)
 ++@ stdcall AnimatePalette(long long long ptr)
 ++@ stdcall AnyLinkedFonts() NtGdiAnyLinkedFonts
 ++@ stdcall Arc(long long long long long long long long long)
 ++@ stdcall ArcTo(long long long long long long long long long)
 ++@ stdcall BRUSHOBJ_hGetColorTransform(ptr) NtGdiBRUSHOBJ_hGetColorTransform
 ++@ stdcall BRUSHOBJ_pvAllocRbrush(ptr long) NtGdiBRUSHOBJ_pvAllocRbrush
 ++@ stdcall BRUSHOBJ_pvGetRbrush(ptr) NtGdiBRUSHOBJ_pvGetRbrush
 ++@ stdcall BRUSHOBJ_ulGetBrushColor(ptr) NtGdiBRUSHOBJ_ulGetBrushColor
 ++@ stdcall BeginPath(long)
 ++@ stdcall BitBlt(long long long long long long long long long)
 ++@ stdcall CLIPOBJ_bEnum(ptr long long) NtGdiCLIPOBJ_bEnum
 ++@ stdcall CLIPOBJ_cEnumStart(ptr long long long long) NtGdiCLIPOBJ_cEnumStart
 ++@ stdcall CLIPOBJ_ppoGetPath(ptr) NtGdiCLIPOBJ_ppoGetPath
 ++@ stdcall CancelDC(long)
 ++@ stdcall CheckColorsInGamut(ptr ptr ptr long)
 ++@ stdcall ChoosePixelFormat(long ptr)
 ++@ stdcall Chord(long long long long long long long long long)
 ++@ stdcall ClearBitmapAttributes(ptr long)
 ++@ stdcall ClearBrushAttributes(ptr long)
 ++@ stdcall CloseEnhMetaFile(long)
 ++@ stdcall CloseFigure(long)
 ++@ stdcall CloseMetaFile(long)
 ++@ stdcall ColorCorrectPalette(ptr ptr long long)
 ++@ stdcall ColorMatchToTarget(ptr ptr long)
 ++@ stdcall CombineRgn(long long long long)
-  @ stdcall GdiFullscreenControl(ptr ptr long ptr ptr) NtGdiFullscreenControl 
+++@ stdcall CombineTransform(ptr ptr ptr)
 ++@ stdcall CopyEnhMetaFileA(long str)
 ++@ stdcall CopyEnhMetaFileW(long wstr)
 ++@ stdcall CopyMetaFileA(long str)
 ++@ stdcall CopyMetaFileW(long wstr)
 ++@ stdcall CreateBitmap(long long long long ptr)
 ++@ stdcall CreateBitmapIndirect(ptr)
 ++@ stdcall CreateBrushIndirect(ptr)
 ++@ stdcall CreateColorSpaceA(ptr)
 ++@ stdcall CreateColorSpaceW(ptr)
 ++@ stdcall CreateCompatibleBitmap(long long long)
 ++@ stdcall CreateCompatibleDC(long)
 ++@ stdcall CreateDCA(str str str ptr)
 ++@ stdcall CreateDCW(wstr wstr wstr ptr)
 ++@ stdcall CreateDIBPatternBrush(long long)
 ++@ stdcall CreateDIBPatternBrushPt(long long)
 ++@ stdcall CreateDIBSection(long ptr long ptr long long)
 ++@ stdcall CreateDIBitmap(long ptr long ptr ptr long)
 ++@ stdcall CreateDiscardableBitmap(long long long)
 ++@ stdcall CreateEllipticRgn(long long long long) NtGdiCreateEllipticRgn
 ++@ stdcall CreateEllipticRgnIndirect(ptr)
 ++@ stdcall CreateEnhMetaFileA(long str ptr str)
 ++@ stdcall CreateEnhMetaFileW(long wstr ptr wstr)
 ++@ stdcall CreateFontA(long long long long long long long long long long long long long str)
 ++@ stdcall CreateFontIndirectA(ptr)
 ++@ stdcall CreateFontIndirectExA(ptr)
 ++@ stdcall CreateFontIndirectExW(ptr)
 ++@ stdcall CreateFontIndirectW(ptr)
 ++@ stdcall CreateFontW(long long long long long long long long long long long long long wstr)
 ++@ stdcall CreateHalftonePalette(long) NtGdiCreateHalftonePalette
 ++@ stdcall CreateHatchBrush(long long)
 ++@ stdcall CreateICA(str str str ptr)
 ++@ stdcall CreateICW(wstr wstr wstr ptr)
 ++@ stdcall CreateMetaFileA(str)
 ++@ stdcall CreateMetaFileW(wstr)
 ++@ stdcall CreatePalette(ptr)
 ++@ stdcall CreatePatternBrush(long)
 ++@ stdcall CreatePen(long long long)
 ++@ stdcall CreatePenIndirect(ptr)
 ++@ stdcall CreatePolyPolygonRgn(ptr ptr long long)
 ++@ stdcall CreatePolygonRgn(ptr long long)
 ++@ stdcall CreateRectRgn(long long long long)
 ++@ stdcall CreateRectRgnIndirect(ptr)
 ++@ stdcall CreateRoundRectRgn(long long long long long long) NtGdiCreateRoundRectRgn
 ++@ stdcall CreateScalableFontResourceA(long str str str)
 ++@ stdcall CreateScalableFontResourceW(long wstr wstr wstr)
 ++@ stdcall CreateSolidBrush(long)
 ++@ stdcall DPtoLP(long ptr long)
 ++@ stdcall DdEntry0(ptr ptr ptr ptr ptr ptr) NtGdiDxgGenericThunk
 ++@ stdcall DdEntry10(ptr ptr) NtGdiDdBeginMoCompFrame
 ++@ stdcall DdEntry11(ptr ptr ptr) NtGdiDdBlt
 ++@ stdcall DdEntry12(ptr ptr) NtGdiDdCanCreateSurface
 ++@ stdcall DdEntry13(ptr ptr) NtGdiDdCanCreateD3DBuffer
 ++@ stdcall DdEntry14(ptr ptr) NtGdiDdColorControl
 ++@ stdcall DdEntry15(ptr) NtGdiDdCreateDirectDrawObject
 ++@ stdcall DdEntry16(ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiDdCreateSurface
 ++@ stdcall DdEntry17(ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiDdCreateD3DBuffer
 ++@ stdcall DdEntry18(ptr ptr) NtGdiDdCreateMoComp
 ++@ stdcall DdEntry19(ptr ptr ptr ptr ptr long) NtGdiDdCreateSurfaceObject
 ++@ stdcall DdEntry1(ptr ptr ptr ptr) NtGdiD3dContextCreate
 ++@ stdcall DdEntry20(ptr) NtGdiDdDeleteDirectDrawObject
 ++@ stdcall DdEntry21(ptr) NtGdiDdDeleteSurfaceObject
 ++@ stdcall DdEntry22(ptr ptr) NtGdiDdDestroyMoComp
 ++@ stdcall DdEntry23(ptr long) NtGdiDdDestroySurface
 ++@ stdcall DdEntry24(ptr) NtGdiDdDestroyD3DBuffer
 ++@ stdcall DdEntry25(ptr ptr) NtGdiDdEndMoCompFrame
 ++@ stdcall DdEntry26(ptr ptr ptr ptr ptr) NtGdiDdFlip
 ++@ stdcall DdEntry27(ptr long) NtGdiDdFlipToGDISurface
 ++@ stdcall DdEntry28(ptr ptr) NtGdiDdGetAvailDriverMemory
 ++@ stdcall DdEntry29(ptr ptr) NtGdiDdGetBltStatus
 ++@ stdcall DdEntry2(ptr) NtGdiD3dContextDestroy
 ++@ stdcall DdEntry30(ptr ptr) NtGdiDdGetDC
 ++@ stdcall DdEntry31(ptr ptr) NtGdiDdGetDriverInfo
 ++@ stdcall DdEntry32(ptr ptr long) NtGdiDdGetDxHandle
 ++@ stdcall DdEntry33(ptr ptr) NtGdiDdGetFlipStatus
 ++@ stdcall DdEntry34(ptr ptr) NtGdiDdGetInternalMoCompInfo
 ++@ stdcall DdEntry35(ptr ptr) NtGdiDdGetMoCompBuffInfo
 ++@ stdcall DdEntry36(ptr ptr) NtGdiDdGetMoCompGuids
 ++@ stdcall DdEntry37(ptr ptr) NtGdiDdGetMoCompFormats
 ++@ stdcall DdEntry38(ptr ptr) NtGdiDdGetScanLine
 ++@ stdcall DdEntry39(ptr ptr ptr) NtGdiDdLock
 ++@ stdcall DdEntry3(ptr) NtGdiD3dContextDestroyAll
 ++@ stdcall DdEntry40(ptr ptr) NtGdiDdLockD3D
 ++@ stdcall DdEntry41(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiDdQueryDirectDrawObject
 ++@ stdcall DdEntry42(ptr ptr) NtGdiDdQueryMoCompStatus
 ++@ stdcall DdEntry43(ptr ptr) NtGdiDdReenableDirectDrawObject
 ++@ stdcall DdEntry44(ptr) NtGdiDdReleaseDC
 ++@ stdcall DdEntry45(ptr ptr) NtGdiDdRenderMoComp
 ++@ stdcall DdEntry46(ptr ptr) NtGdiDdResetVisrgn
 ++@ stdcall DdEntry47(ptr ptr) NtGdiDdSetColorKey
 ++@ stdcall DdEntry48(ptr ptr) NtGdiDdSetExclusiveMode
 ++@ stdcall DdEntry49(ptr ptr ptr) NtGdiDdSetGammaRamp
 ++@ stdcall DdEntry4(ptr) NtGdiD3dValidateTextureStageState
 ++@ stdcall DdEntry50(ptr ptr long) NtGdiDdCreateSurfaceEx
 ++@ stdcall DdEntry51(ptr ptr ptr) NtGdiDdSetOverlayPosition
 ++@ stdcall DdEntry52(ptr ptr) NtGdiDdUnattachSurface
 ++@ stdcall DdEntry53(ptr ptr) NtGdiDdUnlock
 ++@ stdcall DdEntry54(ptr ptr) NtGdiDdUnlockD3D
 ++@ stdcall DdEntry55(ptr ptr long) NtGdiDdUpdateOverlay
 ++@ stdcall DdEntry56(ptr ptr) NtGdiDdWaitForVerticalBlank
 ++@ stdcall DdEntry5(ptr ptr ptr ptr ptr ptr ptr) NtGdiD3dDrawPrimitives2
 ++@ stdcall DdEntry6(ptr) NtGdiDdGetDriverState
 ++@ stdcall DdEntry7(ptr ptr ptr) NtGdiDdAddAttachedSurface
 ++@ stdcall DdEntry8(ptr ptr ptr) NtGdiDdAlphaBlt
 ++@ stdcall DdEntry9(ptr ptr) NtGdiDdAttachSurface
 ++@ stdcall DeleteColorSpace(long) NtGdiDeleteColorSpace
 ++@ stdcall DeleteDC(long)
 ++@ stdcall DeleteEnhMetaFile(long)
 ++@ stdcall DeleteMetaFile(long)
 ++@ stdcall DeleteObject(long)
 ++@ stdcall DescribePixelFormat(long long long ptr)
 ++@ stdcall DeviceCapabilitiesExA(str str long str ptr)
 ++@ stdcall DeviceCapabilitiesExW(wstr wstr long wstr ptr)
 ++@ stdcall DrawEscape(long long long ptr)
 ++@ stdcall Ellipse(long long long long long)
 ++@ stdcall EnableEUDC(long) NtGdiEnableEudc
 ++@ stdcall EndDoc(long)
 ++@ stdcall EndFormPage(ptr)
 ++@ stdcall EndPage(long)
 ++@ stdcall EndPath(long)
 ++@ stdcall EngAcquireSemaphore(ptr)
 ++@ stdcall EngAlphaBlend(ptr ptr ptr ptr ptr ptr ptr) NtGdiEngAlphaBlend
 ++@ stdcall EngAssociateSurface(ptr ptr long) NtGdiEngAssociateSurface
 ++@ stdcall EngBitBlt(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiEngBitBlt
 ++@ stdcall EngCheckAbort(ptr) NtGdiEngCheckAbort
 ++@ stdcall EngComputeGlyphSet(ptr ptr ptr)
 ++@ stdcall EngCopyBits(ptr ptr ptr ptr ptr ptr) NtGdiEngCopyBits
 ++# @ stdcall EngCreateBitmap(longlong long long long ptr) NtGdiEngCreateBitmap
 ++@ stdcall EngCreateBitmap(long long long long long ptr) NtGdiEngCreateBitmap
 ++@ stdcall EngCreateClip() NtGdiEngCreateClip
 ++# @ stdcall EngCreateDeviceBitmap(ptr longlong long) NtGdiEngCreateDeviceBitmap
 ++@ stdcall EngCreateDeviceBitmap(ptr long long long) NtGdiEngCreateDeviceBitmap
 ++# @ stdcall EngCreateDeviceSurface(ptr longlong long) NtGdiEngCreateDeviceSurface
 ++@ stdcall EngCreateDeviceSurface(ptr long long long) NtGdiEngCreateDeviceSurface
 ++@ stdcall EngCreatePalette(long long ptr long long long) NtGdiEngCreatePalette
 ++@ stdcall EngCreateSemaphore()
 ++@ stdcall EngDeleteClip(ptr) NtGdiEngDeleteClip
 ++@ stdcall EngDeletePalette(ptr) NtGdiEngDeletePalette
 ++@ stdcall EngDeletePath(ptr) NtGdiEngDeletePath
 ++@ stdcall EngDeleteSemaphore(ptr)
 ++@ stdcall EngDeleteSurface(ptr) NtGdiEngDeleteSurface
 ++@ stdcall EngEraseSurface(ptr ptr long) NtGdiEngEraseSurface
 ++@ stdcall EngFillPath(ptr ptr ptr ptr ptr ptr ptr) NtGdiEngFillPath
 ++@ stdcall EngFindResource(ptr long long ptr)
 ++@ stdcall EngFreeModule(ptr)
 ++@ stdcall EngGetCurrentCodePage(ptr ptr)
 ++@ stdcall EngGetDriverName(ptr)
 ++@ stdcall EngGetPrinterDataFileName(ptr)
 ++@ stdcall EngGradientFill(ptr ptr ptr ptr long ptr long ptr ptr long) NtGdiEngGradientFill
 ++@ stdcall EngLineTo(ptr ptr ptr long long long long ptr ptr) NtGdiEngLineTo
 ++@ stdcall EngLoadModule(ptr)
 ++@ stdcall EngLockSurface(ptr) NtGdiEngLockSurface
 ++@ stdcall EngMarkBandingSurface(ptr) NtGdiEngMarkBandingSurface
 ++@ stdcall EngMultiByteToUnicodeN(wstr long ptr str long) RtlMultiByteToUnicodeN
 ++@ stdcall EngMultiByteToWideChar(long wstr long str long)
 ++@ stdcall EngPaint(ptr ptr ptr ptr ptr) NtGdiEngPaint
 ++@ stdcall EngPlgBlt(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr long) NtGdiEngPlgBlt
 ++@ stdcall EngQueryEMFInfo(ptr ptr)
 ++@ stdcall EngQueryLocalTime(ptr)
 ++@ stdcall EngReleaseSemaphore(ptr)
 ++@ stdcall EngStretchBlt(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr long) NtGdiEngStretchBlt
 ++@ stdcall EngStretchBltROP(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr long ptr long) NtGdiEngStretchBltROP
 ++@ stdcall EngStrokeAndFillPath(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiEngStrokeAndFillPath
 ++@ stdcall EngStrokePath(ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiEngStrokePath
 ++@ stdcall EngTextOut(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) NtGdiEngTextOut
 ++@ stdcall EngTransparentBlt(ptr ptr ptr ptr ptr ptr long long) NtGdiEngTransparentBlt
 ++@ stdcall EngUnicodeToMultiByteN(str long long wstr long) RtlUnicodeToMultiByteN
 ++@ stdcall EngUnlockSurface(ptr) NtGdiEngUnlockSurface
 ++@ stdcall EngWideCharToMultiByte(long wstr long str long)
 ++@ stdcall EnumEnhMetaFile(long long ptr ptr ptr)
 ++@ stdcall EnumFontFamiliesA(long str ptr long)
 ++@ stdcall EnumFontFamiliesExA(long ptr ptr long long)
 ++@ stdcall EnumFontFamiliesExW(long ptr ptr long long)
 ++@ stdcall EnumFontFamiliesW(long wstr ptr long)
 ++@ stdcall EnumFontsA(long str ptr long)
 ++@ stdcall EnumFontsW(long wstr ptr long)
 ++@ stdcall EnumICMProfilesA(long ptr long)
 ++@ stdcall EnumICMProfilesW(long ptr long)
 ++@ stdcall EnumMetaFile(long long ptr ptr)
 ++@ stdcall EnumObjects(long long ptr long)
 ++@ stdcall EqualRgn(long long) NtGdiEqualRgn
 ++@ stdcall Escape(long long long ptr ptr)
 ++@ stdcall EudcLoadLinkW(wstr wstr long long)
 ++@ stdcall EudcUnloadLinkW(wstr wstr)
 ++@ stdcall ExcludeClipRect(long long long long long)
 ++@ stdcall ExtCreatePen(long long ptr long ptr)
 ++@ stdcall ExtCreateRegion(ptr long ptr)
 ++@ stdcall ExtEscape(long long long ptr long ptr)
 ++@ stdcall ExtFloodFill(long long long long long)
 ++@ stdcall ExtSelectClipRgn(long long long)
 ++@ stdcall ExtTextOutA(long long long long ptr str long ptr)
 ++@ stdcall ExtTextOutW(long long long long ptr wstr long ptr)
 ++@ stdcall FONTOBJ_cGetAllGlyphHandles(ptr ptr) NtGdiFONTOBJ_cGetAllGlyphHandles
 ++@ stdcall FONTOBJ_cGetGlyphs(ptr long long ptr ptr) NtGdiFONTOBJ_cGetGlyphs
 ++@ stdcall FONTOBJ_pQueryGlyphAttrs(ptr long) NtGdiFONTOBJ_pQueryGlyphAttrs
 ++@ stdcall FONTOBJ_pfdg(ptr) NtGdiFONTOBJ_pfdg
 ++@ stdcall FONTOBJ_pifi(ptr) NtGdiFONTOBJ_pifi
 ++@ stdcall FONTOBJ_pvTrueTypeFontFile(ptr ptr) NtGdiFONTOBJ_pvTrueTypeFontFile
 ++@ stdcall FONTOBJ_pxoGetXform(ptr) NtGdiFONTOBJ_pxoGetXform
 ++@ stdcall FONTOBJ_vGetInfo(ptr long ptr) NtGdiFONTOBJ_vGetInfo
 ++@ stdcall FillPath(long)
 ++@ stdcall FillRgn(long long long)
 ++@ stdcall FixBrushOrgEx(long long long ptr)
 ++@ stdcall FlattenPath(long)
 ++@ stdcall FloodFill(long long long long)
 ++@ stdcall FontIsLinked(long) NtGdiFontIsLinked
 ++@ stdcall FrameRgn(long long long long long)
 ++@ stdcall GdiAddFontResourceW(ptr ptr ptr)
 ++@ stdcall GdiAddGlsBounds(ptr ptr)
 ++@ stdcall GdiAddGlsRecord(ptr long ptr ptr)
 ++@ stdcall GdiAlphaBlend(long long long long long long long long long long long)
 ++@ stdcall GdiArtificialDecrementDriver(wstr long)
 ++@ stdcall GdiCleanCacheDC(ptr)
 ++@ stdcall GdiComment(long long ptr)
 ++@ stdcall GdiConsoleTextOut(ptr ptr long ptr) NtGdiConsoleTextOut
 ++@ stdcall GdiConvertAndCheckDC(ptr)
 ++@ stdcall GdiConvertBitmap(ptr)
 ++@ stdcall GdiConvertBitmapV5(ptr ptr long long)
 ++@ stdcall GdiConvertBrush(ptr)
 ++@ stdcall GdiConvertDC(ptr)
 ++@ stdcall GdiConvertEnhMetaFile(ptr)
 ++@ stdcall GdiConvertFont(ptr)
 ++@ stdcall GdiConvertMetaFilePict(ptr)
 ++@ stdcall GdiConvertPalette(ptr)
 ++@ stdcall GdiConvertRegion(ptr)
 ++@ stdcall GdiConvertToDevmodeW(ptr)
 ++@ stdcall GdiCreateLocalEnhMetaFile(ptr)
 ++@ stdcall GdiCreateLocalMetaFilePict(ptr)
 ++@ stdcall GdiDeleteLocalDC(ptr)
 ++@ stdcall GdiDeleteSpoolFileHandle(ptr)
 ++@ stdcall GdiDescribePixelFormat(ptr long long ptr) NtGdiDescribePixelFormat
 ++@ stdcall GdiDllInitialize(ptr long ptr)
 ++@ stdcall GdiDrawStream(ptr long ptr)
 ++@ stdcall GdiEndDocEMF(ptr)
 ++@ stdcall GdiEndPageEMF(ptr long)
 ++@ stdcall GdiEntry10(ptr long)
 ++@ stdcall GdiEntry11(ptr ptr)
 ++@ stdcall GdiEntry12(ptr ptr)
 ++@ stdcall GdiEntry13()
 ++@ stdcall GdiEntry14(ptr ptr long)
 ++@ stdcall GdiEntry15(ptr ptr ptr)
 ++@ stdcall GdiEntry16(ptr ptr ptr)
 ++@ stdcall GdiEntry1(ptr ptr)
 ++@ stdcall GdiEntry2(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr)
 ++@ stdcall GdiEntry3(ptr)
 ++@ stdcall GdiEntry4(ptr long)
 ++@ stdcall GdiEntry5(ptr)
 ++@ stdcall GdiEntry6(ptr ptr)
 ++@ stdcall GdiEntry7(ptr ptr)
 ++@ stdcall GdiEntry8(ptr)
 ++@ stdcall GdiEntry9(ptr ptr ptr ptr ptr ptr)
 ++@ stdcall GdiFixUpHandle(ptr)
 ++@ stdcall GdiFlush()
-  @ stdcall GdiGradientFill(long ptr long ptr long long) 
+++@ stdcall GdiFullscreenControl(ptr ptr long ptr ptr) NtGdiFullscreenControl
 ++@ stdcall GdiGetBatchLimit()
 ++@ stdcall GdiGetBitmapBitsSize(ptr)
 ++@ stdcall GdiGetCharDimensions(long ptr ptr)
 ++@ stdcall GdiGetCodePage(long)
 ++@ stdcall GdiGetDC(ptr)
 ++@ stdcall GdiGetDevmodeForPage(ptr long ptr ptr)
 ++@ stdcall GdiGetLocalBrush(ptr)
 ++@ stdcall GdiGetLocalDC(ptr)
 ++@ stdcall GdiGetLocalFont(ptr)
 ++@ stdcall GdiGetPageCount(ptr)
 ++@ stdcall GdiGetPageHandle(ptr long ptr)
 ++@ stdcall GdiGetSpoolFileHandle(wstr ptr wstr)
 ++@ stdcall GdiGetSpoolMessage(ptr long ptr long) NtGdiGetSpoolMessage
+++@ stdcall GdiGradientFill(long ptr long ptr long long)
 ++@ stdcall GdiInitSpool() NtGdiInitSpool
 ++@ stdcall GdiInitializeLanguagePack(long)
 ++@ stdcall GdiIsMetaFileDC(long)
 ++@ stdcall GdiIsMetaPrintDC(long)
 ++@ stdcall GdiIsPlayMetafileDC(long)
 ++@ stdcall GdiPlayDCScript(long long long long long long)
 ++@ stdcall GdiPlayEMF(wstr ptr wstr ptr ptr)
 ++@ stdcall GdiPlayJournal(long long long long long)
 ++@ stdcall GdiPlayPageEMF(ptr ptr ptr ptr ptr)
 ++@ stdcall GdiPlayPrivatePageEMF(ptr long ptr)
 ++@ stdcall GdiPlayScript(ptr ptr ptr ptr ptr ptr ptr)
 ++@ stdcall GdiPrinterThunk(ptr ptr long)
 ++@ stdcall GdiProcessSetup()
 ++@ stdcall GdiQueryFonts(ptr long ptr) NtGdiQueryFonts
 ++@ stdcall GdiQueryTable()
 ++@ stdcall GdiRealizationInfo(long ptr)
 ++@ stdcall GdiReleaseDC(ptr)
 ++@ stdcall GdiReleaseLocalDC(ptr)
 ++@ stdcall GdiResetDCEMF(ptr ptr)
 ++@ stdcall GdiSetAttrs(ptr)
 ++@ stdcall GdiSetBatchLimit(long)
 ++@ stdcall GdiSetLastError(long)
 ++@ stdcall GdiSetPixelFormat(ptr long) NtGdiSetPixelFormat
 ++@ stdcall GdiSetServerAttr(ptr long)
 ++@ stdcall GdiStartDocEMF(ptr ptr)
 ++@ stdcall GdiStartPageEMF(ptr)
 ++@ stdcall GdiSwapBuffers(ptr) NtGdiSwapBuffers
 ++@ stdcall GdiTransparentBlt(long long long long long long long long long long long)
 ++@ stdcall GdiValidateHandle(ptr)
 ++@ stdcall GetArcDirection(long)
 ++@ stdcall GetAspectRatioFilterEx(long ptr)
 ++@ stdcall GetBitmapAttributes(ptr)
 ++@ stdcall GetBitmapBits(long long ptr) NtGdiGetBitmapBits
 ++@ stdcall GetBitmapDimensionEx(long ptr) NtGdiGetBitmapDimension
 ++@ stdcall GetBkColor(long)
 ++@ stdcall GetBkMode(long)
 ++@ stdcall GetBoundsRect(long ptr long)
 ++@ stdcall GetBrushAttributes(ptr)
 ++@ stdcall GetBrushOrgEx(long ptr)
 ++@ stdcall GetCharABCWidthsA(long long long ptr)
 ++@ stdcall GetCharABCWidthsFloatA(long long long ptr)
 ++@ stdcall GetCharABCWidthsFloatW(long long long ptr)
 ++@ stdcall GetCharABCWidthsI(long long long ptr ptr)
 ++@ stdcall GetCharABCWidthsW(long long long ptr)
 ++@ stdcall GetCharWidth32A(long long long long)
 ++@ stdcall GetCharWidth32W(long long long long)
 ++@ stdcall GetCharWidthA(long long long long) GetCharWidth32A
 ++@ stdcall GetCharWidthFloatA(long long long ptr)
 ++@ stdcall GetCharWidthFloatW(long long long ptr)
 ++@ stdcall GetCharWidthI(ptr long long ptr ptr)
 ++@ stdcall GetCharWidthInfo(ptr ptr) NtGdiGetCharWidthInfo
 ++@ stdcall GetCharWidthW(long long long long)
 ++@ stdcall GetCharacterPlacementA(long str long long ptr long)
 ++@ stdcall GetCharacterPlacementW(long wstr long long ptr long)
 ++@ stdcall GetClipBox(long ptr)
 ++@ stdcall GetClipRgn(long long)
 ++@ stdcall GetColorAdjustment(long ptr) NtGdiGetColorAdjustment
 ++@ stdcall GetColorSpace(long)
 ++@ stdcall GetCurrentObject(long long)
 ++@ stdcall GetCurrentPositionEx(long ptr)
 ++@ stdcall GetDCBrushColor(ptr)
 ++@ stdcall GetDCOrgEx(ptr ptr)
 ++@ stdcall GetDCPenColor(long)
 ++@ stdcall GetDIBColorTable(long long long ptr)
 ++@ stdcall GetDIBits(long long long long ptr ptr long)
 ++@ stdcall GetDeviceCaps(long long)
 ++@ stdcall GetDeviceGammaRamp(long ptr)
 ++@ stdcall GetETM(ptr ptr)
 ++@ stdcall GetEUDCTimeStamp()
 ++@ stdcall GetEUDCTimeStampExW(str)
 ++@ stdcall GetEnhMetaFileA(str)
 ++@ stdcall GetEnhMetaFileBits(long long ptr)
 ++@ stdcall GetEnhMetaFileDescriptionA(long long ptr)
 ++@ stdcall GetEnhMetaFileDescriptionW(long long ptr)
 ++@ stdcall GetEnhMetaFileHeader(long long ptr)
 ++@ stdcall GetEnhMetaFilePaletteEntries (long long ptr)
 ++@ stdcall GetEnhMetaFilePixelFormat(ptr long ptr)
 ++@ stdcall GetEnhMetaFileW(wstr)
 ++@ stdcall GetFontAssocStatus(ptr)
 ++@ stdcall GetFontData(long long long ptr long)
 ++@ stdcall GetFontLanguageInfo(long)
 ++@ stdcall GetFontResourceInfoW(str ptr ptr long)
 ++@ stdcall GetFontUnicodeRanges(ptr ptr) NtGdiGetFontUnicodeRanges
 ++@ stdcall GetGlyphIndicesA(long ptr long ptr long)
 ++@ stdcall GetGlyphIndicesW(long ptr long ptr long) NtGdiGetGlyphIndicesW
 ++@ stdcall GetGlyphOutline(long long long ptr long ptr ptr) GetGlyphOutlineA
 ++@ stdcall GetGlyphOutlineA(long long long ptr long ptr ptr)
 ++@ stdcall GetGlyphOutlineW(long long long ptr long ptr ptr)
 ++@ stdcall GetGlyphOutlineWow(long long long long long long long)
 ++@ stdcall GetGraphicsMode(long)
 ++@ stdcall GetHFONT(ptr)
 ++@ stdcall GetICMProfileA(long ptr ptr)
 ++@ stdcall GetICMProfileW(long ptr ptr)
 ++@ stdcall GetKerningPairs(long long ptr) GetKerningPairsA
 ++@ stdcall GetKerningPairsA(long long ptr)
 ++@ stdcall GetKerningPairsW(long long ptr)
 ++@ stdcall GetLayout(long)
 ++@ stdcall GetLogColorSpaceA(long ptr long)
 ++@ stdcall GetLogColorSpaceW(long ptr long)
 ++@ stdcall GetMapMode(long)
 ++@ stdcall GetMetaFileA(str)
 ++@ stdcall GetMetaFileBitsEx(long long ptr)
 ++@ stdcall GetMetaFileW(wstr)
 ++@ stdcall GetMetaRgn(long long)
 ++@ stdcall GetMiterLimit(long ptr) NtGdiGetMiterLimit
 ++@ stdcall GetNearestColor(long long) NtGdiGetNearestColor
 ++@ stdcall GetNearestPaletteIndex(long long) NtGdiGetNearestPaletteIndex
 ++@ stdcall GetObjectA(long long ptr)
 ++@ stdcall GetObjectType(long)
 ++@ stdcall GetObjectW(long long ptr)
 ++@ stdcall GetOutlineTextMetricsA(long long ptr)
 ++@ stdcall GetOutlineTextMetricsW(long long ptr)
 ++@ stdcall GetPaletteEntries(long long long ptr)
 ++@ stdcall GetPath(long ptr ptr long)
 ++@ stdcall GetPixel(long long long)
 ++@ stdcall GetPixelFormat(long)
 ++@ stdcall GetPolyFillMode(long)
 ++@ stdcall GetROP2(long)
 ++@ stdcall GetRandomRgn(long long long) NtGdiGetRandomRgn
 ++@ stdcall GetRasterizerCaps(ptr long) NtGdiGetRasterizerCaps
 ++@ stdcall GetRegionData(long long ptr)
 ++@ stdcall GetRelAbs(long long)
 ++@ stdcall GetRgnBox(long ptr)
 ++@ stdcall GetStockObject(long)
 ++@ stdcall GetStretchBltMode(long)
 ++@ stdcall GetStringBitmapA(ptr str long long ptr)
 ++@ stdcall GetStringBitmapW(ptr wstr long long ptr)
 ++@ stdcall GetSystemPaletteEntries(long long long ptr)
 ++@ stdcall GetSystemPaletteUse(long) NtGdiGetSystemPaletteUse
 ++@ stdcall GetTextAlign(long)
 ++@ stdcall GetTextCharacterExtra(long)
 ++@ stdcall GetTextCharset(long)
 ++@ stdcall GetTextCharsetInfo(long ptr long) NtGdiGetTextCharsetInfo
 ++@ stdcall GetTextColor(long)
 ++@ stdcall GetTextExtentExPointA(long str long long ptr ptr ptr)
 ++@ stdcall GetTextExtentExPointI(long ptr long long ptr ptr ptr)
 ++@ stdcall GetTextExtentExPointW(long wstr long long ptr ptr ptr)
 ++@ stdcall GetTextExtentExPointWPri(ptr wstr long long long ptr ptr)
 ++@ stdcall GetTextExtentPoint32A(long str long ptr)
 ++@ stdcall GetTextExtentPoint32W(long wstr long ptr)
 ++@ stdcall GetTextExtentPointA(long str long ptr)
 ++@ stdcall GetTextExtentPointI(long ptr long ptr)
 ++@ stdcall GetTextExtentPointW(long wstr long ptr)
 ++@ stdcall GetTextFaceA(long long ptr)
 ++@ stdcall GetTextFaceAliasW(ptr long wstr)
 ++@ stdcall GetTextFaceW(long long ptr)
 ++@ stdcall GetTextMetricsA(long ptr)
 ++@ stdcall GetTextMetricsW(long ptr)
 ++@ stdcall GetTransform(long long ptr) NtGdiGetTransform
 ++@ stdcall GetViewportExtEx(long ptr)
 ++@ stdcall GetViewportOrgEx(long ptr)
 ++@ stdcall GetWinMetaFileBits(long long ptr long long)
 ++@ stdcall GetWindowExtEx(long ptr)
 ++@ stdcall GetWindowOrgEx(long ptr)
 ++@ stdcall GetWorldTransform(long ptr)
 ++@ stdcall HT_Get8BPPFormatPalette(ptr long long long) NtGdiHT_Get8BPPFormatPalette
 ++@ stdcall HT_Get8BPPMaskPalette(ptr long long long long long) NtGdiHT_Get8BPPMaskPalette
 ++@ stdcall IntersectClipRect(long long long long long)
 ++@ stdcall InvertRgn(long long)
 ++@ stdcall IsValidEnhMetaRecord(long long)
 ++@ stdcall IsValidEnhMetaRecordOffExt(long long long long)
 ++@ stdcall LPtoDP(long ptr long)
 ++@ stdcall LineDDA(long long long long ptr long)
 ++@ stdcall LineTo(long long long)
 ++@ stdcall MaskBlt(long long long long long long long long long long long long)
 ++@ stdcall MirrorRgn(ptr ptr)
 ++@ stdcall ModifyWorldTransform(long ptr long)
 ++@ stdcall MoveToEx(long long long ptr)
 ++@ stdcall NamedEscape(ptr wstr long long str long str)
 ++@ stdcall OffsetClipRgn(long long long)
 ++@ stdcall OffsetRgn(long long long)
 ++@ stdcall OffsetViewportOrgEx(long long long ptr)
 ++@ stdcall OffsetWindowOrgEx(long long long ptr)
 ++@ stdcall PATHOBJ_bEnum(ptr ptr) NtGdiPATHOBJ_bEnum
 ++@ stdcall PATHOBJ_bEnumClipLines(ptr long ptr) NtGdiPATHOBJ_bEnumClipLines
 ++@ stdcall PATHOBJ_vEnumStart(ptr) NtGdiPATHOBJ_vEnumStart
 ++@ stdcall PATHOBJ_vEnumStartClipLines(ptr ptr ptr ptr) NtGdiPATHOBJ_vEnumStartClipLines
 ++@ stdcall PATHOBJ_vGetBounds(ptr ptr) NtGdiPATHOBJ_vGetBounds
 ++@ stdcall PaintRgn(long long)
 ++@ stdcall PatBlt(long long long long long long)
 ++@ stdcall PathToRegion(long)
 ++@ stdcall Pie(long long long long long long long long long)
 ++@ stdcall PlayEnhMetaFile(long long ptr)
 ++@ stdcall PlayEnhMetaFileRecord(long ptr ptr long)
 ++@ stdcall PlayMetaFile(long long)
 ++@ stdcall PlayMetaFileRecord(long ptr ptr long)
 ++@ stdcall PlgBlt(long ptr long long long long long long long long)
 ++@ stdcall PolyBezier(long ptr long)
 ++@ stdcall PolyBezierTo(long ptr long)
 ++@ stdcall PolyDraw(long ptr ptr long)
 ++@ stdcall PolyPatBlt(ptr long ptr long long)
 ++@ stdcall PolyPolygon(long ptr ptr long)
 ++@ stdcall PolyPolyline(long ptr ptr long)
 ++@ stdcall PolyTextOutA(long ptr long)
 ++@ stdcall PolyTextOutW(long ptr long)
 ++@ stdcall Polygon(long ptr long)
 ++@ stdcall Polyline(long ptr long)
 ++@ stdcall PolylineTo(long ptr long)
 ++@ stdcall PtInRegion(long long long)
 ++@ stdcall PtVisible(long long long) NtGdiPtVisible
 ++@ stdcall QueryFontAssocStatus()
 ++@ stdcall RealizePalette(long)
 ++@ stdcall RectInRegion(long ptr)
 ++@ stdcall RectVisible(long ptr) NtGdiRectVisible
 ++@ stdcall Rectangle(long long long long long)
 ++@ stdcall RemoveFontMemResourceEx(ptr)
 ++@ stdcall RemoveFontResourceA(str)
 ++@ stdcall RemoveFontResourceExA(str long ptr)
 ++@ stdcall RemoveFontResourceExW(wstr long ptr)
 ++@ stdcall RemoveFontResourceTracking(ptr long)
 ++@ stdcall RemoveFontResourceW(wstr)
 ++@ stdcall ResetDCA(long ptr)
 ++@ stdcall ResetDCW(long ptr)
 ++@ stdcall ResizePalette(long long)
 ++@ stdcall RestoreDC(long long)
 ++@ stdcall RoundRect(long long long long long long long)
 ++@ stdcall STROBJ_bEnum(ptr ptr ptr) NtGdiSTROBJ_bEnum
 ++@ stdcall STROBJ_bEnumPositionsOnly(ptr ptr ptr) NtGdiSTROBJ_bEnumPositionsOnly
 ++@ stdcall STROBJ_bGetAdvanceWidths(ptr long long ptr) NtGdiSTROBJ_bGetAdvanceWidths
 ++@ stdcall STROBJ_dwGetCodePage(ptr) NtGdiSTROBJ_dwGetCodePage
 ++@ stdcall STROBJ_vEnumStart(ptr) NtGdiSTROBJ_vEnumStart
 ++@ stdcall SaveDC(long)
 ++@ stdcall ScaleViewportExtEx(long long long long long ptr)
 ++@ stdcall ScaleWindowExtEx(long long long long long ptr)
 ++@ stdcall SelectBrushLocal(ptr ptr)
 ++@ stdcall SelectClipPath(long long)
 ++@ stdcall SelectClipRgn(long long)
 ++@ stdcall SelectFontLocal(ptr ptr)
 ++@ stdcall SelectObject(long long)
 ++@ stdcall SelectPalette(long long long)
 ++@ stdcall SetAbortProc(long ptr)
 ++@ stdcall SetArcDirection(long long)
 ++@ stdcall SetBitmapAttributes(ptr long)
 ++@ stdcall SetBitmapBits(long long ptr) NtGdiSetBitmapBits
 ++@ stdcall SetBitmapDimensionEx(long long long ptr) NtGdiSetBitmapDimension
 ++@ stdcall SetBkColor(long long)
 ++@ stdcall SetBkMode(long long)
 ++@ stdcall SetBoundsRect(long ptr long)
 ++@ stdcall SetBrushAttributes(ptr long)
 ++@ stdcall SetBrushOrgEx(long long long ptr)
 ++@ stdcall SetColorAdjustment(long ptr)
 ++@ stdcall SetColorSpace(long long)
 ++@ stdcall SetDCBrushColor(long long)
 ++@ stdcall SetDCPenColor(long long)
 ++@ stdcall SetDIBColorTable(long long long ptr)
 ++@ stdcall SetDIBits(long long long long ptr ptr long)
 ++@ stdcall SetDIBitsToDevice(long long long long long long long long long ptr ptr long)
 ++@ stdcall SetDeviceGammaRamp(long ptr)
 ++@ stdcall SetEnhMetaFileBits(long ptr)
 ++@ stdcall SetFontEnumeration(ptr) NtGdiSetFontEnumeration
 ++@ stdcall SetGraphicsMode(long long)
 ++@ stdcall SetICMMode(long long)
 ++@ stdcall SetICMProfileA(long str)
 ++@ stdcall SetICMProfileW(long wstr)
 ++@ stdcall SetLayout(long long)
 ++@ stdcall SetLayoutWidth(ptr long long)
 ++@ stdcall SetMagicColors(ptr long long) NtGdiSetMagicColors
 ++@ stdcall SetMapMode(long long)
 ++@ stdcall SetMapperFlags(long long)
 ++@ stdcall SetMetaFileBitsEx(long ptr)
 ++@ stdcall SetMetaRgn(long)
 ++@ stdcall SetMiterLimit(long long ptr)
 ++@ stdcall SetPaletteEntries(long long long ptr)
 ++@ stdcall SetPixel(long long long long)
 ++@ stdcall SetPixelFormat(long long ptr)
 ++@ stdcall SetPixelV(long long long long)
 ++@ stdcall SetPolyFillMode(long long)
 ++@ stdcall SetROP2(long long)
 ++@ stdcall SetRectRgn(long long long long long)
 ++@ stdcall SetRelAbs(long long)
 ++@ stdcall SetStretchBltMode(long long)
 ++@ stdcall SetSystemPaletteUse(long long) NtGdiSetSystemPaletteUse
 ++@ stdcall SetTextAlign(long long)
 ++@ stdcall SetTextCharacterExtra(long long)
 ++@ stdcall SetTextColor(long long)
 ++@ stdcall SetTextJustification(long long long)
 ++@ stdcall SetViewportExtEx(long long long ptr)
 ++@ stdcall SetViewportOrgEx(long long long ptr)
 ++@ stdcall SetVirtualResolution(long long long long long) NtGdiSetVirtualResolution
 ++@ stdcall SetWinMetaFileBits(long ptr long ptr)
 ++@ stdcall SetWindowExtEx(long long long ptr)
 ++@ stdcall SetWindowOrgEx(long long long ptr)
 ++@ stdcall SetWorldTransform(long ptr)
 ++@ stdcall StartDocA(long ptr)
 ++@ stdcall StartDocW(long ptr)
 ++@ stdcall StartFormPage(ptr)
 ++@ stdcall StartPage(long)
 ++@ stdcall StretchBlt(long long long long long long long long long long long)
 ++@ stdcall StretchDIBits(long long long long long long long long long ptr ptr long long)
 ++@ stdcall StrokeAndFillPath(long)
 ++@ stdcall StrokePath(long)
 ++@ stdcall SwapBuffers(long)
 ++@ stdcall TextOutA(long long long str long)
 ++@ stdcall TextOutW(long long long wstr long)
 ++@ stdcall TranslateCharsetInfo(ptr ptr long)
 ++@ stdcall UnloadNetworkFonts(long)
 ++@ stdcall UnrealizeObject(long)
 ++@ stdcall UpdateColors(long)
 ++@ stdcall UpdateICMRegKeyA(long str str long)
 ++@ stdcall UpdateICMRegKeyW(long wstr wstr long)
 ++@ stdcall WidenPath(long)
 ++@ stdcall XFORMOBJ_bApplyXform(ptr long long ptr ptr) NtGdiXFORMOBJ_bApplyXform
 ++@ stdcall XFORMOBJ_iGetXform(ptr ptr) NtGdiXFORMOBJ_iGetXform
 ++@ stdcall XLATEOBJ_cGetPalette(ptr long long ptr) NtGdiXLATEOBJ_cGetPalette
 ++@ stdcall XLATEOBJ_hGetColorTransform(ptr) NtGdiXLATEOBJ_hGetColorTransform
 ++@ stdcall XLATEOBJ_iXlate(ptr long) NtGdiXLATEOBJ_iXlate
 ++@ stdcall XLATEOBJ_piVector(ptr)
 ++@ stdcall bInitSystemAndFontsDirectoriesW(wstr wstr)
 ++@ stdcall bMakePathNameW(wstr wstr wstr long)
 ++@ stdcall cGetTTFFromFOT(long long long long long long long)
 ++@ stdcall gdiPlaySpoolStream(long long long long long long)
index d76f21a,0000000,49673de..49673de
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,382 -1,0 -1,420 +1,420 @@@@
-  
 + /*
 +  * COPYRIGHT:       See COPYING in the top level directory
 +  * PROJECT:         ReactOS System Libraries
 +  * FILE:            lib/gdi32/include/gdi32p.h
 +  * PURPOSE:         User-Mode Win32 GDI Library Private Header
 +  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
 +  */
 + 
 + 
 + /* DATA **********************************************************************/
 + 
 + extern PGDI_TABLE_ENTRY GdiHandleTable;
 + extern PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable;
 + extern HANDLE hProcessHeap;
 + extern HANDLE CurrentProcessId;
 + extern DWORD GDI_BatchLimit;
 + extern PDEVCAPS GdiDevCaps;
 + extern BOOL gbLpk;          // Global bool LanguagePack
 + extern HANDLE ghSpooler;
 + extern RTL_CRITICAL_SECTION semLocal;
 + 
 + typedef INT
 + (CALLBACK* EMFPLAYPROC)(
 +     HDC hdc,
 +     INT iFunction,
 +     HANDLE hPageQuery
 + );
 + 
 + /* DEFINES *******************************************************************/
 + 
 + #define HANDLE_LIST_INC 20
 + 
 + #define METAFILE_MEMORY 1
 + #define METAFILE_DISK   2
 + 
 + #define SAPCALLBACKDELAY 244
 + 
 + /* MACRO ********************************************************************/
 + 
 + #define ROP_USES_SOURCE(Rop)   (((Rop) << 2 ^ Rop) & 0xCC0000)
 + 
 + /* TYPES *********************************************************************/
 + 
 + // Based on wmfapi.h and Wine.
 + typedef struct tagMETAFILEDC
 + {
 +     PVOID       pvMetaBuffer;
 +     HANDLE      hFile;
 +     DWORD       Size;
 +     DWORD       dwWritten;
 +     METAHEADER  mh;
 +     WORD        reserved;
 +     HLOCAL      MFObjList;
 +     HPEN        hPen;
 +     HBRUSH      hBrush;
 +     HDC         hDc;
 +     HGDIOBJ     hMetaDc;
 +     HPALETTE    hPalette;
 +     HFONT       hFont;
 +     HBITMAP     hBitmap;
 +     HRGN        hRegion;
 +     HGDIOBJ     hMetafile;
 +     HGDIOBJ     hMemDc;
 +     HPEN        hExtPen;
 +     HGDIOBJ     hEnhMetaDc;
 +     HGDIOBJ     hEnhMetaFile;
 +     HCOLORSPACE hColorSpace;
 +     WCHAR       Filename[MAX_PATH+2];
 + } METAFILEDC,*PMETAFILEDC;
 + 
 + // Metafile Entry handle
 + typedef struct tagMF_ENTRY
 + {
 +     LIST_ENTRY   List;
 +     HGDIOBJ      hmDC;             // Handle return from NtGdiCreateClientObj.
 +     PMETAFILEDC pmfDC;
 + } MF_ENTRY, *PMF_ENTRY;
 + 
 + typedef struct tagENHMETAFILE
 + {
 +     PVOID      pvMetaBuffer;
 +     HANDLE     hFile;      /* Handle for disk based MetaFile */
 +     DWORD      Size;
 +     INT        iType;
 +     PENHMETAHEADER emf;
 +     UINT       handles_size, cur_handles;
 +     HGDIOBJ   *handles;
 +     INT        horzres, vertres;
 +     INT        horzsize, vertsize;
 +     INT        logpixelsx, logpixelsy;
 +     INT        bitspixel;
 +     INT        textcaps;
 +     INT        rastercaps;
 +     INT        technology;
 +     INT        planes;
 + } ENHMETAFILE,*PENHMETAFILE;
 + 
 + 
 + #define PDEV_UMPD_ID  0xFEDCBA98
 + // UMPDEV flags
 + #define UMPDEV_NO_ESCAPE      0x0002
 + #define UMPDEV_SUPPORT_ESCAPE 0x0004
 + typedef struct _UMPDEV
 + {
 +     DWORD           Sig;            // Init with PDEV_UMPD_ID
 +     struct _UMPDEV *pumpdNext;
 +     PDRIVER_INFO_5W pdi5Info;
 +     HMODULE         hModule;
 +     DWORD           dwFlags;
 +     DWORD           dwDriverAttributes;
 +     DWORD           dwConfigVersion; // Number of times the configuration
 +     // file for this driver has been upgraded
 +     // or downgraded since the last spooler restart.
 +     DWORD           dwDriverCount;   // After init should be 2
 +     DWORD           WOW64_UMPDev;
 +     DWORD           WOW64_hMod;
 +     DWORD           Unknown;
 +     PVOID           apfn[INDEX_LAST]; // Print Driver pfn
 + } UMPDEV, *PUMPDEV;
 + 
 + #define LOCALFONT_COUNT 10
 + typedef struct _LOCALFONT
 + {
 +     FONT_ATTR  lfa[LOCALFONT_COUNT];
 + } LOCALFONT, *PLOCALFONT;
 + 
 + // sdk/winspool.h
 + typedef BOOL (WINAPI *ABORTPRINTER) (HANDLE);
 + typedef BOOL (WINAPI *CLOSEPRINTER) (HANDLE);
 + typedef BOOL (WINAPI *CLOSESPOOLFILEHANDLE) (HANDLE, HANDLE); // W2k8
 + typedef HANDLE (WINAPI *COMMITSPOOLDATA) (HANDLE,HANDLE,DWORD); // W2k8
 + typedef LONG (WINAPI *DOCUMENTPROPERTIESW) (HWND,HANDLE,LPWSTR,PDEVMODEW,PDEVMODEW,DWORD);
 + typedef BOOL (WINAPI *ENDDOCPRINTER) (HANDLE);
 + typedef BOOL (WINAPI *ENDPAGEPRINTER) (HANDLE);
 + typedef BOOL (WINAPI *GETPRINTERW) (HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
 + typedef BOOL (WINAPI *GETPRINTERDRIVERW) (HANDLE,LPWSTR,DWORD,LPBYTE,DWORD,LPDWORD);
 + typedef HANDLE (WINAPI *GETSPOOLFILEHANDLE) (HANDLE); // W2k8
 + typedef BOOL (WINAPI *ISVALIDDEVMODEW) (PDEVMODEW,size_t);
 + typedef BOOL (WINAPI *OPENPRINTERW) (LPWSTR,PHANDLE,LPPRINTER_DEFAULTSW);
 + typedef BOOL (WINAPI *READPRINTER) (HANDLE,PVOID,DWORD,PDWORD);
 + typedef BOOL (WINAPI *RESETPRINTERW) (HANDLE,LPPRINTER_DEFAULTSW);
 + typedef LPWSTR (WINAPI *STARTDOCDLGW) (HANDLE,DOCINFOW *);
 + typedef DWORD (WINAPI *STARTDOCPRINTERW) (HANDLE,DWORD,PBYTE);
 + typedef BOOL (WINAPI *STARTPAGEPRINTER) (HANDLE);
 + // ddk/winsplp.h
 + typedef BOOL (WINAPI *SEEKPRINTER) (HANDLE,LARGE_INTEGER,PLARGE_INTEGER,DWORD,BOOL);
 + typedef BOOL (WINAPI *SPLREADPRINTER) (HANDLE,LPBYTE *,DWORD);
 + // Same as ddk/winsplp.h DriverUnloadComplete?
 + typedef BOOL (WINAPI *SPLDRIVERUNLOADCOMPLETE) (LPWSTR);
 + // Driver support:
 + // DrvDocumentEvent api/winddiui.h not W2k8 DocumentEventAW
 + typedef INT (WINAPI *DOCUMENTEVENT) (HANDLE,HDC,INT,ULONG,PVOID,ULONG,PVOID);
 + // DrvQueryColorProfile
 + typedef BOOL (WINAPI *QUERYCOLORPROFILE) (HANDLE,PDEVMODEW,ULONG,VOID*,ULONG,FLONG);
 + // Unknown:
 + typedef DWORD (WINAPI *QUERYSPOOLMODE) (HANDLE,DWORD,DWORD);
 + typedef DWORD (WINAPI *QUERYREMOTEFONTS) (DWORD,DWORD,DWORD);
 + 
 + extern CLOSEPRINTER fpClosePrinter;
 + extern OPENPRINTERW fpOpenPrinterW;
 + 
 + /* FUNCTIONS *****************************************************************/
 + 
 + PVOID
 + HEAP_alloc(DWORD len);
 + 
 + NTSTATUS
 + HEAP_strdupA2W(
 +     LPWSTR* ppszW,
 +     LPCSTR lpszA
 + );
 + 
 + VOID
 + HEAP_free(LPVOID memory);
 + 
 + VOID
 + FASTCALL
 + FONT_TextMetricWToA(
 +     const TEXTMETRICW *ptmW,
 +     LPTEXTMETRICA ptmA
 + );
 + 
 + VOID
 + FASTCALL
 + NewTextMetricW2A(
 +     NEWTEXTMETRICA *tma,
 +     NEWTEXTMETRICW *tmw
 + );
 + 
 + VOID
 + FASTCALL
 + NewTextMetricExW2A(
 +     NEWTEXTMETRICEXA *tma,
 +     NEWTEXTMETRICEXW *tmw
 + );
 + 
 + BOOL
 + FASTCALL
 + DeleteRegion( HRGN );
 + 
 + BOOL
 + GdiIsHandleValid(HGDIOBJ hGdiObj);
 + 
 + BOOL
 + GdiGetHandleUserData(
 +     HGDIOBJ hGdiObj,
 +     DWORD ObjectType,
 +     PVOID *UserData
 + );
 + 
 + PLDC
 + FASTCALL
 + GdiGetLDC(HDC hDC);
 + 
 + HGDIOBJ
 + WINAPI
 + GdiFixUpHandle(HGDIOBJ hGO);
 + 
 + BOOL
 + WINAPI
 + CalculateColorTableSize(
 +     CONST BITMAPINFOHEADER *BitmapInfoHeader,
 +     UINT *ColorSpec,
 +     UINT *ColorTableSize
 + );
 + 
 + LPBITMAPINFO
 + WINAPI
 + ConvertBitmapInfo(
 +     CONST BITMAPINFO *BitmapInfo,
 +     UINT ColorSpec,
 +     UINT *BitmapInfoSize,
 +     BOOL FollowedByData
 + );
 + 
 + DWORD
 + WINAPI
 + GetAndSetDCDWord( HDC, INT, DWORD, DWORD, DWORD, DWORD );
 + 
 + DWORD
 + WINAPI
 + GetDCDWord( HDC, INT, DWORD);
 + 
 + HGDIOBJ
 + WINAPI
 + GetDCObject( HDC, INT);
 + 
 + VOID
 + NTAPI
 + LogFontA2W(
 +     LPLOGFONTW pW,
 +     CONST LOGFONTA *pA
 + );
 + 
 + VOID
 + NTAPI
 + LogFontW2A(
 +     LPLOGFONTA pA,
 +     CONST LOGFONTW *pW
 + );
 + 
 + VOID
 + WINAPI
 + EnumLogFontExW2A(
 +     LPENUMLOGFONTEXA fontA,
 +     CONST ENUMLOGFONTEXW *fontW );
 + 
 + /* FIXME: Put in some public header */
 + UINT
 + WINAPI
 + UserRealizePalette(HDC hDC);
 + 
 + int
 + WINAPI
 + GdiAddFontResourceW(LPCWSTR lpszFilename,FLONG fl,DESIGNVECTOR *pdv);
 + 
 + VOID
 + WINAPI
 + GdiSetLastError( DWORD dwErrCode );
 + 
 + DWORD WINAPI GdiGetCodePage(HDC);
 + UINT FASTCALL DIB_BitmapBitsSize( CONST BITMAPINFO* );
 + 
 + int
 + WINAPI
 + GdiGetBitmapBitsSize(BITMAPINFO *lpbmi);
 + 
 + VOID GdiSAPCallback(PLDC pldc);
 + HGDIOBJ FASTCALL hGetPEBHandle(HANDLECACHETYPE,COLORREF);
 + 
 + int FASTCALL DocumentEventEx(PVOID,HANDLE,HDC,int,ULONG,PVOID,ULONG,PVOID);
 + BOOL FASTCALL EndPagePrinterEx(PVOID,HANDLE);
 + BOOL FASTCALL LoadTheSpoolerDrv(VOID);
 + 
 + FORCEINLINE
 + PVOID
 + GdiAllocBatchCommand(
 +     HDC hdc,
 +     USHORT Cmd)
 + {
 +     PTEB pTeb;
 +     ULONG ulSize;
 +     PGDIBATCHHDR pHdr;
 + 
 +     /* Get a pointer to the TEB */
 +     pTeb = NtCurrentTeb();
 + 
 +     /* Check if we have a valid environment */
 +     if (!pTeb || !pTeb->Win32ThreadInfo) return NULL;
 + 
 +     /* Do we use a DC? */
 +     if (hdc)
 +     {
 +         /* If the batch DC is NULL, we set this one as the new one */
 +         if (!pTeb->GdiTebBatch.HDC) pTeb->GdiTebBatch.HDC = hdc;
 + 
 +         /* If not, check if the batch DC equal to our DC */
 +         else if (pTeb->GdiTebBatch.HDC != hdc) return NULL;
 +     }
 + 
 +     /* Get the size of the entry */
 +     switch(Cmd)
 +     {
 +     case GdiBCPatBlt:
 +         ulSize = 0;
 +         break;
 +     case GdiBCPolyPatBlt:
 +         ulSize = 0;
 +         break;
 +     case GdiBCTextOut:
 +         ulSize = 0;
 +         break;
 +     case GdiBCExtTextOut:
 +         ulSize = 0;
 +         break;
 +     case GdiBCSetBrushOrg:
 +         ulSize = 0;
 +         break;
 +     case GdiBCExtSelClipRgn:
 +         ulSize = 0;
 +         break;
 +     case GdiBCSelObj:
 +         ulSize = sizeof(GDIBSOBJECT);
 +         break;
 +     case GdiBCDelRgn:
 +         ulSize = sizeof(GDIBSOBJECT);
 +         break;
 +     case GdiBCDelObj:
 +         ulSize = sizeof(GDIBSOBJECT);
 +         break;
 +     default:
 +         return NULL;
 +     }
 + 
 +     /* Unsupported operation */
 +     if (ulSize == 0) return NULL;
 + 
 +     /* Check if the buffer is full */
 +     if ((pTeb->GdiBatchCount >= GDI_BatchLimit) ||
 +             ((pTeb->GdiTebBatch.Offset + ulSize) > GDIBATCHBUFSIZE))
 +     {
 +         /* Call win32k, the kernel will call NtGdiFlushUserBatch to flush
 +            the current batch */
 +         NtGdiFlush();
 +     }
 + 
 +     /* Get the head of the entry */
 +     pHdr = (PVOID)((PUCHAR)pTeb->GdiTebBatch.Buffer + pTeb->GdiTebBatch.Offset);
 + 
 +     /* Update Offset and batch count */
 +     pTeb->GdiTebBatch.Offset += ulSize;
 +     pTeb->GdiBatchCount++;
 + 
 +     /* Fill in the core fields */
 +     pHdr->Cmd = Cmd;
 +     pHdr->Size = ulSize;
 + 
 +     return pHdr;
 + }
 + 
++ FORCEINLINE
++ PDC_ATTR
++ GdiGetDcAttr(HDC hdc)
++ {
++     PDC_ATTR pdcattr;
++ 
++     if (!GdiGetHandleUserData((HGDIOBJ)hdc, GDI_OBJECT_TYPE_DC, (PVOID*)&pdcattr)) return NULL;
++     return pdcattr;
++ }
++ 
++ #ifdef _M_IX86
++ FLOATL FASTCALL EFtoF(EFLOAT_S * efp);
++ #define FOtoF(pfo) EFtoF((EFLOAT_S*)pfo)
++ #else
++ #define FOtoF(pfo) (*(pfo))
++ #endif
++ 
++ /* This is an inlined version of lrintf. */
++ FORCEINLINE
++ int
++ _lrintf(float f)
++ {
++ #if defined(_M_IX86) && defined(__GNUC__)
++     int ret;
++     __asm__ __volatile__ ("fistpl %0" : "=m" (ret) : "t" (f) : "st");
++     return ret;
++ #elif defined(_M_IX86) && defined(_MSC_VER)
++     int ret;
++     __asm
++     {
++         fld f;
++         fistp ret;
++     }
++ #else
++     /* slow, but portable */
++     return (int)(f >= 0 ? f+0.5 : f-0.5);
++ #endif
++ }
++ 
 + /* EOF */
Simple merge
Simple merge
Simple merge
Simple merge
index e995e8f,0000000,0000000..78feede
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,4107 -1,0 -1,0 +1,4138 @@@@
-      FIXME("%lx %p %ld %ld %lx\n",
 ++/*
 ++ * Configuration manager functions
 ++ *
 ++ * Copyright 2000 James Hatheway
 ++ * Copyright 2005, 2006 Eric Kohl
 ++ *
 ++ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 ++ */
 ++
 ++#include "setupapi_private.h"
 ++
 ++WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 ++
 ++/* Registry key and value names */
 ++static const WCHAR Backslash[] = {'\\', 0};
 ++static const WCHAR Class[]  = {'C','l','a','s','s',0};
 ++
 ++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};
 ++
 ++typedef struct _MACHINE_INFO
 ++{
 ++    WCHAR szMachineName[SP_MAX_MACHINENAME_LENGTH];
 ++    RPC_BINDING_HANDLE BindingHandle;
 ++    HSTRING_TABLE StringTable;
 ++    BOOL bLocal;
 ++} MACHINE_INFO, *PMACHINE_INFO;
 ++
 ++
 ++typedef struct _LOG_CONF_INFO
 ++{
 ++    ULONG ulMagic;
 ++    DEVINST dnDevInst;
 ++    ULONG ulFlags;
 ++    ULONG ulTag;
 ++} LOG_CONF_INFO, *PLOG_CONF_INFO;
 ++
 ++#define LOG_CONF_MAGIC 0x464E434C  /* "LCNF" */
 ++
 ++
 ++static BOOL GuidToString(LPGUID Guid, LPWSTR String)
 ++{
 ++    LPWSTR lpString;
 ++
 ++    if (UuidToStringW(Guid, &lpString) != RPC_S_OK)
 ++        return FALSE;
 ++
 ++    lstrcpyW(&String[1], lpString);
 ++
 ++    String[0] = '{';
 ++    String[MAX_GUID_STRING_LEN - 2] = '}';
 ++    String[MAX_GUID_STRING_LEN - 1] = UNICODE_NULL;
 ++
 ++    RpcStringFreeW(&lpString);
 ++
 ++    return TRUE;
 ++}
 ++
 ++
 ++static CONFIGRET
 ++RpcStatusToCmStatus(RPC_STATUS Status)
 ++{
 ++    return CR_FAILURE;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CMP_WaitNoPendingInstallEvents [SETUPAPI.@]
 ++ */
 ++DWORD WINAPI CMP_WaitNoPendingInstallEvents(
 ++    DWORD dwTimeout)
 ++{
 ++    HANDLE hEvent;
 ++    DWORD ret;
 ++
 ++    hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"Global\\PnP_No_Pending_Install_Events");
 ++    if (hEvent == NULL)
 ++       return WAIT_FAILED;
 ++
 ++    ret = WaitForSingleObject(hEvent, dwTimeout);
 ++    CloseHandle(hEvent);
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CMP_Init_Detection [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CMP_Init_Detection(
 ++    DWORD dwMagic)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lu\n", dwMagic);
 ++
 ++    if (dwMagic != CMP_MAGIC)
 ++        return CR_INVALID_DATA;
 ++
 ++    if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++        return CR_FAILURE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_InitDetection(BindingHandle);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CMP_Report_LogOn [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CMP_Report_LogOn(
 ++    DWORD dwMagic,
 ++    DWORD dwProcessId)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    BOOL bAdmin;
 ++    DWORD i;
 ++
 ++    TRACE("%lu\n", dwMagic);
 ++
 ++    if (dwMagic != CMP_MAGIC)
 ++        return CR_INVALID_DATA;
 ++
 ++    if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++        return CR_FAILURE;
 ++
 ++    bAdmin = IsUserAdmin();
 ++
 ++    for (i = 0; i < 30; i++)
 ++    {
 ++        RpcTryExcept
 ++        {
 ++            ret = PNP_ReportLogOn(BindingHandle,
 ++                                  bAdmin,
 ++                                  dwProcessId);
 ++        }
 ++        RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++        {
 ++            ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++        }
 ++        RpcEndExcept;
 ++
 ++        if (ret == CR_SUCCESS)
 ++            break;
 ++
 ++        Sleep(5000);
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
+++/***********************************************************************
+++ * CMP_WaitServicesAvailable [SETUPAPI.@]
+++ */
+++CONFIGRET
+++WINAPI
+++CMP_WaitServicesAvailable(HMACHINE hMachine)
+++{
+++    RPC_BINDING_HANDLE BindingHandle = NULL;
+++    CONFIGRET ret = CR_SUCCESS;
+++    WORD Version;
+++
+++    if (!PnpGetLocalHandles(&BindingHandle, NULL))
+++        return CR_FAILURE;
+++
+++    RpcTryExcept
+++    {
+++        ret = PNP_GetVersion(BindingHandle, &Version);
+++    }
+++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+++    {
+++        ret = RpcStatusToCmStatus(RpcExceptionCode());
+++    }
+++    RpcEndExcept;
+++
+++    return ret;
+++}
+++
+++
 ++/***********************************************************************
 ++ * CM_Add_Empty_Log_Conf [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_Empty_Log_Conf(
 ++    PLOG_CONF plcLogConf, DEVINST dnDevInst, PRIORITY Priority,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lu %lx\n", plcLogConf, dnDevInst, Priority, ulFlags);
 ++    return CM_Add_Empty_Log_Conf_Ex(plcLogConf, dnDevInst, Priority,
 ++                                    ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Add_Empty_Log_Conf_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_Empty_Log_Conf_Ex(
 ++    PLOG_CONF plcLogConf, DEVINST dnDevInst, PRIORITY Priority,
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    ULONG ulLogConfTag = 0;
 ++    LPWSTR lpDevInst;
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    FIXME("%p %p %lu %lx %p\n",
 ++          plcLogConf, dnDevInst, Priority, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (plcLogConf == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (Priority > 0xFFFF)
 ++        return CR_INVALID_PRIORITY;
 ++
 ++    if (ulFlags & ~(LOG_CONF_BITS | PRIORITY_BIT))
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_AddEmptyLogConf(BindingHandle, lpDevInst, Priority,
 ++                                  &ulLogConfTag, ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
 ++        if (pLogConfInfo == NULL)
 ++        {
 ++            ret = CR_OUT_OF_MEMORY;
 ++        }
 ++        else
 ++        {
 ++            pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
 ++            pLogConfInfo->dnDevInst = dnDevInst;
 ++            pLogConfInfo->ulFlags = ulFlags;
 ++            pLogConfInfo->ulTag = ulLogConfTag;
 ++
 ++            *plcLogConf = (LOG_CONF)pLogConfInfo;
 ++
 ++            ret = CR_SUCCESS;
 ++        }
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Add_IDA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_IDA(
 ++    DEVINST dnDevInst, PSTR pszID, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lx\n", dnDevInst, pszID, ulFlags);
 ++    return CM_Add_ID_ExA(dnDevInst, pszID, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Add_IDW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_IDW(
 ++    DEVINST dnDevInst, PWSTR pszID, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lx\n", dnDevInst, debugstr_w(pszID), ulFlags);
 ++    return CM_Add_ID_ExW(dnDevInst, pszID, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Add_ID_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_ID_ExA(
 ++    DEVINST dnDevInst, PSTR pszID, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    PWSTR pszIDW;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %s %lx %p\n", dnDevInst, pszID, ulFlags, hMachine);
 ++
 ++    if (CaptureAndConvertAnsiArg(pszID, &pszIDW))
 ++        return CR_INVALID_DATA;
 ++
 ++    ret = CM_Add_ID_ExW(dnDevInst, pszIDW, ulFlags, hMachine);
 ++
 ++    MyFree(pszIDW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Add_ID_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Add_ID_ExW(
 ++    DEVINST dnDevInst, PWSTR pszID, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %s %lx %p\n", dnDevInst, debugstr_w(pszID), ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (pszID == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags & ~CM_ADD_ID_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_AddID(BindingHandle,
 ++                        lpDevInst,
 ++                        pszID,
 ++                        ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Connect_MachineA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Connect_MachineA(
 ++    PCSTR UNCServerName, PHMACHINE phMachine)
 ++{
 ++    PWSTR pServerNameW;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%s %p\n", UNCServerName, phMachine);
 ++
 ++    if (UNCServerName == NULL || *UNCServerName == 0)
 ++        return CM_Connect_MachineW(NULL, phMachine);
 ++
 ++    if (CaptureAndConvertAnsiArg(UNCServerName, &pServerNameW))
 ++        return CR_INVALID_DATA;
 ++
 ++    ret = CM_Connect_MachineW(pServerNameW, phMachine);
 ++
 ++    MyFree(pServerNameW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Connect_MachineW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Connect_MachineW(
 ++    PCWSTR UNCServerName, PHMACHINE phMachine)
 ++{
 ++    PMACHINE_INFO pMachine;
 ++
 ++    TRACE("%s %p\n", debugstr_w(UNCServerName), phMachine);
 ++
 ++    if (phMachine == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    *phMachine = NULL;
 ++
 ++    pMachine = HeapAlloc(GetProcessHeap(), 0, sizeof(MACHINE_INFO));
 ++    if (pMachine == NULL)
 ++        return CR_OUT_OF_MEMORY;
 ++
 ++    if (UNCServerName == NULL || *UNCServerName == 0)
 ++    {
 ++        pMachine->bLocal = TRUE;
 ++
 ++        /* FIXME: store the computers name in pMachine->szMachineName */
 ++
 ++        if (!PnpGetLocalHandles(&pMachine->BindingHandle,
 ++                                &pMachine->StringTable))
 ++        {
 ++            HeapFree(GetProcessHeap(), 0, pMachine);
 ++            return CR_FAILURE;
 ++        }
 ++    }
 ++    else
 ++    {
 ++        pMachine->bLocal = FALSE;
 ++        if (wcslen(UNCServerName) >= SP_MAX_MACHINENAME_LENGTH - 1)
 ++        {
 ++            HeapFree(GetProcessHeap(), 0, pMachine);
 ++            return CR_INVALID_MACHINENAME;
 ++        }
 ++        lstrcpyW(pMachine->szMachineName, UNCServerName);
 ++
 ++        pMachine->StringTable = StringTableInitialize();
 ++        if (pMachine->StringTable == NULL)
 ++        {
 ++            HeapFree(GetProcessHeap(), 0, pMachine);
 ++            return CR_FAILURE;
 ++        }
 ++
 ++        StringTableAddString(pMachine->StringTable, L"PLT", 1);
 ++
 ++        if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle))
 ++        {
 ++            StringTableDestroy(pMachine->StringTable);
 ++            HeapFree(GetProcessHeap(), 0, pMachine);
 ++            return CR_INVALID_MACHINENAME;
 ++        }
 ++    }
 ++
 ++    phMachine = (PHMACHINE)pMachine;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Create_DevNodeA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Create_DevNodeA(
 ++    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, DEVINST dnParent,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %p %lx\n",
 ++          pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags);
 ++    return CM_Create_DevNode_ExA(pdnDevInst, pDeviceID, dnParent,
 ++                                 ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Create_DevNodeW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Create_DevNodeW(
 ++    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, DEVINST dnParent,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %p %lx\n",
 ++          pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags);
 ++    return CM_Create_DevNode_ExW(pdnDevInst, pDeviceID, dnParent,
 ++                                 ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Create_DevNode_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Create_DevNode_ExA(
 ++    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, DEVINST dnParent,
 ++    ULONG ulFlags, HANDLE hMachine)
 ++{
 ++    DEVINSTID_W pDeviceIDW;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %s %p %lx %p\n",
 ++          pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags, hMachine);
 ++
 ++    if (CaptureAndConvertAnsiArg(pDeviceID, &pDeviceIDW))
 ++        return CR_INVALID_DATA;
 ++
 ++    ret = CM_Create_DevNode_ExW(pdnDevInst, pDeviceIDW, dnParent, ulFlags,
 ++                                hMachine);
 ++
 ++    MyFree(pDeviceIDW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Create_DevNode_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Create_DevNode_ExW(
 ++    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, DEVINST dnParent,
 ++    ULONG ulFlags, HANDLE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpParentDevInst;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    FIXME("%p %s %p %lx %p\n",
 ++          pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (pdnDevInst == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (pDeviceID == NULL || wcslen(pDeviceID) == 0)
 ++        return CR_INVALID_DEVICE_ID;
 ++
 ++    if (dnParent == 0)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpParentDevInst = StringTableStringFromId(StringTable, dnParent);
 ++    if (lpParentDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_CreateDevInst(BindingHandle,
 ++                                pDeviceID,
 ++                                lpParentDevInst,
 ++                                MAX_DEVICE_ID_LEN,
 ++                                ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        *pdnDevInst = StringTableAddString(StringTable, pDeviceID, 1);
 ++        if (*pdnDevInst == 0)
 ++            ret = CR_NO_SUCH_DEVNODE;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Delete_Class_Key [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Delete_Class_Key(
 ++    LPGUID ClassGuid, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx\n", ClassGuid, ulFlags);
 ++    return CM_Delete_Class_Key_Ex(ClassGuid, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Delete_Class_Key_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Delete_Class_Key_Ex(
 ++    LPGUID ClassGuid, ULONG ulFlags, HANDLE hMachine)
 ++{
 ++    WCHAR szGuidString[MAX_GUID_STRING_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx\n", ClassGuid, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags & ~CM_DELETE_CLASS_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (!GuidToString(ClassGuid, szGuidString))
 ++        return CR_INVALID_DATA;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_DeleteClassKey(BindingHandle,
 ++                                 szGuidString,
 ++                                 ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Delete_DevNode_Key [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Delete_DevNode_Key(
 ++    DEVNODE dnDevNode, ULONG ulHardwareProfile, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lu %lx\n", dnDevNode, ulHardwareProfile, ulFlags);
 ++    return CM_Delete_DevNode_Key_Ex(dnDevNode, ulHardwareProfile, ulFlags,
 ++                                    NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Delete_DevNode_Key_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Delete_DevNode_Key_Ex(
 ++    DEVNODE dnDevNode, ULONG ulHardwareProfile, ULONG ulFlags,
 ++    HANDLE hMachine)
 ++{
 ++    FIXME("%p %lu %lx %p\n",
 ++          dnDevNode, ulHardwareProfile, ulFlags, hMachine);
 ++
 ++    return CR_CALL_NOT_IMPLEMENTED;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Disable_DevNode [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Disable_DevNode(
 ++    DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx\n", dnDevInst, ulFlags);
 ++    return CM_Disable_DevNode_Ex(dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Disable_DevNode_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Disable_DevNode_Ex(
 ++    DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%p %lx %p\n", dnDevInst, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_DeviceInstanceAction(BindingHandle,
 ++                                       PNP_DEVINST_DISABLE,
 ++                                       ulFlags,
 ++                                       lpDevInst,
 ++                                       NULL);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Disconnect_Machine [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Disconnect_Machine(HMACHINE hMachine)
 ++{
 ++    PMACHINE_INFO pMachine;
 ++
 ++    TRACE("%lx\n", hMachine);
 ++
 ++    pMachine = (PMACHINE_INFO)hMachine;
 ++    if (pMachine == NULL)
 ++        return CR_SUCCESS;
 ++
 ++    if (pMachine->bLocal == FALSE)
 ++    {
 ++        if (pMachine->StringTable != NULL)
 ++            StringTableDestroy(pMachine->StringTable);
 ++
 ++        if (!PnpUnbindRpc(pMachine->BindingHandle))
 ++            return CR_ACCESS_DENIED;
 ++    }
 ++
 ++    HeapFree(GetProcessHeap(), 0, pMachine);
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enable_DevNode [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enable_DevNode(
 ++    DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx\n", dnDevInst, ulFlags);
 ++    return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enable_DevNode_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enable_DevNode_Ex(
 ++    DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %p\n", dnDevInst, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_DeviceInstanceAction(BindingHandle,
 ++                                       PNP_DEVINST_ENABLE,
 ++                                       ulFlags,
 ++                                       lpDevInst,
 ++                                       NULL);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_Classes [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_Classes(
 ++    ULONG ulClassIndex, LPGUID ClassGuid, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %p %lx\n", ulClassIndex, ClassGuid, ulFlags);
 ++    return CM_Enumerate_Classes_Ex(ulClassIndex, ClassGuid, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_Classes_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_Classes_Ex(
 ++    ULONG ulClassIndex, LPGUID ClassGuid, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    WCHAR szBuffer[MAX_GUID_STRING_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    ULONG ulLength = MAX_GUID_STRING_LEN;
 ++
 ++    TRACE("%lx %p %lx %p\n", ulClassIndex, ClassGuid, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_EnumerateSubKeys(BindingHandle,
 ++                                   PNP_CLASS_SUBKEYS,
 ++                                   ulClassIndex,
 ++                                   szBuffer,
 ++                                   MAX_GUID_STRING_LEN,
 ++                                   &ulLength,
 ++                                   ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        /* Remove the {} */
 ++        szBuffer[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
 ++
 ++        /* Convert the buffer to a GUID */
 ++        if (UuidFromStringW(&szBuffer[1], ClassGuid) != RPC_S_OK)
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_EnumeratorsA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_EnumeratorsA(
 ++    ULONG ulEnumIndex, PCHAR Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%lu %p %p %lx\n", ulEnumIndex, Buffer, pulLength, ulFlags);
 ++    return CM_Enumerate_Enumerators_ExA(ulEnumIndex, Buffer, pulLength,
 ++                                        ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_EnumeratorsW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_EnumeratorsW(
 ++    ULONG ulEnumIndex, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%lu %p %p %lx\n", ulEnumIndex, Buffer, pulLength, ulFlags);
 ++    return CM_Enumerate_Enumerators_ExW(ulEnumIndex, Buffer, pulLength,
 ++                                        ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_Enumerators_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_Enumerators_ExA(
 ++    ULONG ulEnumIndex, PCHAR Buffer, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szBuffer[MAX_DEVICE_ID_LEN];
 ++    ULONG ulOrigLength;
 ++    ULONG ulLength;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    TRACE("%lu %p %p %lx %lx\n", ulEnumIndex, Buffer, pulLength, ulFlags,
 ++          hMachine);
 ++
 ++    if (Buffer == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    ulOrigLength = *pulLength;
 ++    *pulLength = 0;
 ++
 ++    ulLength = MAX_DEVICE_ID_LEN;
 ++    ret = CM_Enumerate_Enumerators_ExW(ulEnumIndex, szBuffer, &ulLength,
 ++                                       ulFlags, hMachine);
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (WideCharToMultiByte(CP_ACP,
 ++                                0,
 ++                                szBuffer,
 ++                                ulLength,
 ++                                Buffer,
 ++                                ulOrigLength,
 ++                                NULL,
 ++                                NULL) == 0)
 ++            ret = CR_FAILURE;
 ++        else
 ++            *pulLength = lstrlenA(Buffer) + 1;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Enumerate_Enumerators_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Enumerate_Enumerators_ExW(
 ++    ULONG ulEnumIndex, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lu %p %p %lx %lx\n", ulEnumIndex, Buffer, pulLength, ulFlags,
 ++          hMachine);
 ++
 ++    if (Buffer == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    *Buffer = UNICODE_NULL;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_EnumerateSubKeys(BindingHandle,
 ++                                   PNP_ENUMERATOR_SUBKEYS,
 ++                                   ulEnumIndex,
 ++                                   Buffer,
 ++                                   *pulLength,
 ++                                   pulLength,
 ++                                   ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Free_Log_Conf [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Free_Log_Conf(
 ++    LOG_CONF lcLogConfToBeFreed, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lx\n", lcLogConfToBeFreed, ulFlags);
 ++    return CM_Free_Log_Conf_Ex(lcLogConfToBeFreed, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Free_Log_Conf_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Free_Log_Conf_Ex(
 ++    LOG_CONF lcLogConfToBeFreed, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx %lx %lx\n", lcLogConfToBeFreed, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    pLogConfInfo = (PLOG_CONF_INFO)lcLogConfToBeFreed;
 ++    if (pLogConfInfo == NULL || pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
 ++        return CR_INVALID_LOG_CONF;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_FreeLogConf(BindingHandle, lpDevInst, pLogConfInfo->ulFlags,
 ++                              pLogConfInfo->ulTag, 0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Free_Log_Conf_Handle [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Free_Log_Conf_Handle(
 ++    LOG_CONF lcLogConf)
 ++{
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++
 ++    TRACE("%lx\n", lcLogConf);
 ++
 ++    pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
 ++    if (pLogConfInfo == NULL || pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
 ++        return CR_INVALID_LOG_CONF;
 ++
 ++    HeapFree(GetProcessHeap(), 0, pLogConfInfo);
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Child [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Child(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
 ++    return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Child_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Child_Ex(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pdnDevInst == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    *pdnDevInst = -1;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetRelatedDeviceInstance(BindingHandle,
 ++                                           PNP_GET_CHILD_DEVICE_INSTANCE,
 ++                                           lpDevInst,
 ++                                           szRelatedDevInst,
 ++                                           &dwLength,
 ++                                           0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return ret;
 ++
 ++    TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
 ++
 ++    dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
 ++    if (dwIndex == -1)
 ++        return CR_FAILURE;
 ++
 ++    *pdnDevInst = dwIndex;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Key_NameA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_Key_NameA(
 ++    LPGUID ClassGuid, LPSTR pszKeyName, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %p %lx\n",
 ++          ClassGuid, pszKeyName, pulLength, ulFlags);
 ++    return CM_Get_Class_Key_Name_ExA(ClassGuid, pszKeyName, pulLength,
 ++                                     ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Key_NameW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_Key_NameW(
 ++    LPGUID ClassGuid, LPWSTR pszKeyName, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %p %lx\n",
 ++          ClassGuid, pszKeyName, pulLength, ulFlags);
 ++    return CM_Get_Class_Key_Name_ExW(ClassGuid, pszKeyName, pulLength,
 ++                                     ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Key_Name_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_Key_Name_ExA(
 ++    LPGUID ClassGuid, LPSTR pszKeyName, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szBuffer[MAX_GUID_STRING_LEN];
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    ULONG ulLength;
 ++    ULONG ulOrigLength;
 ++
 ++    TRACE("%p %p %p %lx %lx\n",
 ++          ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    ulOrigLength = *pulLength;
 ++    *pulLength = 0;
 ++
 ++    ulLength = MAX_GUID_STRING_LEN;
 ++    ret = CM_Get_Class_Key_Name_ExW(ClassGuid, szBuffer, &ulLength,
 ++                                    ulFlags, hMachine);
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (WideCharToMultiByte(CP_ACP,
 ++                                0,
 ++                                szBuffer,
 ++                                ulLength,
 ++                                pszKeyName,
 ++                                ulOrigLength,
 ++                                NULL,
 ++                                NULL) == 0)
 ++            ret = CR_FAILURE;
 ++        else
 ++            *pulLength = lstrlenA(pszKeyName) + 1;
 ++    }
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_Key_Name_ExW(
 ++    LPGUID ClassGuid, LPWSTR pszKeyName, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    TRACE("%p %p %p %lx %lx\n",
 ++          ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (*pulLength < MAX_GUID_STRING_LEN)
 ++    {
 ++        *pulLength = 0;
 ++        return CR_BUFFER_SMALL;
 ++    }
 ++
 ++    if (!GuidToString(ClassGuid, pszKeyName))
 ++        return CR_INVALID_DATA;
 ++
 ++    *pulLength = MAX_GUID_STRING_LEN;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_NameA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_NameA(
 ++    LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
 ++    return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
 ++                                 NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_NameW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_NameW(
 ++    LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
 ++    return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
 ++                                 NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Name_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Class_Name_ExA(
 ++    LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szBuffer[MAX_CLASS_NAME_LEN];
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    ULONG ulLength;
 ++    ULONG ulOrigLength;
 ++
 ++    TRACE("%p %p %p %lx %lx\n",
 ++          ClassGuid, Buffer, pulLength, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    ulOrigLength = *pulLength;
 ++    *pulLength = 0;
 ++
 ++    ulLength = MAX_CLASS_NAME_LEN;
 ++    ret = CM_Get_Class_Name_ExW(ClassGuid, szBuffer, &ulLength,
 ++                                ulFlags, hMachine);
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (WideCharToMultiByte(CP_ACP,
 ++                                0,
 ++                                szBuffer,
 ++                                ulLength,
 ++                                Buffer,
 ++                                ulOrigLength,
 ++                                NULL,
 ++                                NULL) == 0)
 ++            ret = CR_FAILURE;
 ++        else
 ++            *pulLength = lstrlenA(Buffer) + 1;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Class_Name_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI
 ++CM_Get_Class_Name_ExW(
 ++    LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szGuidString[MAX_GUID_STRING_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %p %p %lx %lx\n",
 ++          ClassGuid, Buffer, pulLength, ulFlags, hMachine);
 ++
 ++    if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (!GuidToString(ClassGuid, szGuidString))
 ++        return CR_INVALID_DATA;
 ++
 ++    TRACE("Guid %s\n", debugstr_w(szGuidString));
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetClassName(BindingHandle,
 ++                               szGuidString,
 ++                               Buffer,
 ++                               pulLength,
 ++                               ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Depth [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Depth(
 ++    PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx %lx\n", pulDepth, dnDevInst, ulFlags);
 ++    return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Depth_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Depth_Ex(
 ++    PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx %lx\n",
 ++          pulDepth, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pulDepth == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetDepth(BindingHandle,
 ++                           lpDevInst,
 ++                           pulDepth,
 ++                           ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyA(
 ++    DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
 ++    PVOID Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lu %p %p %p %lx\n",
 ++          dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
 ++
 ++    return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
 ++                                                pulRegDataType, Buffer,
 ++                                                pulLength, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyW(
 ++    DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
 ++    PVOID Buffer, PULONG pulLength, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lu %p %p %p %lx\n",
 ++          dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
 ++
 ++    return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
 ++                                                pulRegDataType, Buffer,
 ++                                                pulLength, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExA(
 ++    DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
 ++    PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    PVOID BufferW;
 ++    ULONG LengthW;
 ++    ULONG RegDataType = REG_NONE;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx %lu %p %p %p %lx %lx\n",
 ++          dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
 ++          ulFlags, hMachine);
 ++
 ++    if (!pulLength)
 ++        return CR_INVALID_POINTER;
 ++
 ++    LengthW = *pulLength * sizeof(WCHAR);
 ++    BufferW = HeapAlloc(GetProcessHeap(), 0, LengthW);
 ++
 ++    if (!BufferW)
 ++        return CR_OUT_OF_MEMORY;
 ++
 ++    ret = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
 ++                                               ulProperty,
 ++                                               &RegDataType,
 ++                                               BufferW,
 ++                                               &LengthW,
 ++                                               ulFlags,
 ++                                               hMachine);
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (RegDataType == REG_SZ || RegDataType == REG_EXPAND_SZ)
 ++        {
 ++            /* Do W->A conversion */
 ++            *pulLength = WideCharToMultiByte(CP_ACP,
 ++                                             0,
 ++                                             BufferW,
 ++                                             lstrlenW(BufferW) + 1,
 ++                                             Buffer,
 ++                                             *pulLength,
 ++                                             NULL,
 ++                                             NULL);
 ++            if (*pulLength == 0)
 ++                ret = CR_FAILURE;
 ++        }
 ++        else
 ++        {
 ++            /* Directly copy the value */
 ++            if (LengthW <= *pulLength)
 ++                memcpy(Buffer, BufferW, LengthW);
 ++            else
 ++            {
 ++                *pulLength = LengthW;
 ++                ret = CR_BUFFER_SMALL;
 ++            }
 ++        }
 ++    }
 ++
 ++    if (pulRegDataType)
 ++        *pulRegDataType = RegDataType;
 ++
 ++    HeapFree(GetProcessHeap(), 0, BufferW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExW(
 ++    DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
 ++    PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    LPWSTR lpDevInst;
 ++    ULONG ulDataType = 0;
 ++    ULONG ulTransferLength = 0;
 ++
 ++    TRACE("%lx %lu %p %p %p %lx %lx\n",
 ++          dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
 ++          ulFlags, hMachine);
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
 ++        return CR_INVALID_PROPERTY;
 ++
 ++    /* pulRegDataType is optional */
 ++
 ++    /* Buffer is optional */
 ++
 ++    if (pulLength == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (*pulLength == 0)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    ulTransferLength = *pulLength;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetDeviceRegProp(BindingHandle,
 ++                                   lpDevInst,
 ++                                   ulProperty,
 ++                                   &ulDataType,
 ++                                   Buffer,
 ++                                   &ulTransferLength,
 ++                                   pulLength,
 ++                                   ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (pulRegDataType != NULL)
 ++            *pulRegDataType = ulDataType;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Status [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_DevNode_Status(
 ++    PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx %lx\n",
 ++          pulStatus, pulProblemNumber, dnDevInst, ulFlags);
 ++    return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
 ++                                    ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI
 ++CM_Get_DevNode_Status_Ex(
 ++    PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %p %lx %lx %lx\n",
 ++          pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pulStatus == NULL || pulProblemNumber == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetDeviceStatus(BindingHandle,
 ++                                  lpDevInst,
 ++                                  pulStatus,
 ++                                  pulProblemNumber,
 ++                                  ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_IDA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_IDA(
 ++    DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %p %ld %ld\n",
 ++          dnDevInst, Buffer, BufferLen, ulFlags);
 ++    return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_IDW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_IDW(
 ++    DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %p %ld %ld\n",
 ++          dnDevInst, Buffer, BufferLen, ulFlags);
 ++    return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_ExA(
 ++    DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szBufferW[MAX_DEVICE_ID_LEN];
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
-      FIXME("%p %p %ld %ld %lx\n",
+++    TRACE("%lx %p %ld %ld %lx\n",
 ++          dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
 ++
 ++    if (Buffer == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    ret = CM_Get_Device_ID_ExW(dnDevInst,
 ++                               szBufferW,
 ++                               MAX_DEVICE_ID_LEN,
 ++                               ulFlags,
 ++                               hMachine);
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        if (WideCharToMultiByte(CP_ACP,
 ++                                0,
 ++                                szBufferW,
 ++                                lstrlenW(szBufferW) + 1,
 ++                                Buffer,
 ++                                BufferLen,
 ++                                NULL,
 ++                                NULL) == 0)
 ++            ret = CR_FAILURE;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_ExW(
 ++    DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    HSTRING_TABLE StringTable = NULL;
 ++
 ++    TRACE("%lx %p %ld %ld %lx\n",
 ++          dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (Buffer == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(NULL, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    if (!StringTableStringFromIdEx(StringTable,
 ++                                   dnDevInst,
 ++                                   Buffer,
 ++                                   &BufferLen))
 ++        return CR_FAILURE;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_ListA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_ListA(
 ++    PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
 ++    return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
 ++                                     ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_ListW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_ListW(
 ++    PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
 ++    return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
 ++                                     ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_ExA(
 ++    PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    LPWSTR BufferW = NULL;
 ++    LPWSTR pszFilterW = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
-                                  pszFilter,
+++    TRACE("%p %p %ld %ld %lx\n",
 ++          pszFilter, Buffer, BufferLen, ulFlags, hMachine);
 ++
 ++    BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
 ++    if (BufferW == NULL)
 ++        return CR_OUT_OF_MEMORY;
 ++
 ++    if (pszFilter == NULL)
 ++    {
 ++        ret = CM_Get_Device_ID_List_ExW(NULL,
 ++                                        BufferW,
 ++                                        BufferLen,
 ++                                        ulFlags,
 ++                                        hMachine);
 ++    }
 ++    else
 ++    {
 ++        if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
 ++        {
 ++            ret = CR_INVALID_DEVICE_ID;
 ++            goto Done;
 ++        }
 ++
 ++        ret = CM_Get_Device_ID_List_ExW(pszFilterW,
 ++                                        BufferW,
 ++                                        BufferLen,
 ++                                        ulFlags,
 ++                                        hMachine);
 ++
 ++        MyFree(pszFilterW);
 ++    }
 ++
 ++    if (WideCharToMultiByte(CP_ACP,
 ++                            0,
 ++                            BufferW,
 ++                            lstrlenW(BufferW) + 1,
 ++                            Buffer,
 ++                            BufferLen,
 ++                            NULL,
 ++                            NULL) == 0)
 ++        ret = CR_FAILURE;
 ++
 ++Done:
 ++    MyFree(BufferW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_ExW(
 ++    PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %p %ld %ld %lx\n",
 ++          pszFilter, Buffer, BufferLen, ulFlags, hMachine);
 ++
 ++    if (Buffer == NULL || BufferLen == 0)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    *Buffer = 0;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetDeviceList(BindingHandle,
+++                                (LPWSTR)pszFilter,
 ++                                Buffer,
 ++                                &BufferLen,
 ++                                ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA(
 ++    PULONG pulLen, PCSTR pszFilter, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %ld\n", pulLen, pszFilter, ulFlags);
 ++    return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_SizeW(
 ++    PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %ld\n", pulLen, debugstr_w(pszFilter), ulFlags);
 ++    return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExA(
 ++    PULONG pulLen, PCSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    LPWSTR pszFilterW = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    FIXME("%p %s %lx %lx\n", pulLen, pszFilter, ulFlags, hMachine);
 ++
 ++    if (pszFilter == NULL)
 ++    {
 ++        ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
 ++                                             NULL,
 ++                                             ulFlags,
 ++                                             hMachine);
 ++    }
 ++    else
 ++    {
 ++        if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
 ++            return CR_INVALID_DEVICE_ID;
 ++
 ++        ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
 ++                                             pszFilterW,
 ++                                             ulFlags,
 ++                                             hMachine);
 ++
 ++        MyFree(pszFilterW);
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW(
 ++    PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%p %s %ld %lx\n", pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
 ++
 ++    if (pulLen == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    *pulLen = 0;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetDeviceListSize(BindingHandle,
 ++                                    (LPWSTR)pszFilter,
 ++                                    pulLen,
 ++                                    ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_Size [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_Size(
 ++    PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx %lx\n", pulLen, dnDevInst, ulFlags);
 ++    return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Device_ID_Size_Ex(
 ++    PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR DeviceId;
 ++
 ++    TRACE("%p %lx %lx %lx\n", pulLen, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pulLen == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(NULL, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    DeviceId = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (DeviceId == NULL)
 ++    {
 ++        *pulLen = 0;
 ++        return CR_SUCCESS;
 ++    }
 ++
 ++    *pulLen = lstrlenW(DeviceId);
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_First_Log_Conf [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_First_Log_Conf(
 ++    PLOG_CONF plcLogConf, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx %lx\n", plcLogConf, dnDevInst, ulFlags);
 ++    return CM_Get_First_Log_Conf_Ex(plcLogConf, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_First_Log_Conf_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_First_Log_Conf_Ex(
 ++    PLOG_CONF plcLogConf, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    ULONG ulTag;
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++
 ++    FIXME("%p %lx %lx %lx\n", plcLogConf, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags & ~LOG_CONF_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (plcLogConf)
 ++        *plcLogConf = 0;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetFirstLogConf(BindingHandle,
 ++                                  lpDevInst,
 ++                                  ulFlags,
 ++                                  &ulTag,
 ++                                  ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return ret;
 ++
+++    if (plcLogConf)
+++    {
 ++    pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
 ++    if (pLogConfInfo == NULL)
 ++        return CR_OUT_OF_MEMORY;
 ++
 ++    pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
 ++    pLogConfInfo->dnDevInst = dnDevInst;
 ++    pLogConfInfo->ulFlags = ulFlags;
 ++    pLogConfInfo->ulTag = ulTag;
 ++
 ++    *plcLogConf = (LOG_CONF)pLogConfInfo;
+++    }
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Global_State [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Global_State(
 ++    PULONG pulState, ULONG ulFlags)
 ++{
 ++    TRACE("%p %lx\n", pulState, ulFlags);
 ++    return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Global_State_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Global_State_Ex(
 ++    PULONG pulState, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx\n", pulState, ulFlags, hMachine);
 ++
 ++    if (pulState == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_HW_Prof_FlagsA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_HW_Prof_FlagsA(
 ++    DEVINSTID_A szDevInstName, ULONG ulHardwareProfile, PULONG pulValue,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%s %lu %p %lx\n", szDevInstName,
 ++          ulHardwareProfile, pulValue, ulFlags);
 ++
 ++    return CM_Get_HW_Prof_Flags_ExA(szDevInstName, ulHardwareProfile,
 ++                                    pulValue, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_HW_Prof_FlagsW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_HW_Prof_FlagsW(
 ++    DEVINSTID_W szDevInstName, ULONG ulHardwareProfile, PULONG pulValue,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%s %lu %p %lx\n", debugstr_w(szDevInstName),
 ++          ulHardwareProfile, pulValue, ulFlags);
 ++
 ++    return CM_Get_HW_Prof_Flags_ExW(szDevInstName, ulHardwareProfile,
 ++                                    pulValue, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_HW_Prof_Flags_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_HW_Prof_Flags_ExA(
 ++    DEVINSTID_A szDevInstName, ULONG ulHardwareProfile, PULONG pulValue,
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    DEVINSTID_W pszDevIdW = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    TRACE("%s %lu %p %lx %lx\n", szDevInstName,
 ++          ulHardwareProfile, pulValue, ulFlags, hMachine);
 ++
 ++    if (szDevInstName != NULL)
 ++    {
 ++       if (CaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
 ++         return CR_INVALID_DEVICE_ID;
 ++    }
 ++
 ++    ret = CM_Get_HW_Prof_Flags_ExW(pszDevIdW, ulHardwareProfile,
 ++                                   pulValue, ulFlags, hMachine);
 ++
 ++    if (pszDevIdW != NULL)
 ++        MyFree(pszDevIdW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_HW_Prof_Flags_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_HW_Prof_Flags_ExW(
 ++    DEVINSTID_W szDevInstName, ULONG ulHardwareProfile, PULONG pulValue,
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%s %lu %p %lx %lx\n", debugstr_w(szDevInstName),
 ++          ulHardwareProfile, pulValue, ulFlags, hMachine);
 ++
 ++    if ((szDevInstName == NULL) || (pulValue == NULL))
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    /* FIXME: Check whether szDevInstName is valid */
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_HwProfFlags(BindingHandle, PNP_GET_HWPROFFLAGS, szDevInstName,
 ++                              ulHardwareProfile, pulValue, NULL, NULL, 0, 0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Log_Conf_Priority [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Log_Conf_Priority(
 ++    LOG_CONF lcLogConf, PPRIORITY pPriority, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx\n", lcLogConf, pPriority, ulFlags);
 ++    return CM_Get_Log_Conf_Priority_Ex(lcLogConf, pPriority, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Log_Conf_Priority_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Log_Conf_Priority_Ex(
 ++    LOG_CONF lcLogConf, PPRIORITY pPriority, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%p %p %lx %lx\n", lcLogConf, pPriority, ulFlags, hMachine);
 ++
 ++    pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
 ++    if (pLogConfInfo == NULL || pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
 ++        return CR_INVALID_LOG_CONF;
 ++
 ++    if (pPriority == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetLogConfPriority(BindingHandle,
 ++                                     lpDevInst,
 ++                                     pLogConfInfo->ulFlags,
 ++                                     pLogConfInfo->ulTag,
 ++                                     pPriority,
 ++                                     0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Next_Log_Conf [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Next_Log_Conf(
 ++    PLOG_CONF plcLogConf, LOG_CONF lcLogConf, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx\n", plcLogConf, lcLogConf, ulFlags);
 ++    return CM_Get_Next_Log_Conf_Ex(plcLogConf, lcLogConf, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Next_Log_Conf_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Next_Log_Conf_Ex(
 ++    PLOG_CONF plcLogConf, LOG_CONF lcLogConf, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    PLOG_CONF_INFO pLogConfInfo;
 ++    PLOG_CONF_INFO pNewLogConfInfo;
 ++    ULONG ulNewTag;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%p %p %lx %lx\n", plcLogConf, lcLogConf, ulFlags, hMachine);
 ++
 ++    if (plcLogConf)
 ++        *plcLogConf = 0;
 ++
 ++    pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
 ++    if (pLogConfInfo == NULL || pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
 ++        return CR_INVALID_LOG_CONF;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetNextLogConf(BindingHandle,
 ++                                 lpDevInst,
 ++                                 pLogConfInfo->ulFlags,
 ++                                 pLogConfInfo->ulTag,
 ++                                 &ulNewTag,
 ++                                 0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return ret;
 ++
 ++    if (plcLogConf)
 ++    {
 ++        pNewLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
 ++        if (pNewLogConfInfo == NULL)
 ++            return CR_OUT_OF_MEMORY;
 ++
 ++        pNewLogConfInfo->ulMagic = LOG_CONF_MAGIC;
 ++        pNewLogConfInfo->dnDevInst = pLogConfInfo->dnDevInst;
 ++        pNewLogConfInfo->ulFlags = pLogConfInfo->ulFlags;
 ++        pNewLogConfInfo->ulTag = ulNewTag;
 ++
 ++        *plcLogConf = (LOG_CONF)pNewLogConfInfo;
 ++    }
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Parent [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Parent(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
 ++    return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Parent_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Parent_Ex(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pdnDevInst == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    *pdnDevInst = -1;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetRelatedDeviceInstance(BindingHandle,
 ++                                           PNP_GET_PARENT_DEVICE_INSTANCE,
 ++                                           lpDevInst,
 ++                                           szRelatedDevInst,
 ++                                           &dwLength,
 ++                                           0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return ret;
 ++
 ++    TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
 ++
 ++    dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
 ++    if (dwIndex == -1)
 ++        return CR_FAILURE;
 ++
 ++    *pdnDevInst = dwIndex;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Sibling [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Sibling(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
 ++    return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Sibling_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Get_Sibling_Ex(
 ++    PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
 ++
 ++    if (pdnDevInst == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVINST;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    *pdnDevInst = -1;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetRelatedDeviceInstance(BindingHandle,
 ++                                           PNP_GET_SIBLING_DEVICE_INSTANCE,
 ++                                           lpDevInst,
 ++                                           szRelatedDevInst,
 ++                                           &dwLength,
 ++                                           0);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return ret;
 ++
 ++    TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
 ++
 ++    dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
 ++    if (dwIndex == -1)
 ++        return CR_FAILURE;
 ++
 ++    *pdnDevInst = dwIndex;
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Version [SETUPAPI.@]
 ++ */
 ++WORD WINAPI CM_Get_Version(VOID)
 ++{
 ++    TRACE("\n");
 ++    return CM_Get_Version_Ex(NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Get_Version_Ex [SETUPAPI.@]
 ++ */
 ++WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    WORD Version = 0;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx\n", hMachine);
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return 0;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_GetVersion(BindingHandle, &Version);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret != CR_SUCCESS)
 ++        return 0;
 ++
 ++    return Version;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Is_Dock_Station_Present [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Is_Dock_Station_Present(
 ++    PBOOL pbPresent)
 ++{
 ++    TRACE("%p\n", pbPresent);
 ++    return CM_Is_Dock_Station_Present_Ex(pbPresent, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Is_Dock_Station_Present_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Is_Dock_Station_Present_Ex(
 ++    PBOOL pbPresent, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%p %lx\n", pbPresent, hMachine);
 ++
 ++    if (pbPresent == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    *pbPresent = FALSE;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_IsDockStationPresent(BindingHandle,
 ++                                       pbPresent);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Locate_DevNodeA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Locate_DevNodeA(
 ++    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lu\n", pdnDevInst, pDeviceID, ulFlags);
 ++    return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Locate_DevNodeW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Locate_DevNodeW(
 ++    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lu\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags);
 ++    return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Locate_DevNode_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Locate_DevNode_ExA(
 ++    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    DEVINSTID_W pDevIdW = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    TRACE("%p %s %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine);
 ++
 ++    if (pDeviceID != NULL)
 ++    {
 ++       if (CaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
 ++         return CR_INVALID_DEVICE_ID;
 ++    }
 ++
 ++    ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
 ++
 ++    if (pDevIdW != NULL)
 ++        MyFree(pDevIdW);
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Locate_DevNode_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Locate_DevNode_ExW(
 ++    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    CONFIGRET ret = CR_SUCCESS;
 ++
 ++    TRACE("%p %s %lu %lx\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
 ++
 ++    if (pdnDevInst == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
 ++    {
 ++        lstrcpyW(DeviceIdBuffer, pDeviceID);
 ++    }
 ++    else
 ++    {
 ++        RpcTryExcept
 ++        {
 ++            /* Get the root device ID */
 ++            ret = PNP_GetRootDeviceInstance(BindingHandle,
 ++                                            DeviceIdBuffer,
 ++                                            MAX_DEVICE_ID_LEN);
 ++        }
 ++        RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++        {
 ++            ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++        }
 ++        RpcEndExcept;
 ++
 ++        if (ret != CR_SUCCESS)
 ++            return CR_FAILURE;
 ++    }
 ++    TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
 ++
 ++    RpcTryExcept
 ++    {
 ++        /* Validate the device ID */
 ++        ret = PNP_ValidateDeviceInstance(BindingHandle,
 ++                                         DeviceIdBuffer,
 ++                                         ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    if (ret == CR_SUCCESS)
 ++    {
 ++        *pdnDevInst = StringTableAddString(StringTable, DeviceIdBuffer, 1);
 ++        if (*pdnDevInst == -1)
 ++            ret = CR_FAILURE;
 ++    }
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Move_DevNode [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Move_DevNode(
 ++    DEVINST dnFromDevInst, DEVINST dnToDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lx %lx\n", dnFromDevInst, dnToDevInst, ulFlags);
 ++    return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Move_DevNode_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Move_DevNode_Ex(
 ++    DEVINST dnFromDevInst, DEVINST dnToDevInst, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpFromDevInst;
 ++    LPWSTR lpToDevInst;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%lx %lx %lx %lx\n",
 ++          dnFromDevInst, dnToDevInst, ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (dnFromDevInst == 0 || dnToDevInst == 0)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    if (ulFlags != 0)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpFromDevInst = StringTableStringFromId(StringTable, dnFromDevInst);
 ++    if (lpFromDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    lpToDevInst = StringTableStringFromId(StringTable, dnToDevInst);
 ++    if (lpToDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_DeviceInstanceAction(BindingHandle,
 ++                                       PNP_DEVINST_MOVE,
 ++                                       ulFlags,
 ++                                       lpFromDevInst,
 ++                                       lpToDevInst);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_Class_KeyA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_Class_KeyA(
 ++    LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
 ++    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lx %lx %p %lx\n",
 ++          debugstr_guid(pClassGuid), pszClassName,
 ++          samDesired, Disposition, phkClass, ulFlags);
 ++
 ++    return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
 ++                                 Disposition, phkClass, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_Class_KeyW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_Class_KeyW(
 ++    LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
 ++    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
 ++{
 ++    TRACE("%p %s %lx %lx %p %lx\n",
 ++          debugstr_guid(pClassGuid), debugstr_w(pszClassName),
 ++          samDesired, Disposition, phkClass, ulFlags);
 ++
 ++    return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
 ++                                 Disposition, phkClass, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_Class_Key_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_Class_Key_ExA(
 ++    LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
 ++    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    CONFIGRET rc = CR_SUCCESS;
 ++    LPWSTR pszClassNameW = NULL;
 ++
 ++    TRACE("%p %s %lx %lx %p %lx %lx\n",
 ++          debugstr_guid(pClassGuid), pszClassName,
 ++          samDesired, Disposition, phkClass, ulFlags, hMachine);
 ++
 ++    if (pszClassName != NULL)
 ++    {
 ++       if (CaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
 ++         return CR_INVALID_DATA;
 ++    }
 ++
 ++    rc = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
 ++                               Disposition, phkClass, ulFlags, hMachine);
 ++
 ++    if (pszClassNameW != NULL)
 ++        MyFree(pszClassNameW);
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_Class_Key_ExW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_Class_Key_ExW(
 ++    LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
 ++    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    WCHAR szKeyName[MAX_PATH];
 ++    LPWSTR lpGuidString;
 ++    DWORD dwDisposition;
 ++    DWORD dwError;
 ++    HKEY hKey;
 ++
 ++    TRACE("%p %s %lx %lx %p %lx %lx\n",
 ++          debugstr_guid(pClassGuid), debugstr_w(pszClassName),
 ++          samDesired, Disposition, phkClass, ulFlags, hMachine);
 ++
 ++    /* Check Disposition and ulFlags */
 ++    if ((Disposition & ~RegDisposition_Bits) ||
 ++        (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
 ++        return CR_INVALID_FLAG;
 ++
 ++    /* Check phkClass */
 ++    if (phkClass == NULL)
 ++        return CR_INVALID_POINTER;
 ++
 ++    *phkClass = NULL;
 ++
 ++    if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
 ++        pszClassName != NULL)
 ++        return CR_INVALID_DATA;
 ++
 ++    if (hMachine == NULL)
 ++    {
 ++        hKey = HKEY_LOCAL_MACHINE;
 ++    }
 ++    else
 ++    {
 ++       if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
 ++                               HKEY_LOCAL_MACHINE, &hKey))
 ++           return CR_REGISTRY_ERROR;
 ++    }
 ++
 ++    if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
 ++    {
 ++        lstrcpyW(szKeyName, DeviceClasses);
 ++    }
 ++    else
 ++    {
 ++        lstrcpyW(szKeyName, ControlClass);
 ++    }
 ++
 ++    if (pClassGuid != NULL)
 ++    {
 ++        if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
 ++        {
 ++            RegCloseKey(hKey);
 ++            return CR_INVALID_DATA;
 ++        }
 ++
 ++        lstrcatW(szKeyName, Backslash);
 ++        lstrcatW(szKeyName, lpGuidString);
 ++    }
 ++
 ++    if (Disposition == RegDisposition_OpenAlways)
 ++    {
 ++        dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
 ++                                  NULL, phkClass, &dwDisposition);
 ++    }
 ++    else
 ++    {
 ++        dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
 ++    }
 ++
 ++    RegCloseKey(hKey);
 ++
 ++    if (pClassGuid != NULL)
 ++        RpcStringFreeW(&lpGuidString);
 ++
 ++    if (dwError != ERROR_SUCCESS)
 ++    {
 ++        *phkClass = NULL;
 ++        return CR_NO_SUCH_REGISTRY_KEY;
 ++    }
 ++
 ++    if (pszClassName != NULL)
 ++    {
 ++        RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
 ++                       (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
 ++    }
 ++
 ++    return CR_SUCCESS;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_DevNode_Key [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_DevNode_Key(
 ++    DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile,
 ++    REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lx %lu %lx %p %lx\n", dnDevNode, samDesired,
 ++          ulHardwareProfile, Disposition, phkDevice, ulFlags);
 ++    return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
 ++                                  Disposition, phkDevice, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Open_DevNode_Key_Ex(
 ++    DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile,
 ++    REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags,
 ++    HMACHINE hMachine)
 ++{
 ++    FIXME("%lx %lx %lu %lx %p %lx %lx\n", dnDevNode, samDesired,
 ++          ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
 ++
 ++    return CR_CALL_NOT_IMPLEMENTED;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Reenumerate_DevNode [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Reenumerate_DevNode(
 ++    DEVINST dnDevInst, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lx\n", dnDevInst, ulFlags);
 ++    return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Reenumerate_DevNode_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI
 ++CM_Reenumerate_DevNode_Ex(
 ++    DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    FIXME("%lx %lx %lx\n", dnDevInst, ulFlags, hMachine);
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    if (ulFlags & ~CM_REENUMERATE_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_DeviceInstanceAction(BindingHandle,
 ++                                       PNP_DEVINST_REENUMERATE,
 ++                                       ulFlags,
 ++                                       lpDevInst,
 ++                                       NULL);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Request_Eject_PC [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Request_Eject_PC(VOID)
 ++{
 ++    TRACE("\n");
 ++    return CM_Request_Eject_PC_Ex(NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Request_Eject_PC_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Request_Eject_PC_Ex(
 ++    HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx\n", hMachine);
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_RequestEjectPC(BindingHandle);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Run_Detection [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Run_Detection(
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%lx\n", ulFlags);
 ++    return CM_Run_Detection_Ex(ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Run_Detection_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Run_Detection_Ex(
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx %lx\n", ulFlags, hMachine);
 ++
 ++    if (!IsUserAdmin())
 ++        return CR_ACCESS_DENIED;
 ++
 ++    if (ulFlags & ~CM_DETECT_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, NULL))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_RunDetection(BindingHandle,
 ++                               ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Set_DevNode_Problem [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Set_DevNode_Problem(
 ++    DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lx %lx\n", dnDevInst, ulProblem, ulFlags);
 ++    return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Set_DevNode_Problem_Ex(
 ++    DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    RPC_BINDING_HANDLE BindingHandle = NULL;
 ++    HSTRING_TABLE StringTable = NULL;
 ++    LPWSTR lpDevInst;
 ++    CONFIGRET ret;
 ++
 ++    TRACE("%lx %lx %lx %lx\n", dnDevInst, ulProblem, ulFlags, hMachine);
 ++
 ++    if (dnDevInst == 0)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
 ++        return CR_INVALID_FLAG;
 ++
 ++    if (hMachine != NULL)
 ++    {
 ++        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
 ++        if (BindingHandle == NULL)
 ++            return CR_FAILURE;
 ++
 ++        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
 ++        if (StringTable == 0)
 ++            return CR_FAILURE;
 ++    }
 ++    else
 ++    {
 ++        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
 ++            return CR_FAILURE;
 ++    }
 ++
 ++    lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
 ++    if (lpDevInst == NULL)
 ++        return CR_INVALID_DEVNODE;
 ++
 ++    RpcTryExcept
 ++    {
 ++        ret = PNP_SetDeviceProblem(BindingHandle,
 ++                                   lpDevInst,
 ++                                   ulProblem,
 ++                                   ulFlags);
 ++    }
 ++    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
 ++    {
 ++        ret = RpcStatusToCmStatus(RpcExceptionCode());
 ++    }
 ++    RpcEndExcept;
 ++
 ++    return ret;
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyA(
 ++    DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lu %p %lx %lx\n",
 ++          dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
 ++    return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
 ++                                                Buffer, ulLength,
 ++                                                ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyW(
 ++    DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
 ++    ULONG ulFlags)
 ++{
 ++    TRACE("%lx %lu %p %lx %lx\n",
 ++          dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
 ++    return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
 ++                                                Buffer, ulLength,
 ++                                                ulFlags, NULL);
 ++}
 ++
 ++
 ++/***********************************************************************
 ++ * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
 ++ */
 ++CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExA(
 ++    DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
 ++    ULONG ulFlags, HMACHINE hMachine)
 ++{
 ++    CONFIGRET ret = CR_SUCCESS;
 ++    LPWSTR lpBuffer;
 ++    ULONG ulType;
 ++
 ++    FIXME("%lx %lu %p %lx %lx %lx\n",
 ++          dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
 ++
 ++    if (Buffer == NULL && ulLength != 0)
 ++        return CR_INVALID_POINTER;
 ++
 ++    if (Buffer == NULL)
 ++    {
 ++        ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
 ++                                                   ulProperty,
 ++                                                   NULL,
 ++                                                   0,
 ++                                                   ulFlags,
 ++                                                   hMachine);
 ++    }
 ++    else
 ++    {
 ++        /* Get property type */
 ++        switch (ulProperty)
 ++        {
 ++            case CM_DRP_DEVICEDESC:
 ++                ulType = REG_SZ;
 ++                break;
 ++
 ++            case CM_DRP_HARDWAREID:
 ++                ulType = REG_MULTI_SZ;
 ++                break;
 ++
 ++            case CM_DRP_COMPATIBLEIDS:
 ++                ulType = REG_MULTI_SZ;
 ++                break;
 ++
 ++            case CM_DRP_SERVICE:
 ++                ulType = REG_SZ;
 ++                break;
 ++
 ++            case CM_DRP_CLASS:
 ++                ulType = REG_SZ;
 ++                break;
 ++
 ++            case CM_DRP_CLASSGUID:
 ++                ulType = REG_SZ;
 ++                break;
 ++
 ++   &nb