ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

umpnpmgr.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2005 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * COPYRIGHT:        See COPYING in the top level directory
00021  * PROJECT:          ReactOS kernel
00022  * FILE:             services/umpnpmgr/umpnpmgr.c
00023  * PURPOSE:          User-mode Plug and Play manager
00024  * PROGRAMMER:       Eric Kohl
00025  *                   Hervé Poussineau (hpoussin@reactos.org)
00026  *                   Colin Finck (colin@reactos.org)
00027  */
00028 
00029 /* INCLUDES *****************************************************************/
00030 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
00031 #define WIN32_NO_STATUS
00032 #include <windows.h>
00033 #include <stdio.h>
00034 #include <cmtypes.h>
00035 #include <cmfuncs.h>
00036 #include <rtlfuncs.h>
00037 #include <setypes.h>
00038 #include <umpnpmgr/sysguid.h>
00039 #include <wdmguid.h>
00040 #include <cfgmgr32.h>
00041 #include <regstr.h>
00042 #include <userenv.h>
00043 
00044 #include <rpc.h>
00045 #include <rpcdce.h>
00046 
00047 #include "pnp_s.h"
00048 
00049 #define NDEBUG
00050 #include <debug.h>
00051 
00052 /* GLOBALS ******************************************************************/
00053 
00054 static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
00055 static WCHAR ServiceName[] = L"PlugPlay";
00056 static SERVICE_TABLE_ENTRYW ServiceTable[] =
00057 {
00058     {ServiceName, ServiceMain},
00059     {NULL, NULL}
00060 };
00061 
00062 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
00063 static SERVICE_STATUS ServiceStatus;
00064 
00065 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
00066 
00067 static HKEY hEnumKey = NULL;
00068 static HKEY hClassKey = NULL;
00069 
00070 static HANDLE hUserToken = NULL;
00071 static HANDLE hInstallEvent = NULL;
00072 static HANDLE hNoPendingInstalls = NULL;
00073 
00074 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
00075 static SLIST_HEADER DeviceInstallListHead;
00076 #else
00077 static LIST_ENTRY DeviceInstallListHead;
00078 #endif
00079 static HANDLE hDeviceInstallListNotEmpty;
00080 
00081 typedef struct
00082 {
00083 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
00084     SLIST_ENTRY ListEntry;
00085 #else
00086     LIST_ENTRY ListEntry;
00087 #endif
00088     WCHAR DeviceIds[1];
00089 } DeviceInstallParams;
00090 
00091 /* FUNCTIONS *****************************************************************/
00092 
00093 static DWORD WINAPI
00094 RpcServerThread(LPVOID lpParameter)
00095 {
00096     RPC_STATUS Status;
00097     BOOLEAN RegisteredProtSeq = FALSE;
00098 
00099     UNREFERENCED_PARAMETER(lpParameter);
00100 
00101     DPRINT("RpcServerThread() called\n");
00102 
00103 #if 0
00104     /* XP-compatible protocol sequence/endpoint */
00105     Status = RpcServerUseProtseqEpW(L"ncacn_np",
00106                                     20,
00107                                     L"\\pipe\\ntsvcs",
00108                                     NULL);  // Security descriptor
00109     if (Status == RPC_S_OK)
00110         RegisteredProtSeq = TRUE;
00111     else
00112         DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
00113 #endif
00114 
00115     /* Vista-compatible protocol sequence/endpoint */
00116     Status = RpcServerUseProtseqEpW(L"ncacn_np",
00117                                     20,
00118                                     L"\\pipe\\plugplay",
00119                                     NULL);  // Security descriptor
00120     if (Status == RPC_S_OK)
00121         RegisteredProtSeq = TRUE;
00122     else
00123         DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
00124 
00125     /* Make sure there's a usable endpoint */
00126     if (RegisteredProtSeq == FALSE)
00127         return 0;
00128 
00129     Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
00130                                  NULL,
00131                                  NULL);
00132     if (Status != RPC_S_OK)
00133     {
00134         DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
00135         return 0;
00136     }
00137 
00138     Status = RpcServerListen(1,
00139                              20,
00140                              FALSE);
00141     if (Status != RPC_S_OK)
00142     {
00143         DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
00144         return 0;
00145     }
00146 
00147     /* ROS HACK (this should never happen...) */
00148     DPRINT1("*** Other devices won't be installed correctly. If something\n");
00149     DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
00150 
00151     DPRINT("RpcServerThread() done\n");
00152 
00153     return 0;
00154 }
00155 
00156 
00157 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
00158 {
00159     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
00160 }
00161 
00162 
00163 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
00164 {
00165     HeapFree(GetProcessHeap(), 0, ptr);
00166 }
00167 
00168 
00169 static CONFIGRET WINAPI
00170 NtStatusToCrError(NTSTATUS Status)
00171 {
00172     switch (Status)
00173     {
00174         case STATUS_NO_SUCH_DEVICE:
00175             return CR_NO_SUCH_DEVINST;
00176 
00177         default:
00178             /* FIXME: add more mappings */
00179             DPRINT1("Unable to map status 0x%08lx\n", Status);
00180             return CR_FAILURE;
00181     }
00182 }
00183 
00184 
00185 /* Function 0 */
00186 DWORD PNP_Disconnect(
00187     handle_t hBinding)
00188 {
00189     UNREFERENCED_PARAMETER(hBinding);
00190     return CR_SUCCESS;
00191 }
00192 
00193 
00194 /* Function 1 */
00195 DWORD PNP_Connect(
00196     handle_t hBinding)
00197 {
00198     UNREFERENCED_PARAMETER(hBinding);
00199     return CR_SUCCESS;
00200 }
00201 
00202 
00203 /* Function 2 */
00204 DWORD PNP_GetVersion(
00205     handle_t hBinding,
00206     WORD *pVersion)
00207 {
00208     UNREFERENCED_PARAMETER(hBinding);
00209 
00210     *pVersion = 0x0400;
00211     return CR_SUCCESS;
00212 }
00213 
00214 
00215 /* Function 3 */
00216 DWORD PNP_GetGlobalState(
00217     handle_t hBinding,
00218     DWORD *pulState,
00219     DWORD ulFlags)
00220 {
00221     UNREFERENCED_PARAMETER(hBinding);
00222     UNREFERENCED_PARAMETER(ulFlags);
00223 
00224     *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
00225     return CR_SUCCESS;
00226 }
00227 
00228 
00229 /* Function 4 */
00230 DWORD PNP_InitDetection(
00231     handle_t hBinding)
00232 {
00233     UNREFERENCED_PARAMETER(hBinding);
00234 
00235     DPRINT("PNP_InitDetection() called\n");
00236     return CR_SUCCESS;
00237 }
00238 
00239 
00240 /* Function 5 */
00241 DWORD PNP_ReportLogOn(
00242     handle_t hBinding,
00243     BOOL Admin,
00244     DWORD ProcessId)
00245 {
00246     DWORD ReturnValue = CR_FAILURE;
00247     HANDLE hProcess;
00248 
00249     UNREFERENCED_PARAMETER(hBinding);
00250     UNREFERENCED_PARAMETER(Admin);
00251 
00252     DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
00253 
00254     /* Get the users token */
00255     hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
00256 
00257     if(!hProcess)
00258     {
00259         DPRINT1("OpenProcess failed with error %u\n", GetLastError());
00260         goto cleanup;
00261     }
00262 
00263     if (hUserToken)
00264     {
00265         CloseHandle(hUserToken);
00266         hUserToken = NULL;
00267     }
00268 
00269     if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
00270     {
00271         DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
00272         goto cleanup;
00273     }
00274 
00275     /* Trigger the installer thread */
00276     if (hInstallEvent)
00277         SetEvent(hInstallEvent);
00278 
00279     ReturnValue = CR_SUCCESS;
00280 
00281 cleanup:
00282     if(hProcess)
00283         CloseHandle(hProcess);
00284 
00285     return ReturnValue;
00286 }
00287 
00288 
00289 /* Function 6 */
00290 DWORD PNP_ValidateDeviceInstance(
00291     handle_t hBinding,
00292     LPWSTR pDeviceID,
00293     DWORD ulFlags)
00294 {
00295     CONFIGRET ret = CR_SUCCESS;
00296     HKEY hDeviceKey = NULL;
00297 
00298     UNREFERENCED_PARAMETER(hBinding);
00299     UNREFERENCED_PARAMETER(ulFlags);
00300 
00301     DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
00302            pDeviceID, ulFlags);
00303 
00304     if (RegOpenKeyExW(hEnumKey,
00305                       pDeviceID,
00306                       0,
00307                       KEY_READ,
00308                       &hDeviceKey))
00309     {
00310         DPRINT("Could not open the Device Key!\n");
00311         ret = CR_NO_SUCH_DEVNODE;
00312         goto Done;
00313     }
00314 
00315     /* FIXME: add more tests */
00316 
00317 Done:
00318     if (hDeviceKey != NULL)
00319         RegCloseKey(hDeviceKey);
00320 
00321     DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
00322 
00323     return ret;
00324 }
00325 
00326 
00327 /* Function 7 */
00328 DWORD PNP_GetRootDeviceInstance(
00329     handle_t hBinding,
00330     LPWSTR pDeviceID,
00331     PNP_RPC_STRING_LEN ulLength)
00332 {
00333     CONFIGRET ret = CR_SUCCESS;
00334 
00335     UNREFERENCED_PARAMETER(hBinding);
00336 
00337     DPRINT("PNP_GetRootDeviceInstance() called\n");
00338 
00339     if (!pDeviceID)
00340     {
00341         ret = CR_INVALID_POINTER;
00342         goto Done;
00343     }
00344     if (ulLength < lstrlenW(szRootDeviceId) + 1)
00345     {
00346         ret = CR_BUFFER_SMALL;
00347         goto Done;
00348     }
00349 
00350     lstrcpyW(pDeviceID,
00351              szRootDeviceId);
00352 
00353 Done:
00354     DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
00355 
00356     return ret;
00357 }
00358 
00359 
00360 /* Function 8 */
00361 DWORD PNP_GetRelatedDeviceInstance(
00362     handle_t hBinding,
00363     DWORD ulRelationship,
00364     LPWSTR pDeviceID,
00365     LPWSTR pRelatedDeviceId,
00366     PNP_RPC_STRING_LEN *pulLength,
00367     DWORD ulFlags)
00368 {
00369     PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
00370     CONFIGRET ret = CR_SUCCESS;
00371     NTSTATUS Status;
00372 
00373     UNREFERENCED_PARAMETER(hBinding);
00374     UNREFERENCED_PARAMETER(ulFlags);
00375 
00376     DPRINT("PNP_GetRelatedDeviceInstance() called\n");
00377     DPRINT("  Relationship %ld\n", ulRelationship);
00378     DPRINT("  DeviceId %S\n", pDeviceID);
00379 
00380     RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
00381                          pDeviceID);
00382 
00383     PlugPlayData.Relation = ulRelationship;
00384 
00385     PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
00386     PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
00387 
00388     Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
00389                                (PVOID)&PlugPlayData,
00390                                sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
00391     if (!NT_SUCCESS(Status))
00392     {
00393         ret = NtStatusToCrError(Status);
00394     }
00395 
00396     DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
00397     if (ret == CR_SUCCESS)
00398     {
00399         DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
00400     }
00401 
00402     return ret;
00403 }
00404 
00405 
00406 /* Function 9 */
00407 DWORD PNP_EnumerateSubKeys(
00408     handle_t hBinding,
00409     DWORD ulBranch,
00410     DWORD ulIndex,
00411     LPWSTR Buffer,
00412     PNP_RPC_STRING_LEN ulLength,
00413     PNP_RPC_STRING_LEN *pulRequiredLen,
00414     DWORD ulFlags)
00415 {
00416     CONFIGRET ret = CR_SUCCESS;
00417     HKEY hKey;
00418     DWORD dwError;
00419 
00420     UNREFERENCED_PARAMETER(hBinding);
00421     UNREFERENCED_PARAMETER(ulFlags);
00422 
00423     DPRINT("PNP_EnumerateSubKeys() called\n");
00424 
00425     switch (ulBranch)
00426     {
00427         case PNP_ENUMERATOR_SUBKEYS:
00428             hKey = hEnumKey;
00429             break;
00430 
00431         case PNP_CLASS_SUBKEYS:
00432             hKey = hClassKey;
00433             break;
00434 
00435         default:
00436             return CR_FAILURE;
00437     }
00438 
00439     *pulRequiredLen = ulLength;
00440     dwError = RegEnumKeyExW(hKey,
00441                             ulIndex,
00442                             Buffer,
00443                             pulRequiredLen,
00444                             NULL,
00445                             NULL,
00446                             NULL,
00447                             NULL);
00448     if (dwError != ERROR_SUCCESS)
00449     {
00450         ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
00451     }
00452     else
00453     {
00454         (*pulRequiredLen)++;
00455     }
00456 
00457     DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
00458 
00459     return ret;
00460 }
00461 
00462 
00463 /* Function 10 */
00464 DWORD PNP_GetDeviceList(
00465     handle_t hBinding,
00466     LPWSTR pszFilter,
00467     LPWSTR Buffer,
00468     PNP_RPC_STRING_LEN *pulLength,
00469     DWORD ulFlags)
00470 {
00471     UNIMPLEMENTED;
00472     return CR_CALL_NOT_IMPLEMENTED;
00473 }
00474 
00475 
00476 /* Function 11 */
00477 DWORD PNP_GetDeviceListSize(
00478     handle_t hBinding,
00479     LPWSTR pszFilter,
00480     PNP_RPC_BUFFER_SIZE *pulLen,
00481     DWORD ulFlags)
00482 {
00483     UNIMPLEMENTED;
00484     return CR_CALL_NOT_IMPLEMENTED;
00485 }
00486 
00487 
00488 /* Function 12 */
00489 DWORD PNP_GetDepth(
00490     handle_t hBinding,
00491     LPWSTR pszDeviceID,
00492     DWORD *pulDepth,
00493     DWORD ulFlags)
00494 {
00495     PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
00496     CONFIGRET ret = CR_SUCCESS;
00497     NTSTATUS Status;
00498 
00499     UNREFERENCED_PARAMETER(hBinding);
00500     UNREFERENCED_PARAMETER(ulFlags);
00501 
00502     DPRINT("PNP_GetDepth() called\n");
00503 
00504     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
00505                          pszDeviceID);
00506 
00507     Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
00508                                (PVOID)&PlugPlayData,
00509                                sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
00510     if (NT_SUCCESS(Status))
00511     {
00512         *pulDepth = PlugPlayData.Depth;
00513     }
00514     else
00515     {
00516         ret = NtStatusToCrError(Status);
00517     }
00518 
00519     DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
00520 
00521     return ret;
00522 }
00523 
00524 
00525 /* Function 13 */
00526 DWORD PNP_GetDeviceRegProp(
00527     handle_t hBinding,
00528     LPWSTR pDeviceID,
00529     DWORD ulProperty,
00530     DWORD *pulRegDataType,
00531     BYTE *Buffer,
00532     PNP_PROP_SIZE *pulTransferLen,
00533     PNP_PROP_SIZE *pulLength,
00534     DWORD ulFlags)
00535 {
00536     PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
00537     CONFIGRET ret = CR_SUCCESS;
00538     LPWSTR lpValueName = NULL;
00539     HKEY hKey = NULL;
00540     LONG lError;
00541     NTSTATUS Status;
00542 
00543     UNREFERENCED_PARAMETER(hBinding);
00544 
00545     DPRINT("PNP_GetDeviceRegProp() called\n");
00546 
00547     if (pulTransferLen == NULL || pulLength == NULL)
00548     {
00549         ret = CR_INVALID_POINTER;
00550         goto done;
00551     }
00552 
00553     if (ulFlags != 0)
00554     {
00555         ret = CR_INVALID_FLAG;
00556         goto done;
00557     }
00558 
00559     /* FIXME: Check pDeviceID */
00560 
00561     if (*pulLength < *pulTransferLen)
00562         *pulLength = *pulTransferLen;
00563 
00564     *pulTransferLen = 0;
00565 
00566     switch (ulProperty)
00567     {
00568         case CM_DRP_DEVICEDESC:
00569             lpValueName = L"DeviceDesc";
00570             break;
00571 
00572         case CM_DRP_HARDWAREID:
00573             lpValueName = L"HardwareID";
00574             break;
00575 
00576         case CM_DRP_COMPATIBLEIDS:
00577             lpValueName = L"CompatibleIDs";
00578             break;
00579 
00580         case CM_DRP_SERVICE:
00581             lpValueName = L"Service";
00582             break;
00583 
00584         case CM_DRP_CLASS:
00585             lpValueName = L"Class";
00586             break;
00587 
00588         case CM_DRP_CLASSGUID:
00589             lpValueName = L"ClassGUID";
00590             break;
00591 
00592         case CM_DRP_DRIVER:
00593             lpValueName = L"Driver";
00594             break;
00595 
00596         case CM_DRP_CONFIGFLAGS:
00597             lpValueName = L"ConfigFlags";
00598             break;
00599 
00600         case CM_DRP_MFG:
00601             lpValueName = L"Mfg";
00602             break;
00603 
00604         case CM_DRP_FRIENDLYNAME:
00605             lpValueName = L"FriendlyName";
00606             break;
00607 
00608         case CM_DRP_LOCATION_INFORMATION:
00609             lpValueName = L"LocationInformation";
00610             break;
00611 
00612         case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
00613             lpValueName = NULL;
00614             break;
00615 
00616         case CM_DRP_CAPABILITIES:
00617             lpValueName = L"Capabilities";
00618             break;
00619 
00620         case CM_DRP_UI_NUMBER:
00621             lpValueName = NULL;
00622             break;
00623 
00624         case CM_DRP_UPPERFILTERS:
00625             lpValueName = L"UpperFilters";
00626             break;
00627 
00628         case CM_DRP_LOWERFILTERS:
00629             lpValueName = L"LowerFilters";
00630             break;
00631 
00632         case CM_DRP_BUSTYPEGUID:
00633             lpValueName = NULL;
00634             break;
00635 
00636         case CM_DRP_LEGACYBUSTYPE:
00637             lpValueName = NULL;
00638             break;
00639 
00640         case CM_DRP_BUSNUMBER:
00641             lpValueName = NULL;
00642             break;
00643 
00644         case CM_DRP_ENUMERATOR_NAME:
00645             lpValueName = NULL;
00646             break;
00647 
00648         case CM_DRP_SECURITY:
00649             lpValueName = L"Security";
00650             break;
00651 
00652         case CM_DRP_DEVTYPE:
00653             lpValueName = L"DeviceType";
00654             break;
00655 
00656         case CM_DRP_EXCLUSIVE:
00657             lpValueName = L"Exclusive";
00658             break;
00659 
00660         case CM_DRP_CHARACTERISTICS:
00661             lpValueName = L"DeviceCharacteristics";
00662             break;
00663 
00664         case CM_DRP_ADDRESS:
00665             lpValueName = NULL;
00666             break;
00667 
00668         case CM_DRP_UI_NUMBER_DESC_FORMAT:
00669             lpValueName = L"UINumberDescFormat";
00670             break;
00671 
00672         case CM_DRP_DEVICE_POWER_DATA:
00673             lpValueName = NULL;
00674             break;
00675 
00676         case CM_DRP_REMOVAL_POLICY:
00677             lpValueName = NULL;
00678             break;
00679 
00680         case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
00681             lpValueName = NULL;
00682             break;
00683 
00684         case CM_DRP_REMOVAL_POLICY_OVERRIDE:
00685             lpValueName = L"RemovalPolicy";
00686             break;
00687 
00688         case CM_DRP_INSTALL_STATE:
00689             lpValueName = NULL;
00690             break;
00691 
00692 #if (WINVER >= _WIN32_WINNT_WS03)
00693         case CM_DRP_LOCATION_PATHS:
00694             lpValueName = NULL;
00695             break;
00696 #endif
00697 
00698 #if (WINVER >= _WIN32_WINNT_WIN7)
00699         case CM_DRP_BASE_CONTAINERID:
00700             lpValueName = NULL;
00701             break;
00702 #endif
00703 
00704         default:
00705             ret = CR_INVALID_PROPERTY;
00706             goto done;
00707     }
00708 
00709     DPRINT("Value name: %S\n", lpValueName);
00710 
00711     if (lpValueName)
00712     {
00713         /* Retrieve information from the Registry */
00714         lError = RegOpenKeyExW(hEnumKey,
00715                                pDeviceID,
00716                                0,
00717                                KEY_QUERY_VALUE,
00718                                &hKey);
00719         if (lError != ERROR_SUCCESS)
00720         {
00721             hKey = NULL;
00722             *pulLength = 0;
00723             ret = CR_INVALID_DEVNODE;
00724             goto done;
00725         }
00726 
00727         lError = RegQueryValueExW(hKey,
00728                                   lpValueName,
00729                                   NULL,
00730                                   pulRegDataType,
00731                                   Buffer,
00732                                   pulLength);
00733         if (lError != ERROR_SUCCESS)
00734         {
00735             if (lError == ERROR_MORE_DATA)
00736             {
00737                 ret = CR_BUFFER_SMALL;
00738             }
00739             else
00740             {
00741                 *pulLength = 0;
00742                 ret = CR_NO_SUCH_VALUE;
00743             }
00744         }
00745     }
00746     else
00747     {
00748         /* Retrieve information from the Device Node */
00749         RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
00750                              pDeviceID);
00751         PlugPlayData.Buffer = Buffer;
00752         PlugPlayData.BufferSize = *pulLength;
00753 
00754         switch (ulProperty)
00755         {
00756             case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
00757                 PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
00758                 break;
00759 
00760             case CM_DRP_UI_NUMBER:
00761                 PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
00762                 break;
00763 
00764             case CM_DRP_BUSTYPEGUID:
00765                 PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
00766                 break;
00767 
00768             case CM_DRP_LEGACYBUSTYPE:
00769                 PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
00770                 break;
00771 
00772             case CM_DRP_BUSNUMBER:
00773                 PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
00774                 break;
00775 
00776             case CM_DRP_ENUMERATOR_NAME:
00777                 PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName;
00778                 break;
00779 
00780             case CM_DRP_ADDRESS:
00781                 PlugPlayData.Property = 0x10; // DevicePropertyAddress;
00782                 break;
00783 
00784 #if 0
00785             /* FIXME: This property is not supported by IoGetDeviceProperty */
00786             case CM_DRP_DEVICE_POWER_DATA:
00787 #endif
00788 
00789             case CM_DRP_REMOVAL_POLICY:
00790                 PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy
00791                 break;
00792 
00793 #if 0
00794             /* FIXME: This property is not supported by IoGetDeviceProperty */
00795             case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
00796 #endif
00797 
00798             case CM_DRP_INSTALL_STATE:
00799                 PlugPlayData.Property = 0x12; // DevicePropertyInstallState;
00800                 break;
00801 
00802 #if 0
00803             /* FIXME: This property is not supported by IoGetDeviceProperty */
00804 #if (WINVER >= _WIN32_WINNT_WS03)
00805             case CM_DRP_LOCATION_PATHS:
00806 #endif
00807 #endif
00808 
00809 #if (WINVER >= _WIN32_WINNT_WIN7)
00810             case CM_DRP_BASE_CONTAINERID:
00811                 PlugPlayData.Property = 0x16; // DevicePropertyContainerID;
00812                 break;
00813 #endif
00814 
00815             default:
00816                 return CR_INVALID_PROPERTY;
00817         }
00818 
00819         Status = NtPlugPlayControl(PlugPlayControlProperty,
00820                                    (PVOID)&PlugPlayData,
00821                                    sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
00822         if (NT_SUCCESS(Status))
00823         {
00824             *pulLength = PlugPlayData.BufferSize;
00825         }
00826         else
00827         {
00828             ret = NtStatusToCrError(Status);
00829         }
00830     }
00831 
00832 done:
00833     *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
00834 
00835     if (hKey != NULL)
00836         RegCloseKey(hKey);
00837 
00838     DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
00839 
00840     return ret;
00841 }
00842 
00843 
00844 /* Function 14 */
00845 DWORD PNP_SetDeviceRegProp(
00846     handle_t hBinding,
00847     LPWSTR pDeviceId,
00848     DWORD ulProperty,
00849     DWORD ulDataType,
00850     BYTE *Buffer,
00851     PNP_PROP_SIZE ulLength,
00852     DWORD ulFlags)
00853 {
00854     CONFIGRET ret = CR_SUCCESS;
00855     LPWSTR lpValueName = NULL;
00856     HKEY hKey = 0;
00857 
00858     UNREFERENCED_PARAMETER(hBinding);
00859     UNREFERENCED_PARAMETER(ulFlags);
00860 
00861     DPRINT("PNP_SetDeviceRegProp() called\n");
00862 
00863     DPRINT("DeviceId: %S\n", pDeviceId);
00864     DPRINT("Property: %lu\n", ulProperty);
00865     DPRINT("DataType: %lu\n", ulDataType);
00866     DPRINT("Length: %lu\n", ulLength);
00867 
00868     switch (ulProperty)
00869     {
00870         case CM_DRP_DEVICEDESC:
00871             lpValueName = L"DeviceDesc";
00872             break;
00873 
00874         case CM_DRP_HARDWAREID:
00875             lpValueName = L"HardwareID";
00876             break;
00877 
00878         case CM_DRP_COMPATIBLEIDS:
00879             lpValueName = L"CompatibleIDs";
00880             break;
00881 
00882         case CM_DRP_SERVICE:
00883             lpValueName = L"Service";
00884             break;
00885 
00886         case CM_DRP_CLASS:
00887             lpValueName = L"Class";
00888             break;
00889 
00890         case CM_DRP_CLASSGUID:
00891             lpValueName = L"ClassGUID";
00892             break;
00893 
00894         case CM_DRP_DRIVER:
00895             lpValueName = L"Driver";
00896             break;
00897 
00898         case CM_DRP_CONFIGFLAGS:
00899             lpValueName = L"ConfigFlags";
00900             break;
00901 
00902         case CM_DRP_MFG:
00903             lpValueName = L"Mfg";
00904             break;
00905 
00906         case CM_DRP_FRIENDLYNAME:
00907             lpValueName = L"FriendlyName";
00908             break;
00909 
00910         case CM_DRP_LOCATION_INFORMATION:
00911             lpValueName = L"LocationInformation";
00912             break;
00913 
00914         case CM_DRP_UPPERFILTERS:
00915             lpValueName = L"UpperFilters";
00916             break;
00917 
00918         case CM_DRP_LOWERFILTERS:
00919             lpValueName = L"LowerFilters";
00920             break;
00921 
00922         case CM_DRP_SECURITY:
00923             lpValueName = L"Security";
00924             break;
00925 
00926         case CM_DRP_DEVTYPE:
00927             lpValueName = L"DeviceType";
00928             break;
00929 
00930         case CM_DRP_EXCLUSIVE:
00931             lpValueName = L"Exclusive";
00932             break;
00933 
00934         case CM_DRP_CHARACTERISTICS:
00935             lpValueName = L"DeviceCharacteristics";
00936             break;
00937 
00938         case CM_DRP_UI_NUMBER_DESC_FORMAT:
00939             lpValueName = L"UINumberDescFormat";
00940             break;
00941 
00942         case CM_DRP_REMOVAL_POLICY_OVERRIDE:
00943             lpValueName = L"RemovalPolicy";
00944             break;
00945 
00946         default:
00947             return CR_INVALID_PROPERTY;
00948     }
00949 
00950     DPRINT("Value name: %S\n", lpValueName);
00951 
00952     if (RegOpenKeyExW(hEnumKey,
00953                       pDeviceId,
00954                       0,
00955                       KEY_SET_VALUE,
00956                       &hKey))
00957         return CR_INVALID_DEVNODE;
00958 
00959     if (ulLength == 0)
00960     {
00961         if (RegDeleteValueW(hKey,
00962                             lpValueName))
00963             ret = CR_REGISTRY_ERROR;
00964     }
00965     else
00966     {
00967         if (RegSetValueExW(hKey,
00968                            lpValueName,
00969                            0,
00970                            ulDataType,
00971                            Buffer,
00972                            ulLength))
00973             ret = CR_REGISTRY_ERROR;
00974     }
00975 
00976     RegCloseKey(hKey);
00977 
00978     DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
00979 
00980     return ret;
00981 }
00982 
00983 
00984 /* Function 15 */
00985 DWORD PNP_GetClassInstance(
00986     handle_t hBinding,
00987     LPWSTR pDeviceId,
00988     LPWSTR pszClassInstance,
00989     PNP_RPC_STRING_LEN ulLength)
00990 {
00991     UNIMPLEMENTED;
00992     return CR_CALL_NOT_IMPLEMENTED;
00993 }
00994 
00995 
00996 /* Function 16 */
00997 DWORD PNP_CreateKey(
00998     handle_t hBinding,
00999     LPWSTR pszSubKey,
01000     DWORD samDesired,
01001     DWORD ulFlags)
01002 {
01003     HKEY hKey = 0;
01004 
01005     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
01006                         pszSubKey,
01007                         0,
01008                         NULL,
01009                         0,
01010                         KEY_ALL_ACCESS,
01011                         NULL,
01012                         &hKey,
01013                         NULL))
01014         return CR_REGISTRY_ERROR;
01015 
01016     /* FIXME: Set security key */
01017 
01018     RegCloseKey(hKey);
01019 
01020     return CR_SUCCESS;
01021 }
01022 
01023 
01024 /* Function 17 */
01025 DWORD PNP_DeleteRegistryKey(
01026     handle_t hBinding,
01027     LPWSTR pszDeviceID,
01028     LPWSTR pszParentKey,
01029     LPWSTR pszChildKey,
01030     DWORD ulFlags)
01031 {
01032     UNIMPLEMENTED;
01033     return CR_CALL_NOT_IMPLEMENTED;
01034 }
01035 
01036 
01037 /* Function 18 */
01038 DWORD PNP_GetClassCount(
01039     handle_t hBinding,
01040     DWORD *pulClassCount,
01041     DWORD ulFlags)
01042 {
01043     HKEY hKey;
01044     DWORD dwError;
01045 
01046     UNREFERENCED_PARAMETER(hBinding);
01047     UNREFERENCED_PARAMETER(ulFlags);
01048 
01049     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
01050                             REGSTR_PATH_CLASS,
01051                             0,
01052                             KEY_QUERY_VALUE,
01053                             &hKey);
01054     if (dwError != ERROR_SUCCESS)
01055         return CR_INVALID_DATA;
01056 
01057     dwError = RegQueryInfoKeyW(hKey,
01058                                NULL,
01059                                NULL,
01060                                NULL,
01061                                pulClassCount,
01062                                NULL,
01063                                NULL,
01064                                NULL,
01065                                NULL,
01066                                NULL,
01067                                NULL,
01068                                NULL);
01069     RegCloseKey(hKey);
01070     if (dwError != ERROR_SUCCESS)
01071         return CR_INVALID_DATA;
01072 
01073     return CR_SUCCESS;
01074 }
01075 
01076 
01077 /* Function 19 */
01078 DWORD PNP_GetClassName(
01079     handle_t hBinding,
01080     LPWSTR pszClassGuid,
01081     LPWSTR Buffer,
01082     PNP_RPC_STRING_LEN *pulLength,
01083     DWORD ulFlags)
01084 {
01085     WCHAR szKeyName[MAX_PATH];
01086     CONFIGRET ret = CR_SUCCESS;
01087     HKEY hKey;
01088     DWORD dwSize;
01089 
01090     UNREFERENCED_PARAMETER(hBinding);
01091     UNREFERENCED_PARAMETER(ulFlags);
01092 
01093     DPRINT("PNP_GetClassName() called\n");
01094 
01095     lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
01096     if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
01097         lstrcatW(szKeyName, pszClassGuid);
01098     else return CR_INVALID_DATA;
01099 
01100     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
01101                       szKeyName,
01102                       0,
01103                       KEY_QUERY_VALUE,
01104                       &hKey))
01105         return CR_REGISTRY_ERROR;
01106 
01107     dwSize = *pulLength * sizeof(WCHAR);
01108     if (RegQueryValueExW(hKey,
01109                          L"Class",
01110                          NULL,
01111                          NULL,
01112                          (LPBYTE)Buffer,
01113                          &dwSize))
01114     {
01115         *pulLength = 0;
01116         ret = CR_REGISTRY_ERROR;
01117     }
01118     else
01119     {
01120         *pulLength = dwSize / sizeof(WCHAR);
01121     }
01122 
01123     RegCloseKey(hKey);
01124 
01125     DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
01126 
01127     return ret;
01128 }
01129 
01130 
01131 /* Function 20 */
01132 DWORD PNP_DeleteClassKey(
01133     handle_t hBinding,
01134     LPWSTR pszClassGuid,
01135     DWORD ulFlags)
01136 {
01137     CONFIGRET ret = CR_SUCCESS;
01138 
01139     UNREFERENCED_PARAMETER(hBinding);
01140 
01141     DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
01142 
01143     if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
01144     {
01145         if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
01146             ret = CR_REGISTRY_ERROR;
01147     }
01148     else
01149     {
01150         if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
01151             ret = CR_REGISTRY_ERROR;
01152     }
01153 
01154     DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
01155 
01156     return ret;
01157 }
01158 
01159 
01160 /* Function 21 */
01161 DWORD PNP_GetInterfaceDeviceAlias(
01162     handle_t hBinding,
01163     LPWSTR pszInterfaceDevice,
01164     GUID *AliasInterfaceGuid,
01165     LPWSTR pszAliasInterfaceDevice,
01166     PNP_RPC_STRING_LEN *pulLength,
01167     PNP_RPC_STRING_LEN *pulTransferLen,
01168     DWORD ulFlags)
01169 {
01170     UNIMPLEMENTED;
01171     return CR_CALL_NOT_IMPLEMENTED;
01172 }
01173 
01174 
01175 /* Function 22 */
01176 DWORD PNP_GetInterfaceDeviceList(
01177     handle_t hBinding,
01178     GUID *InterfaceGuid,
01179     LPWSTR pszDeviceID,
01180     BYTE *Buffer,
01181     PNP_RPC_BUFFER_SIZE *pulLength,
01182     DWORD ulFlags)
01183 {
01184     UNIMPLEMENTED;
01185     return CR_CALL_NOT_IMPLEMENTED;
01186 }
01187 
01188 
01189 /* Function 23 */
01190 DWORD PNP_GetInterfaceDeviceListSize(
01191     handle_t hBinding,
01192     PNP_RPC_BUFFER_SIZE *pulLen,
01193     GUID *InterfaceGuid,
01194     LPWSTR pszDeviceID,
01195     DWORD ulFlags)
01196 {
01197     UNIMPLEMENTED;
01198     return CR_CALL_NOT_IMPLEMENTED;
01199 }
01200 
01201 
01202 /* Function 24 */
01203 DWORD PNP_RegisterDeviceClassAssociation(
01204     handle_t hBinding,
01205     LPWSTR pszDeviceID,
01206     GUID *InterfaceGuid,
01207     LPWSTR pszReference,
01208     LPWSTR pszSymLink,
01209     PNP_RPC_STRING_LEN *pulLength,
01210     PNP_RPC_STRING_LEN *pulTransferLen,
01211     DWORD ulFlags)
01212 {
01213     UNIMPLEMENTED;
01214     return CR_CALL_NOT_IMPLEMENTED;
01215 }
01216 
01217 
01218 /* Function 25 */
01219 DWORD PNP_UnregisterDeviceClassAssociation(
01220     handle_t hBinding,
01221     LPWSTR pszInterfaceDevice,
01222     DWORD ulFlags)
01223 {
01224     UNIMPLEMENTED;
01225     return CR_CALL_NOT_IMPLEMENTED;
01226 }
01227 
01228 
01229 /* Function 26 */
01230 DWORD PNP_GetClassRegProp(
01231     handle_t hBinding,
01232     LPWSTR pszClassGuid,
01233     DWORD ulProperty,
01234     DWORD *pulRegDataType,
01235     BYTE *Buffer,
01236     PNP_RPC_STRING_LEN *pulTransferLen,
01237     PNP_RPC_STRING_LEN *pulLength,
01238     DWORD ulFlags)
01239 {
01240     CONFIGRET ret = CR_SUCCESS;
01241     LPWSTR lpValueName = NULL;
01242     HKEY hInstKey = NULL;
01243     HKEY hPropKey = NULL;
01244     LONG lError;
01245 
01246     UNREFERENCED_PARAMETER(hBinding);
01247 
01248     DPRINT("PNP_GetClassRegProp() called\n");
01249 
01250     if (pulTransferLen == NULL || pulLength == NULL)
01251     {
01252         ret = CR_INVALID_POINTER;
01253         goto done;
01254     }
01255 
01256     if (ulFlags != 0)
01257     {
01258         ret = CR_INVALID_FLAG;
01259         goto done;
01260     }
01261 
01262     if (*pulLength < *pulTransferLen)
01263         *pulLength = *pulTransferLen;
01264 
01265     *pulTransferLen = 0;
01266 
01267     switch (ulProperty)
01268     {
01269         case CM_CRP_SECURITY:
01270             lpValueName = L"Security";
01271             break;
01272 
01273         case CM_CRP_DEVTYPE:
01274             lpValueName = L"DeviceType";
01275             break;
01276 
01277         case CM_CRP_EXCLUSIVE:
01278             lpValueName = L"Exclusive";
01279             break;
01280 
01281         case CM_CRP_CHARACTERISTICS:
01282             lpValueName = L"DeviceCharacteristics";
01283             break;
01284 
01285         default:
01286             ret = CR_INVALID_PROPERTY;
01287             goto done;
01288     }
01289 
01290     DPRINT("Value name: %S\n", lpValueName);
01291 
01292     lError = RegOpenKeyExW(hClassKey,
01293                            pszClassGuid,
01294                            0,
01295                            KEY_READ,
01296                            &hInstKey);
01297     if (lError != ERROR_SUCCESS)
01298     {
01299         *pulLength = 0;
01300         ret = CR_NO_SUCH_REGISTRY_KEY;
01301         goto done;
01302     }
01303 
01304     lError = RegOpenKeyExW(hInstKey,
01305                            L"Properties",
01306                            0,
01307                            KEY_READ,
01308                            &hPropKey);
01309     if (lError != ERROR_SUCCESS)
01310     {
01311         *pulLength = 0;
01312         ret = CR_NO_SUCH_REGISTRY_KEY;
01313         goto done;
01314     }
01315 
01316     lError = RegQueryValueExW(hPropKey,
01317                               lpValueName,
01318                               NULL,
01319                               pulRegDataType,
01320                               Buffer,
01321                               pulLength);
01322     if (lError != ERROR_SUCCESS)
01323     {
01324         if (lError == ERROR_MORE_DATA)
01325         {
01326             ret = CR_BUFFER_SMALL;
01327         }
01328         else
01329         {
01330             *pulLength = 0;
01331             ret = CR_NO_SUCH_VALUE;
01332         }
01333     }
01334 
01335 done:;
01336     if (ret == CR_SUCCESS)
01337         *pulTransferLen = *pulLength;
01338 
01339     if (hPropKey != NULL)
01340         RegCloseKey(hPropKey);
01341 
01342     if (hInstKey != NULL)
01343         RegCloseKey(hInstKey);
01344 
01345     DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
01346 
01347     return ret;
01348 }
01349 
01350 
01351 /* Function 27 */
01352 DWORD PNP_SetClassRegProp(
01353     handle_t hBinding,
01354     LPWSTR pszClassGuid,
01355     DWORD ulProperty,
01356     DWORD ulDataType,
01357     BYTE *Buffer,
01358     PNP_PROP_SIZE ulLength,
01359     DWORD ulFlags)
01360 {
01361     CONFIGRET ret = CR_SUCCESS;
01362     LPWSTR lpValueName = NULL;
01363     HKEY hInstKey = 0;
01364     HKEY hPropKey = 0;
01365     LONG lError;
01366 
01367     UNREFERENCED_PARAMETER(hBinding);
01368 
01369     DPRINT("PNP_SetClassRegProp() called\n");
01370 
01371     if (ulFlags != 0)
01372         return CR_INVALID_FLAG;
01373 
01374     switch (ulProperty)
01375     {
01376         case CM_CRP_SECURITY:
01377             lpValueName = L"Security";
01378             break;
01379 
01380         case CM_CRP_DEVTYPE:
01381             lpValueName = L"DeviceType";
01382             break;
01383 
01384         case CM_CRP_EXCLUSIVE:
01385             lpValueName = L"Exclusive";
01386             break;
01387 
01388         case CM_CRP_CHARACTERISTICS:
01389             lpValueName = L"DeviceCharacteristics";
01390             break;
01391 
01392         default:
01393             return CR_INVALID_PROPERTY;
01394     }
01395 
01396     lError = RegOpenKeyExW(hClassKey,
01397                            pszClassGuid,
01398                            0,
01399                            KEY_WRITE,
01400                            &hInstKey);
01401     if (lError != ERROR_SUCCESS)
01402     {
01403         ret = CR_NO_SUCH_REGISTRY_KEY;
01404         goto done;
01405     }
01406 
01407     /* FIXME: Set security descriptor */
01408     lError = RegCreateKeyExW(hInstKey,
01409                              L"Properties",
01410                              0,
01411                              NULL,
01412                              REG_OPTION_NON_VOLATILE,
01413                              KEY_ALL_ACCESS,
01414                              NULL,
01415                              &hPropKey,
01416                              NULL);
01417     if (lError != ERROR_SUCCESS)
01418     {
01419         ret = CR_REGISTRY_ERROR;
01420         goto done;
01421     }
01422 
01423     if (ulLength == 0)
01424     {
01425         if (RegDeleteValueW(hPropKey,
01426                             lpValueName))
01427             ret = CR_REGISTRY_ERROR;
01428     }
01429     else
01430     {
01431         if (RegSetValueExW(hPropKey,
01432                            lpValueName,
01433                            0,
01434                            ulDataType,
01435                            Buffer,
01436                            ulLength))
01437             ret = CR_REGISTRY_ERROR;
01438     }
01439 
01440 done:;
01441     if (hPropKey != NULL)
01442         RegCloseKey(hPropKey);
01443 
01444     if (hInstKey != NULL)
01445         RegCloseKey(hInstKey);
01446 
01447     return ret;
01448 }
01449 
01450 
01451 static VOID
01452 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
01453                       OUT LPWSTR pszEnumerator,
01454                       OUT LPWSTR pszDevice,
01455                       OUT LPWSTR pszInstance)
01456 {
01457     WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
01458     LPWSTR lpEnumerator = NULL;
01459     LPWSTR lpDevice = NULL;
01460     LPWSTR lpInstance = NULL;
01461     LPWSTR ptr;
01462 
01463     wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
01464 
01465     *pszEnumerator = 0;
01466     *pszDevice = 0;
01467     *pszInstance = 0;
01468 
01469     lpEnumerator = szLocalDeviceInstanceID;
01470 
01471     ptr = wcschr(lpEnumerator, L'\\');
01472     if (ptr != NULL)
01473     {
01474         *ptr = 0;
01475         lpDevice = ++ptr;
01476 
01477         ptr = wcschr(lpDevice, L'\\');
01478         if (ptr != NULL)
01479         {
01480             *ptr = 0;
01481             lpInstance = ++ptr;
01482         }
01483     }
01484 
01485     if (lpEnumerator != NULL)
01486         wcscpy(pszEnumerator, lpEnumerator);
01487 
01488     if (lpDevice != NULL)
01489         wcscpy(pszDevice, lpDevice);
01490 
01491     if (lpInstance != NULL)
01492         wcscpy(pszInstance, lpInstance);
01493 }
01494 
01495 
01496 static CONFIGRET
01497 CreateDeviceInstance(LPWSTR pszDeviceID)
01498 {
01499     WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
01500     WCHAR szDevice[MAX_DEVICE_ID_LEN];
01501     WCHAR szInstance[MAX_DEVICE_ID_LEN];
01502     HKEY hKeyEnumerator;
01503     HKEY hKeyDevice;
01504     HKEY hKeyInstance;
01505     HKEY hKeyControl;
01506     LONG lError;
01507 
01508     /* Split the instance ID */
01509     SplitDeviceInstanceID(pszDeviceID,
01510                           szEnumerator,
01511                           szDevice,
01512                           szInstance);
01513 
01514     /* Open or create the enumerator key */
01515     lError = RegCreateKeyExW(hEnumKey,
01516                              szEnumerator,
01517                              0,
01518                              NULL,
01519                              REG_OPTION_NON_VOLATILE,
01520                              KEY_ALL_ACCESS,
01521                              NULL,
01522                              &hKeyEnumerator,
01523                              NULL);
01524     if (lError != ERROR_SUCCESS)
01525     {
01526         return CR_REGISTRY_ERROR;
01527     }
01528 
01529     /* Open or create the device key */
01530     lError = RegCreateKeyExW(hKeyEnumerator,
01531                              szDevice,
01532                              0,
01533                              NULL,
01534                              REG_OPTION_NON_VOLATILE,
01535                              KEY_ALL_ACCESS,
01536                              NULL,
01537                              &hKeyDevice,
01538                              NULL);
01539 
01540     /* Close the enumerator key */
01541     RegCloseKey(hKeyEnumerator);
01542 
01543     if (lError != ERROR_SUCCESS)
01544     {
01545         return CR_REGISTRY_ERROR;
01546     }
01547 
01548     /* Try to open the instance key and fail if it exists */
01549     lError = RegOpenKeyExW(hKeyDevice,
01550                            szInstance,
01551                            0,
01552                            KEY_SET_VALUE,
01553                            &hKeyInstance);
01554     if (lError == ERROR_SUCCESS)
01555     {
01556         DPRINT1("Instance %S already exists!\n", szInstance);
01557         RegCloseKey(hKeyInstance);
01558         RegCloseKey(hKeyDevice);
01559         return CR_ALREADY_SUCH_DEVINST;
01560     }
01561 
01562     /* Create a new instance key */
01563     lError = RegCreateKeyExW(hKeyDevice,
01564                              szInstance,
01565                              0,
01566                              NULL,
01567                              REG_OPTION_NON_VOLATILE,
01568                              KEY_ALL_ACCESS,
01569                              NULL,
01570                              &hKeyInstance,
01571                              NULL);
01572 
01573     /* Close the device key */
01574     RegCloseKey(hKeyDevice);
01575 
01576     if (lError != ERROR_SUCCESS)
01577     {
01578         return CR_REGISTRY_ERROR;
01579     }
01580 
01581     /* Create the 'Control' sub key */
01582     lError = RegCreateKeyExW(hKeyInstance,
01583                              L"Control",
01584                              0,
01585                              NULL,
01586                              REG_OPTION_NON_VOLATILE,
01587                              KEY_ALL_ACCESS,
01588                              NULL,
01589                              &hKeyControl,
01590                              NULL);
01591     if (lError == ERROR_SUCCESS)
01592     {
01593         RegCloseKey(hKeyControl);
01594     }
01595 
01596     RegCloseKey(hKeyInstance);
01597 
01598     return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
01599 }
01600 
01601 
01602 /* Function 28 */
01603 DWORD PNP_CreateDevInst(
01604     handle_t hBinding,
01605     LPWSTR pszDeviceID,
01606     LPWSTR pszParentDeviceID,
01607     PNP_RPC_STRING_LEN ulLength,
01608     DWORD ulFlags)
01609 {
01610     CONFIGRET ret = CR_SUCCESS;
01611 
01612     DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
01613 
01614     if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
01615     {
01616         /* FIXME */
01617         DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
01618         ret = CR_CALL_NOT_IMPLEMENTED;
01619         goto done;
01620     }
01621 
01622     /* Create the device instance */
01623     ret = CreateDeviceInstance(pszDeviceID);
01624 
01625 done:;
01626     DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
01627 
01628     return ret;
01629 }
01630 
01631 
01632 static CONFIGRET
01633 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
01634                    LPWSTR pszDeviceInstanceSource)
01635 {
01636     DPRINT("MoveDeviceInstance: not implemented\n");
01637     /* FIXME */
01638     return CR_CALL_NOT_IMPLEMENTED;
01639 }
01640 
01641 
01642 static CONFIGRET
01643 SetupDeviceInstance(LPWSTR pszDeviceInstance,
01644                     DWORD ulFlags)
01645 {
01646     DPRINT("SetupDeviceInstance: not implemented\n");
01647     /* FIXME */
01648     return CR_CALL_NOT_IMPLEMENTED;
01649 }
01650 
01651 
01652 static CONFIGRET
01653 EnableDeviceInstance(LPWSTR pszDeviceInstance)
01654 {
01655     PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
01656     CONFIGRET ret = CR_SUCCESS;
01657     NTSTATUS Status;
01658 
01659     DPRINT("Enable device instance\n");
01660 
01661     RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
01662     Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
01663     if (!NT_SUCCESS(Status))
01664         ret = NtStatusToCrError(Status);
01665 
01666     return ret;
01667 }
01668 
01669 
01670 static CONFIGRET
01671 DisableDeviceInstance(LPWSTR pszDeviceInstance)
01672 {
01673     DPRINT("DisableDeviceInstance: not implemented\n");
01674     /* FIXME */
01675     return CR_CALL_NOT_IMPLEMENTED;
01676 }
01677 
01678 
01679 static CONFIGRET
01680 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
01681 {
01682     DPRINT("ReenumerateDeviceInstance: not implemented\n");
01683     /* FIXME */
01684     return CR_CALL_NOT_IMPLEMENTED;
01685 }
01686 
01687 
01688 /* Function 29 */
01689 DWORD PNP_DeviceInstanceAction(
01690     handle_t hBinding,
01691     DWORD ulAction,
01692     DWORD ulFlags,
01693     LPWSTR pszDeviceInstance1,
01694     LPWSTR pszDeviceInstance2)
01695 {
01696     CONFIGRET ret = CR_SUCCESS;
01697 
01698     UNREFERENCED_PARAMETER(hBinding);
01699 
01700     DPRINT("PNP_DeviceInstanceAction() called\n");
01701 
01702     switch (ulAction)
01703     {
01704         case PNP_DEVINST_MOVE:
01705             ret = MoveDeviceInstance(pszDeviceInstance1,
01706                                      pszDeviceInstance2);
01707             break;
01708 
01709         case PNP_DEVINST_SETUP:
01710             ret = SetupDeviceInstance(pszDeviceInstance1,
01711                                       ulFlags);
01712             break;
01713 
01714         case PNP_DEVINST_ENABLE:
01715             ret = EnableDeviceInstance(pszDeviceInstance1);
01716             break;
01717 
01718         case PNP_DEVINST_DISABLE:
01719             ret = DisableDeviceInstance(pszDeviceInstance1);
01720             break;
01721 
01722         case PNP_DEVINST_REENUMERATE:
01723             ret = ReenumerateDeviceInstance(pszDeviceInstance1);
01724             break;
01725 
01726         default:
01727             DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
01728             ret = CR_CALL_NOT_IMPLEMENTED;
01729     }
01730 
01731     DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
01732 
01733     return ret;
01734 }
01735 
01736 
01737 /* Function 30 */
01738 DWORD PNP_GetDeviceStatus(
01739     handle_t hBinding,
01740     LPWSTR pDeviceID,
01741     DWORD *pulStatus,
01742     DWORD *pulProblem,
01743     DWORD ulFlags)
01744 {
01745     PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
01746     CONFIGRET ret = CR_SUCCESS;
01747     NTSTATUS Status;
01748 
01749     UNREFERENCED_PARAMETER(hBinding);
01750     UNREFERENCED_PARAMETER(ulFlags);
01751 
01752     DPRINT("PNP_GetDeviceStatus() called\n");
01753 
01754     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
01755                          pDeviceID);
01756     PlugPlayData.Operation = 0; /* Get status */
01757 
01758     Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
01759                                (PVOID)&PlugPlayData,
01760                                sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
01761     if (NT_SUCCESS(Status))
01762     {
01763         *pulStatus = PlugPlayData.DeviceStatus;
01764         *pulProblem = PlugPlayData.DeviceProblem;
01765     }
01766     else
01767     {
01768         ret = NtStatusToCrError(Status);
01769     }
01770 
01771     DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
01772 
01773     return ret;
01774 }
01775 
01776 
01777 /* Function 31 */
01778 DWORD PNP_SetDeviceProblem(
01779     handle_t hBinding,
01780     LPWSTR pDeviceID,
01781     DWORD ulProblem,
01782     DWORD ulFlags)
01783 {
01784     UNIMPLEMENTED;
01785     return CR_CALL_NOT_IMPLEMENTED;
01786 }
01787 
01788 
01789 /* Function 32 */
01790 DWORD PNP_DisableDevInst(
01791     handle_t hBinding,
01792     LPWSTR pDeviceID,
01793     PPNP_VETO_TYPE pVetoType,
01794     LPWSTR pszVetoName,
01795     DWORD ulNameLength,
01796     DWORD ulFlags)
01797 {
01798     UNIMPLEMENTED;
01799     return CR_CALL_NOT_IMPLEMENTED;
01800 }
01801 
01802 /* Function 33 */
01803 DWORD PNP_UninstallDevInst(
01804     handle_t hBinding,
01805     LPWSTR pDeviceID,
01806     DWORD ulFlags)
01807 {
01808     UNIMPLEMENTED;
01809     return CR_CALL_NOT_IMPLEMENTED;
01810 }
01811 
01812 
01813 static BOOL
01814 CheckForDeviceId(LPWSTR lpDeviceIdList,
01815                  LPWSTR lpDeviceId)
01816 {
01817     LPWSTR lpPtr;
01818     DWORD dwLength;
01819 
01820     lpPtr = lpDeviceIdList;
01821     while (*lpPtr != 0)
01822     {
01823         dwLength = wcslen(lpPtr);
01824         if (0 == _wcsicmp(lpPtr, lpDeviceId))
01825             return TRUE;
01826 
01827         lpPtr += (dwLength + 1);
01828     }
01829 
01830     return FALSE;
01831 }
01832 
01833 
01834 static VOID
01835 AppendDeviceId(LPWSTR lpDeviceIdList,
01836                LPDWORD lpDeviceIdListSize,
01837                LPWSTR lpDeviceId)
01838 {
01839     DWORD dwLen;
01840     DWORD dwPos;
01841 
01842     dwLen = wcslen(lpDeviceId);
01843     dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
01844 
01845     wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
01846 
01847     dwPos += (dwLen + 1);
01848 
01849     lpDeviceIdList[dwPos] = 0;
01850 
01851     *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
01852 }
01853 
01854 
01855 /* Function 34 */
01856 DWORD PNP_AddID(
01857     handle_t hBinding,
01858     LPWSTR pszDeviceID,
01859     LPWSTR pszID,
01860     DWORD ulFlags)
01861 {
01862     CONFIGRET ret = CR_SUCCESS;
01863     HKEY hDeviceKey;
01864     LPWSTR pszSubKey;
01865     DWORD dwDeviceIdListSize;
01866     DWORD dwNewDeviceIdSize;
01867     WCHAR * pszDeviceIdList = NULL;
01868 
01869     UNREFERENCED_PARAMETER(hBinding);
01870 
01871     DPRINT("PNP_AddID() called\n");
01872     DPRINT("  DeviceInstance: %S\n", pszDeviceID);
01873     DPRINT("  DeviceId: %S\n", pszID);
01874     DPRINT("  Flags: %lx\n", ulFlags);
01875 
01876     if (RegOpenKeyExW(hEnumKey,
01877                       pszDeviceID,
01878                       0,
01879                       KEY_QUERY_VALUE | KEY_SET_VALUE,
01880                       &hDeviceKey) != ERROR_SUCCESS)
01881     {
01882         DPRINT("Failed to open the device key!\n");
01883         return CR_INVALID_DEVNODE;
01884     }
01885 
01886     pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
01887 
01888     if (RegQueryValueExW(hDeviceKey,
01889                          pszSubKey,
01890                          NULL,
01891                          NULL,
01892                          NULL,
01893                          &dwDeviceIdListSize) != ERROR_SUCCESS)
01894     {
01895         DPRINT("Failed to query the desired ID string!\n");
01896         ret = CR_REGISTRY_ERROR;
01897         goto Done;
01898     }
01899 
01900     dwNewDeviceIdSize = lstrlenW(pszDeviceID);
01901     if (!dwNewDeviceIdSize)
01902     {
01903         ret = CR_INVALID_POINTER;
01904         goto Done;
01905     }
01906 
01907     dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
01908 
01909     pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
01910     if (!pszDeviceIdList)
01911     {
01912         DPRINT("Failed to allocate memory for the desired ID string!\n");
01913         ret = CR_OUT_OF_MEMORY;
01914         goto Done;
01915     }
01916 
01917     if (RegQueryValueExW(hDeviceKey,
01918                          pszSubKey,
01919                          NULL,
01920                          NULL,
01921                          (LPBYTE)pszDeviceIdList,
01922                          &dwDeviceIdListSize) != ERROR_SUCCESS)
01923     {
01924         DPRINT("Failed to query the desired ID string!\n");
01925         ret = CR_REGISTRY_ERROR;
01926         goto Done;
01927     }
01928 
01929     /* Check whether the device ID is already in use */
01930     if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
01931     {
01932         DPRINT("Device ID was found in the ID string!\n");
01933         ret = CR_SUCCESS;
01934         goto Done;
01935     }
01936 
01937     /* Append the Device ID */
01938     AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
01939 
01940     if (RegSetValueExW(hDeviceKey,
01941                        pszSubKey,
01942                        0,
01943                        REG_MULTI_SZ,
01944                        (LPBYTE)pszDeviceIdList,
01945                        dwDeviceIdListSize) != ERROR_SUCCESS)
01946     {
01947         DPRINT("Failed to set the desired ID string!\n");
01948         ret = CR_REGISTRY_ERROR;
01949     }
01950 
01951 Done:
01952     RegCloseKey(hDeviceKey);
01953     if (pszDeviceIdList)
01954         HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
01955 
01956     DPRINT("PNP_AddID() done (returns %lx)\n", ret);
01957 
01958     return ret;
01959 }
01960 
01961 
01962 /* Function 35 */
01963 DWORD PNP_RegisterDriver(
01964     handle_t hBinding,
01965     LPWSTR pszDeviceID,
01966     DWORD ulFlags)
01967 {
01968     UNIMPLEMENTED;
01969     return CR_CALL_NOT_IMPLEMENTED;
01970 }
01971 
01972 
01973 /* Function 36 */
01974 DWORD PNP_QueryRemove(
01975     handle_t hBinding,
01976     LPWSTR pszDeviceID,
01977     PPNP_VETO_TYPE pVetoType,
01978     LPWSTR pszVetoName,
01979     DWORD ulNameLength,
01980     DWORD ulFlags)
01981 {
01982     UNIMPLEMENTED;
01983     return CR_CALL_NOT_IMPLEMENTED;
01984 }
01985 
01986 
01987 /* Function 37 */
01988 DWORD PNP_RequestDeviceEject(
01989     handle_t hBinding,
01990     LPWSTR pszDeviceID,
01991     PPNP_VETO_TYPE pVetoType,
01992     LPWSTR pszVetoName,
01993     DWORD ulNameLength,
01994     DWORD ulFlags)
01995 {
01996     UNIMPLEMENTED;
01997     return CR_CALL_NOT_IMPLEMENTED;
01998 }
01999 
02000 /* Function 38 */
02001 CONFIGRET
02002 PNP_IsDockStationPresent(handle_t hBinding,
02003                          BOOL *Present)
02004 {
02005     HKEY hKey;
02006     DWORD dwType;
02007     DWORD dwValue;
02008     DWORD dwSize;
02009     CONFIGRET ret = CR_SUCCESS;
02010 
02011     UNREFERENCED_PARAMETER(hBinding);
02012 
02013     DPRINT1("PNP_IsDockStationPresent() called\n");
02014 
02015     *Present = FALSE;
02016 
02017     if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
02018                       L"CurrentDockInfo",
02019                       0,
02020                       KEY_READ,
02021                       &hKey) != ERROR_SUCCESS)
02022         return CR_REGISTRY_ERROR;
02023 
02024     dwSize = sizeof(DWORD);
02025     if (RegQueryValueExW(hKey,
02026                          L"DockingState",
02027                          NULL,
02028                          &dwType,
02029                          (LPBYTE)&dwValue,
02030                          &dwSize) != ERROR_SUCCESS)
02031         ret = CR_REGISTRY_ERROR;
02032 
02033     RegCloseKey(hKey);
02034 
02035     if (ret == CR_SUCCESS)
02036     {
02037         if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
02038         {
02039             ret = CR_REGISTRY_ERROR;
02040         }
02041         else if (dwValue != 0)
02042         {
02043             *Present = TRUE;
02044         }
02045     }
02046 
02047     DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
02048 
02049     return ret;
02050 }
02051 
02052 
02053 /* Function 39 */
02054 DWORD PNP_RequestEjectPC(
02055     handle_t hBinding)
02056 {
02057     UNIMPLEMENTED;
02058     return CR_CALL_NOT_IMPLEMENTED;
02059 }
02060 
02061 
02062 /* Function 40 */
02063 DWORD PNP_HwProfFlags(
02064     handle_t hBinding,
02065     DWORD ulAction,
02066     LPWSTR pDeviceID,
02067     DWORD ulConfig,
02068     DWORD *pulValue,
02069     PPNP_VETO_TYPE pVetoType,
02070     LPWSTR pszVetoName,
02071     DWORD ulNameLength,
02072     DWORD ulFlags)
02073 {
02074     CONFIGRET ret = CR_SUCCESS;
02075     WCHAR szKeyName[MAX_PATH];
02076     HKEY hKey;
02077     HKEY hDeviceKey;
02078     DWORD dwSize;
02079 
02080     UNREFERENCED_PARAMETER(hBinding);
02081 
02082     DPRINT("PNP_HwProfFlags() called\n");
02083 
02084     if (ulConfig == 0)
02085     {
02086         wcscpy(szKeyName,
02087                L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
02088     }
02089     else
02090     {
02091         swprintf(szKeyName,
02092                  L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
02093                  ulConfig);
02094     }
02095 
02096     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
02097                       szKeyName,
02098                       0,
02099                       KEY_QUERY_VALUE,
02100                       &hKey) != ERROR_SUCCESS)
02101         return CR_REGISTRY_ERROR;
02102 
02103     if (ulAction == PNP_GET_HWPROFFLAGS)
02104     {
02105          if (RegOpenKeyExW(hKey,
02106                            pDeviceID,
02107                            0,
02108                            KEY_QUERY_VALUE,
02109                            &hDeviceKey) != ERROR_SUCCESS)
02110          {
02111             *pulValue = 0;
02112          }
02113          else
02114          {
02115              dwSize = sizeof(DWORD);
02116              if (!RegQueryValueExW(hDeviceKey,
02117                                    L"CSConfigFlags",
02118                                    NULL,
02119                                    NULL,
02120                                    (LPBYTE)pulValue,
02121                                    &dwSize) != ERROR_SUCCESS)
02122              {
02123                  *pulValue = 0;
02124              }
02125 
02126              RegCloseKey(hDeviceKey);
02127          }
02128     }
02129     else if (ulAction == PNP_SET_HWPROFFLAGS)
02130     {
02131         /* FIXME: not implemented yet */
02132         ret = CR_CALL_NOT_IMPLEMENTED;
02133     }
02134 
02135     RegCloseKey(hKey);
02136 
02137     return ret;
02138 }
02139 
02140 
02141 /* Function 41 */
02142 DWORD PNP_GetHwProfInfo(
02143     handle_t hBinding,
02144     DWORD ulIndex,
02145     HWPROFILEINFO *pHWProfileInfo,
02146     DWORD ulProfileInfoSize,
02147     DWORD ulFlags)
02148 {
02149     WCHAR szProfileName[5];
02150     HKEY hKeyConfig = NULL;
02151     HKEY hKeyProfiles = NULL;
02152     HKEY hKeyProfile = NULL;
02153     DWORD dwDisposition;
02154     DWORD dwSize;
02155     LONG lError;
02156     CONFIGRET ret = CR_SUCCESS;
02157 
02158     UNREFERENCED_PARAMETER(hBinding);
02159 
02160     DPRINT("PNP_GetHwProfInfo() called\n");
02161 
02162     if (ulProfileInfoSize == 0)
02163     {
02164         ret = CR_INVALID_DATA;
02165         goto done;
02166     }
02167 
02168     if (ulFlags != 0)
02169     {
02170         ret = CR_INVALID_FLAG;
02171         goto done;
02172     }
02173 
02174     /* Initialize the profile information */
02175     pHWProfileInfo->HWPI_ulHWProfile = 0;
02176     pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
02177     pHWProfileInfo->HWPI_dwFlags = 0;
02178 
02179     /* Open the 'IDConfigDB' key */
02180     lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
02181                              L"System\\CurrentControlSet\\Control\\IDConfigDB",
02182                              0,
02183                              NULL,
02184                              REG_OPTION_NON_VOLATILE,
02185                              KEY_QUERY_VALUE,
02186                              NULL,
02187                              &hKeyConfig,
02188                              &dwDisposition);
02189     if (lError != ERROR_SUCCESS)
02190     {
02191         ret = CR_REGISTRY_ERROR;
02192         goto done;
02193     }
02194 
02195     /* Open the 'Hardware Profiles' subkey */
02196     lError = RegCreateKeyExW(hKeyConfig,
02197                              L"Hardware Profiles",
02198                              0,
02199                              NULL,
02200                              REG_OPTION_NON_VOLATILE,
02201                              KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
02202                              NULL,
02203                              &hKeyProfiles,
02204                              &dwDisposition);
02205     if (lError != ERROR_SUCCESS)
02206     {
02207         ret = CR_REGISTRY_ERROR;
02208         goto done;
02209     }
02210 
02211     if (ulIndex == (ULONG)-1)
02212     {
02213         dwSize = sizeof(ULONG);
02214         lError = RegQueryValueExW(hKeyConfig,
02215                                   L"CurrentConfig",
02216                                   NULL,
02217                                   NULL,
02218                                   (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
02219                                   &dwSize);
02220         if (lError != ERROR_SUCCESS)
02221         {
02222             pHWProfileInfo->HWPI_ulHWProfile = 0;
02223             ret = CR_REGISTRY_ERROR;
02224             goto done;
02225         }
02226     }
02227     else
02228     {
02229         /* FIXME: not implemented yet */
02230         ret = CR_CALL_NOT_IMPLEMENTED;
02231         goto done;
02232     }
02233 
02234     swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
02235 
02236     lError = RegOpenKeyExW(hKeyProfiles,
02237                            szProfileName,
02238                            0,
02239                            KEY_QUERY_VALUE,
02240                            &hKeyProfile);
02241     if (lError != ERROR_SUCCESS)
02242     {
02243         ret = CR_REGISTRY_ERROR;
02244         goto done;
02245     }
02246 
02247     dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
02248     lError = RegQueryValueExW(hKeyProfile,
02249                               L"FriendlyName",
02250                               NULL,
02251                               NULL,
02252                               (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
02253                               &dwSize);
02254     if (lError != ERROR_SUCCESS)
02255     {
02256         ret = CR_REGISTRY_ERROR;
02257         goto done;
02258     }
02259 
02260 done:
02261     if (hKeyProfile != NULL)
02262         RegCloseKey(hKeyProfile);
02263 
02264     if (hKeyProfiles != NULL)
02265         RegCloseKey(hKeyProfiles);
02266 
02267     if (hKeyConfig != NULL)
02268         RegCloseKey(hKeyConfig);
02269 
02270     return ret;
02271 }
02272 
02273 
02274 /* Function 42 */
02275 DWORD PNP_AddEmptyLogConf(
02276     handle_t hBinding,
02277     LPWSTR pDeviceID,
02278     DWORD ulPriority,
02279     DWORD *pulLogConfTag,
02280     DWORD ulFlags)
02281 {
02282     UNIMPLEMENTED;
02283     return CR_CALL_NOT_IMPLEMENTED;
02284 }
02285 
02286 
02287 /* Function 43 */
02288 DWORD PNP_FreeLogConf(
02289     handle_t hBinding,
02290     LPWSTR pDeviceID,
02291     DWORD ulLogConfType,
02292     DWORD ulLogConfTag,
02293     DWORD ulFlags)
02294 {
02295     UNIMPLEMENTED;
02296     return CR_CALL_NOT_IMPLEMENTED;
02297 }
02298 
02299 
02300 /* Function 44 */
02301 DWORD PNP_GetFirstLogConf(
02302     handle_t hBinding,
02303     LPWSTR pDeviceID,
02304     DWORD ulLogConfType,
02305     DWORD *pulLogConfTag,
02306     DWORD ulFlags)
02307 {
02308     UNIMPLEMENTED;
02309     return CR_CALL_NOT_IMPLEMENTED;
02310 }
02311 
02312 
02313 /* Function 45 */
02314 DWORD PNP_GetNextLogConf(
02315     handle_t hBinding,
02316     LPWSTR pDeviceID,
02317     DWORD ulLogConfType,
02318     DWORD ulCurrentTag,
02319     DWORD *pulNextTag,
02320     DWORD ulFlags)
02321 {
02322     UNIMPLEMENTED;
02323     return CR_CALL_NOT_IMPLEMENTED;
02324 }
02325 
02326 
02327 /* Function 46 */
02328 DWORD PNP_GetLogConfPriority(
02329     handle_t hBinding,
02330     LPWSTR pDeviceID,
02331     DWORD ulType,
02332     DWORD ulTag,
02333     DWORD *pPriority,
02334     DWORD ulFlags)
02335 {
02336     UNIMPLEMENTED;
02337     return CR_CALL_NOT_IMPLEMENTED;
02338 }
02339 
02340 
02341 /* Function 47 */
02342 DWORD PNP_AddResDes(
02343     handle_t hBinding,
02344     LPWSTR pDeviceID,
02345     DWORD ulLogConfTag,
02346     DWORD ulLogConfType,
02347     RESOURCEID ResourceID,
02348     DWORD *pulResourceTag,
02349     BYTE *ResourceData,
02350     PNP_RPC_BUFFER_SIZE ResourceLen,
02351     DWORD ulFlags)
02352 {
02353     UNIMPLEMENTED;
02354     return CR_CALL_NOT_IMPLEMENTED;
02355 }
02356 
02357 
02358 /* Function 48 */
02359 DWORD PNP_FreeResDes(
02360     handle_t hBinding,
02361     LPWSTR pDeviceID,
02362     DWORD ulLogConfTag,
02363     DWORD ulLogConfType,
02364     RESOURCEID ResourceID,
02365     DWORD ulResourceTag,
02366     DWORD *pulPreviousResType,
02367     DWORD *pulPreviousResTag,
02368     DWORD ulFlags)
02369 {
02370     UNIMPLEMENTED;
02371     return CR_CALL_NOT_IMPLEMENTED;
02372 }
02373 
02374 
02375 /* Function 49 */
02376 DWORD PNP_GetNextResDes(
02377     handle_t hBinding,
02378     LPWSTR pDeviceID,
02379     DWORD ulLogConfTag,
02380     DWORD ulLogConfType,
02381     RESOURCEID ResourceID,
02382     DWORD ulResourceTag,
02383     DWORD *pulNextResType,
02384     DWORD *pulNextResTag,
02385     DWORD ulFlags)
02386 {
02387     UNIMPLEMENTED;
02388     return CR_CALL_NOT_IMPLEMENTED;
02389 }
02390 
02391 
02392 /* Function 50 */
02393 DWORD PNP_GetResDesData(
02394     handle_t hBinding,
02395     LPWSTR pDeviceID,
02396     DWORD ulLogConfTag,
02397     DWORD ulLogConfType,
02398     RESOURCEID ResourceID,
02399     DWORD ulResourceTag,
02400     BYTE *Buffer,
02401     PNP_RPC_BUFFER_SIZE BufferLen,
02402     DWORD ulFlags)
02403 {
02404     UNIMPLEMENTED;
02405     return CR_CALL_NOT_IMPLEMENTED;
02406 }
02407 
02408 
02409 /* Function 51 */
02410 DWORD PNP_GetResDesDataSize(
02411     handle_t hBinding,
02412     LPWSTR pDeviceID,
02413     DWORD ulLogConfTag,
02414     DWORD ulLogConfType,
02415     RESOURCEID ResourceID,
02416     DWORD ulResourceTag,
02417     DWORD *pulSize,
02418     DWORD ulFlags)
02419 {
02420     UNIMPLEMENTED;
02421     return CR_CALL_NOT_IMPLEMENTED;
02422 }
02423 
02424 
02425 /* Function 52 */
02426 DWORD PNP_ModifyResDes(
02427     handle_t hBinding,
02428     LPWSTR pDeviceID,
02429     DWORD ulLogConfTag,
02430     DWORD ulLogConfType,
02431     RESOURCEID CurrentResourceID,
02432     RESOURCEID NewResourceID,
02433     DWORD ulResourceTag,
02434     BYTE *ResourceData,
02435     PNP_RPC_BUFFER_SIZE ResourceLen,
02436     DWORD ulFlags)
02437 {
02438     UNIMPLEMENTED;
02439     return CR_CALL_NOT_IMPLEMENTED;
02440 }
02441 
02442 
02443 /* Function 53 */
02444 DWORD PNP_DetectResourceConflict(
02445     handle_t hBinding,
02446     LPWSTR pDeviceID,
02447     RESOURCEID ResourceID,
02448     BYTE *ResourceData,
02449     PNP_RPC_BUFFER_SIZE ResourceLen,
02450     BOOL *pbConflictDetected,
02451     DWORD ulFlags)
02452 {
02453     UNIMPLEMENTED;
02454     return CR_CALL_NOT_IMPLEMENTED;
02455 }
02456 
02457 
02458 /* Function 54 */
02459 DWORD PNP_QueryResConfList(
02460     handle_t hBinding,
02461     LPWSTR pDeviceID,
02462     RESOURCEID ResourceID,
02463     BYTE *ResourceData,
02464     PNP_RPC_BUFFER_SIZE ResourceLen,
02465     BYTE *Buffer,
02466     PNP_RPC_BUFFER_SIZE BufferLen,
02467     DWORD ulFlags)
02468 {
02469     UNIMPLEMENTED;
02470     return CR_CALL_NOT_IMPLEMENTED;
02471 }
02472 
02473 
02474 /* Function 55 */
02475 DWORD PNP_SetHwProf(
02476     handle_t hBinding,
02477     DWORD ulHardwareProfile,
02478     DWORD ulFlags)
02479 {
02480     UNIMPLEMENTED;
02481     return CR_CALL_NOT_IMPLEMENTED;
02482 }
02483 
02484 
02485 /* Function 56 */
02486 DWORD PNP_QueryArbitratorFreeData(
02487     handle_t hBinding,
02488     BYTE *pData,
02489     DWORD DataLen,
02490     LPWSTR pDeviceID,
02491     RESOURCEID ResourceID,
02492     DWORD ulFlags)
02493 {
02494     UNIMPLEMENTED;
02495     return CR_CALL_NOT_IMPLEMENTED;
02496 }
02497 
02498 
02499 /* Function 57 */
02500 DWORD PNP_QueryArbitratorFreeSize(
02501     handle_t hBinding,
02502     DWORD *pulSize,
02503     LPWSTR pDeviceID,
02504     RESOURCEID ResourceID,
02505     DWORD ulFlags)
02506 {
02507     UNIMPLEMENTED;
02508     return CR_CALL_NOT_IMPLEMENTED;
02509 }
02510 
02511 
02512 /* Function 58 */
02513 CONFIGRET
02514 PNP_RunDetection(
02515     handle_t hBinding,
02516     DWORD ulFlags)
02517 {
02518     return CR_CALL_NOT_IMPLEMENTED;
02519 }
02520 
02521 
02522 /* Function 59 */
02523 DWORD PNP_RegisterNotification(
02524     handle_t hBinding)
02525 {
02526     UNIMPLEMENTED;
02527     return CR_CALL_NOT_IMPLEMENTED;
02528 }
02529 
02530 
02531 /* Function 60 */
02532 DWORD PNP_UnregisterNotification(
02533     handle_t hBinding)
02534 {
02535     UNIMPLEMENTED;
02536     return CR_CALL_NOT_IMPLEMENTED;
02537 }
02538 
02539 
02540 /* Function 61 */
02541 DWORD PNP_GetCustomDevProp(
02542     handle_t hBinding,
02543     LPWSTR pDeviceID,
02544     LPWSTR CustomPropName,
02545     DWORD *pulRegDataType,
02546     BYTE *Buffer,
02547     PNP_RPC_STRING_LEN *pulTransferLen,
02548     PNP_RPC_STRING_LEN *pulLength,
02549     DWORD ulFlags)
02550 {
02551     HKEY hDeviceKey = NULL;
02552     HKEY hParamKey = NULL;
02553     LONG lError;
02554     CONFIGRET ret = CR_SUCCESS;
02555 
02556     UNREFERENCED_PARAMETER(hBinding);
02557 
02558     DPRINT("PNP_GetCustomDevProp() called\n");
02559 
02560     if (pulTransferLen == NULL || pulLength == NULL)
02561     {
02562         ret = CR_INVALID_POINTER;
02563         goto done;
02564     }
02565 
02566     if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
02567     {
02568         ret = CR_INVALID_FLAG;
02569         goto done;
02570     }
02571 
02572     if (*pulLength < *pulTransferLen)
02573         *pulLength = *pulTransferLen;
02574 
02575     *pulTransferLen = 0;
02576 
02577     lError = RegOpenKeyExW(hEnumKey,
02578                            pDeviceID,
02579                            0,
02580                            KEY_READ,
02581                            &hDeviceKey);
02582     if (lError != ERROR_SUCCESS)
02583     {
02584         ret = CR_REGISTRY_ERROR;
02585         goto done;
02586     }
02587 
02588     lError = RegOpenKeyExW(hDeviceKey,
02589                            L"Device Parameters",
02590                            0,
02591                            KEY_READ,
02592                            &hParamKey);
02593     if (lError != ERROR_SUCCESS)
02594     {
02595         ret = CR_REGISTRY_ERROR;
02596         goto done;
02597     }
02598 
02599     lError = RegQueryValueExW(hParamKey,
02600                               CustomPropName,
02601                               NULL,
02602                               pulRegDataType,
02603                               Buffer,
02604                               pulLength);
02605     if (lError != ERROR_SUCCESS)
02606     {
02607         if (lError == ERROR_MORE_DATA)
02608         {
02609             ret = CR_BUFFER_SMALL;
02610         }
02611         else
02612         {
02613             *pulLength = 0;
02614             ret = CR_NO_SUCH_VALUE;
02615         }
02616     }
02617 
02618 done:;
02619     if (ret == CR_SUCCESS)
02620         *pulTransferLen = *pulLength;
02621 
02622     if (hParamKey != NULL)
02623         RegCloseKey(hParamKey);
02624 
02625     if (hDeviceKey != NULL)
02626         RegCloseKey(hDeviceKey);
02627 
02628     DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
02629 
02630     return ret;
02631 }
02632 
02633 
02634 /* Function 62 */
02635 DWORD PNP_GetVersionInternal(
02636     handle_t hBinding,
02637     WORD *pwVersion)
02638 {
02639     *pwVersion = 0x501;
02640     return CR_SUCCESS;
02641     UNIMPLEMENTED;
02642     return CR_CALL_NOT_IMPLEMENTED;
02643 }
02644 
02645 
02646 /* Function 63 */
02647 DWORD PNP_GetBlockedDriverInfo(
02648     handle_t hBinding,
02649     BYTE *Buffer,
02650     PNP_RPC_BUFFER_SIZE *pulTransferLen,
02651     PNP_RPC_BUFFER_SIZE *pulLength,
02652     DWORD ulFlags)
02653 {
02654     UNIMPLEMENTED;
02655     return CR_CALL_NOT_IMPLEMENTED;
02656 }
02657 
02658 
02659 /* Function 64 */
02660 DWORD PNP_GetServerSideDeviceInstallFlags(
02661     handle_t hBinding,
02662     DWORD *pulSSDIFlags,
02663     DWORD ulFlags)
02664 {
02665     UNIMPLEMENTED;
02666     return CR_CALL_NOT_IMPLEMENTED;
02667 }
02668 
02669 
02670 /* Function 65 */
02671 DWORD PNP_GetObjectPropKeys(
02672     handle_t hBinding,
02673     LPWSTR ObjectName,
02674     DWORD ObjectType,
02675     LPWSTR PropertyCultureName,
02676     PNP_PROP_COUNT *PropertyCount,
02677     PNP_PROP_COUNT *TransferLen,
02678     DEVPROPKEY *PropertyKeys,
02679     DWORD Flags)
02680 {
02681     UNIMPLEMENTED;
02682     return CR_CALL_NOT_IMPLEMENTED;
02683 }
02684 
02685 
02686 /* Function 66 */
02687 DWORD PNP_GetObjectProp(
02688     handle_t hBinding,
02689     LPWSTR ObjectName,
02690     DWORD ObjectType,
02691     LPWSTR PropertyCultureName,
02692     const DEVPROPKEY *PropertyKey,
02693     DEVPROPTYPE *PropertyType,
02694     PNP_PROP_SIZE *PropertySize,
02695     PNP_PROP_SIZE *TransferLen,
02696     BYTE *PropertyBuffer,
02697     DWORD Flags)
02698 {
02699     UNIMPLEMENTED;
02700     return CR_CALL_NOT_IMPLEMENTED;
02701 }
02702 
02703 
02704 /* Function 67 */
02705 DWORD PNP_SetObjectProp(
02706     handle_t hBinding,
02707     LPWSTR ObjectName,
02708     DWORD ObjectType,
02709     LPWSTR PropertyCultureName,
02710     const DEVPROPKEY *PropertyKey,
02711     DEVPROPTYPE PropertyType,
02712     PNP_PROP_SIZE PropertySize,
02713     BYTE *PropertyBuffer,
02714     DWORD Flags)
02715 {
02716     UNIMPLEMENTED;
02717     return CR_CALL_NOT_IMPLEMENTED;
02718 }
02719 
02720 
02721 /* Function 68 */
02722 DWORD PNP_InstallDevInst(
02723     handle_t hBinding)
02724 {
02725     UNIMPLEMENTED;
02726     return CR_CALL_NOT_IMPLEMENTED;
02727 }
02728 
02729 
02730 /* Function 69 */
02731 DWORD PNP_ApplyPowerSettings(
02732     handle_t hBinding)
02733 {
02734     UNIMPLEMENTED;
02735     return CR_CALL_NOT_IMPLEMENTED;
02736 }
02737 
02738 
02739 /* Function 70 */
02740 DWORD PNP_DriverStoreAddDriverPackage(
02741     handle_t hBinding)
02742 {
02743     UNIMPLEMENTED;
02744     return CR_CALL_NOT_IMPLEMENTED;
02745 }
02746 
02747 
02748 /* Function 71 */
02749 DWORD PNP_DriverStoreDeleteDriverPackage(
02750     handle_t hBinding)
02751 {
02752     UNIMPLEMENTED;
02753     return CR_CALL_NOT_IMPLEMENTED;
02754 }
02755 
02756 
02757 /* Function 72 */
02758 DWORD PNP_RegisterServiceNotification(
02759     handle_t hBinding)
02760 {
02761     UNIMPLEMENTED;
02762     return CR_CALL_NOT_IMPLEMENTED;
02763 }
02764 
02765 
02766 /* Function 73 */
02767 DWORD PNP_SetActiveService(
02768     handle_t hBinding)
02769 {
02770     UNIMPLEMENTED;
02771     return CR_CALL_NOT_IMPLEMENTED;
02772 }
02773 
02774 
02775 /* Function 74 */
02776 DWORD PNP_DeleteServiceDevices(
02777     handle_t hBinding)
02778 {
02779     UNIMPLEMENTED;
02780     return CR_CALL_NOT_IMPLEMENTED;
02781 }
02782 
02783 
02784 static BOOL
02785 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
02786 {
02787     BOOL DeviceInstalled = FALSE;
02788     DWORD BytesWritten;
02789     DWORD Value;
02790     HANDLE hPipe = INVALID_HANDLE_VALUE;
02791     LPVOID Environment = NULL;
02792     PROCESS_INFORMATION ProcessInfo;
02793     STARTUPINFOW StartupInfo;
02794     UUID RandomUuid;
02795     HKEY DeviceKey;
02796 
02797     /* The following lengths are constant (see below), they cannot overflow */
02798     WCHAR CommandLine[116];
02799     WCHAR InstallEventName[73];
02800     WCHAR PipeName[74];
02801     WCHAR UuidString[39];
02802 
02803     DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
02804 
02805     ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
02806 
02807     if (RegOpenKeyExW(hEnumKey,
02808                       DeviceInstance,
02809                       0,
02810                       KEY_QUERY_VALUE,
02811                       &DeviceKey) == ERROR_SUCCESS)
02812     {
02813         if (RegQueryValueExW(DeviceKey,
02814                              L"Class",
02815                              NULL,
02816                              NULL,
02817                              NULL,
02818                              NULL) == ERROR_SUCCESS)
02819         {
02820             DPRINT("No need to install: %S\n", DeviceInstance);
02821             RegCloseKey(DeviceKey);
02822             return TRUE;
02823         }
02824 
02825         RegCloseKey(DeviceKey);
02826     }
02827 
02828     DPRINT1("Installing: %S\n", DeviceInstance);
02829 
02830     /* Create a random UUID for the named pipe */
02831     UuidCreate(&RandomUuid);
02832     swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
02833         RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
02834         RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
02835         RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
02836         RandomUuid.Data4[6], RandomUuid.Data4[7]);
02837 
02838     /* Create the named pipe */
02839     wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
02840     wcscat(PipeName, UuidString);
02841     hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
02842 
02843     if(hPipe == INVALID_HANDLE_VALUE)
02844     {
02845         DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
02846         goto cleanup;
02847     }
02848 
02849     /* Launch rundll32 to call ClientSideInstallW */
02850     wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
02851     wcscat(CommandLine, PipeName);
02852 
02853     ZeroMemory(&StartupInfo, sizeof(StartupInfo));
02854     StartupInfo.cb = sizeof(StartupInfo);
02855 
02856     if(hUserToken)
02857     {
02858         /* newdev has to run under the environment of the current user */
02859         if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
02860         {
02861             DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
02862             goto cleanup;
02863         }
02864 
02865         if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
02866         {
02867             DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
02868             goto cleanup;
02869         }
02870     }
02871     else
02872     {
02873         /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
02874 
02875            Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
02876            (ShowWizard is only set to FALSE for these two modes) */
02877         ASSERT(!ShowWizard);
02878 
02879         if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
02880         {
02881             DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
02882             goto cleanup;
02883         }
02884     }
02885 
02886     /* Wait for the function to connect to our pipe */
02887     if(!ConnectNamedPipe(hPipe, NULL))
02888     {
02889         DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
02890         goto cleanup;
02891     }
02892 
02893     /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
02894     wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
02895     wcscat(InstallEventName, UuidString);
02896 
02897     Value = sizeof(InstallEventName);
02898     WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
02899     WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
02900 
02901     /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
02902        Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
02903     WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
02904 
02905     Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
02906     WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
02907     WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
02908 
02909     /* Wait for newdev.dll to finish processing */
02910     WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
02911 
02912     /* The following check for success is probably not compatible to Windows, but should do its job */
02913     if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
02914     {
02915         DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
02916         goto cleanup;
02917     }
02918 
02919     DeviceInstalled = Value;
02920 
02921 cleanup:
02922     if(hPipe != INVALID_HANDLE_VALUE)
02923         CloseHandle(hPipe);
02924 
02925     if(Environment)
02926         DestroyEnvironmentBlock(Environment);
02927 
02928     if(ProcessInfo.hProcess)
02929         CloseHandle(ProcessInfo.hProcess);
02930 
02931     if(ProcessInfo.hThread)
02932         CloseHandle(ProcessInfo.hThread);
02933 
02934     DPRINT1("Success? %d\n", DeviceInstalled);
02935 
02936     return DeviceInstalled;
02937 }
02938 
02939 
02940 static LONG
02941 ReadRegSzKey(
02942     IN HKEY hKey,
02943     IN LPCWSTR pszKey,
02944     OUT LPWSTR* pValue)
02945 {
02946     LONG rc;
02947     DWORD dwType;
02948     DWORD cbData = 0;
02949     LPWSTR Value;
02950 
02951     if (!pValue)
02952         return ERROR_INVALID_PARAMETER;
02953 
02954     *pValue = NULL;
02955     rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
02956     if (rc != ERROR_SUCCESS)
02957         return rc;
02958     if (dwType != REG_SZ)
02959         return ERROR_FILE_NOT_FOUND;
02960     Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
02961     if (!Value)
02962         return ERROR_NOT_ENOUGH_MEMORY;
02963     rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
02964     if (rc != ERROR_SUCCESS)
02965     {
02966         HeapFree(GetProcessHeap(), 0, Value);
02967         return rc;
02968     }
02969     /* NULL-terminate the string */
02970     Value[cbData / sizeof(WCHAR)] = '\0';
02971 
02972     *pValue = Value;
02973     return ERROR_SUCCESS;
02974 }
02975 
02976 
02977 static BOOL
02978 SetupIsActive(VOID)
02979 {
02980     HKEY hKey = NULL;
02981     DWORD regType, active, size;
02982     LONG rc;
02983     BOOL ret = FALSE;
02984 
02985     rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
02986     if (rc != ERROR_SUCCESS)
02987         goto cleanup;
02988 
02989     size = sizeof(DWORD);
02990     rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
02991     if (rc != ERROR_SUCCESS)
02992         goto cleanup;
02993     if (regType != REG_DWORD || size != sizeof(DWORD))
02994         goto cleanup;
02995 
02996     ret = (active != 0);
02997 
02998 cleanup:
02999     if (hKey != NULL)
03000         RegCloseKey(hKey);
03001 
03002     DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
03003 
03004     return ret;
03005 }
03006 
03007 
03008 static BOOL
03009 IsConsoleBoot(VOID)
03010 {
03011     HKEY ControlKey = NULL;
03012     LPWSTR SystemStartOptions = NULL;
03013     LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
03014     BOOL ConsoleBoot = FALSE;
03015     LONG rc;
03016 
03017     rc = RegOpenKeyExW(
03018         HKEY_LOCAL_MACHINE,
03019         L"SYSTEM\\CurrentControlSet\\Control",
03020         0,
03021         KEY_QUERY_VALUE,
03022         &ControlKey);
03023 
03024     rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
03025     if (rc != ERROR_SUCCESS)
03026         goto cleanup;
03027 
03028     /* Check for CMDCONS in SystemStartOptions */
03029     CurrentOption = SystemStartOptions;
03030     while (CurrentOption)
03031     {
03032         NextOption = wcschr(CurrentOption, L' ');
03033         if (NextOption)
03034             *NextOption = L'\0';
03035         if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
03036         {
03037             DPRINT("Found %S. Switching to console boot\n", CurrentOption);
03038             ConsoleBoot = TRUE;
03039             goto cleanup;
03040         }
03041         CurrentOption = NextOption ? NextOption + 1 : NULL;
03042     }
03043 
03044 cleanup:
03045     if (ControlKey != NULL)
03046         RegCloseKey(ControlKey);
03047     HeapFree(GetProcessHeap(), 0, SystemStartOptions);
03048     return ConsoleBoot;
03049 }
03050 
03051 
03052 /* Loop to install all queued devices installations */
03053 static DWORD WINAPI
03054 DeviceInstallThread(LPVOID lpParameter)
03055 {
03056 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
03057     PSLIST_ENTRY ListEntry;
03058 #else
03059     PLIST_ENTRY ListEntry;
03060 #endif
03061     DeviceInstallParams* Params;
03062     BOOL showWizard;
03063 
03064     UNREFERENCED_PARAMETER(lpParameter);
03065 
03066     WaitForSingleObject(hInstallEvent, INFINITE);
03067 
03068     showWizard = !SetupIsActive() && !IsConsoleBoot();
03069 
03070     while (TRUE)
03071     {
03072 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
03073         ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
03074 #else
03075         if ((BOOL)IsListEmpty(&DeviceInstallListHead))
03076             ListEntry = NULL;
03077         else
03078             ListEntry = RemoveHeadList(&DeviceInstallListHead);
03079 #endif
03080         if (ListEntry == NULL)
03081         {
03082             SetEvent(hNoPendingInstalls);
03083             WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
03084         }
03085         else
03086         {
03087             ResetEvent(hNoPendingInstalls);
03088             Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
03089             InstallDevice(Params->DeviceIds, showWizard);
03090         }
03091     }
03092 
03093     return 0;
03094 }
03095 
03096 
03097 static DWORD WINAPI
03098 PnpEventThread(LPVOID lpParameter)
03099 {
03100     PPLUGPLAY_EVENT_BLOCK PnpEvent;
03101     ULONG PnpEventSize;
03102     NTSTATUS Status;
03103     RPC_STATUS RpcStatus;
03104 
03105     UNREFERENCED_PARAMETER(lpParameter);
03106 
03107     PnpEventSize = 0x1000;
03108     PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
03109     if (PnpEvent == NULL)
03110         return ERROR_OUTOFMEMORY;
03111 
03112     for (;;)
03113     {
03114         DPRINT("Calling NtGetPlugPlayEvent()\n");
03115 
03116         /* Wait for the next pnp event */
03117         Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
03118 
03119         /* Resize the buffer for the PnP event if it's too small. */
03120         if (Status == STATUS_BUFFER_TOO_SMALL)
03121         {
03122             PnpEventSize += 0x400;
03123             HeapFree(GetProcessHeap(), 0, PnpEvent);
03124             PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
03125             if (PnpEvent == NULL)
03126                 return ERROR_OUTOFMEMORY;
03127             continue;
03128         }
03129 
03130         if (!NT_SUCCESS(Status))
03131         {
03132             DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
03133             break;
03134         }
03135 
03136         /* Process the pnp event */
03137         DPRINT("Received PnP Event\n");
03138         if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
03139         {
03140             DeviceInstallParams* Params;
03141             DWORD len;
03142             DWORD DeviceIdLength;
03143 
03144             DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
03145 
03146             DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
03147             if (DeviceIdLength)
03148             {
03149                 /* Queue device install (will be dequeued by DeviceInstallThread */
03150                 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
03151                 Params = HeapAlloc(GetProcessHeap(), 0, len);
03152                 if (Params)
03153                 {
03154                     wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
03155 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
03156                     InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
03157 #else
03158                     InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
03159 #endif
03160                     SetEvent(hDeviceInstallListNotEmpty);
03161                 }
03162             }
03163         }
03164         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
03165         {
03166             DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
03167             /* FIXME: ? */
03168         }
03169         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
03170         {
03171             DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
03172         }
03173         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
03174         {
03175             DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
03176         }
03177         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
03178         {
03179             DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
03180         }
03181         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
03182         {
03183             DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
03184         }
03185         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
03186         {
03187             DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
03188         }
03189         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
03190         {
03191             DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
03192         }
03193         else
03194         {
03195             DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
03196                 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
03197                 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
03198                 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
03199                 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
03200         }
03201 
03202         /* Dequeue the current pnp event and signal the next one */
03203         NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
03204     }
03205 
03206     HeapFree(GetProcessHeap(), 0, PnpEvent);
03207 
03208     return ERROR_SUCCESS;
03209 }
03210 
03211 
03212 static VOID
03213 UpdateServiceStatus(DWORD dwState)
03214 {
03215     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
03216     ServiceStatus.dwCurrentState = dwState;
03217     ServiceStatus.dwControlsAccepted = 0;
03218     ServiceStatus.dwWin32ExitCode = 0;
03219     ServiceStatus.dwServiceSpecificExitCode = 0;
03220     ServiceStatus.dwCheckPoint = 0;
03221 
03222     if (dwState == SERVICE_START_PENDING ||
03223         dwState == SERVICE_STOP_PENDING ||
03224         dwState == SERVICE_PAUSE_PENDING ||
03225         dwState == SERVICE_CONTINUE_PENDING)
03226         ServiceStatus.dwWaitHint = 10000;
03227     else
03228         ServiceStatus.dwWaitHint = 0;
03229 
03230     SetServiceStatus(ServiceStatusHandle,
03231                      &ServiceStatus);
03232 }
03233 
03234 
03235 static DWORD WINAPI
03236 ServiceControlHandler(DWORD dwControl,
03237                       DWORD dwEventType,
03238                       LPVOID lpEventData,
03239                       LPVOID lpContext)
03240 {
03241     DPRINT1("ServiceControlHandler() called\n");
03242 
03243     switch (dwControl)
03244     {
03245         case SERVICE_CONTROL_STOP:
03246             DPRINT1("  SERVICE_CONTROL_STOP received\n");
03247             /* Stop listening to RPC Messages */
03248             RpcMgmtStopServerListening(NULL);
03249             UpdateServiceStatus(SERVICE_STOPPED);
03250             return ERROR_SUCCESS;
03251 
03252         case SERVICE_CONTROL_PAUSE:
03253             DPRINT1("  SERVICE_CONTROL_PAUSE received\n");
03254             UpdateServiceStatus(SERVICE_PAUSED);
03255             return ERROR_SUCCESS;
03256 
03257         case SERVICE_CONTROL_CONTINUE:
03258             DPRINT1("  SERVICE_CONTROL_CONTINUE received\n");
03259             UpdateServiceStatus(SERVICE_RUNNING);
03260             return ERROR_SUCCESS;
03261 
03262         case SERVICE_CONTROL_INTERROGATE:
03263             DPRINT1("  SERVICE_CONTROL_INTERROGATE received\n");
03264             SetServiceStatus(ServiceStatusHandle,
03265                              &ServiceStatus);
03266             return ERROR_SUCCESS;
03267 
03268         case SERVICE_CONTROL_SHUTDOWN:
03269             DPRINT1("  SERVICE_CONTROL_SHUTDOWN received\n");
03270             /* Stop listening to RPC Messages */
03271             RpcMgmtStopServerListening(NULL);
03272             UpdateServiceStatus(SERVICE_STOPPED);
03273             return ERROR_SUCCESS;
03274 
03275         default :
03276             DPRINT1("  Control %lu received\n");
03277             return ERROR_CALL_NOT_IMPLEMENTED;
03278     }
03279 }
03280 
03281 
03282 static VOID CALLBACK
03283 ServiceMain(DWORD argc, LPTSTR *argv)
03284 {
03285     HANDLE hThread;
03286     DWORD dwThreadId;
03287 
03288     UNREFERENCED_PARAMETER(argc);
03289     UNREFERENCED_PARAMETER(argv);
03290 
03291     DPRINT("ServiceMain() called\n");
03292 
03293     ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
03294                                                         ServiceControlHandler,
03295                                                         NULL);
03296     if (!ServiceStatusHandle)
03297     {
03298         DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
03299         return;
03300     }
03301 
03302     UpdateServiceStatus(SERVICE_START_PENDING);
03303 
03304     hThread = CreateThread(NULL,
03305                            0,
03306                            PnpEventThread,
03307                            NULL,
03308                            0,
03309                            &dwThreadId);
03310     if (hThread != NULL)
03311         CloseHandle(hThread);
03312 
03313     hThread = CreateThread(NULL,
03314                            0,
03315                            RpcServerThread,
03316                            NULL,
03317                            0,
03318                            &dwThreadId);
03319     if (hThread != NULL)
03320         CloseHandle(hThread);
03321 
03322     hThread = CreateThread(NULL,
03323                            0,
03324                            DeviceInstallThread,
03325                            NULL,
03326                            0,
03327                            &dwThreadId);
03328     if (hThread != NULL)
03329         CloseHandle(hThread);
03330 
03331     UpdateServiceStatus(SERVICE_RUNNING);
03332 
03333     DPRINT("ServiceMain() done\n");
03334 }
03335 
03336 
03337 int
03338 wmain(int argc, WCHAR *argv[])
03339 {
03340     BOOLEAN OldValue;
03341     DWORD dwError;
03342 
03343     UNREFERENCED_PARAMETER(argc);
03344     UNREFERENCED_PARAMETER(argv);
03345 
03346     DPRINT("Umpnpmgr: main() started\n");
03347 
03348     /* We need this privilege for using CreateProcessAsUserW */
03349     RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
03350 
03351     hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
03352     if (hInstallEvent == NULL)
03353     {
03354         dwError = GetLastError();
03355         DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
03356         return dwError;
03357     }
03358 
03359     hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
03360     if (hDeviceInstallListNotEmpty == NULL)
03361     {
03362         dwError = GetLastError();
03363         DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
03364         return dwError;
03365     }
03366 
03367     hNoPendingInstalls = CreateEventW(NULL,
03368                                       TRUE,
03369                                       FALSE,
03370                                       L"Global\\PnP_No_Pending_Install_Events");
03371     if (hNoPendingInstalls == NULL)
03372     {
03373         dwError = GetLastError();
03374         DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
03375         return dwError;
03376     }
03377 
03378 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
03379     InitializeSListHead(&DeviceInstallListHead);
03380 #else
03381     InitializeListHead(&DeviceInstallListHead);
03382 #endif
03383 
03384     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
03385                             L"System\\CurrentControlSet\\Enum",
03386                             0,
03387                             KEY_ALL_ACCESS,
03388                             &hEnumKey);
03389     if (dwError != ERROR_SUCCESS)
03390     {
03391         DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
03392         return dwError;
03393     }
03394 
03395     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
03396                             L"System\\CurrentControlSet\\Control\\Class",
03397                             0,
03398                             KEY_ALL_ACCESS,
03399                             &hClassKey);
03400     if (dwError != ERROR_SUCCESS)
03401     {
03402         DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
03403         return dwError;
03404     }
03405 
03406     StartServiceCtrlDispatcher(ServiceTable);
03407 
03408     DPRINT("Umpnpmgr: main() done\n");
03409 
03410     ExitThread(0);
03411 
03412     return 0;
03413 }
03414 
03415 /* EOF */

Generated on Sat May 26 2012 04:16:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.