Esempio n. 1
0
File: device.c Progetto: iXit/wine
NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
{
    SP_DEVINFO_DATA Data;
    UNICODE_STRING nameW;
    NTSTATUS status;
    HDEVINFO devinfo;
    GUID hidGuid;
    BASE_DEVICE_EXTENSION *ext;

    HidD_GetHidGuid(&hidGuid);
    ext = device->DeviceExtension;

    RtlInitUnicodeString( &nameW, ext->device_name);

    devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_HIDCLASS, NULL, NULL, DIGCF_DEVICEINTERFACE);
    if (!devinfo)
    {
        FIXME( "failed to get ClassDevs %x\n", GetLastError());
        return STATUS_UNSUCCESSFUL;
    }
    Data.cbSize = sizeof(Data);
    if (!SetupDiCreateDeviceInfoW(devinfo, ext->instance_id, &GUID_DEVCLASS_HIDCLASS, NULL, NULL, DICD_INHERIT_CLASSDRVS, &Data))
    {
        if (GetLastError() == ERROR_DEVINST_ALREADY_EXISTS)
        {
            SetupDiDestroyDeviceInfoList(devinfo);
            return STATUS_SUCCESS;
        }
        FIXME( "failed to Create Device Info %x\n", GetLastError());
        goto error;
    }
    if (!SetupDiRegisterDeviceInfo( devinfo, &Data, 0, NULL, NULL, NULL ))
    {
        FIXME( "failed to Register Device Info %x\n", GetLastError());
        goto error;
    }
    SetupDiDestroyDeviceInfoList(devinfo);

    status = IoRegisterDeviceInterface(device, &hidGuid, NULL, &ext->link_name);
    if (status != STATUS_SUCCESS)
    {
        FIXME( "failed to register device interface %x\n", status );
        return status;
    }

    return STATUS_SUCCESS;

error:
    SetupDiDestroyDeviceInfoList(devinfo);
    return STATUS_UNSUCCESSFUL;
}
Esempio n. 2
0
HRESULT
xDiEnumDriverFiles(
	__in_opt HWND Owner,
	__in LPCWSTR OemInfFullPath,
	__in DWORD Flags,
	__in XDI_ENUM_DRIVER_FILE_CALLBACK EnumCallback,
	__in LPVOID EnumContext)
{
	HRESULT hr;
	BOOL success;

	WCHAR infFullPath[MAX_PATH];

	DWORD n = GetFullPathNameW(OemInfFullPath, MAX_PATH, infFullPath, NULL);
	if (0 == n)
	{
		hr = HRESULT_FROM_WIN32(GetLastError());
		hr = (SUCCEEDED(hr)) ? E_FAIL : hr;
		goto error0;
	}

	HDEVINFO devInfoSet = SetupDiCreateDeviceInfoList(NULL, Owner);
	if (INVALID_HANDLE_VALUE == devInfoSet)
	{
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error0;
	}

	SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };

	success = SetupDiCreateDeviceInfoW(
		devInfoSet,
		L"XDI_Temporary_Enumerator",
		&GUID_NULL,
		NULL,
		NULL,
		DICD_GENERATE_ID,
		&devInfoData);

	if (!success)
	{
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error1;
	}

	HSPFILEQ fileQueueHandle = SetupOpenFileQueue();

	if (INVALID_HANDLE_VALUE == fileQueueHandle)
	{
		// Error from SetupOpenFileQueue is only from out-of-memory situation
		// without the last error set
		hr = E_OUTOFMEMORY;
		goto error2;
	}

	SP_DEVINSTALL_PARAMS devInstallParams = {sizeof(SP_DEVINSTALL_PARAMS)};

	success = SetupDiGetDeviceInstallParamsW(
		devInfoSet,
		&devInfoData,
		&devInstallParams);

	if (!success)
	{
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error3;
	}

	//
	// Specify the search path
	//

	hr = StringCchCopyW(
		devInstallParams.DriverPath,
		MAX_PATH,
		infFullPath);

	if (FAILED(hr))
	{
		goto error3;
	}

	devInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
	devInstallParams.FileQueue = fileQueueHandle;
	devInstallParams.Flags |= DI_NOVCP;
	devInstallParams.Flags |= DI_ENUMSINGLEINF;

	success = SetupDiSetDeviceInstallParamsW(
		devInfoSet,
		&devInfoData,
		&devInstallParams);

	if (!success)
	{
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error3;
	}

	//
	// use DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE if possible 
	// to ensure we look at duplicate nodes (which is broken in itself)
	//
#ifndef DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE
#define DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE  0x08000000L  // Don't remove identical driver nodes from the class list
#endif

	if (xDipWindowsXPOrLater())
	{
		devInstallParams.FlagsEx |= DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE;

		success = SetupDiSetDeviceInstallParamsW(
			devInfoSet,
			&devInfoData,
			&devInstallParams);

		if (!success)
		{
			devInstallParams.FlagsEx &= ~DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE;
		}
	}

	//
	// Build a class driver list with every driver
	//

	success = SetupDiBuildDriverInfoList(
		devInfoSet,
		&devInfoData,
		SPDIT_CLASSDRIVER);

	if (!success)
	{
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error3;
	}

	SP_DRVINFO_DATA drvInfoData = { sizeof(SP_DRVINFO_DATA) };

	for (DWORD index = 0; ; ++index)
	{
		success = SetupDiEnumDriverInfoW(
			devInfoSet, 
			&devInfoData, 
			SPDIT_CLASSDRIVER, 
			index, 
			&drvInfoData);

		if (!success)
		{
			break;
		}

		SP_DRVINFO_DETAIL_DATA drvInfoDetail = { sizeof(SP_DRVINFO_DETAIL_DATA) };

		success = SetupDiGetDriverInfoDetailW(
			devInfoSet, 
			&devInfoData,
			&drvInfoData,
			&drvInfoDetail,
			sizeof(SP_DRVINFO_DETAIL_DATA),
			NULL);

		if (!success && ERROR_INSUFFICIENT_BUFFER != GetLastError())
		{
			hr = HRESULT_FROM_SETUPAPI(GetLastError());
			goto error4;
		}

		success = SetupDiSetSelectedDriverW(
			devInfoSet,
			&devInfoData,
			&drvInfoData);

		if (!success)
		{
			hr = HRESULT_FROM_SETUPAPI(GetLastError());
			goto error4;
		}

		if (Flags & XDI_EDF_NO_CLASS_INSTALLER)
		{
			success = SetupDiInstallDriverFiles(
				devInfoSet, &devInfoData);

			if (!success)
			{
				hr = HRESULT_FROM_SETUPAPI(GetLastError());
				goto error4;
			}
		}
		else
		{
			success = SetupDiCallClassInstaller(
				DIF_INSTALLDEVICEFILES, devInfoSet, &devInfoData);

			if (!success)
			{
				hr = HRESULT_FROM_SETUPAPI(GetLastError());
				goto error4;
			}
		}
	}

	//
	// SPQ_SCAN_USE_CALLBACK_EX checks the digital signature of the file
	// We do not want to check the signature here.
	//
	// SPQ_SCAN_FILE_PRESENCE avoids checking the digital signature of the file
	// in Windows XP or later. (Not in Windows 2000) when used 
	// with SPQ_SCAN_USE_CALLBACK_EX
	//

	XDI_ENUM_FQS_CONTEXT fqsContext = {0};
	fqsContext.Callback = EnumCallback;
	fqsContext.CallbackContext = EnumContext;

	DWORD scanResult;
	success = SetupScanFileQueueW(
		fileQueueHandle, 
		SPQ_SCAN_USE_CALLBACK,
		// SPQ_SCAN_USE_CALLBACKEX | SPQ_SCAN_FILE_PRESENCE,
		Owner,
		xDipEnumFileQueueScanCallback,
		&fqsContext,
		&scanResult);

	if (!success)
	{
		//
		// SetupScanFileQueue may fail using SPQ_SCAN_FILE_PRESENSE flag
		// Try again without SPQ_SCAN_FILE_PRESENSE
		// (when using SPQ_SCAN_USE_CALLBACKEX)
		//
		hr = HRESULT_FROM_SETUPAPI(GetLastError());
		goto error4;
	}

	hr = S_OK;

#pragma warning(disable: 4533) // to use goto in cpp

error4:

	SetupDiDestroyDriverInfoList(
		devInfoSet, &devInfoData, SPDIT_CLASSDRIVER);

error3:

	SetupCloseFileQueue(fileQueueHandle);

error2:

	SetupDiDeleteDeviceInfo(devInfoSet, &devInfoData);

error1:

	SetupDiDestroyDeviceInfoList(devInfoSet);

error0:

#pragma warning(default: 4533)

	return hr;
}
Esempio n. 3
0
NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device, LPCWSTR serial, LPCWSTR index)
{
    WCHAR regname[255];
    WCHAR dev_link[255];
    SP_DEVINFO_DATA Data;
    UNICODE_STRING nameW, linkW;
    NTSTATUS status;
    HDEVINFO devinfo;
    GUID hidGuid;
    BASE_DEVICE_EXTENSION *ext;

    HidD_GetHidGuid(&hidGuid);
    ext = device->DeviceExtension;

    sprintfW(dev_link, device_link_fmtW, ext->information.VendorID,
        ext->information.ProductID, index, ext->information.VersionNumber, serial,
        class_guid);
    struprW(dev_link);

    RtlInitUnicodeString( &nameW, ext->device_name);
    RtlInitUnicodeString( &linkW, dev_link );

    TRACE("Create link %s\n", debugstr_w(dev_link));

    ext->link_name = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (lstrlenW(dev_link) + 1));
    lstrcpyW(ext->link_name, dev_link);

    status = IoCreateSymbolicLink( &linkW, &nameW );
    if (status)
    {
        FIXME( "failed to create link error %x\n", status );
        return status;
    }

    sprintfW(regname, device_regname_fmtW, ext->information.VendorID, ext->information.ProductID, index, ext->information.VersionNumber, serial);

    devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_HIDCLASS, NULL, NULL, DIGCF_DEVICEINTERFACE);
    if (!devinfo)
    {
        FIXME( "failed to get ClassDevs %x\n", GetLastError());
        return GetLastError();
    }
    Data.cbSize = sizeof(Data);
    if (!SetupDiCreateDeviceInfoW(devinfo, regname, &GUID_DEVCLASS_HIDCLASS, NULL, NULL, DICD_INHERIT_CLASSDRVS, &Data))
    {
        if (GetLastError() == ERROR_DEVINST_ALREADY_EXISTS)
        {
            SetupDiDestroyDeviceInfoList(devinfo);
            return ERROR_SUCCESS;
        }
        FIXME( "failed to Create Device Info %x\n", GetLastError());
        return GetLastError();
    }
    if (!SetupDiRegisterDeviceInfo( devinfo, &Data, 0, NULL, NULL, NULL ))
    {
        FIXME( "failed to Register Device Info %x\n", GetLastError());
        return GetLastError();
    }
    if (!SetupDiCreateDeviceInterfaceW( devinfo, &Data,  &hidGuid, NULL, 0, NULL))
    {
        FIXME( "failed to Create Device Interface %x\n", GetLastError());
        return GetLastError();
    }
    SetupDiDestroyDeviceInfoList(devinfo);

    return S_OK;
}
Esempio n. 4
0
static
void
create_ramdisk_device(std::string full_inf_file_path,
                      std::string hardware_id) {
  GUID class_guid;
  WCHAR class_name_w[MAX_CLASS_NAME_LEN];
  auto success =
    SetupDiGetINFClassW(w32util::widen(full_inf_file_path).c_str(),
                        &class_guid,
                        class_name_w, safe::numelementsf(class_name_w),
                        nullptr);
  if (!success) w32util::throw_windows_error();

  /* don't install device if it already exists */
  auto create_device = true;
  {
    HDEVINFO device_info_set =
      SetupDiGetClassDevsEx(&class_guid, nullptr, nullptr, 0,
			    nullptr, nullptr, nullptr);
    if (device_info_set == INVALID_HANDLE_VALUE) {
      w32util::throw_setupapi_error();
    }

    SP_DEVINFO_DATA device_info_data;
    zero_object(device_info_data);
    device_info_data.cbSize = sizeof(device_info_data);
    for (DWORD idx = 0;
	 create_device &&
	 SetupDiEnumDeviceInfo(device_info_set, idx, &device_info_data);
	 ++idx) {
      /* first get hardware id reg key for this device info */
      CHAR buffer[1024];
      BOOL success_prop =
	SetupDiGetDeviceRegistryPropertyA(device_info_set,
					  &device_info_data,
					  SPDRP_HARDWAREID,
					  nullptr,
					  (PBYTE) buffer,
					  sizeof(buffer),
					  nullptr);
      if (!success_prop) w32util::throw_setupapi_error();

      PCHAR bp = buffer;
      while(*bp) {
	if (!strcmp(bp, hardware_id.c_str())) {
	  create_device = false;
	  break;
	}
	bp += strlen(bp) + 1;
      }
    }
  }

  // device already exists, no need to create it
  if (!create_device) return;

  auto device_info_set =
    SetupDiCreateDeviceInfoList(&class_guid, NULL);
  if (device_info_set == INVALID_HANDLE_VALUE) w32util::throw_setupapi_error();
  auto _destroy_device_info_set =
    safe::create_deferred(SetupDiDestroyDeviceInfoList, device_info_set);

  SP_DEVINFO_DATA device_info_data;
  zero_object(device_info_data);
  device_info_data.cbSize = sizeof(device_info_data);
  auto success_create_device_info =
    SetupDiCreateDeviceInfoW(device_info_set, class_name_w,
                             &class_guid, nullptr, 0,
                             DICD_GENERATE_ID, &device_info_data);
  if (!success_create_device_info) w32util::throw_setupapi_error();

  // TODO: runtime stack array is a GCC extension
  auto reg_hardware_id_len = hardware_id.size() + 2;
  auto reg_hardware_id_size = reg_hardware_id_len * sizeof(WCHAR);
  auto reg_hardware_id = std::unique_ptr<WCHAR[]>(new WCHAR[reg_hardware_id_len]);
  memset(reg_hardware_id.get(), 0, reg_hardware_id_size);
  memcpy(reg_hardware_id.get(), w32util::widen(hardware_id).data(),
         hardware_id.size() * sizeof(WCHAR));

  auto success_set_hardware_id =
    SetupDiSetDeviceRegistryPropertyW(device_info_set,
                                      &device_info_data,
                                      SPDRP_HARDWAREID,
                                      (BYTE *) reg_hardware_id.get(),
                                      reg_hardware_id_size);
  if (!success_set_hardware_id) w32util::throw_setupapi_error();

  auto success_class_installer =
    SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info_set,
                              &device_info_data);
  if (!success_class_installer) w32util::throw_setupapi_error();

  create_ramdisk_hardware_keys(device_info_set, &device_info_data);
}