Sync trunk up to r50477.
svn path=/branches/cmake-bringup/; revision=50504
--- /dev/null
--- /dev/null
++
+++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)
--- /dev/null
--- /dev/null
- 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 */
--- /dev/null
--- /dev/null
++/* $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"
--- /dev/null
- 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.
--- /dev/null
- 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 = Відкритий офісний пакет.
--- /dev/null
--- /dev/null
--- /dev/null
- 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
--- /dev/null
--- /dev/null
++
++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)
--- /dev/null
- 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;
+ }
--- /dev/null
--- /dev/null
- #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;
++ }
++}
++
++
--- /dev/null
--- /dev/null
++
++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)
--- /dev/null
--- /dev/null
- @ 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)
--- /dev/null
-
+ /*
+ * 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 */
--- /dev/null
--- /dev/null
- 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