STDMETHODIMP CSoftKeyboard::get_Typematic( KEYBOARD_TYPEMATIC_PARAMETERS **ppTypematic) /*++ Routine Description: Implement the get Typematic propery for the interface ISoftInputKbdDevice. Synchronization: None Arguments: ppTypematic - caller gets allocated buffer with the property. Caller must release. Return Value: E_POINTER Invalid pointer for output parameter E_OUTOFMEMORY Could not allocate memory for KEYBOARD_TYPEMATIC_PARAMETERS structure. S_OK otherwise --*/ { HRESULT hr = S_OK; IfFalseHrGo(NULL != ppTypematic, E_POINTER); *ppTypematic = NULL; // Allocate memory for the returned structure *ppTypematic = (KEYBOARD_TYPEMATIC_PARAMETERS*)m_pMalloc->Alloc(sizeof(m_KbdTypematicParam)); if (NULL == *ppTypematic) { hr = E_OUTOFMEMORY; goto Exit; } CopyMemory(*ppTypematic, &m_KbdTypematicParam, sizeof(m_KbdTypematicParam)); Exit: return hr; } // CSoftKeyboard::get_Typematic
STDMETHODIMP CSoftKeyboard::get_IndicatorTranslation( KEYBOARD_INDICATOR_TRANSLATION **ppIndicatorTrans) /*++ Routine Description: Implement the get Indicator translation property for the interface ISoftInputKbdDevice. Synchronization: None Arguments: ppIndicatorTrans - caller gets allocated buffer with the property. Caller must release. Return Value: E_POINTER Invalid pointer for output parameter E_OUTOFMEMORY Could not allocate memory for KEYBOARD_INDICATOR_TRANSLATION structure. S_OK otherwise --*/ { HRESULT hr = S_OK; IfFalseHrGo(NULL != ppIndicatorTrans, E_POINTER); *ppIndicatorTrans = NULL; // Allocate memory for the returned structure *ppIndicatorTrans = (KEYBOARD_INDICATOR_TRANSLATION*)m_pMalloc->Alloc(sizeof(m_KbdIndicatorTrans)); if (NULL == *ppIndicatorTrans) { hr = E_OUTOFMEMORY; goto Exit; } CopyMemory(*ppIndicatorTrans, &m_KbdIndicatorTrans, sizeof(m_KbdIndicatorTrans)); Exit: return hr; } // CSoftKeyboard::get_IndicatorTranslation
STDMETHODIMP CSoftKeyboard::get_IndicatorStatus( INDICATOR_KEY LedKey, VARIANT_BOOL *pfvarStatus) /*++ Routine Description: This property returns the status of a LED indicator. Synchronization: None Arguments: sLedKey - LedKey for which the status is being asked for. pfvarStatus - caller allocated space to hold the property value. Return Value: E_POINTER Invalid pointer for output parameter From called function --*/ { HRESULT hr = S_OK; VARIANT_BOOL fvarStatus = FALSE; // Check if we have valid pointer to returned parameter IfFalseHrGo(NULL != pfvarStatus, E_POINTER); *pfvarStatus = FALSE; fvarStatus = ((m_KbdIndicatorParam.usLedFlags & LedKey) == LedKey); *pfvarStatus = fvarStatus; Exit: return hr; } // CSoftKeyboard::get_IndicatorStatus
HRESULT CSoftHIDInputKbdMapper::ProcessKbdInput() /*++ Routine Description: Reads and handles data from input keyboard buffer. Synchronization: None Arguments: None Return Value: S_OK Success E_FAIL Could not read data from keyboard buffer --*/ { USHORT usUnits = 0; KEYBOARD_INPUT_DATA* pKbdData = NULL; HRESULT hr = S_OK; // Read data from keyboard buffer IfFalseHrGo(NULL != m_piSoftKeyboard, E_FAIL); IfFailHrGo(m_piSoftKeyboard->Read(&usUnits, &pKbdData)); IfFalseHrGo(NULL != pKbdData, E_FAIL); // Check whether Protocol Translator interface pointer is set // If not, do not fail the function, but dispose the data IfFalseHrGo(NULL != m_piSoftProtXlator, S_OK); // Process keyboard data for(USHORT i = 0; i < usUnits; i++) { // Generate Input Report if (GenInputReport((USHORT)pKbdData[i].ulMakeCode, pKbdData[i].usFlags)) { // Send Input Report IfFailHrGo(SendInputReport(&m_InputReport, sizeof(m_InputReport))); } // Report phantom state else { HID_INPUTREPORT PhantomReport; // Initialize Phantom report. Modifier byte is still reported. FillMemory(&PhantomReport, sizeof(PhantomReport), 1); PhantomReport.bReserved = 0; PhantomReport.bModifier = m_InputReport.bModifier; // Send Phantom Report IfFailHrGo(SendInputReport(&PhantomReport, sizeof(PhantomReport))); } } Exit: // Release COM buffer if (NULL != pKbdData) { m_pMalloc->Free(pKbdData); } return hr; } // CSoftHIDInputKbdMapper::ProcessKbdInput
STDMETHODIMP CSoftKeyboard::Read(USHORT *pUnits, KEYBOARD_INPUT_DATA **ppKbdData) /*++ Routine Description: Implement the read method for the interface ISoftInputKbdDevice. Transfers Keyboard input data to the lower layers. When simulated key is pressed or released, a KEYBOARD_INPUT_DATA structure is put into keyboard buffer and IDSFKbdDeviceEvents::KeyTouched event is fired, indicating that Read() method can be called. Synchronization: None Arguments: pUnits - number of KEYBOARD_INPUT_DATA structures there are in the array ppKbdData - Array of KEYBOARD_INPUT_DATA. Return Value: E_POINTER Invalid pointer for output parameter E_OUTOFMEMORY Could not allocate memory for KEYBOARD_INPUT_DATA structures. E_FAIL Internal error prevents proceeding. S_OK Success --*/ { HRESULT hr = S_OK; USHORT usUnits = 0; PVOID pKbdData = NULL; // This method is called from msg pump thread of // the SoftHidDevice so we must protect the buffer m_KbdBufferLock.Lock(); // Check if we have valid pointer to returned parameter IfFalseHrGo(NULL != pUnits, E_POINTER); IfFalseHrGo(NULL != ppKbdData, E_POINTER); *pUnits = 0; *ppKbdData = NULL; // All data in the buffer is stored consequently if (m_usTailAnchor > m_usHeadAnchor) { UINT_PTR cbSize = 0; usUnits = m_usTailAnchor - m_usHeadAnchor; // Calculate size of memory to allocate cbSize = sizeof(KEYBOARD_INPUT_DATA) * usUnits; // Allocate memory pKbdData = m_pMalloc->Alloc(cbSize); IfFalseHrGo(NULL != pKbdData, E_OUTOFMEMORY); // Copy data from keyboard buffer CopyMemory(pKbdData, &m_KbdBuffer[m_usHeadAnchor], cbSize); } // Data is stored in two chunks due to wrap around else if (m_usTailAnchor < m_usHeadAnchor) { UINT_PTR cbSize1 = 0; UINT_PTR cbSize2 = 0; usUnits = cusKeyboardBufferSize - m_usHeadAnchor + m_usTailAnchor; // Calculate size of chunk 1 cbSize1 = sizeof(KEYBOARD_INPUT_DATA) * (cusKeyboardBufferSize - m_usHeadAnchor); // Calculate size of chunk 2 cbSize2 = sizeof(KEYBOARD_INPUT_DATA) * m_usTailAnchor; // Check buffer boundaries for integer uderflow or overflow if ((cbSize1 + cbSize2) > (cusKeyboardBufferSize * sizeof(KEYBOARD_INPUT_DATA)) || (cbSize1 + cbSize2) < cbSize1) { hr = E_FAIL; goto Exit; } // Allocate memory pKbdData = m_pMalloc->Alloc(cbSize1 + cbSize2); IfFalseHrGo(NULL != pKbdData, E_OUTOFMEMORY); // Copy data chunks from keyboard buffer CopyMemory(pKbdData, &m_KbdBuffer[m_usHeadAnchor], cbSize1); //buffer has wrapped around need to copy from the start of the buffer. CopyMemory((PUCHAR)pKbdData + cbSize1, &m_KbdBuffer[0], cbSize2); } // Buffer is empty now m_usHeadAnchor = m_usTailAnchor; Exit: m_KbdBufferLock.Unlock(); *pUnits = usUnits; *ppKbdData = (KEYBOARD_INPUT_DATA*)pKbdData; return hr; } // CSoftKeyboard::Read
STDMETHODIMP CSoftKeyboard::PressAndReleaseKeys( BSTR bstrKeyStrokes) /*++ Routine Description: Implement the PressAndRelease method for the interface ISoftKeyboard. This simulate a key stroke for a UNICODE character Synchronization: None Arguments: bstrKeyStrokes - Keystrokes to be simulated Return Value: E_FAIL Could not generate a sequence of keycodes to simulate a keystroke. E_INVALIDARG Invalid keystroke length. S_OK Success. --*/ { HRESULT hr = S_OK; UINT nUnits = 0; KBD_KEYCODE* pKeyCodes = NULL; UINT nSize = SysStringLen(bstrKeyStrokes); // Check if string is not NULL IfFalseHrGo(nSize != 0, E_INVALIDARG); // Check is Translator property is set IfFalseHrGo(NULL != m_piSoftKbdTranslator, E_UNEXPECTED); hr = m_piSoftKbdTranslator->TranslateString2Keycodes(nSize, bstrKeyStrokes, &nUnits, &pKeyCodes); IfFailHrGo(hr); // Go through returned sequence and queue it for processing for(UINT i = 0; i < nUnits; i++) { // Call PressKey method if (KEY_MAKE == pKeyCodes[i].ucFlag) { IfFailHrGo(PressKey(pKeyCodes[i].KeyCode)); } // Call ReleaseKey method else if (KEY_BREAK == pKeyCodes[i].ucFlag) { IfFailHrGo(ReleaseKey(pKeyCodes[i].KeyCode)); } // Call HitKeyOnce method else if ((KEY_BREAK | KEY_MAKE) == pKeyCodes[i].ucFlag) { IfFailHrGo(HitKeyOnce(pKeyCodes[i].KeyCode)); } // Should never hit this code, but check anyway else { IfFailHrGo(E_FAIL); } } Exit: m_pMalloc->Free(pKeyCodes); return hr; } // CSoftKeyboard::PressAndReleaseKeys
HRESULT CLoopbackDevice::CreateStrings() { HRESULT hr = S_OK; ISoftUSBStringList* piStringList = NULL; ISoftUSBString* piStringManufacturer = NULL; ISoftUSBString* piStringProductDesc = NULL; ISoftUSBString* piStringSerialNo = NULL; ISoftUSBString* piStringConfig = NULL; ISoftUSBString* piStringEndpoint = NULL; BSTR bstrManufacturer = ::SysAllocString(L"Google, Inc"); BSTR bstrProductDesc = ::SysAllocString(L"USB Emulating Device"); BSTR bstrSerialNo = ::SysAllocString(L"123456789ABCDEF"); BSTR bstrConfig = ::SysAllocString(L"Configuration with a single interface"); BSTR bstrEndpoint = ::SysAllocString(L"Interface with bulk IN endpoint and bulk OUT endpoint"); VARIANT varIndex; VariantInit(&varIndex); // Check that all BSTR allocations succeeded IfFalseHrGo(0 != ::SysStringLen(bstrManufacturer), E_OUTOFMEMORY); IfFalseHrGo(0 != ::SysStringLen(bstrProductDesc), E_OUTOFMEMORY); IfFalseHrGo(0 != ::SysStringLen(bstrSerialNo), E_OUTOFMEMORY); IfFalseHrGo(0 != ::SysStringLen(bstrConfig), E_OUTOFMEMORY); IfFalseHrGo(0 != ::SysStringLen(bstrEndpoint), E_OUTOFMEMORY); //Set up the varaint used as the index varIndex.vt = VT_I4; varIndex.lVal = STRING_IDX_MANUFACTURER; //Create and initialize the string descriptors. Also create a string //descriptor index for each. This index is used both to set the string's //descriptors position in the m_piSoftUSBDevice.Strings and is the index value //the GetDescriptors request from the host. Note that we don't use //string descriptor index zero because that is a reserved value for a //device's language ID descriptor. //Get the string list from the device hr = m_piSoftUSBDevice->get_Strings(&piStringList); IfFailHrGo(hr); hr = CoCreateInstance(CLSID_SoftUSBString, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISoftUSBString), reinterpret_cast<void**>(&piStringManufacturer)); IfFailHrGo(hr); IfFailHrGo(piStringManufacturer->put_Value(bstrManufacturer)); IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringManufacturer), varIndex)); hr = CoCreateInstance(CLSID_SoftUSBString, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISoftUSBString), reinterpret_cast<void**>(&piStringProductDesc)); IfFailHrGo(hr); IfFailHrGo(piStringProductDesc->put_Value(bstrProductDesc)); varIndex.lVal = STRING_IDX_PRODUCT_DESC; IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringProductDesc), varIndex)); hr = CoCreateInstance(CLSID_SoftUSBString, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISoftUSBString), reinterpret_cast<void**>(&piStringSerialNo)); IfFailHrGo(hr); IfFailHrGo(piStringSerialNo->put_Value(bstrSerialNo)); varIndex.lVal = STRING_IDX_SERIAL_NO; IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringSerialNo), varIndex)); hr = CoCreateInstance(CLSID_SoftUSBString, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISoftUSBString), reinterpret_cast<void**>(&piStringConfig)); IfFailHrGo(hr); IfFailHrGo(piStringConfig->put_Value(bstrConfig)); varIndex.lVal = STRING_IDX_CONFIG; m_iConfigString = varIndex.lVal; IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringConfig), varIndex)); hr = CoCreateInstance(CLSID_SoftUSBString, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISoftUSBString), reinterpret_cast<void**>(&piStringEndpoint)); IfFailHrGo(hr); IfFailHrGo(piStringEndpoint->put_Value(bstrEndpoint)); varIndex.lVal = STRING_IDX_INTERFACE; m_iInterfaceString = varIndex.lVal; IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringEndpoint), varIndex)); Exit: RELEASE(piStringList); RELEASE(piStringManufacturer); RELEASE(piStringProductDesc); RELEASE(piStringSerialNo); RELEASE(piStringConfig); RELEASE(piStringEndpoint); ::SysFreeString(bstrManufacturer); ::SysFreeString(bstrProductDesc); ::SysFreeString(bstrSerialNo); ::SysFreeString(bstrConfig); ::SysFreeString(bstrEndpoint); return hr; }