📄 ufnmdd.cpp
字号:
!pPddInterfaceInfo->pfnSetAddress ||
!pPddInterfaceInfo->pfnIsEndpointHalted ||
!pPddInterfaceInfo->pfnInitiateRemoteWakeup ||
!pPddInterfaceInfo->pfnPowerDown ||
!pPddInterfaceInfo->pfnPowerUp ||
!pPddInterfaceInfo->pfnIOControl ) {
fRet = FALSE;
}
return fRet;
}
// Initialize the MDD, PDD, and client.
extern "C"
DWORD
UFN_Init(
LPCTSTR pszContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwErr;
PUFN_MDD_CONTEXT pContext = NULL;
CReg regActive;
UFN_MDD_INTERFACE_INFO MddInterfaceInfo = {
UFN_PDD_INTERFACE_VERSION, &UfnMdd_Notify
};
DEBUGCHK(pszContext);
if (!regActive.Open(HKEY_LOCAL_MACHINE, pszContext)) {
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open active key\r\n"), pszFname));
goto EXIT;
}
// Allocate our context
pContext = (PUFN_MDD_CONTEXT) LocalAlloc(LPTR, sizeof(*pContext));
if (pContext == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname,
GetLastError()));
goto EXIT;
}
pContext->dwSig = UFN_MDD_SIG;
pContext->Speed = BS_UNKNOWN_SPEED;
pContext->bEnterTestMode = FALSE;
pContext->iTestMode = 0;
InitializeCriticalSection(&pContext->csMddAccess);
InitializeCriticalSection(&pContext->csBusIoctlAccess);
pContext->hevReadyForNotifications = CreateEvent(NULL, TRUE, TRUE, NULL);
if (pContext->hevReadyForNotifications == NULL) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to create event. Error = %d\r\n"),
pszFname, dwErr));
goto EXIT;
}
// Open the device key
pContext->hKey = OpenDeviceKey(pszContext);
if (pContext->hKey == NULL) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open device key \"%s\". Error = %d\r\n"),
pszFname, pszContext, dwErr));
goto EXIT;
}
pContext->pUfnBus = new CUfnBus(pszContext, pContext);
if ( (pContext->pUfnBus == NULL) || (!pContext->pUfnBus->Init()) ) {
goto EXIT;
}
// Initialize the PDD
dwErr = UfnPdd_Init(pszContext, pContext, &MddInterfaceInfo, &pContext->PddInfo);
if (dwErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s PDD initialization failed.\r\n"), pszFname));
goto EXIT;
}
if (IsPddInterfaceInfoValid(&pContext->PddInfo)) {
DEBUGMSG(ZONE_INIT, (_T("%s PDD has %u endpoints\r\n"), pszFname,
pContext->PddInfo.dwEndpointCount));
DEBUGMSG(ZONE_INIT, (_T("%s PDD supports speeds 0x%x\r\n"), pszFname,
pContext->PddInfo.dwCapabilities));
pContext->fPddInitialized = TRUE;
}
else {
RETAILMSG(1, (_T("%s PDD interface info is invalid.\r\n"),
pszFname));
// Try to call PDD's deinit.
if (pContext->PddInfo.pfnDeinit) {
pContext->PddInfo.pfnDeinit(pContext->PddInfo.pvPddContext);
}
}
EXIT:
if (pContext && !pContext->fPddInitialized) {
// Failed to initialize. Free resources.
FreeContext(pContext);
pContext = NULL;
}
FUNCTION_LEAVE_MSG();
return (DWORD) pContext;
}
extern "C"
BOOL
UFN_PreDeinit (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
VERIFY_PCONTEXT();
ValidateContext(pContext);
// No threads to release
EXIT:
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
// Deinitialize the client, PDD, and MDD.
extern "C"
BOOL
UFN_Deinit (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
VERIFY_PCONTEXT();
ValidateContext(pContext);
FreeContext(pContext);
EXIT:
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
static
VOID
ValidateBusContext(
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext
)
{
PREFAST_DEBUGCHK(pBusContext);
DEBUGCHK(pBusContext->dwSig == UFN_MDD_BUS_SIG);
DEBUGCHK(pBusContext->pMddContext);
ValidateContext(pBusContext->pMddContext);
DEBUGCHK(pBusContext->hkClients);
}
extern "C"
DWORD
UFN_Open (
DWORD dwContext,
DWORD dwAccessMode,
DWORD dwShareMode
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
if (dwAccessMode & DEVACCESS_BUSNAMESPACE) {
// This is a bus access
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext = (PUFN_MDD_BUS_OPEN_CONTEXT)
LocalAlloc(LPTR, sizeof(UFN_MDD_BUS_OPEN_CONTEXT));
if (pBusContext) {
pBusContext->dwSig = UFN_MDD_BUS_SIG;
pBusContext->pMddContext = pContext;
DWORD dwErr = CUfnBus::OpenFunctionKey(&pBusContext->hkClients);
if (dwErr != ERROR_SUCCESS) {
LocalFree(pBusContext);
pBusContext = NULL;
}
}
if (pBusContext) {
ValidateBusContext(pBusContext);
}
dwRet = (DWORD) pBusContext;
}
else {
// Standard access
dwRet = (DWORD) pContext;
}
FUNCTION_LEAVE_MSG();
return dwRet;
}
extern "C"
BOOL
UFN_PreClose (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
dwRet = ERROR_INVALID_HANDLE;
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pBusContext);
}
else if (pMddContextSig->dwSig == UFN_MDD_SIG) {
PUFN_MDD_CONTEXT pMddContext =
(PUFN_MDD_CONTEXT) pMddContextSig;
ValidateContext(pMddContext);
}
// No threads to release.
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
}
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
extern "C"
BOOL
UFN_Close (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
dwRet = ERROR_INVALID_HANDLE;
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pBusContext);
RegCloseKey(pBusContext->hkClients);
LocalFree(pBusContext);
}
else if (pMddContextSig->dwSig == UFN_MDD_SIG) {
PUFN_MDD_CONTEXT pMddContext =
(PUFN_MDD_CONTEXT) pMddContextSig;
ValidateContext(pMddContext);
}
else {
DEBUGCHK(FALSE);
dwRet = ERROR_INVALID_HANDLE;
}
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
}
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
// Pass power down request to the PDD.
extern "C"
void
UFN_PowerDown(
DWORD dwContext
)
{
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
if (!pContext->pUfnBus->IsChildPowerManaged()) {
pContext->pUfnBus->SetChildDevicePowerState(D4);
}
pContext->PddInfo.pfnPowerDown(pContext->PddInfo.pvPddContext);
}
// Pass power up request to the PDD.
extern "C"
void
UFN_PowerUp(
DWORD dwContext
)
{
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
pContext->PddInfo.pfnPowerUp(pContext->PddInfo.pvPddContext);
if (!pContext->pUfnBus->IsChildPowerManaged()) {
pContext->pUfnBus->SetChildDevicePowerState(D0);
}
}
DWORD
GetClientFunctions(
PUFN_FUNCTIONS pUfnFunctions
)
{
SETFNAME();
PREFAST_DEBUGCHK(pUfnFunctions);
DWORD dwRet = ERROR_SUCCESS;
pUfnFunctions->lpRegisterDevice = &UfnMdd_RegisterDevice;
pUfnFunctions->lpStart = &UfnMdd_Start;
pUfnFunctions->lpStop = &UfnMdd_Stop;
pUfnFunctions->lpDeregisterDevice = &UfnMdd_DeregisterDevice;
pUfnFunctions->lpOpenPipe = &UfnMdd_OpenPipe;
pUfnFunctions->lpClosePipe = &UfnMdd_ClosePipe;
pUfnFunctions->lpIssueTransfer = &UfnMdd_IssueTransfer;
pUfnFunctions->lpGetTransferStatus = &UfnMdd_GetTransferStatus;
pUfnFunctions->lpAbortTransfer = &UfnMdd_AbortTransfer;
pUfnFunctions->lpCloseTransfer = &UfnMdd_CloseTransfer;
pUfnFunctions->lpStallPipe = &UfnMdd_StallPipe;
pUfnFunctions->lpClearPipeStall = &UfnMdd_ClearPipeStall;
pUfnFunctions->lpInitiateRemoteWakeup = &UfnMdd_InitiateRemoteWakeup;
pUfnFunctions->lpSendControlStatusHandshake = &UfnMdd_SendControlStatusHandshake;
return dwRet;
}
// IOCTLs with a Function value between 0x200 and 0x2FF are reserved
// for the OEM and the PDD.
extern "C"
BOOL
UFN_IOControl (
DWORD dwContext,
DWORD dwCode,
PBYTE pbInBuf,
DWORD cbInBuf,
PBYTE pbOutBuf,
DWORD cbOutBuf,
PDWORD pcbActualOutBuf
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
BOOL fRet = FALSE;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
SetLastError(ERROR_INVALID_HANDLE);
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pBusContext);
EnterCriticalSection(&pBusContext->pMddContext->csBusIoctlAccess);
fRet = pBusContext->pMddContext->pUfnBus->IOControl(pBusContext, dwCode, pbInBuf, cbInBuf,
pbOutBuf, cbOutBuf, pcbActualOutBuf);
LeaveCriticalSection(&pBusContext->pMddContext->csBusIoctlAccess);
}
else if (pMddContextSig->dwSig == UFN_MDD_SIG) {
PUFN_MDD_CONTEXT pMddContext =
(PUFN_MDD_CONTEXT) pMddContextSig;
ValidateContext(pMddContext);
// Pass all normal IOCTLs to the PDD
DWORD dwRet = pMddContext->PddInfo.pfnIOControl(
pMddContext->PddInfo.pvPddContext, EXTERN_IOCTL, dwCode,
pbInBuf, cbInBuf, pbOutBuf, cbOutBuf, pcbActualOutBuf);
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
}
else {
fRet = TRUE;
}
}
else {
SetLastError(ERROR_INVALID_HANDLE);
}
FUNCTION_LEAVE_MSG();
return fRet;
}
// Send a notification.
BOOL
SendDeviceNotification(
LPUFN_NOTIFY lpNotify,
PVOID pvNotifyParameter,
DWORD dwMsg,
DWORD dwParam
)
{
SETFNAME();
BOOL fRet = TRUE;
__try {
if (lpNotify) {
(*lpNotify)(pvNotifyParameter, dwMsg, dwParam);
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_ERROR, (_T("%s Exception in notification routine!\r\n"), pszFname));
fRet = FALSE;
}
return fRet;
}
extern "C"
BOOL
WINAPI
DllEntry(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpReserved
)
{
SETFNAME();
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hDllHandle);
DEBUGMSG(ZONE_INIT, (_T("%s Attach\r\n"), pszFname));
DisableThreadLibraryCalls((HMODULE) hDllHandle);
svsutil_Initialize();
CTransferQueue<CUfnMddTransfer>::InitializeClass(DEFAULT_TRANSFER_LIST_SIZE);
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (_T("%s Detach\r\n"), pszFname));
CTra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -