[devmgr]
[reactos.git] / reactos / base / services / umpnpmgr / umpnpmgr.c
index 73aec74..e224ee7 100644 (file)
@@ -12,9 +12,9 @@
  *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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.
  */
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PURPOSE:          User-mode Plug and Play manager
  * PROGRAMMER:       Eric Kohl
  *                   HervĂ© Poussineau (hpoussin@reactos.org)
+ *                   Colin Finck (colin@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
 #define WIN32_NO_STATUS
 #include <windows.h>
+#include <stdio.h>
 #include <cmtypes.h>
 #include <cmfuncs.h>
 #include <rtlfuncs.h>
+#include <setypes.h>
 #include <umpnpmgr/sysguid.h>
 #include <wdmguid.h>
 #include <cfgmgr32.h>
+#include <regstr.h>
+#include <userenv.h>
 
 #include <rpc.h>
 #include <rpcdce.h>
 
-#include "pnp_c.h"
+#include "pnp_s.h"
 
 #define NDEBUG
 #include <debug.h>
@@ -130,7 +135,7 @@ RpcServerThread(LPVOID lpParameter)
 }
 
 
-void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
 {
     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
 }
@@ -158,37 +163,57 @@ NtStatusToCrError(NTSTATUS Status)
 }
 
 
+/* Function 0 */
+DWORD PNP_Disconnect(
+    handle_t hBinding)
+{
+    UNREFERENCED_PARAMETER(hBinding);
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 1 */
+DWORD PNP_Connect(
+    handle_t hBinding)
+{
+    UNREFERENCED_PARAMETER(hBinding);
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /* Function 2 */
-CONFIGRET
-PNP_GetVersion(handle_t BindingHandle,
-               unsigned short *Version)
+DWORD PNP_GetVersion(
+    handle_t hBinding,
+    WORD *pVersion)
 {
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
-    *Version = 0x0400;
+    *pVersion = 0x0400;
     return CR_SUCCESS;
 }
 
 
 /* Function 3 */
-CONFIGRET
-PNP_GetGlobalState(handle_t BindingHandle,
-                   unsigned long *State,
-                   unsigned long Flags)
+DWORD PNP_GetGlobalState(
+    handle_t hBinding,
+    DWORD *pulState,
+    DWORD ulFlags)
 {
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
-    *State = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
+    *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
     return CR_SUCCESS;
 }
 
 
 /* Function 4 */
-CONFIGRET
-PNP_InitDetection(handle_t BindingHandle)
+DWORD PNP_InitDetection(
+    handle_t hBinding)
 {
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
     DPRINT("PNP_InitDetection() called\n");
     return CR_SUCCESS;
@@ -196,62 +221,71 @@ PNP_InitDetection(handle_t BindingHandle)
 
 
 /* Function 5 */
-CONFIGRET
-PNP_ReportLogOn(handle_t BindingHandle,
-                BOOL Admin,
-                DWORD ProcessId)
+DWORD PNP_ReportLogOn(
+    handle_t hBinding,
+    BOOL Admin,
+    DWORD ProcessId)
 {
+    DWORD ReturnValue = CR_FAILURE;
     HANDLE hProcess;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(Admin);
 
     DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
 
-    if (hInstallEvent != NULL)
-        SetEvent(hInstallEvent);
-
     /* Get the users token */
-    hProcess = OpenProcess(PROCESS_ALL_ACCESS,
-                           TRUE,
-                           ProcessId);
-    if (hProcess != NULL)
+    hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
+
+    if(!hProcess)
     {
-        if (hUserToken != NULL)
-        {
-            CloseHandle(hUserToken);
-            hUserToken = NULL;
-        }
+        DPRINT1("OpenProcess failed with error %u\n", GetLastError());
+        goto cleanup;
+    }
 
-        OpenProcessToken(hProcess,
-                         TOKEN_ALL_ACCESS,
-                         &hUserToken);
-        CloseHandle(hProcess);
+    if (hUserToken)
+    {
+        CloseHandle(hUserToken);
+        hUserToken = NULL;
+    }
+
+    if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
+    {
+        DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
+        goto cleanup;
     }
 
     /* Trigger the installer thread */
-    /*if (hInstallEvent != NULL)
-        SetEvent(hInstallEvent);*/
+    if (hInstallEvent)
+        SetEvent(hInstallEvent);
 
-    return CR_SUCCESS;
+    ReturnValue = CR_SUCCESS;
+
+cleanup:
+    if(hProcess)
+        CloseHandle(hProcess);
+
+    return ReturnValue;
 }
 
 
 /* Function 6 */
-CONFIGRET
-PNP_ValidateDeviceInstance(handle_t BindingHandle,
-                           wchar_t *DeviceInstance,
-                           DWORD Flags)
+DWORD PNP_ValidateDeviceInstance(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulFlags)
 {
     CONFIGRET ret = CR_SUCCESS;
     HKEY hDeviceKey = NULL;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
-           DeviceInstance, Flags);
+           pDeviceID, ulFlags);
 
     if (RegOpenKeyExW(hEnumKey,
-                      DeviceInstance,
+                      pDeviceID,
                       0,
                       KEY_READ,
                       &hDeviceKey))
@@ -274,24 +308,29 @@ Done:
 
 
 /* Function 7 */
-CONFIGRET
-PNP_GetRootDeviceInstance(handle_t BindingHandle,
-                          wchar_t *DeviceInstance,
-                          DWORD Length)
+DWORD PNP_GetRootDeviceInstance(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    PNP_RPC_STRING_LEN ulLength)
 {
     CONFIGRET ret = CR_SUCCESS;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
     DPRINT("PNP_GetRootDeviceInstance() called\n");
 
-    if (Length < lstrlenW(szRootDeviceId) + 1)
+    if (!pDeviceID)
+    {
+        ret = CR_INVALID_POINTER;
+        goto Done;
+    }
+    if (ulLength < lstrlenW(szRootDeviceId) + 1)
     {
         ret = CR_BUFFER_SMALL;
         goto Done;
     }
 
-    lstrcpyW(DeviceInstance,
+    lstrcpyW(pDeviceID,
              szRootDeviceId);
 
 Done:
@@ -302,32 +341,32 @@ Done:
 
 
 /* Function 8 */
-CONFIGRET
-PNP_GetRelatedDeviceInstance(handle_t BindingHandle,
-                             DWORD Relationship,
-                             wchar_t *DeviceId,
-                             wchar_t *RelatedDeviceId,
-                             DWORD Length,
-                             DWORD Flags)
+DWORD PNP_GetRelatedDeviceInstance(
+    handle_t hBinding,
+    DWORD ulRelationship,
+    LPWSTR pDeviceID,
+    LPWSTR pRelatedDeviceId,
+    PNP_RPC_STRING_LEN *pulLength,
+    DWORD ulFlags)
 {
     PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetRelatedDeviceInstance() called\n");
-    DPRINT("  Relationship %ld\n", Relationship);
-    DPRINT("  DeviceId %S\n", DeviceId);
+    DPRINT("  Relationship %ld\n", ulRelationship);
+    DPRINT("  DeviceId %S\n", pDeviceID);
 
     RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
-                         DeviceId);
+                         pDeviceID);
 
-    PlugPlayData.Relation = Relationship;
+    PlugPlayData.Relation = ulRelationship;
 
-    PlugPlayData.RelatedDeviceInstanceLength = Length;
-    PlugPlayData.RelatedDeviceInstance = RelatedDeviceId;
+    PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
+    PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
 
     Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
                                (PVOID)&PlugPlayData,
@@ -348,31 +387,31 @@ PNP_GetRelatedDeviceInstance(handle_t BindingHandle,
 
 
 /* Function 9 */
-CONFIGRET
-PNP_EnumerateSubKeys(handle_t BindingHandle,
-                     DWORD Branch,
-                     DWORD Index,
-                     wchar_t *Buffer,
-                     DWORD Length,
-                     DWORD *RequiredLength,
-                     DWORD Flags)
+DWORD PNP_EnumerateSubKeys(
+    handle_t hBinding,
+    DWORD ulBranch,
+    DWORD ulIndex,
+    LPWSTR Buffer,
+    PNP_RPC_STRING_LEN ulLength,
+    PNP_RPC_STRING_LEN *pulRequiredLen,
+    DWORD ulFlags)
 {
     CONFIGRET ret = CR_SUCCESS;
     HKEY hKey;
     DWORD dwError;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_EnumerateSubKeys() called\n");
 
-    switch (Branch)
+    switch (ulBranch)
     {
-        case PNP_BRANCH_ENUM:
+        case PNP_ENUMERATOR_SUBKEYS:
             hKey = hEnumKey;
             break;
 
-        case PNP_BRANCH_CLASS:
+        case PNP_CLASS_SUBKEYS:
             hKey = hClassKey;
             break;
 
@@ -380,11 +419,11 @@ PNP_EnumerateSubKeys(handle_t BindingHandle,
             return CR_FAILURE;
     }
 
-    *RequiredLength = Length;
+    *pulRequiredLen = ulLength;
     dwError = RegEnumKeyExW(hKey,
-                            Index,
+                            ulIndex,
                             Buffer,
-                            RequiredLength,
+                            pulRequiredLen,
                             NULL,
                             NULL,
                             NULL,
@@ -395,7 +434,7 @@ PNP_EnumerateSubKeys(handle_t BindingHandle,
     }
     else
     {
-        (*RequiredLength)++;
+        (*pulRequiredLen)++;
     }
 
     DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
@@ -404,51 +443,56 @@ PNP_EnumerateSubKeys(handle_t BindingHandle,
 }
 
 
-/* Function 11 */
-CONFIGRET
-PNP_GetDeviceListSize(handle_t BindingHandle,
-                      wchar_t *Filter,
-                      unsigned long *Length,
-                      DWORD Flags)
+/* Function 10 */
+DWORD PNP_GetDeviceList(
+    handle_t hBinding,
+    LPWSTR pszFilter,
+    LPWSTR Buffer,
+    PNP_RPC_STRING_LEN *pulLength,
+    DWORD ulFlags)
 {
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Filter);
-    UNREFERENCED_PARAMETER(Flags);
-
-    DPRINT("PNP_GetDeviceListSize() called\n");
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    /* FIXME */
-    *Length = 2;
 
-    return CR_SUCCESS;
+/* Function 11 */
+DWORD PNP_GetDeviceListSize(
+    handle_t hBinding,
+    LPWSTR pszFilter,
+    PNP_RPC_BUFFER_SIZE *pulLen,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 12 */
-CONFIGRET
-PNP_GetDepth(handle_t BindingHandle,
-             wchar_t *DeviceInstance,
-             unsigned long *Depth,
-             DWORD Flags)
+DWORD PNP_GetDepth(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    DWORD *pulDepth,
+    DWORD ulFlags)
 {
     PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetDepth() called\n");
 
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
-                         DeviceInstance);
+                         pszDeviceID);
 
     Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
                                (PVOID)&PlugPlayData,
                                sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
     if (NT_SUCCESS(Status))
     {
-        *Depth = PlugPlayData.Depth;
+        *pulDepth = PlugPlayData.Depth;
     }
     else
     {
@@ -462,15 +506,15 @@ PNP_GetDepth(handle_t BindingHandle,
 
 
 /* Function 13 */
-CONFIGRET
-PNP_GetDeviceRegProp(handle_t BindingHandle,
-                     wchar_t *DeviceInstance,
-                     DWORD Property,
-                     DWORD *DataType,
-                     char *Buffer,
-                     DWORD *TransferLen,
-                     DWORD *Length,
-                     DWORD Flags)
+DWORD PNP_GetDeviceRegProp(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulProperty,
+    DWORD *pulRegDataType,
+    BYTE *Buffer,
+    PNP_PROP_SIZE *pulTransferLen,
+    PNP_PROP_SIZE *pulLength,
+    DWORD ulFlags)
 {
     PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
     CONFIGRET ret = CR_SUCCESS;
@@ -478,12 +522,12 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
     HKEY hKey = 0;
     NTSTATUS Status;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetDeviceRegProp() called\n");
 
-    switch (Property)
+    switch (ulProperty)
     {
         case CM_DRP_DEVICEDESC:
             lpValueName = L"DeviceDesc";
@@ -575,7 +619,7 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
     {
         /* Retrieve information from the Registry */
         if (RegOpenKeyExW(hEnumKey,
-                          DeviceInstance,
+                          pDeviceID,
                           0,
                           KEY_ALL_ACCESS,
                           &hKey))
@@ -584,9 +628,9 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
         if (RegQueryValueExW(hKey,
                              lpValueName,
                              NULL,
-                             DataType,
-                             (LPBYTE)Buffer,
-                             Length))
+                             pulRegDataType,
+                             Buffer,
+                             pulLength))
             ret = CR_REGISTRY_ERROR;
 
         /* FIXME: Check buffer size */
@@ -597,11 +641,11 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
     {
         /* Retrieve information from the Device Node */
         RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
-                             DeviceInstance);
+                             pDeviceID);
         PlugPlayData.Buffer = Buffer;
-        PlugPlayData.BufferSize = *TransferLen;
+        PlugPlayData.BufferSize = *pulTransferLen;
 
-        switch (Property)
+        switch (ulProperty)
         {
 #if 0
             case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
@@ -623,11 +667,11 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
             case CM_DRP_BUSNUMBER:
                 PlugPlayData.Property = DevicePropertyBusNumber;
                 break;
+#endif
 
             case CM_DRP_ENUMERATOR_NAME:
-                PlugPlayData.Property = DevicePropertyEnumeratorName;
+                PlugPlayData.Property = 15; //DevicePropertyEnumeratorName;
                 break;
-#endif
 
             default:
                 return CR_INVALID_PROPERTY;
@@ -638,7 +682,7 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
                                    sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
         if (NT_SUCCESS(Status))
         {
-            *Length = PlugPlayData.BufferSize;
+            *pulLength = PlugPlayData.BufferSize;
         }
         else
         {
@@ -653,30 +697,30 @@ PNP_GetDeviceRegProp(handle_t BindingHandle,
 
 
 /* Function 14 */
-CONFIGRET
-PNP_SetDeviceRegProp(handle_t BindingHandle,
-                     wchar_t *DeviceId,
-                     unsigned long Property,
-                     unsigned long DataType,
-                     char *Buffer,
-                     unsigned long Length,
-                     unsigned long Flags)
+DWORD PNP_SetDeviceRegProp(
+    handle_t hBinding,
+    LPWSTR pDeviceId,
+    DWORD ulProperty,
+    DWORD ulDataType,
+    BYTE *Buffer,
+    PNP_PROP_SIZE ulLength,
+    DWORD ulFlags)
 {
     CONFIGRET ret = CR_SUCCESS;
     LPWSTR lpValueName = NULL;
     HKEY hKey = 0;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_SetDeviceRegProp() called\n");
 
-    DPRINT("DeviceId: %S\n", DeviceId);
-    DPRINT("Property: %lu\n", Property);
-    DPRINT("DataType: %lu\n", DataType);
-    DPRINT("Length: %lu\n", Length);
+    DPRINT("DeviceId: %S\n", pDeviceId);
+    DPRINT("Property: %lu\n", ulProperty);
+    DPRINT("DataType: %lu\n", ulDataType);
+    DPRINT("Length: %lu\n", ulLength);
 
-    switch (Property)
+    switch (ulProperty)
     {
         case CM_DRP_DEVICEDESC:
             lpValueName = L"DeviceDesc";
@@ -737,13 +781,13 @@ PNP_SetDeviceRegProp(handle_t BindingHandle,
     DPRINT("Value name: %S\n", lpValueName);
 
     if (RegOpenKeyExW(hEnumKey,
-                      DeviceId,
+                      pDeviceId,
                       0,
-                      KEY_ALL_ACCESS,
+                      KEY_ALL_ACCESS, /* FIXME: so much? */
                       &hKey))
         return CR_INVALID_DEVNODE;
 
-    if (Length == 0)
+    if (ulLength == 0)
     {
         if (RegDeleteValueW(hKey,
                             lpValueName))
@@ -754,9 +798,9 @@ PNP_SetDeviceRegProp(handle_t BindingHandle,
         if (RegSetValueExW(hKey,
                            lpValueName,
                            0,
-                           DataType,
-                           (const BYTE*)Buffer,
-                           Length))
+                           ulDataType,
+                           Buffer,
+                           ulLength))
             ret = CR_REGISTRY_ERROR;
     }
 
@@ -769,87 +813,56 @@ PNP_SetDeviceRegProp(handle_t BindingHandle,
 
 
 /* Function 15 */
-CONFIGRET
-PNP_GetClassInstance(handle_t BindingHandle,
-                     wchar_t *DeviceId, /* in */
-                     wchar_t *Buffer, /* out */
-                     unsigned long Length)
+DWORD PNP_GetClassInstance(
+    handle_t hBinding,
+    LPWSTR pDeviceId,
+    LPWSTR pszClassInstance,
+    PNP_RPC_STRING_LEN ulLength)
 {
-    CONFIGRET ret = CR_SUCCESS;
-
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceId);
-    UNREFERENCED_PARAMETER(Buffer);
-    UNREFERENCED_PARAMETER(Length);
-
-    DPRINT("PNP_Get_Class_Instance() called\n");
-
-    DPRINT("PNP_Get_Class_Instance() done (returns %lx)\n", ret);
-
-    return ret;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 16 */
-CONFIGRET
-PNP_CreateKey(handle_t BindingHandle,
-              wchar_t *SubKey,
-              unsigned long samDesired,
-              unsigned long Flags)
+DWORD PNP_CreateKey(
+    handle_t hBinding,
+    LPWSTR pszSubKey,
+    DWORD samDesired,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
-
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(SubKey);
-    UNREFERENCED_PARAMETER(samDesired);
-    UNREFERENCED_PARAMETER(Flags);
-
-    DPRINT("PNP_CreateKey() called\n");
-
-    DPRINT("PNP_CreateKey() done (returns %lx)\n", ret);
-
-    return ret;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 17 */
-CONFIGRET
-PNP_DeleteRegistryKey(handle_t BindingHandle,
-                      wchar_t *DeviceId,
-                      wchar_t *ParentKey,
-                      wchar_t *ChildKey,
-                      unsigned long Flags)
+DWORD PNP_DeleteRegistryKey(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    LPWSTR pszParentKey,
+    LPWSTR pszChildKey,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
-
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceId);
-    UNREFERENCED_PARAMETER(ParentKey);
-    UNREFERENCED_PARAMETER(ChildKey);
-    UNREFERENCED_PARAMETER(Flags);
-
-    DPRINT("PNP_DeleteRegistryKey() called\n");
-
-    DPRINT("PNP_DeleteRegistryKey() done (returns %lx)\n", ret);
-
-    return ret;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 18 */
-#if 0
-CONFIGRET
-PNP_GetClassCount(handle_t BindingHandle,
-                  unsigned long *ClassCount,
-                  unsigned long Flags)
+DWORD PNP_GetClassCount(
+    handle_t hBinding,
+    DWORD *pulClassCount,
+    DWORD ulFlags)
 {
-    HANDLE hKey = NULL;
+    HKEY hKey;
     DWORD dwError;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                            pszRegPathClass,
+                            REGSTR_PATH_CLASS,
                             0,
                             KEY_QUERY_VALUE,
                             &hKey);
@@ -860,7 +873,7 @@ PNP_GetClassCount(handle_t BindingHandle,
                                NULL,
                                NULL,
                                NULL,
-                               &ClassCount,
+                               pulClassCount,
                                NULL,
                                NULL,
                                NULL,
@@ -874,31 +887,29 @@ PNP_GetClassCount(handle_t BindingHandle,
 
     return CR_SUCCESS;
 }
-#endif
 
 
 /* Function 19 */
-CONFIGRET
-PNP_GetClassName(handle_t BindingHandle,
-                 wchar_t *ClassGuid,
-                 wchar_t *Buffer,
-                 unsigned long *Length,
-                 unsigned long Flags)
+DWORD PNP_GetClassName(
+    handle_t hBinding,
+    LPWSTR pszClassGuid,
+    LPWSTR Buffer,
+    PNP_RPC_STRING_LEN *pulLength,
+    DWORD ulFlags)
 {
     WCHAR szKeyName[MAX_PATH];
     CONFIGRET ret = CR_SUCCESS;
-    HKEY hKey = NULL;
+    HKEY hKey;
     DWORD dwSize;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetClassName() called\n");
 
-    lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class");
-    lstrcatW(szKeyName, L"\\");
-    if(lstrlenW(ClassGuid) < sizeof(szKeyName)/sizeof(WCHAR)-lstrlenW(szKeyName))
-        lstrcatW(szKeyName, ClassGuid);
+    lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
+    if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
+        lstrcatW(szKeyName, pszClassGuid);
     else return CR_INVALID_DATA;
 
     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
@@ -908,7 +919,7 @@ PNP_GetClassName(handle_t BindingHandle,
                       &hKey))
         return CR_REGISTRY_ERROR;
 
-    dwSize = *Length * sizeof(WCHAR);
+    dwSize = *pulLength * sizeof(WCHAR);
     if (RegQueryValueExW(hKey,
                          L"Class",
                          NULL,
@@ -916,12 +927,12 @@ PNP_GetClassName(handle_t BindingHandle,
                          (LPBYTE)Buffer,
                          &dwSize))
     {
-        *Length = 0;
+        *pulLength = 0;
         ret = CR_REGISTRY_ERROR;
     }
     else
     {
-        *Length = dwSize / sizeof(WCHAR);
+        *pulLength = dwSize / sizeof(WCHAR);
     }
 
     RegCloseKey(hKey);
@@ -933,25 +944,25 @@ PNP_GetClassName(handle_t BindingHandle,
 
 
 /* Function 20 */
-CONFIGRET
-PNP_DeleteClassKey(handle_t BindingHandle,
-                   wchar_t *ClassGuid,
-                   unsigned long Flags)
+DWORD PNP_DeleteClassKey(
+    handle_t hBinding,
+    LPWSTR pszClassGuid,
+    DWORD ulFlags)
 {
     CONFIGRET ret = CR_SUCCESS;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetClassName(%S, %lx) called\n", ClassGuid, Flags);
+    DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
 
-    if (Flags & CM_DELETE_CLASS_SUBKEYS)
+    if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
     {
-        if (RegDeleteTreeW(hClassKey, ClassGuid) != ERROR_SUCCESS)
+        if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
             ret = CR_REGISTRY_ERROR;
     }
     else
     {
-        if (RegDeleteKeyW(hClassKey, ClassGuid) != ERROR_SUCCESS)
+        if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
             ret = CR_REGISTRY_ERROR;
     }
 
@@ -961,81 +972,163 @@ PNP_DeleteClassKey(handle_t BindingHandle,
 }
 
 
-/* Function 28 */
-CONFIGRET
-PNP_CreateDevInst(handle_t BindingHandle,
-                  wchar_t *DeviceId,       /* [in, out, string, size_is(Length)] */
-                  wchar_t *ParentDeviceId, /* [in, string] */
-                  unsigned long Length,    /* [in] */
-                  unsigned long Flags)     /* [in] */
+/* Function 21 */
+DWORD PNP_GetInterfaceDeviceAlias(
+    handle_t hBinding,
+    LPWSTR pszInterfaceDevice,
+    GUID *AliasInterfaceGuid,
+    LPWSTR pszAliasInterfaceDevice,
+    PNP_RPC_STRING_LEN *pulLength,
+    PNP_RPC_STRING_LEN *pulTransferLen,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceId);
-    UNREFERENCED_PARAMETER(ParentDeviceId);
-    UNREFERENCED_PARAMETER(Length);
-    UNREFERENCED_PARAMETER(Flags);
 
-    DPRINT1("PNP_CreateDevInst() called\n");
+/* Function 22 */
+DWORD PNP_GetInterfaceDeviceList(
+    handle_t hBinding,
+    GUID *InterfaceGuid,
+    LPWSTR pszDeviceID,
+    BYTE *Buffer,
+    PNP_RPC_BUFFER_SIZE *pulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    DPRINT1("PNP_CreateDevInst() done (returns %lx)\n", ret);
 
-    return ret;
+/* Function 23 */
+DWORD PNP_GetInterfaceDeviceListSize(
+    handle_t hBinding,
+    PNP_RPC_BUFFER_SIZE *pulLen,
+    GUID *InterfaceGuid,
+    LPWSTR pszDeviceID,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 24 */
+DWORD PNP_RegisterDeviceClassAssociation(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    GUID *InterfaceGuid,
+    LPWSTR pszReference,
+    LPWSTR pszSymLink,
+    PNP_RPC_STRING_LEN *pulLength,
+    PNP_RPC_STRING_LEN *pulTransferLen,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 25 */
+DWORD PNP_UnregisterDeviceClassAssociation(
+    handle_t hBinding,
+    LPWSTR pszInterfaceDevice,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 26 */
+DWORD PNP_GetClassRegProp(
+    handle_t hBinding,
+    LPWSTR pszClassGuid,
+    DWORD ulProperty,
+    DWORD *pulRegDataType,
+    BYTE *Buffer,
+    PNP_RPC_STRING_LEN *pulTransferLen,
+    PNP_RPC_STRING_LEN *pulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 27 */
+DWORD PNP_SetClassRegProp(
+    handle_t hBinding,
+    LPWSTR *pszClassGuid,
+    DWORD ulProperty,
+    DWORD ulDataType,
+    BYTE *Buffer,
+    PNP_PROP_SIZE ulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 28 */
+DWORD PNP_CreateDevInst(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    LPWSTR pszParentDeviceID,
+    PNP_RPC_STRING_LEN ulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 29 */
-CONFIGRET
-PNP_DeviceInstanceAction(handle_t BindingHandle,
-                         unsigned long MajorAction,
-                         unsigned long MinorAction,
-                         wchar_t *DeviceInstance1,
-                         wchar_t *DeviceInstance2)
+DWORD PNP_DeviceInstanceAction(
+    handle_t hBinding,
+    DWORD ulMajorAction,
+    DWORD ulMinorAction,
+    LPWSTR pszDeviceInstance1,
+    LPWSTR pszDeviceInstance2)
 {
     CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(MinorAction);
-    UNREFERENCED_PARAMETER(DeviceInstance1);
-    UNREFERENCED_PARAMETER(DeviceInstance2);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulMinorAction);
+    UNREFERENCED_PARAMETER(pszDeviceInstance2);
 
     DPRINT("PNP_DeviceInstanceAction() called\n");
 
-    switch (MajorAction)
+    switch (ulMajorAction)
     {
-        case 2:
-            DPRINT("Move device instance\n");
-            /* FIXME */
-            ret = CR_CALL_NOT_IMPLEMENTED;
-            break;
-
-        case 3:
+        case PNP_DEVINST_SETUP:
             DPRINT("Setup device instance\n");
             /* FIXME */
             ret = CR_CALL_NOT_IMPLEMENTED;
             break;
 
-        case 4:
+        case PNP_DEVINST_ENABLE:
+        {
+            PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
             DPRINT("Enable device instance\n");
-            /* FIXME */
-            ret = CR_CALL_NOT_IMPLEMENTED;
-            break;
-
-        case 5:
-            DPRINT("Disable device instance\n");
-            /* FIXME */
-            ret = CR_CALL_NOT_IMPLEMENTED;
+            RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance1);
+            Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+            if (!NT_SUCCESS(Status))
+                ret = NtStatusToCrError(Status);
             break;
+        }
 
-        case 7:
+        case PNP_DEVINST_REENUMERATE:
             DPRINT("Reenumerate device instance\n");
             /* FIXME */
             ret = CR_CALL_NOT_IMPLEMENTED;
             break;
 
         default:
-            DPRINT1("Unknown function %lu\n", MajorAction);
+            DPRINT1("Unknown function %lu\n", ulMajorAction);
             ret = CR_CALL_NOT_IMPLEMENTED;
     }
 
@@ -1046,24 +1139,24 @@ PNP_DeviceInstanceAction(handle_t BindingHandle,
 
 
 /* Function 30 */
-CONFIGRET
-PNP_GetDeviceStatus(handle_t BindingHandle,
-                    wchar_t *DeviceInstance,
-                    unsigned long *pStatus,
-                    unsigned long *pProblem,
-                    DWORD Flags)
+DWORD PNP_GetDeviceStatus(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD *pulStatus,
+    DWORD *pulProblem,
+    DWORD ulFlags)
 {
     PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetDeviceStatus() called\n");
 
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
-                         DeviceInstance);
+                         pDeviceID);
     PlugPlayData.Operation = 0; /* Get status */
 
     Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
@@ -1071,8 +1164,8 @@ PNP_GetDeviceStatus(handle_t BindingHandle,
                                sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
     if (NT_SUCCESS(Status))
     {
-        *pStatus = PlugPlayData.DeviceStatus;
-        *pProblem = PlugPlayData.DeviceProblem;
+        *pulStatus = PlugPlayData.DeviceStatus;
+        *pulProblem = PlugPlayData.DeviceProblem;
     }
     else
     {
@@ -1086,48 +1179,38 @@ PNP_GetDeviceStatus(handle_t BindingHandle,
 
 
 /* Function 31 */
-CONFIGRET
-PNP_SetDeviceProblem(handle_t BindingHandle,
-                     wchar_t *DeviceInstance,
-                     unsigned long Problem,
-                     DWORD Flags)
+DWORD PNP_SetDeviceProblem(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulProblem,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
-
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(Problem);
-    UNREFERENCED_PARAMETER(Flags);
-
-    DPRINT1("PNP_SetDeviceProblem() called\n");
-
-    /* FIXME */
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
 
-    return ret;
+/* Function 32 */
+DWORD PNP_DisableDevInst(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    PPNP_VETO_TYPE pVetoType,
+    LPWSTR pszVetoName,
+    DWORD ulNameLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
-
 /* Function 33 */
-CONFIGRET
-PNP_UninstallDevInst(handle_t BindingHandle,
-                     wchar_t *DeviceInstance,
-                     DWORD Flags)
+DWORD PNP_UninstallDevInst(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
-
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(Flags);
-
-    DPRINT1("PNP_UninstallDevInst() called\n");
-
-    /* FIXME */
-
-    DPRINT1("PNP_UninstallDevInst() done (returns %lx)\n", ret);
-
-    return ret;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
@@ -1174,27 +1257,28 @@ AppendDeviceId(LPWSTR lpDeviceIdList,
 
 
 /* Function 34 */
-CONFIGRET
-PNP_AddID(handle_t BindingHandle,
-          wchar_t *DeviceInstance,
-          wchar_t *DeviceId,
-          DWORD Flags)
+DWORD PNP_AddID(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    LPWSTR pszID,
+    DWORD ulFlags)
 {
     CONFIGRET ret = CR_SUCCESS;
     HKEY hDeviceKey;
     LPWSTR pszSubKey;
     DWORD dwDeviceIdListSize;
-    WCHAR szDeviceIdList[512];
+    DWORD dwNewDeviceIdSize;
+    WCHAR * pszDeviceIdList = NULL;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
     DPRINT("PNP_AddID() called\n");
-    DPRINT("  DeviceInstance: %S\n", DeviceInstance);
-    DPRINT("  DeviceId: %S\n", DeviceId);
-    DPRINT("  Flags: %lx\n", Flags);
+    DPRINT("  DeviceInstance: %S\n", pszDeviceID);
+    DPRINT("  DeviceId: %S\n", pszID);
+    DPRINT("  Flags: %lx\n", ulFlags);
 
     if (RegOpenKeyExW(hEnumKey,
-                      DeviceInstance,
+                      pszDeviceID,
                       0,
                       KEY_QUERY_VALUE | KEY_SET_VALUE,
                       &hDeviceKey) != ERROR_SUCCESS)
@@ -1203,14 +1287,42 @@ PNP_AddID(handle_t BindingHandle,
         return CR_INVALID_DEVNODE;
     }
 
-    pszSubKey = (Flags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
+    pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
+
+    if (RegQueryValueExW(hDeviceKey,
+                         pszSubKey,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &dwDeviceIdListSize) != ERROR_SUCCESS)
+    {
+        DPRINT("Failed to query the desired ID string!\n");
+        ret = CR_REGISTRY_ERROR;
+        goto Done;
+    }
+
+    dwNewDeviceIdSize = lstrlenW(pszDeviceID);
+    if (!dwNewDeviceIdSize)
+    {
+        ret = CR_INVALID_POINTER;
+        goto Done;
+    }
+
+    dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
+
+    pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
+    if (!pszDeviceIdList)
+    {
+        DPRINT("Failed to allocate memory for the desired ID string!\n");
+        ret = CR_OUT_OF_MEMORY;
+        goto Done;
+    }
 
-    dwDeviceIdListSize = 512 * sizeof(WCHAR);
     if (RegQueryValueExW(hDeviceKey,
                          pszSubKey,
                          NULL,
                          NULL,
-                         (LPBYTE)szDeviceIdList,
+                         (LPBYTE)pszDeviceIdList,
                          &dwDeviceIdListSize) != ERROR_SUCCESS)
     {
         DPRINT("Failed to query the desired ID string!\n");
@@ -1219,7 +1331,7 @@ PNP_AddID(handle_t BindingHandle,
     }
 
     /* Check whether the device ID is already in use */
-    if (CheckForDeviceId(szDeviceIdList, DeviceId))
+    if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
     {
         DPRINT("Device ID was found in the ID string!\n");
         ret = CR_SUCCESS;
@@ -1227,13 +1339,13 @@ PNP_AddID(handle_t BindingHandle,
     }
 
     /* Append the Device ID */
-    AppendDeviceId(szDeviceIdList, &dwDeviceIdListSize, DeviceId);
+    AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
 
     if (RegSetValueExW(hDeviceKey,
                        pszSubKey,
                        0,
                        REG_MULTI_SZ,
-                       (LPBYTE)szDeviceIdList,
+                       (LPBYTE)pszDeviceIdList,
                        dwDeviceIdListSize) != ERROR_SUCCESS)
     {
         DPRINT("Failed to set the desired ID string!\n");
@@ -1242,6 +1354,8 @@ PNP_AddID(handle_t BindingHandle,
 
 Done:
     RegCloseKey(hDeviceKey);
+    if (pszDeviceIdList)
+        HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
 
     DPRINT("PNP_AddID() done (returns %lx)\n", ret);
 
@@ -1249,10 +1363,48 @@ Done:
 }
 
 
+/* Function 35 */
+DWORD PNP_RegisterDriver(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 36 */
+DWORD PNP_QueryRemove(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    PPNP_VETO_TYPE pVetoType,
+    LPWSTR pszVetoName,
+    DWORD ulNameLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 37 */
+DWORD PNP_RequestDeviceEject(
+    handle_t hBinding,
+    LPWSTR pszDeviceID,
+    PPNP_VETO_TYPE pVetoType,
+    LPWSTR pszVetoName,
+    DWORD ulNameLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 /* Function 38 */
 CONFIGRET
-PNP_IsDockStationPresent(handle_t BindingHandle,
-                         unsigned long *Present)
+PNP_IsDockStationPresent(handle_t hBinding,
+                         BOOL *Present)
 {
     HKEY hKey;
     DWORD dwType;
@@ -1260,7 +1412,7 @@ PNP_IsDockStationPresent(handle_t BindingHandle,
     DWORD dwSize;
     CONFIGRET ret = CR_SUCCESS;
 
-    UNREFERENCED_PARAMETER(BindingHandle);
+    UNREFERENCED_PARAMETER(hBinding);
 
     DPRINT1("PNP_IsDockStationPresent() called\n");
 
@@ -1303,206 +1455,488 @@ PNP_IsDockStationPresent(handle_t BindingHandle,
 
 
 /* Function 39 */
-CONFIGRET
-PNP_RequestEjectPC(handle_t BindingHandle)
+DWORD PNP_RequestEjectPC(
+    handle_t hBinding)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
 
-    DPRINT1("PNP_RequestEjectPC() called\n");
+/* Function 40 */
+DWORD PNP_HwProfFlags(
+    handle_t hBinding,
+    DWORD ulAction,
+    LPWSTR pDeviceID,
+    DWORD ulConfig,
+    DWORD *pulValue,
+    PPNP_VETO_TYPE pVetoType,
+    LPWSTR pszVetoName,
+    DWORD ulNameLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    ret = CR_FAILURE; /* FIXME */
 
-    DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
+/* Function 41 */
+DWORD PNP_GetHwProfInfo(
+    handle_t hBinding,
+    DWORD ulIndex,
+    HWPROFILEINFO *pHWProfileInfo,
+    DWORD ulProfileInfoSize,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
-    return ret;
+/* Function 42 */
+DWORD PNP_AddEmptyLogConf(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulPriority,
+    DWORD *pulLogConfTag,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 40 */
-CONFIGRET
-PNP_HwProfFlags(handle_t BindingHandle,
-                DWORD Action,
-                wchar_t *DeviceId,
-                DWORD ProfileId,
-                DWORD *Value, // out
-                DWORD Flags)
+/* Function 43 */
+DWORD PNP_FreeLogConf(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfType,
+    DWORD ulLogConfTag,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Action);
-    UNREFERENCED_PARAMETER(DeviceId);
-    UNREFERENCED_PARAMETER(ProfileId);
-    UNREFERENCED_PARAMETER(Value);
-    UNREFERENCED_PARAMETER(Flags);
 
-    DPRINT1("PNP_HwProfFlags() called\n");
+/* Function 44 */
+DWORD PNP_GetFirstLogConf(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfType,
+    DWORD *pulLogConfTag,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    ret = CR_CALL_NOT_IMPLEMENTED; /* FIXME */
 
-    DPRINT1("PNP_HwProfFlags() done (returns %lx)\n", ret);
+/* Function 45 */
+DWORD PNP_GetNextLogConf(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfType,
+    DWORD ulCurrentTag,
+    DWORD *pulNextTag,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    return ret;
+
+/* Function 46 */
+DWORD PNP_GetLogConfPriority(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulType,
+    DWORD ulTag,
+    DWORD *pPriority,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 42 */
-CONFIGRET
-PNP_AddEmptyLogConf(handle_t BindingHandle,
-                    wchar_t *DeviceInstance,
-                    unsigned long ulPriority,
-                    unsigned long *pulLogConfTag,
-                    unsigned long ulFlags)
+/* Function 47 */
+DWORD PNP_AddResDes(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID ResourceID,
+    DWORD *pulResourceTag,
+    BYTE *ResourceData,
+    PNP_RPC_BUFFER_SIZE ResourceLen,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(ulPriority);
-    UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT1("PNP_AddEmptyLogConf() called\n");
+/* Function 48 */
+DWORD PNP_FreeResDes(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID ResourceID,
+    DWORD ulResourceTag,
+    DWORD *pulPreviousResType,
+    DWORD *pulPreviousResTag,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
-    *pulLogConfTag = 0; /* FIXME */
+/* Function 49 */
+DWORD PNP_GetNextResDes(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID ResourceID,
+    DWORD ulResourceTag,
+    DWORD *pulNextResType,
+    DWORD *pulNextResTag,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    DPRINT1("PNP_AddEmptyLogConf() done (returns %lx)\n", ret);
 
-    return ret;
+/* Function 50 */
+DWORD PNP_GetResDesData(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID ResourceID,
+    DWORD ulResourceTag,
+    BYTE *Buffer,
+    PNP_RPC_BUFFER_SIZE BufferLen,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 43 */
-CONFIGRET
-PNP_FreeLogConf(handle_t BindingHandle,
-                wchar_t *DeviceInstance,
-                unsigned long ulType,
-                unsigned long ulLogConfTag,
-                unsigned long ulFlags)
+/* Function 51 */
+DWORD PNP_GetResDesDataSize(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID ResourceID,
+    DWORD ulResourceTag,
+    DWORD *pulSize,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(ulType);
-    UNREFERENCED_PARAMETER(ulLogConfTag);
-    UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT1("PNP_FreeLogConf() called\n");
+/* Function 52 */
+DWORD PNP_ModifyResDes(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    DWORD ulLogConfTag,
+    DWORD ulLogConfType,
+    RESOURCEID CurrentResourceID,
+    RESOURCEID NewResourceID,
+    DWORD ulResourceTag,
+    BYTE *ResourceData,
+    PNP_RPC_BUFFER_SIZE ResourceLen,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
 
-    DPRINT1("PNP_FreeLogConf() done (returns %lx)\n", ret);
+/* Function 53 */
+DWORD PNP_DetectResourceConflict(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    RESOURCEID ResourceID,
+    BYTE *ResourceData,
+    PNP_RPC_BUFFER_SIZE ResourceLen,
+    BOOL *pbConflictDetected,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    return ret;
+
+/* Function 54 */
+DWORD PNP_QueryResConfList(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    RESOURCEID ResourceID,
+    BYTE *ResourceData,
+    PNP_RPC_BUFFER_SIZE ResourceLen,
+    BYTE *Buffer,
+    PNP_RPC_BUFFER_SIZE BufferLen,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 44 */
+/* Function 55 */
+DWORD PNP_SetHwProf(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 56 */
+DWORD PNP_QueryArbitratorFreeData(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 57 */
+DWORD PNP_QueryArbitratorFreeSize(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 58 */
 CONFIGRET
-PNP_GetFirstLogConf(handle_t BindingHandle,
-                    wchar_t *DeviceInstance,
-                    unsigned long ulPriority,
-                    unsigned long *pulLogConfTag,
-                    unsigned long ulFlags)
+PNP_RunDetection(
+    handle_t hBinding,
+    DWORD ulFlags)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(ulPriority);
-    UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT1("PNP_GetFirstLogConf() called\n");
+/* Function 59 */
+DWORD PNP_RegisterNotification(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
-    *pulLogConfTag = 0; /* FIXME */
+/* Function 60 */
+DWORD PNP_UnregisterNotification(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    DPRINT1("PNP_GetFirstLogConf() done (returns %lx)\n", ret);
 
-    return ret;
+/* Function 61 */
+DWORD PNP_GetCustomDevProp(
+    handle_t hBinding,
+    LPWSTR pDeviceID,
+    LPWSTR CustomPropName,
+    DWORD *pulRegDataType,
+    BYTE *Buffer,
+    PNP_RPC_STRING_LEN *pulTransferLen,
+    PNP_RPC_STRING_LEN *pulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 45 */
-CONFIGRET
-PNP_GetNextLogConf(handle_t BindingHandle,
-                   wchar_t *DeviceInstance,
-                   unsigned long ulLogConfType,
-                   unsigned long ulCurrentTag,
-                   unsigned long *pulNextTag,
-                   unsigned long ulFlags)
+/* Function 62 */
+DWORD PNP_GetVersionInternal(
+    handle_t hBinding,
+    WORD *pwVersion)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(ulLogConfType);
-    UNREFERENCED_PARAMETER(ulCurrentTag);
-    UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT1("PNP_GetNextLogConf() called\n");
+/* Function 63 */
+DWORD PNP_GetBlockedDriverInfo(
+    handle_t hBinding,
+    BYTE *Buffer,
+    PNP_RPC_BUFFER_SIZE *pulTransferLen,
+    PNP_RPC_BUFFER_SIZE *pulLength,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
-    *pulNextTag = 0; /* FIXME */
+/* Function 64 */
+DWORD PNP_GetServerSideDeviceInstallFlags(
+    handle_t hBinding,
+    DWORD *pulSSDIFlags,
+    DWORD ulFlags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    DPRINT1("PNP_GetNextLogConf() done (returns %lx)\n", ret);
 
-    return ret;
+/* Function 65 */
+DWORD PNP_GetObjectPropKeys(
+    handle_t hBinding,
+    LPWSTR ObjectName,
+    DWORD ObjectType,
+    LPWSTR PropertyCultureName,
+    PNP_PROP_COUNT *PropertyCount,
+    PNP_PROP_COUNT *TransferLen,
+    DEVPROPKEY *PropertyKeys,
+    DWORD Flags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 46 */
-CONFIGRET
-PNP_GetLogConfPriority(handle_t BindingHandle,
-                       wchar_t *DeviceInstance,
-                       unsigned long ulLogConfType,
-                       unsigned long ulCurrentTag,
-                       unsigned long *pPriority,
-                       unsigned long ulFlags)
+/* Function 66 */
+DWORD PNP_GetObjectProp(
+    handle_t hBinding,
+    LPWSTR ObjectName,
+    DWORD ObjectType,
+    LPWSTR PropertyCultureName,
+    const DEVPROPKEY *PropertyKey,
+    DEVPROPTYPE *PropertyType,
+    PNP_PROP_SIZE *PropertySize,
+    PNP_PROP_SIZE *TransferLen,
+    BYTE *PropertyBuffer,
+    DWORD Flags)
 {
-    CONFIGRET ret = CR_SUCCESS;
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(DeviceInstance);
-    UNREFERENCED_PARAMETER(ulLogConfType);
-    UNREFERENCED_PARAMETER(ulCurrentTag);
-    UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT1("PNP_GetLogConfPriority() called\n");
+/* Function 67 */
+DWORD PNP_SetObjectProp(
+    handle_t hBinding,
+    LPWSTR ObjectName,
+    DWORD ObjectType,
+    LPWSTR PropertyCultureName,
+    const DEVPROPKEY *PropertyKey,
+    DEVPROPTYPE PropertyType,
+    PNP_PROP_SIZE PropertySize,
+    BYTE *PropertyBuffer,
+    DWORD Flags)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    *pPriority = 0; /* FIXME */
 
-    DPRINT1("PNP_GetLogConfPriority() done (returns %lx)\n", ret);
+/* Function 68 */
+DWORD PNP_InstallDevInst(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
 
-    return ret;
+
+/* Function 69 */
+DWORD PNP_ApplyPowerSettings(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-/* Function 58 */
-CONFIGRET
-PNP_RunDetection(handle_t BindingHandle,
-                 unsigned long Flags)
+/* Function 70 */
+DWORD PNP_DriverStoreAddDriverPackage(
+    handle_t hBinding)
 {
-    UNREFERENCED_PARAMETER(BindingHandle);
-    UNREFERENCED_PARAMETER(Flags);
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
-    DPRINT("PNP_RunDetection() called\n");
+/* Function 71 */
+DWORD PNP_DriverStoreDeleteDriverPackage(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
 }
 
 
-typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
+/* Function 72 */
+DWORD PNP_RegisterServiceNotification(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 73 */
+DWORD PNP_SetActiveService(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 74 */
+DWORD PNP_DeleteServiceDevices(
+    handle_t hBinding)
+{
+    UNIMPLEMENTED;
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
 
 static BOOL
 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
 {
     PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
-    HMODULE hNewDev = NULL;
-    PDEV_INSTALL_W DevInstallW;
     NTSTATUS Status;
     BOOL DeviceInstalled = FALSE;
+    DWORD BytesWritten;
+    DWORD Value;
+    HANDLE hPipe = INVALID_HANDLE_VALUE;
+    LPVOID Environment = NULL;
+    PROCESS_INFORMATION ProcessInfo;
+    STARTUPINFOW StartupInfo;
+    UUID RandomUuid;
+
+    /* The following lengths are constant (see below), they cannot overflow */
+    WCHAR CommandLine[116];
+    WCHAR InstallEventName[73];
+    WCHAR PipeName[74];
+    WCHAR UuidString[39];
 
     DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
 
+    ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
+
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
                          DeviceInstance);
     PlugPlayData.Operation = 0; /* Get status */
@@ -1524,34 +1958,109 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
         return TRUE;
     }
 
-    /* Install device */
-    SetEnvironmentVariableW(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
+    /* Create a random UUID for the named pipe */
+    UuidCreate(&RandomUuid);
+    swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+        RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
+        RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
+        RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
+        RandomUuid.Data4[6], RandomUuid.Data4[7]);
+
+    /* Create the named pipe */
+    wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
+    wcscat(PipeName, UuidString);
+    hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
 
-    hNewDev = LoadLibraryW(L"newdev.dll");
-    if (!hNewDev)
+    if(hPipe == INVALID_HANDLE_VALUE)
     {
-        DPRINT1("Unable to load newdev.dll\n");
+        DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
         goto cleanup;
     }
 
-    DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
-    if (!DevInstallW)
+    /* Launch rundll32 to call ClientSideInstallW */
+    wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
+    wcscat(CommandLine, PipeName);
+
+    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
+    StartupInfo.cb = sizeof(StartupInfo);
+
+    if(hUserToken)
     {
-        DPRINT1("'DevInstallW' not found in newdev.dll\n");
+        /* newdev has to run under the environment of the current user */
+        if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
+        {
+            DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
+            goto cleanup;
+        }
+
+        if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
+        {
+            DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
+            goto cleanup;
+        }
+    }
+    else
+    {
+        /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
+
+           Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
+           (ShowWizard is only set to FALSE for these two modes) */
+        ASSERT(!ShowWizard);
+
+        if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
+        {
+            DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
+            goto cleanup;
+        }
+    }
+
+    /* Wait for the function to connect to our pipe */
+    if(!ConnectNamedPipe(hPipe, NULL))
+    {
+        DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
         goto cleanup;
     }
 
-    if (!DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE))
+    /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
+    wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
+    wcscat(InstallEventName, UuidString);
+
+    Value = sizeof(InstallEventName);
+    WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
+    WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
+
+    /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
+       Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
+    WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
+
+    Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
+    WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
+    WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
+
+    /* Wait for newdev.dll to finish processing */
+    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
+
+    /* The following check for success is probably not compatible to Windows, but should do its job */
+    if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
     {
-        DPRINT1("DevInstallW('%S') failed\n", DeviceInstance);
+        DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
         goto cleanup;
     }
 
-    DeviceInstalled = TRUE;
+    DeviceInstalled = Value;
 
 cleanup:
-    if (hNewDev != NULL)
-        FreeLibrary(hNewDev);
+    if(hPipe != INVALID_HANDLE_VALUE)
+        CloseHandle(hPipe);
+
+    if(Environment)
+        DestroyEnvironmentBlock(Environment);
+
+    if(ProcessInfo.hProcess)
+        CloseHandle(ProcessInfo.hProcess);
+
+    if(ProcessInfo.hThread)
+        CloseHandle(ProcessInfo.hThread);
 
     return DeviceInstalled;
 }
@@ -1652,7 +2161,7 @@ IsConsoleBoot(VOID)
         NextOption = wcschr(CurrentOption, L' ');
         if (NextOption)
             *NextOption = L'\0';
-        if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
+        if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
         {
             DPRINT("Found %S. Switching to console boot\n", CurrentOption);
             ConsoleBoot = TRUE;
@@ -1740,7 +2249,8 @@ PnpEventThread(LPVOID lpParameter)
         if (Status == STATUS_BUFFER_TOO_SMALL)
         {
             PnpEventSize += 0x400;
-            PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
+            HeapFree(GetProcessHeap(), 0, PnpEvent);
+            PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
             if (PnpEvent == NULL)
                 return ERROR_OUTOFMEMORY;
             continue;
@@ -1754,31 +2264,39 @@ PnpEventThread(LPVOID lpParameter)
 
         /* Process the pnp event */
         DPRINT("Received PnP Event\n");
-        if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
+        if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
         {
             DeviceInstallParams* Params;
             DWORD len;
+            DWORD DeviceIdLength;
 
             DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
 
-            /* Queue device install (will be dequeued by DeviceInstallThread */
-            len = FIELD_OFFSET(DeviceInstallParams, DeviceIds)
-                + wcslen(PnpEvent->TargetDevice.DeviceIds) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
-            Params = HeapAlloc(GetProcessHeap(), 0, len);
-            if (Params)
+            DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
+            if (DeviceIdLength)
             {
-                wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
+                /* Queue device install (will be dequeued by DeviceInstallThread */
+                len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
+                Params = HeapAlloc(GetProcessHeap(), 0, len);
+                if (Params)
+                {
+                    wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
-                InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
+                    InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
 #else
-                InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
+                    InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
 #endif
-                SetEvent(hDeviceInstallListNotEmpty);
+                    SetEvent(hDeviceInstallListNotEmpty);
+                }
             }
         }
         else
         {
-            DPRINT1("Unknown event\n");
+            DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
+                PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
+                PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
+                PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
+                PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
         }
 
         /* Dequeue the current pnp event and signal the next one */
@@ -1802,11 +2320,6 @@ ServiceMain(DWORD argc, LPTSTR *argv)
 
     DPRINT("ServiceMain() called\n");
 
-    hNoPendingInstalls = CreateEventW(NULL,
-                                      TRUE,
-                                      FALSE,
-                                      L"Global\\PnP_No_Pending_Install_Events");
-
     hThread = CreateThread(NULL,
                            0,
                            PnpEventThread,
@@ -1818,7 +2331,7 @@ ServiceMain(DWORD argc, LPTSTR *argv)
 
     hThread = CreateThread(NULL,
                            0,
-                           DeviceInstallThread,
+                           RpcServerThread,
                            NULL,
                            0,
                            &dwThreadId);
@@ -1827,7 +2340,7 @@ ServiceMain(DWORD argc, LPTSTR *argv)
 
     hThread = CreateThread(NULL,
                            0,
-                           RpcServerThread,
+                           DeviceInstallThread,
                            NULL,
                            0,
                            &dwThreadId);
@@ -1839,8 +2352,9 @@ ServiceMain(DWORD argc, LPTSTR *argv)
 
 
 int
-main(int argc, char *argv[])
+wmain(int argc, WCHAR *argv[])
 {
+    BOOLEAN OldValue;
     DWORD dwError;
 
     UNREFERENCED_PARAMETER(argc);
@@ -1848,6 +2362,9 @@ main(int argc, char *argv[])
 
     DPRINT("Umpnpmgr: main() started\n");
 
+    /* We need this privilege for using CreateProcessAsUserW */
+    RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
+
     hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
     if (hInstallEvent == NULL)
     {
@@ -1864,6 +2381,17 @@ main(int argc, char *argv[])
         return dwError;
     }
 
+    hNoPendingInstalls = CreateEventW(NULL,
+                                      TRUE,
+                                      FALSE,
+                                      L"Global\\PnP_No_Pending_Install_Events");
+    if (hNoPendingInstalls == NULL)
+    {
+        dwError = GetLastError();
+        DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
+        return dwError;
+    }
+
 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
     InitializeSListHead(&DeviceInstallListHead);
 #else