2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 2005 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
2009-10-27 10:34:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2015-09-12 10:58:07 +00:00
|
|
|
* FILE: base/services/umpnpmgr/umpnpmgr.c
|
2005-07-31 12:11:56 +00:00
|
|
|
* PURPOSE: User-mode Plug and Play manager
|
2017-04-17 11:34:08 +00:00
|
|
|
* PROGRAMMER: Eric Kohl (eric.kohl@reactos.org)
|
2022-03-20 16:21:45 +00:00
|
|
|
* Hervé Poussineau (hpoussin@reactos.org)
|
2009-04-14 22:31:36 +00:00
|
|
|
* Colin Finck (colin@reactos.org)
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
2014-09-25 23:44:28 +00:00
|
|
|
|
2019-05-30 09:48:29 +00:00
|
|
|
#include "precomp.h"
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2019-05-30 09:48:29 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2010-02-27 17:15:49 +00:00
|
|
|
static WCHAR ServiceName[] = L"PlugPlay";
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2010-02-27 17:15:49 +00:00
|
|
|
static SERVICE_STATUS_HANDLE ServiceStatusHandle;
|
|
|
|
static SERVICE_STATUS ServiceStatus;
|
|
|
|
|
2019-05-30 09:48:29 +00:00
|
|
|
HKEY hEnumKey = NULL;
|
|
|
|
HKEY hClassKey = NULL;
|
2019-06-19 15:51:11 +00:00
|
|
|
BOOL g_IsUISuppressed = FALSE;
|
2005-12-17 19:58:23 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2010-02-27 17:15:49 +00:00
|
|
|
static VOID
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(
|
|
|
|
_In_ DWORD dwState,
|
|
|
|
_In_ DWORD dwCheckPoint)
|
2010-02-27 17:15:49 +00:00
|
|
|
{
|
|
|
|
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
|
ServiceStatus.dwCurrentState = dwState;
|
|
|
|
ServiceStatus.dwWin32ExitCode = 0;
|
|
|
|
ServiceStatus.dwServiceSpecificExitCode = 0;
|
2022-03-20 16:21:45 +00:00
|
|
|
ServiceStatus.dwCheckPoint = dwCheckPoint;
|
|
|
|
|
|
|
|
if (dwState == SERVICE_RUNNING)
|
|
|
|
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN;
|
|
|
|
else
|
|
|
|
ServiceStatus.dwControlsAccepted = 0;
|
2010-02-27 17:15:49 +00:00
|
|
|
|
|
|
|
if (dwState == SERVICE_START_PENDING ||
|
|
|
|
dwState == SERVICE_STOP_PENDING ||
|
|
|
|
dwState == SERVICE_PAUSE_PENDING ||
|
|
|
|
dwState == SERVICE_CONTINUE_PENDING)
|
|
|
|
ServiceStatus.dwWaitHint = 10000;
|
|
|
|
else
|
|
|
|
ServiceStatus.dwWaitHint = 0;
|
|
|
|
|
|
|
|
SetServiceStatus(ServiceStatusHandle,
|
|
|
|
&ServiceStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD WINAPI
|
|
|
|
ServiceControlHandler(DWORD dwControl,
|
|
|
|
DWORD dwEventType,
|
|
|
|
LPVOID lpEventData,
|
|
|
|
LPVOID lpContext)
|
|
|
|
{
|
|
|
|
DPRINT1("ServiceControlHandler() called\n");
|
|
|
|
|
|
|
|
switch (dwControl)
|
|
|
|
{
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
DPRINT1(" SERVICE_CONTROL_STOP received\n");
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_STOP_PENDING, 1);
|
2011-08-15 20:55:07 +00:00
|
|
|
/* Stop listening to RPC Messages */
|
|
|
|
RpcMgmtStopServerListening(NULL);
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_STOPPED, 0);
|
2010-02-27 17:15:49 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
|
|
DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_PAUSED, 0);
|
2010-02-27 17:15:49 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
|
|
DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_RUNNING, 0);
|
2010-02-27 17:15:49 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
|
|
DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
|
|
|
|
SetServiceStatus(ServiceStatusHandle,
|
|
|
|
&ServiceStatus);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
|
|
DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_STOP_PENDING, 1);
|
2011-10-29 21:54:24 +00:00
|
|
|
/* Stop listening to RPC Messages */
|
|
|
|
RpcMgmtStopServerListening(NULL);
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_STOPPED, 0);
|
2010-02-27 17:15:49 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
default :
|
2015-06-08 23:29:59 +00:00
|
|
|
DPRINT1(" Control %lu received\n", dwControl);
|
2010-02-27 17:15:49 +00:00
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 15:51:11 +00:00
|
|
|
static DWORD
|
|
|
|
GetBooleanRegValue(
|
|
|
|
IN HKEY hKey,
|
|
|
|
IN PCWSTR lpSubKey,
|
|
|
|
IN PCWSTR lpValue,
|
|
|
|
OUT PBOOL pValue)
|
|
|
|
{
|
|
|
|
DWORD dwError, dwType, dwData;
|
|
|
|
DWORD cbData = sizeof(dwData);
|
|
|
|
HKEY hSubKey = NULL;
|
|
|
|
|
|
|
|
/* Default value */
|
|
|
|
*pValue = FALSE;
|
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(hKey,
|
|
|
|
lpSubKey,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT("GetBooleanRegValue(): RegOpenKeyExW() has failed to open '%S' key! (Error: %lu)\n",
|
|
|
|
lpSubKey, dwError);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hSubKey,
|
|
|
|
lpValue,
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
(PBYTE)&dwData,
|
|
|
|
&cbData);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT("GetBooleanRegValue(): RegQueryValueExW() has failed to query '%S' value! (Error: %lu)\n",
|
|
|
|
lpValue, dwError);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
if (dwType != REG_DWORD)
|
|
|
|
{
|
|
|
|
DPRINT("GetBooleanRegValue(): The value is not of REG_DWORD type!\n");
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the value */
|
|
|
|
*pValue = (dwData == 1);
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
GetSuppressNewUIValue(VOID)
|
|
|
|
{
|
|
|
|
BOOL bSuppressNewHWUI = FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Query the SuppressNewHWUI policy registry value. Don't cache it
|
|
|
|
* as we want to update our behaviour in consequence.
|
|
|
|
*/
|
|
|
|
GetBooleanRegValue(HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Policies\\Microsoft\\Windows\\DeviceInstall\\Settings",
|
|
|
|
L"SuppressNewHWUI",
|
|
|
|
&bSuppressNewHWUI);
|
|
|
|
if (bSuppressNewHWUI)
|
|
|
|
DPRINT("GetSuppressNewUIValue(): newdev.dll's wizard UI won't be shown!\n");
|
|
|
|
|
|
|
|
return bSuppressNewHWUI;
|
|
|
|
}
|
2010-02-27 17:15:49 +00:00
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
VOID WINAPI
|
2010-02-22 19:26:54 +00:00
|
|
|
ServiceMain(DWORD argc, LPTSTR *argv)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2010-02-22 19:26:54 +00:00
|
|
|
HANDLE hThread;
|
|
|
|
DWORD dwThreadId;
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(argc);
|
|
|
|
UNREFERENCED_PARAMETER(argv);
|
|
|
|
|
|
|
|
DPRINT("ServiceMain() called\n");
|
|
|
|
|
2010-02-27 17:15:49 +00:00
|
|
|
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
|
|
|
|
ServiceControlHandler,
|
|
|
|
NULL);
|
|
|
|
if (!ServiceStatusHandle)
|
|
|
|
{
|
|
|
|
DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_START_PENDING, 1);
|
2010-02-27 17:15:49 +00:00
|
|
|
|
2010-02-22 19:26:54 +00:00
|
|
|
hThread = CreateThread(NULL,
|
|
|
|
0,
|
|
|
|
PnpEventThread,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&dwThreadId);
|
|
|
|
if (hThread != NULL)
|
|
|
|
CloseHandle(hThread);
|
|
|
|
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_START_PENDING, 2);
|
|
|
|
|
2010-02-22 19:26:54 +00:00
|
|
|
hThread = CreateThread(NULL,
|
|
|
|
0,
|
|
|
|
RpcServerThread,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&dwThreadId);
|
|
|
|
if (hThread != NULL)
|
|
|
|
CloseHandle(hThread);
|
|
|
|
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_START_PENDING, 3);
|
|
|
|
|
2010-02-22 19:26:54 +00:00
|
|
|
hThread = CreateThread(NULL,
|
|
|
|
0,
|
|
|
|
DeviceInstallThread,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&dwThreadId);
|
|
|
|
if (hThread != NULL)
|
|
|
|
CloseHandle(hThread);
|
|
|
|
|
2022-03-20 16:21:45 +00:00
|
|
|
UpdateServiceStatus(SERVICE_RUNNING, 0);
|
2010-02-27 17:15:49 +00:00
|
|
|
|
2010-02-22 19:26:54 +00:00
|
|
|
DPRINT("ServiceMain() done\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
static DWORD
|
|
|
|
InitializePnPManager(VOID)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2010-02-19 20:03:11 +00:00
|
|
|
BOOLEAN OldValue;
|
2010-02-22 19:26:54 +00:00
|
|
|
DWORD dwError;
|
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
DPRINT("UMPNPMGR: InitializePnPManager() started\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2009-04-14 22:31:36 +00:00
|
|
|
/* We need this privilege for using CreateProcessAsUserW */
|
2010-02-22 19:26:54 +00:00
|
|
|
RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
|
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
hInstallEvent = CreateEventW(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
|
2005-12-17 19:58:23 +00:00
|
|
|
if (hInstallEvent == NULL)
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
[UMPNPMGR][USETUP] Fix the way device-install events are queued and dequeued. Fixes CORE-16103.
Dedicated to the hard work of Joachim Henze! xD
This reverts part of commit 043a98dd (see also commit b2aeafca).
Contrary to what I assumed in commit 043a98dd (and was also assumed in
the older commit b2aeafca), we cannot use the singled-linked lists to
queue and dequeue the PnP device-install events, because:
- the events must be treated from the oldest to the newest ones, for
consistency, otherwise this creates problems, as shown by e.g. CORE-16103;
- the system singled-linked lists only offer access to the top of the
list (like a stack) instead of to both the top and the bottom of the
list, as would be required for a queue. Using the SLISTs would mean
that only the newest-received events would be treated first, while the
oldest (which were the first received) events would be treated last,
and this is wrong.
Therefore one must use e.g. the standard doubly-linked list. Also, using
locked operations (insertion & removal) on the list of device-install
events is necessary, because these operations are done concurrently by
two different threads: PnpEventThread() and DeviceInstallThread().
Since the interlocked linked list functions are not available in user-mode,
we need to use instead locking access through e.g. a mutex.
2020-09-28 20:38:55 +00:00
|
|
|
hNoPendingInstalls = CreateEventW(NULL,
|
|
|
|
TRUE,
|
|
|
|
FALSE,
|
|
|
|
L"Global\\PnP_No_Pending_Install_Events");
|
|
|
|
if (hNoPendingInstalls == NULL)
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
DPRINT1("Could not create the Pending-Install Event! (Error %lu)\n", dwError);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the device-install event list
|
|
|
|
*/
|
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
hDeviceInstallListNotEmpty = CreateEventW(NULL, FALSE, FALSE, NULL);
|
2006-10-02 18:46:39 +00:00
|
|
|
if (hDeviceInstallListNotEmpty == NULL)
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
[UMPNPMGR][USETUP] Fix the way device-install events are queued and dequeued. Fixes CORE-16103.
Dedicated to the hard work of Joachim Henze! xD
This reverts part of commit 043a98dd (see also commit b2aeafca).
Contrary to what I assumed in commit 043a98dd (and was also assumed in
the older commit b2aeafca), we cannot use the singled-linked lists to
queue and dequeue the PnP device-install events, because:
- the events must be treated from the oldest to the newest ones, for
consistency, otherwise this creates problems, as shown by e.g. CORE-16103;
- the system singled-linked lists only offer access to the top of the
list (like a stack) instead of to both the top and the bottom of the
list, as would be required for a queue. Using the SLISTs would mean
that only the newest-received events would be treated first, while the
oldest (which were the first received) events would be treated last,
and this is wrong.
Therefore one must use e.g. the standard doubly-linked list. Also, using
locked operations (insertion & removal) on the list of device-install
events is necessary, because these operations are done concurrently by
two different threads: PnpEventThread() and DeviceInstallThread().
Since the interlocked linked list functions are not available in user-mode,
we need to use instead locking access through e.g. a mutex.
2020-09-28 20:38:55 +00:00
|
|
|
DPRINT1("Could not create the List Event! (Error %lu)\n", dwError);
|
2006-10-02 18:46:39 +00:00
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
[UMPNPMGR][USETUP] Fix the way device-install events are queued and dequeued. Fixes CORE-16103.
Dedicated to the hard work of Joachim Henze! xD
This reverts part of commit 043a98dd (see also commit b2aeafca).
Contrary to what I assumed in commit 043a98dd (and was also assumed in
the older commit b2aeafca), we cannot use the singled-linked lists to
queue and dequeue the PnP device-install events, because:
- the events must be treated from the oldest to the newest ones, for
consistency, otherwise this creates problems, as shown by e.g. CORE-16103;
- the system singled-linked lists only offer access to the top of the
list (like a stack) instead of to both the top and the bottom of the
list, as would be required for a queue. Using the SLISTs would mean
that only the newest-received events would be treated first, while the
oldest (which were the first received) events would be treated last,
and this is wrong.
Therefore one must use e.g. the standard doubly-linked list. Also, using
locked operations (insertion & removal) on the list of device-install
events is necessary, because these operations are done concurrently by
two different threads: PnpEventThread() and DeviceInstallThread().
Since the interlocked linked list functions are not available in user-mode,
we need to use instead locking access through e.g. a mutex.
2020-09-28 20:38:55 +00:00
|
|
|
hDeviceInstallListMutex = CreateMutexW(NULL, FALSE, NULL);
|
|
|
|
if (hDeviceInstallListMutex == NULL)
|
2008-12-06 12:54:24 +00:00
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
[UMPNPMGR][USETUP] Fix the way device-install events are queued and dequeued. Fixes CORE-16103.
Dedicated to the hard work of Joachim Henze! xD
This reverts part of commit 043a98dd (see also commit b2aeafca).
Contrary to what I assumed in commit 043a98dd (and was also assumed in
the older commit b2aeafca), we cannot use the singled-linked lists to
queue and dequeue the PnP device-install events, because:
- the events must be treated from the oldest to the newest ones, for
consistency, otherwise this creates problems, as shown by e.g. CORE-16103;
- the system singled-linked lists only offer access to the top of the
list (like a stack) instead of to both the top and the bottom of the
list, as would be required for a queue. Using the SLISTs would mean
that only the newest-received events would be treated first, while the
oldest (which were the first received) events would be treated last,
and this is wrong.
Therefore one must use e.g. the standard doubly-linked list. Also, using
locked operations (insertion & removal) on the list of device-install
events is necessary, because these operations are done concurrently by
two different threads: PnpEventThread() and DeviceInstallThread().
Since the interlocked linked list functions are not available in user-mode,
we need to use instead locking access through e.g. a mutex.
2020-09-28 20:38:55 +00:00
|
|
|
DPRINT1("Could not create the List Mutex! (Error %lu)\n", dwError);
|
2008-12-06 12:54:24 +00:00
|
|
|
return dwError;
|
|
|
|
}
|
[UMPNPMGR][USETUP] Fix the way device-install events are queued and dequeued. Fixes CORE-16103.
Dedicated to the hard work of Joachim Henze! xD
This reverts part of commit 043a98dd (see also commit b2aeafca).
Contrary to what I assumed in commit 043a98dd (and was also assumed in
the older commit b2aeafca), we cannot use the singled-linked lists to
queue and dequeue the PnP device-install events, because:
- the events must be treated from the oldest to the newest ones, for
consistency, otherwise this creates problems, as shown by e.g. CORE-16103;
- the system singled-linked lists only offer access to the top of the
list (like a stack) instead of to both the top and the bottom of the
list, as would be required for a queue. Using the SLISTs would mean
that only the newest-received events would be treated first, while the
oldest (which were the first received) events would be treated last,
and this is wrong.
Therefore one must use e.g. the standard doubly-linked list. Also, using
locked operations (insertion & removal) on the list of device-install
events is necessary, because these operations are done concurrently by
two different threads: PnpEventThread() and DeviceInstallThread().
Since the interlocked linked list functions are not available in user-mode,
we need to use instead locking access through e.g. a mutex.
2020-09-28 20:38:55 +00:00
|
|
|
InitializeListHead(&DeviceInstallListHead);
|
2006-10-02 18:46:39 +00:00
|
|
|
|
2019-06-19 15:51:11 +00:00
|
|
|
/* Query the SuppressUI registry value and cache it for our whole lifetime */
|
|
|
|
GetBooleanRegValue(HKEY_LOCAL_MACHINE,
|
|
|
|
L"System\\CurrentControlSet\\Services\\PlugPlay\\Parameters",
|
|
|
|
L"SuppressUI",
|
|
|
|
&g_IsUISuppressed);
|
|
|
|
if (g_IsUISuppressed)
|
|
|
|
DPRINT("UMPNPMGR: newdev.dll's wizard UI won't be shown!\n");
|
|
|
|
|
2005-08-01 19:42:19 +00:00
|
|
|
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"System\\CurrentControlSet\\Enum",
|
|
|
|
0,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&hEnumKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"System\\CurrentControlSet\\Control\\Class",
|
|
|
|
0,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&hClassKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
DPRINT("UMPNPMGR: InitializePnPManager() done\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
DllMain(HINSTANCE hinstDLL,
|
|
|
|
DWORD fdwReason,
|
|
|
|
LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
switch (fdwReason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DisableThreadLibraryCalls(hinstDLL);
|
|
|
|
InitializePnPManager();
|
|
|
|
break;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-09-25 23:44:28 +00:00
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|