📄 usbswitch.cpp
字号:
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Use of this source code is subject to the terms of the Microsoft license agreement
// under which you licensed this source code. If you did not accept the terms of the
// license agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement signed by you and
// Microsoft or, if applicable, see the LICENSE.RTF on your install media.
#include <windows.h>
#define OSV_WINCENET
//ICS
#ifndef OSV_WINCENET
#include <ossvcs.h>
#include <ehm.h>
#include <aygshell.h>
#include <miscsvcs.h>
#include <regext.h>
#else
#include "guts.h"
#include "ehm.h"
#endif
#include <CommCtrl.h>
#include <usbfnioctl.h>
#include <ras.h>
#include <tapi.h>
#include <unimodem.h>
#include "USBSwitchRes.h"
static HINSTANCE g_hInstance = NULL;
static const TCHAR c_szAppMutexName[] = _T("UsbSwitch_sdf$sdf#k");
static const TCHAR c_szDevClass[] = _T("comm/datamodem");
static const TCHAR c_szDefaultConnect[] = _T("Comm\\DefaultConnections");
// Guid for the USB BUS
#define USBBUS_GUID L"{E2BDC372-598F-4619-BC50-54B3F7848D35}"
static const TCHAR c_szDriverRegKey[] = _T("Drivers\\USB\\FunctionDrivers");
static const TCHAR c_szFunctionDriver[] = _T("DefaultClientDriver");
static const TCHAR c_szRndisFnName[] = _T("RNDIS");
static const TCHAR c_szUsbSerialFnName[] = _T("Serial_Class");
static const TCHAR c_szMassStorageFnName[] = _T("Mass_Storage_Class");
static const TCHAR c_szUsbRasName[] = _T("My Connection");
#define ENTERTRACE() Trace(L">>> %S", __FUNCTION__)
#define EXITTRACE(hr) Trace(L"<<< %S (0x%x)", __FUNCTION__, hr)
//ICS
#ifdef OSV_WINCENET
HRESULT RegistryGetString(HKEY hKey,
LPCTSTR pszSubKey,
LPCTSTR pszValueName,
LPTSTR pszData,
UINT cchData)
{
HRESULT hr = S_OK;
HKEY hkey = NULL;
DWORD type, size;
hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, 0, &hKey);
if(hr != ERROR_SUCCESS) return (hr);
hr = RegQueryValueEx(hKey, pszValueName, NULL, &type, NULL, &size);
if(hr != ERROR_SUCCESS) return (hr);
size = (size + 1) * sizeof(WCHAR);
hr = RegQueryValueEx(hKey, pszValueName, NULL, &type, (BYTE *)pszData, &size);
return (hr);
}
HRESULT RegistrySetString(HKEY hKey,
LPCTSTR pszSubKey,
LPCTSTR pszValueName,
LPCTSTR pszData)
{
HRESULT hr = S_OK;
HKEY hkey = NULL;
DWORD type, size;
hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, 0, &hKey);
if(hr != ERROR_SUCCESS) return (hr);
hr = RegQueryValueEx(hKey, pszValueName, NULL, &type, NULL, &size);
if(hr != ERROR_SUCCESS) return (hr);
size = (size + 1) * sizeof(WCHAR);
hr = RegSetValueEx(hKey, pszValueName, NULL, REG_SZ, (BYTE *)pszData, size);
return (hr);
}
#endif
//
// Traces a string to \Windows\ActiveSync
//
void Trace(LPWSTR format, ...)
{
FILE *fOutput = NULL;
WCHAR buffer[1024] = { 0 };
if ((fOutput = fopen("\\NandStorge\\q\\usb.txt", "a+")) != NULL)
{
va_list va;
va_start(va, format);
wvsprintf(buffer, format, va);
va_end(va);
fwprintf(fOutput, buffer);
fwprintf(fOutput, L"\r\n");
fclose(fOutput);
}
}
//
// NULL function. can't do lineInitialize without this function.
//
void CALLBACK
lineCallbackFunc(DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
UNREFERENCED_PARAMETER(dwDevice);
UNREFERENCED_PARAMETER(dwMsg);
UNREFERENCED_PARAMETER(dwCallbackInstance);
UNREFERENCED_PARAMETER(dwParam1);
UNREFERENCED_PARAMETER(dwParam2);
UNREFERENCED_PARAMETER(dwParam3);
}
//
// Finds a device id by TAPI line name
//
HRESULT FindDeviceID(__in LPCTSTR pszDeviceName, __out DWORD* pdwDeviceId, __out LPBOOL pfUnimodem)
{
ENTERTRACE();
Trace(L"pszDeviceName=%s", pszDeviceName);
HRESULT hr = S_OK;
DWORD dwDeviceID = 0;
DWORD dwNumDevices = 0;
LONG lRet = 0;
HLINEAPP hLineApp = NULL;
LPLINEDEVCAPS pDevCaps = NULL;
DWORD cbDevCaps = 0;
LPTSTR pszTSP = NULL;
BOOL fFound = FALSE;
lRet = lineInitialize(&hLineApp, g_hInstance, lineCallbackFunc, __TEXT("RASENTRY"), &dwNumDevices);
CBREx(lRet == 0, HRESULT_FROM_WIN32(lRet));
*pfUnimodem = FALSE;
cbDevCaps = sizeof(LINEDEVCAPS) + 256;
// search for TAPI device whole line name matches pszDeviceName
for (dwDeviceID=0; dwDeviceID < dwNumDevices; dwDeviceID++)
{
pDevCaps = (LPLINEDEVCAPS) LocalAlloc(LPTR, cbDevCaps);
CPR(pDevCaps);
pDevCaps->dwTotalSize = cbDevCaps;
lRet = lineGetDevCaps(hLineApp, dwDeviceID, TAPI_CURRENT_VERSION, 0, pDevCaps);
if (lRet && lRet != LINEERR_STRUCTURETOOSMALL)
{
LocalFree(pDevCaps);
pDevCaps = NULL;
continue;
}
// Even if call succeeds,
// Make sure we get the full devcaps info
if (pDevCaps->dwTotalSize < pDevCaps->dwNeededSize)
{
cbDevCaps = pDevCaps->dwNeededSize;
LocalFree(pDevCaps);
pDevCaps = (LPLINEDEVCAPS) LocalAlloc(LPTR, cbDevCaps);
CPR(pDevCaps);
pDevCaps->dwTotalSize = cbDevCaps;
lRet = lineGetDevCaps(hLineApp, dwDeviceID, TAPI_CURRENT_VERSION, 0, pDevCaps);
if (lRet)
{
LocalFree(pDevCaps);
pDevCaps = NULL;
continue;
}
}
Trace(L"%s", (LPTSTR)((char *)pDevCaps + pDevCaps->dwLineNameOffset));
// Check the TAPI device's line name
if (!_tcscmp((LPTSTR)((char *)pDevCaps + pDevCaps->dwLineNameOffset), pszDeviceName))
{
// it's a match, check for unimodem device
if (pDevCaps->dwProviderInfoSize)
{
pszTSP = (LPTSTR)((DWORD)pDevCaps + pDevCaps->dwProviderInfoOffset);
if (!_tcscmp(pszTSP, __TEXT("UNIMODEM")))
{
*pfUnimodem = TRUE;
}
}
*pdwDeviceId = dwDeviceID;
// we are done
fFound = TRUE;
break;
}
LocalFree(pDevCaps);
pDevCaps = NULL;
}
CBREx(fFound, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
Error:
LocalFree(pDevCaps);
if (hLineApp)
{
lineShutdown(hLineApp);
}
EXITTRACE(hr);
return hr;
}
//
// Sets boud rate on specified RAS entry
//
HRESULT SetBaudRate(RASENTRY *pRasEntry, LPCTSTR pszBaud, LPVARSTRING *ppDevConfig)
{
ENTERTRACE();
HRESULT hr = S_OK;
DWORD dwDeviceID = 0;
BOOL fUnimodem = FALSE;
LONG lRet = 0;
HLINEAPP hLineApp = NULL;
HLINE hLine = NULL;
DWORD cbDevConfig = 0;
DWORD dwNumDevices = 0;
UNIMDM_CHG_DEVCFG UCD = { 0 };
LPVARSTRING pDevConfig = NULL;
hr = FindDeviceID(pRasEntry->szDeviceName, &dwDeviceID, &fUnimodem);
CHR(hr);
CBR(fUnimodem);
lRet = lineInitialize(&hLineApp, g_hInstance, lineCallbackFunc, __TEXT("RASENTRY"), &dwNumDevices);
if (lRet)
{
Trace(L"lineInitialize Failed");
CBR(FALSE);
}
// Open the TAPI device
lRet = lineOpen(hLineApp, dwDeviceID, &hLine, TAPI_CURRENT_VERSION,
0, 0, LINECALLPRIVILEGE_MONITOR,
0, NULL); // leave dwMediaMode==0 so device closes properly
if (lRet)
{
Trace(L"lineOpen Failed");
CBR(FALSE);
}
cbDevConfig = sizeof(VARSTRING) + 256;
pDevConfig = (LPVARSTRING)LocalAlloc(LPTR, cbDevConfig);
CPR(pDevConfig);
pDevConfig->dwTotalSize = cbDevConfig;
lRet = lineGetDevConfig(dwDeviceID, pDevConfig, c_szDevClass);
if (lRet && lRet != LINEERR_STRUCTURETOOSMALL)
{
Trace(L"lineGetDevConfig Failed");
CBR(FALSE);
}
// Even if call succeeds,
// Make sure we get the full devcaps info
if (pDevConfig->dwTotalSize < pDevConfig->dwNeededSize)
{
cbDevConfig = pDevConfig->dwNeededSize;
LocalFree(pDevConfig);
pDevConfig = (LPVARSTRING)LocalAlloc(LPTR, cbDevConfig);
CPR(pDevConfig);
pDevConfig->dwTotalSize = cbDevConfig;
lRet = lineGetDevConfig(dwDeviceID, pDevConfig, c_szDevClass);
CBR(lRet == 0);
}
// Use the lineDevSpecific interface to unimodem to edit the baud rate
// in the devconfig. Only works with unimodem devices.
UCD.dwCommand = UNIMDM_CMD_CHG_DEVCFG;
UCD.lpszDeviceClass = c_szDevClass;
UCD.lpDevConfig = pDevConfig;
UCD.dwOption = UNIMDM_OPT_BAUDRATE;
UCD.dwValue = _tcstol(pszBaud, (TCHAR)0, 10);
lRet = lineDevSpecific(hLine, 0, NULL, &UCD, sizeof(UCD));
// LINEERR_INVALPARAM here probably means it was an IR device.
if (!(lRet & 0x80000000) || (lRet == LINEERR_INVALPARAM) )
{
*ppDevConfig = pDevConfig; // Caller responsible for freeing
pDevConfig = NULL;
}
Error:
if (hLine)
{
VBR(lineClose(hLine) == 0);
}
if (hLineApp)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -