USB Architecture in Windows Virtual PC
Some old legacy devices may not have driver support for newer operating systems (Windows® Vista and beyond). Windows® Virtual PC (WVPC) makes it possible to use these devices in Windows® 7, using Windows® XP Mode. Users can, at the same time, utilize the benefits of newer and secure features of Windows® 7. In this article, we will describe the USB architecture in WVPC. Typical USB devices used in a Virtual Machine (VM) are:
- Printers
- Flash memory sticks
- External hard disks
- Webcams and Digital cameras
- Smartcards
Figure 1a: USB Menu on a Virtual Machine’s Tool Bar
Figure 1b: Manage USB Devices for Virtual Applications
Details on using these devices with the VM can be found in an earlier post.
WVPC uses the Redirection Policy Manager (RPM) of the Windows to provide the USB redirection in a Virtual Machine. It loads an alternate driver in the lieu of the original driver to redirect the device to a Virtual machine. WVPC creates a virtualized host controller in the Virtual Machine that is being offered using a VPCBus Channel. For more details, please refer to earlier post.
USB Architecture
The overall USB architecture is shown in Figure 2.
Figure 2: USB Architecture showing a USB Device in VM
USB architecture consists of a server side component running in Host OS and a client side component running in Virtual Machine. The server side involves a Connector driver to manage USB devices and a Stub instance for every USB Device. The client side implements a VPCBus enumerated virtual host controller that supports the subset of the USB driver interfaces that are necessary for compatibility with the supported devices. The redirection process also triggers the connector driver to send commands to the guest to create the PDO for the redirected device. After this the Stub driver, Connector driver and the Virtual bus/hub driver work in unison to enable communication of commands, responses and data between physical USB device and the redirected USB device. Component details are described below:
Server Side (Host OS)
A channel is created by Virtual PC host process (VPC.exe) through the Connector Driver using VPCBus whenever a VM boots up. Also, a server side hub instance is created internally by the Connector with this channel for every VM. There are two drivers on the server side as below:
- The Connector driver provides services regardless of the devices that are currently connected.
- The USB Stub driver is the alternate driver loaded by the USB stack instead of the vendor supplied or system supplied driver for the device using RPM. Please refer Figure 2. The Stub driver just forwards requests from the Connector driver to the PDO created by the hub driver.
A total of up to 8 USB devices can be assigned to a VM at a time. HID and Hub Class Devices cannot be assigned to the VM. The USB devices in VM can be safely removed just like in Host OS whenever the USB device driver supports.
Client Side (Virtual Machine)
The virtual host controller is a VPCBus enumerated bus driver (USB Virtualization Bus Driver) that takes the place of normal host controller driver. It is exposed to the system as two devices – a host controller and a root-hub device.
The virtual hub (USB Virtualization Hub Driver) creates the PDOs that mirror virtualized devices in the parent partition. The PNP manager loads the Client USB device drivers (or stacks of drivers) for the device. The virtual hub driver handles the IOCTLs either locally or sends the same to the USB device using Connector Driver. Please refer Figure 3 showing the Device Manager of Guest and Host.
Figure 3: A USB Device assigned to a Virtual Machine
Power State Changes of Host and Virtual Machine
USB Device assigned to a Virtual Machine reacts to the power state changes of the host OS as well as Virtual Machine. The changes are described below:
Virtual Machine Power State Changes
A USB device gets automatically assigned to host OS whenever a Virtual machine is shutdown, restarted, turned off or saved. The device remains within the VM whenever a VM is put to ‘Sleep’ state.
Host Power State Changes
USB Device gets assigned to host OS on host restart/shutdown/logoff. It remains within the VM on host sleep/hibernate.
Device Sharing vs. USB Device Redirection
Devices like printers, smart cards and USB external/flash drives are shared with Virtual Machine in Integration Features Enabled mode by the (Remote Desktop Protocol) RDP. These devices can be used with host OS as well as the Virtual Machine(s) at the same time. More details about this can be found in an earlier post.
Assigning a USB Device to a VM removes the device from host OS. It is only visible to the Virtual machine it is attached to and an application running on the host OS cannot access the device.
Prevent Device Redirection using Group Policy
Group policy can be used to prevent the redirection of selected USB devices to a Virtual Machine, for security or compliance reasons for example. This can be done at per device/device-class level. Also, all USB devices can be prevented to be used inside a VM. These settings are helpful in an organization where users are not allowed to use these devices in the physical machine as well.
These Group policy settings can be found under Computer Configuration -> Administrative Templates -> System->Device Redirection -> Device Redirection Restrictions as shown below (Figure 4).
Figure 4: Group Policy Settings for USB Device restrictions
There are two group policy settings for the Device Redirection Restrictions as described below:
Preventing redirection of devices that match any of these Device IDs
Enabling this policy setting will prevent the redirection of specific USB devices on a machine that matches the criteria specified in the Value field. For example, to block all USB Audio class devices (USB Class Code 01) for the redirection, the policy needs to be configured with Class_01 as shown below (Figure 5).
Figure 5: Group Policy setting for redirection of specific USB devices restrictions
Preventing redirection of USB devices
Enabling this policy setting will prevent the redirection of all USB devices on a machine.
More details about these policy settings can be found on MSDN here.
Implementation and Code examples
WVPC provides COM support to manage USB devices. The APIs are documented on MSDN at https://msdn.microsoft.com/en-us/library/dd796758(VS.85).aspx. Let’s take a look few scenarios for using these APIs to manage USB devices. A user wants to assign a USB Device whenever a VM is started. Another scenario is that an IT admin wants to restrict the USB Device Redirection feature due to some piracy/security concerns. In these scenarios, a developer can write scripts in VB/powershell or a code in any COM capable language to achieve this. Some samples are provided below:
Assign a USB Device
A developer can use AttachUSBDevice method of IVMVirtualMachine interface to assign a USB device to the VM. A sample C++ code is shown below:
1: // Steps to Assign a Device
2: // Step 1: Get the Virtual PC object
3: // Step 2: Get the Virtual Machine Object
4: // Step 3: Start the Virtual Machine if it's not running
5: // Step 3: Get the USB Device Collection
6: // Step 4: Get the USB Device Object to be assigned based on Device String
7: // Step 5: Assign the Device
8:
9:
10: #define CHECK_NULL_RELEASE(obj) if(obj) \
11: {\
12: obj->Release();\
13: obj = NULL;\
14: }
15:
16: int __cdecl main(int , char* )
17: {
18: IVMVirtualMachine* pVM = NULL;
19: IVMVirtualPC* pIVPC = NULL;
20: HRESULT hr = S_OK;
21: BSTR bName = NULL;
22: VMVMState vmState = vmVMState_Invalid;
23: IVMTask* pIVMTask = NULL;
24: IVMUSBDeviceCollection* pUSBDeviceCollection = NULL;
25: long usbDeviceCount = 0;
26: IVMUSBDevice* pUsbDevice = NULL;
27: long index = 0;
28: BSTR bDeviceString = NULL;
29: bool bDeviceFound = FALSE;
30:
31: // Change the VM name as needed
32: LPWSTR lVMNameToBeAssigned = L"Windows XP Mode";
33:
34: // Change the Device String as needed
35: LPWSTR lUsbDeviceString = L"Cruzer Micro"; //L"Mass Storage Device";
36:
37: // Initialize VPC COM interfaces.
38: hr = InitVPCComInterfaces(&pIVPC);
39: if (hr != S_OK)
40: {
41: goto Cleanup;
42: }
43:
44: // Allocate the Memory for the Virtual Machine Name
45: // on which Device needs to be assigned.
46: bName = SysAllocString(lVMNameToBeAssigned);
47: if (bName == NULL) // Unable to allocate the Memory for VM Name String
48: {
49: hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
50: goto Cleanup;
51: }
52:
53: // Get the Virtual Machine object of the provided VMNAME
54: hr = pIVPC->FindVirtualMachine(bName, &pVM);
55: if (hr != S_OK)
56: {
57: goto Cleanup;
58: }
59:
60: // Start the Virtual Machine if it's not running
61: hr = pVM->get_State(&vmState);
62: if (hr != S_OK)
63: {
64: goto Cleanup;
65: }
66:
67: if(vmState == vmVMState_Running)
68: {
69: // VM is already Running
70: }
71: else
72: {
73: hr = pVM->Startup(&pIVMTask);
74: if (hr !=S_OK)
75: {
76: goto Cleanup;
77: }
78:
79: // Wait till the VM boots up
80: hr = pIVMTask->WaitForCompletion(-1);
81: if (hr != S_OK)
82: {
83: goto Cleanup;
84: }
85: }
86:
87: // Get the USB Device Collection
88: hr = pIVPC->get_USBDeviceCollection(&pUSBDeviceCollection);
89: if (hr != S_OK)
90: {
91: goto Cleanup;
92: }
93:
94: // Get the USB Device Collection Count
95: hr = pUSBDeviceCollection->get_Count(&usbDeviceCount);
96: if (hr != S_OK)
97: {
98: goto Cleanup;
99: }
100:
101: if (usbDeviceCount == 0)
102: goto Cleanup;
103:
104: // Iterate through the USB Device Collection for the Device to be Assigned
105: for ( index = 1; index <= usbDeviceCount; index++)
106: {
107: hr = pUSBDeviceCollection->get_Item(index, &pUsbDevice);
108: if (hr != S_OK)
109: goto Cleanup;
110:
111: // Get the Device Name or Manufacturer String
112: hr = pUsbDevice->get_DeviceString(&bDeviceString);
113: if (hr != S_OK)
114: goto Cleanup;
115:
116: // Check the Device String for the Match
117: if (_wcsicmp(bDeviceString, lUsbDeviceString) == 0 )
118: {
119: // Device is Found
120: bDeviceFound = TRUE;
121: break;
122: }
123: }
124:
125: if (bDeviceFound == TRUE)
126: {
127: // Device was found above.
128: // Assign the Device to the VM
129: hr = pVM->AttachUSBDevice(pUsbDevice);
130: if (hr != S_OK)
131: goto Cleanup;
132: }
133:
134: Cleanup:
135: CHECK_NULL_RELEASE(pIVPC);
136: CHECK_NULL_RELEASE(pVM);
137: CHECK_NULL_RELEASE(pUSBDeviceCollection);
138: CHECK_NULL_RELEASE(pUsbDevice);
139: CHECK_NULL_RELEASE(pIVMTask);
140: SysFreeString(bName);
141: SysFreeString(bDeviceString);
142:
143: return 0;
144: }
145:
146: HRESULT
147: InitVPCComInterfaces(
148: __inout IVMVirtualPC** ppIVPC
149: )
150: {
151: HRESULT hr = S_OK;
152: BSTR bVer = NULL;
153:
154: // Initialize COM
155:
156: hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
157: if (hr != S_OK)
158: return hr;
159:
160: REFCLSID classID = _uuidof(VMVirtualPC);
161:
162: // Get the VPC object
163: hr = CoCreateInstance(classID,
164: NULL,
165: CLSCTX_ALL,
166: IID_IVMVirtualPC,
167: (LPVOID*)ppIVPC);
168:
169: if (SUCCEEDED(hr) && (*ppIVPC != NULL))
170: {
171: // Make a call to the VPC interface and see if it works.
172: hr = (*ppIVPC)->get_Version(&bVer);
173: }
174:
175: SysFreeString(bVer);
176: return hr;
177: }
Release a USB Device
Similarly, a developer can use DetachUSBDevice method of IVMVirtualMachine interface to release a USB device from the VM. A sample C++ code is shown below:
1: // Steps to Release a Device
2: // Step 1: Get the Virtual PC object
3: // Step 2: Get the Virtual Machine Object
4: // Step 3: Get the USB Device Collection
5: // Step 4: Get the USB Device Object to be assigned based on Device String
6: // Step 5: Verify the Device is attached to the VM
7: // Step 6: Release the USB Device
8:
9: #define SAFE_RELEASE(obj) if(obj) \
10: {\
11: obj->Release();\
12: obj = NULL;\
13: }
14:
15: int __cdecl main(int , char* )
16: {
17: IVMVirtualMachine* pVM = NULL;
18: IVMVirtualPC* pIVPC = NULL;
19: HRESULT hr = S_OK;
20: BSTR bName = NULL;
21: BSTR bVmNameAttachedTo = NULL;
22: VMVMState vmState = vmVMState_Invalid;
23: IVMUSBDeviceCollection* pUSBDeviceCollection = NULL;
24: long usbDeviceCount = 0;
25: IVMUSBDevice* pUsbDevice = NULL;
26: long index = 0;
27: BSTR bDeviceString = NULL;
28: bool bDeviceFound = FALSE;
29:
30: // Change the VM name as needed
31: LPWSTR lVMNameToBeAssigned = L"Windows XP Mode";
32:
33: // Change the Device String as needed
34: LPWSTR lUsbDeviceString = L"Mass Storage Device";
35:
36: // Initialize VPC COM interfaces.
37: hr = InitVPCComInterfaces(&pIVPC);
38: if (hr != S_OK)
39: {
40: goto Cleanup;
41: }
42:
43: // Allocate the Memory for the Virtual Machine Name
44: // on which Device needs to be assigned.
45: bName = SysAllocString(lVMNameToBeAssigned);
46: if (bName == NULL) // Unable to allocate the Memory for VM Name String
47: {
48: hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
49: goto Cleanup;
50: }
51:
52: // Get the Virtual Machine object of the provided VMNAME
53: hr = pIVPC->FindVirtualMachine(bName, &pVM);
54: if (hr != S_OK)
55: {
56: goto Cleanup;
57: }
58:
59: // Check the Virtual Machine State for Running
60: hr = pVM->get_State(&vmState);
61: if (hr != S_OK)
62: {
63: goto Cleanup;
64: }
65:
66: if(vmState == vmVMState_Running)
67: {
68: // VM is Running
69: }
70: else
71: {
72: // VM is not Running
73: goto Cleanup;
74: }
75:
76: // Get the USB Device Collection
77: hr = pIVPC->get_USBDeviceCollection(&pUSBDeviceCollection);
78: if (hr != S_OK)
79: {
80: goto Cleanup;
81: }
82:
83: // Get the USB Device Collection Count
84: hr = pUSBDeviceCollection->get_Count(&usbDeviceCount);
85: if (hr != S_OK)
86: {
87: goto Cleanup;
88: }
89:
90: if (usbDeviceCount == 0) // No USB Devices Connected to the Machine
91: goto Cleanup;
92:
93: // Iterate through the USB Device Collection for the Device to be Assigned
94: for ( index = 1; index <= usbDeviceCount; index++)
95: {
96: hr = pUSBDeviceCollection->get_Item(index, &pUsbDevice);
97: if (hr != S_OK)
98: goto Cleanup;
99:
100: // Get the Device Name or Manufacturer String
101: hr = pUsbDevice->get_DeviceString(&bDeviceString);
102: if (hr != S_OK)
103: goto Cleanup;
104:
105: // Check the Device String for the Match
106: if (_wcsicmp(bDeviceString, lUsbDeviceString) == 0 )
107: {
108: // Verify that the Device is attached to this VM
109: hr = pUsbDevice->get_AttachedToVM(&bVmNameAttachedTo);
110: if (hr != S_OK)
111: goto Cleanup;
112:
113: if (_wcsicmp(bVmNameAttachedTo, bName) == 0 )
114: {
115: // Device is Found attached to this VM
116: bDeviceFound = TRUE;
117: break;
118: }
119: }
120: }
121:
122: if (bDeviceFound == TRUE)
123: {
124: // Device was found above.
125: // Assign the Device to the VM
126: hr = pVM->DetachUSBDevice(pUsbDevice);
127: if (hr != S_OK)
128: goto Cleanup;
129: }
130:
131: Cleanup:
132: SAFE_RELEASE(pIVPC);
133: SAFE_RELEASE(pVM);
134: SAFE_RELEASE(pUSBDeviceCollection);
135: SAFE_RELEASE(pUsbDevice);
136: SysFreeString(bName);
137: SysFreeString(bDeviceString);
138: SysFreeString(bVmNameAttachedTo);
139:
140: return 0;
141: }
142:
143: HRESULT
144: InitVPCComInterfaces(
145: __inout IVMVirtualPC** ppIVPC
146: )
147: {
148: HRESULT hr = S_OK;
149: BSTR bVer = NULL;
150:
151: // Initialize COM
152:
153: hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
154: if (hr != S_OK)
155: return hr;
156:
157: REFCLSID classID = _uuidof(VMVirtualPC);
158:
159: // Get the VPC object
160: hr = CoCreateInstance(classID,
161: NULL,
162: CLSCTX_ALL,
163: IID_IVMVirtualPC,
164: (LPVOID*)ppIVPC);
165:
166: if (SUCCEEDED(hr) && (*ppIVPC != NULL))
167: {
168: // Make a call to the VPC interface and see if it works.
169: hr = (*ppIVPC)->get_Version(&bVer);
170: }
171:
172: SysFreeString(bVer);
173: return hr;
174: }
Using Group Policy Objects to restrict USB Devices
In Windows 7, GP objects can be managed using Powershell or using COM scripts. These can be extended to restrict USB Devices in Virtual Machines.
Create own applications on top of these APIs
A device gets assigned to host OS whenever the VM is hibernated, shutdown/restarted. WVPC doesn’t provide a direct option to assign a USB device automatically in these scenarios. However, a developer can create their own applications using the above APIs.
Conclusion
Managing USB devices of Windows XP Mode and WVPC is very simple and straightforward. USB devices can be shared or even assigned to a VM. COM APIs can be used to assign-release devices or even creating applications for their own customized scenarios. We hope this information is useful to you.
Technorati Tags: Windows 7,Windows Virtual PC,Windows XP Mode,Networking,Application Compatibility,Windows Upgrade,VPC,VM,Virtual Machine,Virtualization,USB,Device Redirection
Rahul Rajwanshi
SDET
Microsoft Virtualization Team
Comments
Anonymous
February 06, 2010
The comment has been removedAnonymous
October 26, 2010
The comment has been removedAnonymous
November 23, 2010
I do drafting / design with Chief Architect 9.5 full version. I use a hardware lock that connects to my usb port. On Windows XP 32bit works perfect. I've read all compatibly list and Chief Architect design and many other software is there but not my complete software. When i update to Windows7 Professional will I be able to use my Chief Architect 9.5Anonymous
December 13, 2010
Debbie - Have you found anything out? I have Chief Architect X1 and I am having the same issue.Anonymous
December 16, 2010
Hi , I am trying to connect a MPI port from siemens plc s7-300 via converter to usb....but as described above i find no usb tab in my virtual pc 2007.hence the only way i could use pen drive instead was through sharing.please help how to get usb port in settings of virtual pc so that connect my plc to xp mode.Please help. <a target='_blank' href='img196.imageshack.us/.../& src='img196.imageshack.us/.../nousb.th.jpg& border='0'/></a> or img196.imageshack.us/img19Anonymous
February 03, 2011
That's my case, and I'm hopless about it. I have a Philips Foot Control, an USB device tha control commands Play, Rewind and Forwind on my bussines software. That device is used with a XP based software. The problem is: The device works with his test and configuration software in windows 7. The software works without that device in windows 7. They works together on windows XP They don't works together in windows 7. Then, I used the XP Mode trying to make them work together again, but the Windows Virtual PC don't recognize the device. Someone can help me?Anonymous
June 29, 2011
Why can I not run xp xp64 on dualing partitions ?Anonymous
May 06, 2012
When tring to use the Analog Recorder in Microsoft Plus! Digital Media Edition in virtual XP mode on Windows 7, its states that it does not recognize the recording device and that it needs to be reconfigured. Trouble is, there is no way to reconfigure the recording device in virtual XP mode. Is there a workaround, or is this a lost cause? Thanks.