*/
/* INCLUDES *****************************************************************/
+
//#define HAVE_SLIST_ENTRY_IMPLEMENTED
#define WIN32_NO_STATUS
-#include <windows.h>
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <winsvc.h>
#include <stdio.h>
-#include <cmtypes.h>
#include <cmfuncs.h>
#include <rtlfuncs.h>
#include <setypes.h>
#include <umpnpmgr/sysguid.h>
-#include <wdmguid.h>
#include <cfgmgr32.h>
#include <regstr.h>
#include <userenv.h>
-
-#include <rpc.h>
-#include <rpcdce.h>
-
-#include "pnp_s.h"
+#include <shlwapi.h>
+#include <pnp_s.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ******************************************************************/
-static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
static WCHAR ServiceName[] = L"PlugPlay";
-static SERVICE_TABLE_ENTRYW ServiceTable[] =
-{
- {ServiceName, ServiceMain},
- {NULL, NULL}
-};
static SERVICE_STATUS_HANDLE ServiceStatusHandle;
static SERVICE_STATUS ServiceStatus;
DPRINT("RpcServerThread() called\n");
#if 0
- /* XP-compatible protocol sequence/endpoint */
+ /* 2k/XP/2k3-compatible protocol sequence/endpoint */
Status = RpcServerUseProtseqEpW(L"ncacn_np",
20,
L"\\pipe\\ntsvcs",
DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
#endif
- /* Vista-compatible protocol sequence/endpoint */
+ /* Vista/7-compatible protocol sequence/endpoint */
Status = RpcServerUseProtseqEpW(L"ncacn_np",
20,
L"\\pipe\\plugplay",
pulRegDataType,
Buffer,
pulLength);
- if (lError == ERROR_MORE_DATA)
- {
- ret = CR_BUFFER_SMALL;
- }
- else
+ if (lError != ERROR_SUCCESS)
{
- *pulLength = 0;
- ret = CR_NO_SUCH_VALUE;
+ if (lError == ERROR_MORE_DATA)
+ {
+ ret = CR_BUFFER_SMALL;
+ }
+ else
+ {
+ *pulLength = 0;
+ ret = CR_NO_SUCH_VALUE;
+ }
}
}
else
RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
pDeviceID);
PlugPlayData.Buffer = Buffer;
- PlugPlayData.BufferSize = *pulTransferLen;
+ PlugPlayData.BufferSize = *pulLength;
switch (ulProperty)
{
}
}
-done:;
- *pulTransferLen = (ret != CR_SUCCESS) ? 0 : *pulLength;
+done:
+ *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
if (hKey != NULL)
RegCloseKey(hKey);
if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
{
- if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
+ if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
ret = CR_REGISTRY_ERROR;
}
else
PNP_RPC_STRING_LEN *pulLength,
DWORD ulFlags)
{
- UNIMPLEMENTED;
- return CR_CALL_NOT_IMPLEMENTED;
+ CONFIGRET ret = CR_SUCCESS;
+ LPWSTR lpValueName = NULL;
+ HKEY hInstKey = NULL;
+ HKEY hPropKey = NULL;
+ LONG lError;
+
+ UNREFERENCED_PARAMETER(hBinding);
+
+ DPRINT("PNP_GetClassRegProp() called\n");
+
+ if (pulTransferLen == NULL || pulLength == NULL)
+ {
+ ret = CR_INVALID_POINTER;
+ goto done;
+ }
+
+ if (ulFlags != 0)
+ {
+ ret = CR_INVALID_FLAG;
+ goto done;
+ }
+
+ if (*pulLength < *pulTransferLen)
+ *pulLength = *pulTransferLen;
+
+ *pulTransferLen = 0;
+
+ switch (ulProperty)
+ {
+ case CM_CRP_SECURITY:
+ lpValueName = L"Security";
+ break;
+
+ case CM_CRP_DEVTYPE:
+ lpValueName = L"DeviceType";
+ break;
+
+ case CM_CRP_EXCLUSIVE:
+ lpValueName = L"Exclusive";
+ break;
+
+ case CM_CRP_CHARACTERISTICS:
+ lpValueName = L"DeviceCharacteristics";
+ break;
+
+ default:
+ ret = CR_INVALID_PROPERTY;
+ goto done;
+ }
+
+ DPRINT("Value name: %S\n", lpValueName);
+
+ lError = RegOpenKeyExW(hClassKey,
+ pszClassGuid,
+ 0,
+ KEY_READ,
+ &hInstKey);
+ if (lError != ERROR_SUCCESS)
+ {
+ *pulLength = 0;
+ ret = CR_NO_SUCH_REGISTRY_KEY;
+ goto done;
+ }
+
+ lError = RegOpenKeyExW(hInstKey,
+ L"Properties",
+ 0,
+ KEY_READ,
+ &hPropKey);
+ if (lError != ERROR_SUCCESS)
+ {
+ *pulLength = 0;
+ ret = CR_NO_SUCH_REGISTRY_KEY;
+ goto done;
+ }
+
+ lError = RegQueryValueExW(hPropKey,
+ lpValueName,
+ NULL,
+ pulRegDataType,
+ Buffer,
+ pulLength);
+ if (lError != ERROR_SUCCESS)
+ {
+ if (lError == ERROR_MORE_DATA)
+ {
+ ret = CR_BUFFER_SMALL;
+ }
+ else
+ {
+ *pulLength = 0;
+ ret = CR_NO_SUCH_VALUE;
+ }
+ }
+
+done:
+ if (ret == CR_SUCCESS)
+ *pulTransferLen = *pulLength;
+
+ if (hPropKey != NULL)
+ RegCloseKey(hPropKey);
+
+ if (hInstKey != NULL)
+ RegCloseKey(hInstKey);
+
+ DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
+
+ return ret;
}
switch (ulProperty)
{
- case CM_DRP_SECURITY:
+ case CM_CRP_SECURITY:
lpValueName = L"Security";
break;
- case CM_DRP_DEVTYPE:
+ case CM_CRP_DEVTYPE:
lpValueName = L"DeviceType";
break;
- case CM_DRP_EXCLUSIVE:
+ case CM_CRP_EXCLUSIVE:
lpValueName = L"Exclusive";
break;
- case CM_DRP_CHARACTERISTICS:
+ case CM_CRP_CHARACTERISTICS:
lpValueName = L"DeviceCharacteristics";
break;
ret = CR_REGISTRY_ERROR;
}
-done:;
+done:
if (hPropKey != NULL)
RegCloseKey(hPropKey);
if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
{
- /* FIXME */
- DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
- ret = CR_CALL_NOT_IMPLEMENTED;
- goto done;
- }
+ WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
+ DWORD dwInstanceNumber;
+
+ /* Generated ID is: Root\<Device ID>\<Instance number> */
+ dwInstanceNumber = 0;
+ do
+ {
+ swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
+ pszDeviceID, dwInstanceNumber);
- /* Create the device instance */
- ret = CreateDeviceInstance(pszDeviceID);
+ /* Try to create a device instance with this ID */
+ ret = CreateDeviceInstance(szGeneratedInstance);
+
+ dwInstanceNumber++;
+ }
+ while (ret == CR_ALREADY_SUCH_DEVINST);
+
+ if (ret == CR_SUCCESS)
+ {
+ /* pszDeviceID is an out parameter too for generated IDs */
+ if (wcslen(szGeneratedInstance) > ulLength)
+ {
+ ret = CR_BUFFER_SMALL;
+ }
+ else
+ {
+ wcscpy(pszDeviceID, szGeneratedInstance);
+ }
+ }
+ }
+ else
+ {
+ /* Create the device instance */
+ ret = CreateDeviceInstance(pszDeviceID);
+ }
-done:;
DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
return ret;
else
{
swprintf(szKeyName,
- L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
+ L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
ulConfig);
}
DWORD ulProfileInfoSize,
DWORD ulFlags)
{
- UNIMPLEMENTED;
- return CR_CALL_NOT_IMPLEMENTED;
+ WCHAR szProfileName[5];
+ HKEY hKeyConfig = NULL;
+ HKEY hKeyProfiles = NULL;
+ HKEY hKeyProfile = NULL;
+ DWORD dwDisposition;
+ DWORD dwSize;
+ LONG lError;
+ CONFIGRET ret = CR_SUCCESS;
+
+ UNREFERENCED_PARAMETER(hBinding);
+
+ DPRINT("PNP_GetHwProfInfo() called\n");
+
+ if (ulProfileInfoSize == 0)
+ {
+ ret = CR_INVALID_DATA;
+ goto done;
+ }
+
+ if (ulFlags != 0)
+ {
+ ret = CR_INVALID_FLAG;
+ goto done;
+ }
+
+ /* Initialize the profile information */
+ pHWProfileInfo->HWPI_ulHWProfile = 0;
+ pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
+ pHWProfileInfo->HWPI_dwFlags = 0;
+
+ /* Open the 'IDConfigDB' key */
+ lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Control\\IDConfigDB",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_QUERY_VALUE,
+ NULL,
+ &hKeyConfig,
+ &dwDisposition);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+ /* Open the 'Hardware Profiles' subkey */
+ lError = RegCreateKeyExW(hKeyConfig,
+ L"Hardware Profiles",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+ NULL,
+ &hKeyProfiles,
+ &dwDisposition);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+ if (ulIndex == (ULONG)-1)
+ {
+ dwSize = sizeof(ULONG);
+ lError = RegQueryValueExW(hKeyConfig,
+ L"CurrentConfig",
+ NULL,
+ NULL,
+ (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
+ &dwSize);
+ if (lError != ERROR_SUCCESS)
+ {
+ pHWProfileInfo->HWPI_ulHWProfile = 0;
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+ }
+ else
+ {
+ /* FIXME: not implemented yet */
+ ret = CR_CALL_NOT_IMPLEMENTED;
+ goto done;
+ }
+
+ swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
+
+ lError = RegOpenKeyExW(hKeyProfiles,
+ szProfileName,
+ 0,
+ KEY_QUERY_VALUE,
+ &hKeyProfile);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+ dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
+ lError = RegQueryValueExW(hKeyProfile,
+ L"FriendlyName",
+ NULL,
+ NULL,
+ (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
+ &dwSize);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+done:
+ if (hKeyProfile != NULL)
+ RegCloseKey(hKeyProfile);
+
+ if (hKeyProfiles != NULL)
+ RegCloseKey(hKeyProfiles);
+
+ if (hKeyConfig != NULL)
+ RegCloseKey(hKeyConfig);
+
+ return ret;
}
PNP_RPC_STRING_LEN *pulLength,
DWORD ulFlags)
{
- UNIMPLEMENTED;
- return CR_CALL_NOT_IMPLEMENTED;
+ HKEY hDeviceKey = NULL;
+ HKEY hParamKey = NULL;
+ LONG lError;
+ CONFIGRET ret = CR_SUCCESS;
+
+ UNREFERENCED_PARAMETER(hBinding);
+
+ DPRINT("PNP_GetCustomDevProp() called\n");
+
+ if (pulTransferLen == NULL || pulLength == NULL)
+ {
+ ret = CR_INVALID_POINTER;
+ goto done;
+ }
+
+ if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
+ {
+ ret = CR_INVALID_FLAG;
+ goto done;
+ }
+
+ if (*pulLength < *pulTransferLen)
+ *pulLength = *pulTransferLen;
+
+ *pulTransferLen = 0;
+
+ lError = RegOpenKeyExW(hEnumKey,
+ pDeviceID,
+ 0,
+ KEY_READ,
+ &hDeviceKey);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+ lError = RegOpenKeyExW(hDeviceKey,
+ L"Device Parameters",
+ 0,
+ KEY_READ,
+ &hParamKey);
+ if (lError != ERROR_SUCCESS)
+ {
+ ret = CR_REGISTRY_ERROR;
+ goto done;
+ }
+
+ lError = RegQueryValueExW(hParamKey,
+ CustomPropName,
+ NULL,
+ pulRegDataType,
+ Buffer,
+ pulLength);
+ if (lError != ERROR_SUCCESS)
+ {
+ if (lError == ERROR_MORE_DATA)
+ {
+ ret = CR_BUFFER_SMALL;
+ }
+ else
+ {
+ *pulLength = 0;
+ ret = CR_NO_SUCH_VALUE;
+ }
+ }
+
+done:
+ if (ret == CR_SUCCESS)
+ *pulTransferLen = *pulLength;
+
+ if (hParamKey != NULL)
+ RegCloseKey(hParamKey);
+
+ if (hDeviceKey != NULL)
+ RegCloseKey(hDeviceKey);
+
+ DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
+
+ return ret;
}
handle_t hBinding,
WORD *pwVersion)
{
+ *pwVersion = 0x501;
+ return CR_SUCCESS;
UNIMPLEMENTED;
return CR_CALL_NOT_IMPLEMENTED;
}
/* Function 73 */
DWORD PNP_SetActiveService(
- handle_t hBinding)
+ handle_t hBinding,
+ LPWSTR pszFilter,
+ DWORD ulFlags)
{
UNIMPLEMENTED;
return CR_CALL_NOT_IMPLEMENTED;
&DeviceKey) == ERROR_SUCCESS)
{
if (RegQueryValueExW(DeviceKey,
- L"ClassGUID",
+ L"Class",
NULL,
NULL,
NULL,
/* Wait for the function to connect to our pipe */
if(!ConnectNamedPipe(hPipe, NULL))
{
- DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
- goto cleanup;
+ if (GetLastError() != ERROR_PIPE_CONNECTED)
+ {
+ DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
+ goto cleanup;
+ }
}
/* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
if (rc != ERROR_SUCCESS)
goto cleanup;
- /* Check for CMDCONS in SystemStartOptions */
+ /* Check for CONSOLE switch in SystemStartOptions */
CurrentOption = SystemStartOptions;
while (CurrentOption)
{
DWORD len;
DWORD DeviceIdLength;
- DPRINT1("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
if (DeviceIdLength)
}
else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
{
- DPRINT1("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
/* FIXME: ? */
}
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
+ {
+ DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
+ {
+ DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
+ {
+ DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
+ {
+ DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
+ {
+ DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
+ else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
+ {
+ DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
+ }
else
{
DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
{
case SERVICE_CONTROL_STOP:
DPRINT1(" SERVICE_CONTROL_STOP received\n");
+ /* Stop listening to RPC Messages */
+ RpcMgmtStopServerListening(NULL);
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_SHUTDOWN:
DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
+ /* Stop listening to RPC Messages */
+ RpcMgmtStopServerListening(NULL);
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
}
-static VOID CALLBACK
+VOID WINAPI
ServiceMain(DWORD argc, LPTSTR *argv)
{
HANDLE hThread;
DPRINT("ServiceMain() done\n");
}
-
-int
-wmain(int argc, WCHAR *argv[])
+static DWORD
+InitializePnPManager(VOID)
{
BOOLEAN OldValue;
DWORD dwError;
- UNREFERENCED_PARAMETER(argc);
- UNREFERENCED_PARAMETER(argv);
-
- DPRINT("Umpnpmgr: main() started\n");
+ DPRINT("UMPNPMGR: InitializePnPManager() started\n");
/* We need this privilege for using CreateProcessAsUserW */
RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
- hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
+ hInstallEvent = CreateEventW(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
if (hInstallEvent == NULL)
{
dwError = GetLastError();
return dwError;
}
- hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hDeviceInstallListNotEmpty = CreateEventW(NULL, FALSE, FALSE, NULL);
if (hDeviceInstallListNotEmpty == NULL)
{
dwError = GetLastError();
return dwError;
}
- StartServiceCtrlDispatcher(ServiceTable);
+ DPRINT("UMPNPMGR: InitializePnPManager() done\n");
- DPRINT("Umpnpmgr: main() done\n");
+ return 0;
+}
- ExitThread(0);
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+ InitializePnPManager();
+ break;
- return 0;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
}
/* EOF */