📄 wshirda.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name: wshirda.c
Abstract: Contains winsock helper functions.
Contents:
--*/
#include "irdatdi.h"
//
// Globals.
//
const WINSOCK_MAPPING IRLMP_Mapping = { 1, 3, AF_IRDA, SOCK_STREAM, 0 };
LIST_ENTRY g_SocketList;
CRITICAL_SECTION g_csWshIrda;
INT g_IrdaLinkState;
HANDLE g_hEvWaitToRelLink;
CTEEvent g_evReleaseLink;
///
// IrdaLinkStates
//
#define IRDALINKSTATE_CLOSED 1
#define IRDALINKSTATE_CLOSING 2
#define IRDALINKSTATE_OPENED 3
#define IRDALINKSTATE_OPENING 4
#define IRLMP_OPENSOCKET_MAX_WAIT 10000
//
// Prototypes.
//
static INT
TdiEnumDevices(
PDEVICELIST pDeviceList,
DWORD cDevices
);
static INT
TdiIasQuery(
PIAS_QUERY pIasQuery,
DWORD cbAttrib
);
static INT
TdiReleaseLink(
struct CTEEvent *pEvent,
VOID *pvNULL
);
static VOID
DeleteSocketAttribs(
PIRLMP_SOCKET_CONTEXT pSocket
);
#ifdef DEBUG
#define DUMP_WSHOBJECTS(zone) if (zone) DumpWshObjects()
VOID
DumpWshObjects()
{
PLIST_ENTRY pEntry;
PIRLMP_SOCKET_CONTEXT pContext;
PWSHIRDA_IAS_ATTRIB pAttrib;
EnterCriticalSection(&g_csWshIrda);
DEBUGMSG(1,
(TEXT("*** WSHIRDA Objects : %hs\r\n"),
IsListEmpty(&g_SocketList) ? "EMPTY" : ""));
for (pEntry = g_SocketList.Flink;
pEntry != &g_SocketList;
pEntry = pEntry->Flink)
{
pContext = (PIRLMP_SOCKET_CONTEXT)pEntry;
DEBUGMSG(1,
(TEXT("SockContext:%#x, Excl:%hs LPT:%hs, 9Wire:%hs, Sharp:%hs, Next:%#x\r\n"),
pContext,
pContext->UseExclusiveMode == TRUE ? "T" : "F",
pContext->UseIrLPTMode == TRUE ? "T" : "F",
pContext->Use9WireMode == TRUE ? "T" : "F",
pContext->UseSharpMode == TRUE ? "T" : "F",
pEntry->Flink != &g_SocketList ? pEntry->Flink : NULL));
for (pAttrib = pContext->pIasAttribs;
pAttrib != NULL;
pAttrib = pAttrib->pNext)
{
DEBUGMSG(1, (TEXT(" Socket attribute handle:%#x, Next:%#x\r\n"),
pAttrib->AttributeHandle,
pAttrib->pNext));
}
}
LeaveCriticalSection(&g_csWshIrda);
}
#else // DEBUG
#define DUMP_WSHOBJECTS(zone) ((void)0)
#endif // !DEBUG
/*++
Function: WshIrdaInit
Description: Initializes the WinSock Helper code.
Arguments:
None.
Returns:
STATUS_SUCCESS.
Comments:
--*/
DWORD WshIrdaInit()
{
DEBUGMSG(ZONE_WSHIRDA | ZONE_INIT, (TEXT("WshIrdaInit\r\n")));
g_hEvWaitToRelLink = CreateEvent(
NULL, // security attribs.
TRUE, // manual reset event.
TRUE, // initial state is signalled.
NULL); // no name.
if (g_hEvWaitToRelLink == NULL)
{
return (STATUS_INSUFFICIENT_RESOURCES);
}
InitializeCriticalSection(&g_csWshIrda);
InitializeListHead(&g_SocketList);
CTEInitEvent(&g_evReleaseLink, TdiReleaseLink);
// WinCE miniports start without resources acquired.
g_IrdaLinkState = IRDALINKSTATE_CLOSED;
return (STATUS_SUCCESS);
}
/*++
Function: WshIrdaDeinit
Description: Deinitalizes the WinSock Helper code.
Arguments:
None.
Returns:
STATUS_SUCCESS.
Comments:
--*/
DWORD WshIrdaDeinit()
{
PIRLMP_SOCKET_CONTEXT pSocket;
DEBUGMSG(ZONE_WSHIRDA | ZONE_INIT, (TEXT("WshIrdaDeinit\r\n")));
DUMP_WSHOBJECTS(ZONE_WSHIRDA);
EnterCriticalSection(&g_csWshIrda);
for (pSocket = (PIRLMP_SOCKET_CONTEXT) g_SocketList.Flink;
pSocket != (PIRLMP_SOCKET_CONTEXT) &g_SocketList;
pSocket = (PIRLMP_SOCKET_CONTEXT) pSocket->Linkage.Flink)
{
DeleteSocketAttribs(pSocket);
}
CloseHandle(g_hEvWaitToRelLink);
g_hEvWaitToRelLink = NULL;
LeaveCriticalSection(&g_csWshIrda);
DeleteCriticalSection(&g_csWshIrda);
return (STATUS_SUCCESS);
}
/*****************************************************************************
*
* @func INT | IRLMP_GetSockaddrType |
* Called after bind(). Returns address information.
*
* @rdesc
* NO_ERROR (winerror.h) on success, or (winsock.h)
* @errors
* @ecode WSAEAFNOSUPPORT | AddressFamily != AF_IRDA.
* @ecode WSAEFAULT | SockaddrLen != sizeof(SOCKADDR_IRDA).
*
* @parm PSOCKADDR | pSockaddr |
* Pointer to input SOCKADDR (winsock.h) struct.
* @parm DWORD | SockaddrLen |
* Length of input SOCKADDR struct.
* @parm PSOCKADDR_INFO | pSockaddrInfo |
* Pointer to output SOCKADDR_INFO (tdice.h) struct.
* <nl>pSockaddrInfo.AddressInfo can return
* <nl> SockaddrAddressInfoNormal
* <nl> SockaddrAddressInfoWildcard
* <nl> SockaddrAddressInfoBroadcast
* <nl> SockaddrAddressInfoLoopback
* <nl>pSockaddrInfo.EndPointInfo can return
* <nl> SockaddrEndpointInfoNormal
* <nl> SockaddrEndpointInfoWildcard
* <nl> SockaddrEndpointInfoReserved
* <nl>IrLmp will return SockaddrAddressInfoNormal and
* SockaddrEndpointInfoNormal.
*/
INT
IRLMP_GetSockaddrType(IN PSOCKADDR pSockaddr,
IN DWORD SockaddrLen,
OUT PSOCKADDR_INFO pSockaddrInfo)
{
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_GetSockaddrType(0x%X,0x%X,0x%X)\r\n"),
pSockaddr, SockaddrLen, pSockaddrInfo));
if (SockaddrLen < sizeof(SOCKADDR_IRDA))
return(WSAEFAULT);
if (pSockaddr->sa_family != AF_IRDA)
return WSAEAFNOSUPPORT;
if (((SOCKADDR_IRDA *) pSockaddr)->irdaServiceName[0] == 0)
{
pSockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
pSockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
}
else
{
pSockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
pSockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
}
return(NO_ERROR);
}
/*****************************************************************************
*
* @func INT | IRLMP_GetWildCardSockaddr |
* Called after connect() without previous bind(). Returns a
* SOCKADDR_IRDA suitable for an implicit bind().
*
* @rdesc
* NO_ERROR (winerror.h) on success, or (winsock.h)
* @errors
* @ecode WSAEFAULT | SockaddrLen != sizeof(SOCKADDR_IRDA).
*
* @parm PVOID | pHelperDllSocketContext |
* Pointer to the IRLMP_SOCKET_CONTEXT returned by IRLMP_OpenSocket().
* @parm PSOCKADDR | pSockaddr |
* Pointer to output SOCKADDR (winsock.h) struct.
* @parm PINT | pSockaddrLen |
* Pointer to input and output PSOCKADDR struct length.
*/
INT
IRLMP_GetWildcardSockaddr(IN PVOID pHelperDllSocketContext,
OUT PSOCKADDR pSockaddr,
OUT PINT pSockaddrLen)
{
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_GetWildcardSockaddr(0x%X,0x%X,0x%X)\r\n"),
pHelperDllSocketContext, pSockaddr, pSockaddrLen));
if (*pSockaddrLen < (int)sizeof(SOCKADDR_IRDA))
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IRLMP_GetWildcardSockaddr *pSockaddrLen < sizeof(SOCKADDR_IRDA) %d\r\n")));
return(WSAEFAULT);
}
*pSockaddrLen = sizeof(SOCKADDR_IRDA);
memset(pSockaddr, sizeof(SOCKADDR_IRDA), 0);
((SOCKADDR_IRDA *) pSockaddr)->irdaAddressFamily = AF_IRDA;
return(NO_ERROR);
}
/*****************************************************************************
*
* @func INT | IRLMP_GetSocketInformation |
* Called by the Winsock DLL when a level/option name combination
* is passed to getsockopt() that the winsock DLL does not understand.
*
* @rdesc
* NO_ERROR (winerror.h) on success, or (winsock.h)
* @errors
* @ecode WSAEINVAL | Unsupported level.
* @ecode WSAEFAULT | pOptionLen in invalid.
* @ecode WSAENOPROTOOPT | Unsupported option.
*
* @parm PVOID | pHelperDllSocketContext |
* Pointer to the IRLMP_SOCKET_CONTEXT returned by IRLMP_OpenSocket().
* @parm SOCKET | SocketHandle |
* Handle of the socket for which we're getting information.
* @parm HANDLE | TdiAddressObjectHandle |
* TDI address object of the socket, or NULL.
* @parm HANDLE | TdiConnectionObjectHandle |
* TDI connection object of the socket, or NULL.
* @parm INT | Level |
* level, from getsockopt().
* @parm INT | OptionName |
* optname, from getsockopt().
* @parm PCHAR | pOptionValue |
* optval, from getsockopt().
* @parm PINT | pOptionLen |
* optlen, from getsockopt().
*/
INT
IRLMP_GetSocketInformation(IN PVOID pHelperDllSocketContext,
IN SOCKET SocketHandle,
IN HANDLE TdiAddressObjectHandle,
IN HANDLE TdiConnectionObjectHandle,
IN INT Level,
IN INT OptionName,
OUT PCHAR pOptionValue,
OUT PINT pOptionLen)
{
int Status = WSAENOPROTOOPT;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_GetSocketInformation(0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"),
pHelperDllSocketContext,
(unsigned) SocketHandle,
(unsigned) TdiAddressObjectHandle,
(unsigned) TdiConnectionObjectHandle,
Level,
OptionName,
pOptionValue,
pOptionLen));
if (Level == SOL_INTERNAL && OptionName == SO_CONTEXT)
{
// Copy pHelperDllSocketContext to pOptionValue
if ((*pOptionLen = sizeof(IRLMP_SOCKET_CONTEXT)) <
(int)sizeof(IRLMP_SOCKET_CONTEXT))
{
Status = WSAEFAULT;
goto done;
}
if (pOptionValue != NULL)
{
memcpy(pOptionValue, pHelperDllSocketContext,
sizeof(IRLMP_SOCKET_CONTEXT));
((PIRLMP_SOCKET_CONTEXT)pOptionValue)->Linkage.Flink = NULL;
((PIRLMP_SOCKET_CONTEXT)pOptionValue)->Linkage.Blink = NULL;
((PIRLMP_SOCKET_CONTEXT)pOptionValue)->pIasAttribs = NULL;
}
Status = NO_ERROR;
}
if (Level == SOL_IRLMP && OptionName == IRLMP_SEND_PDU_LEN)
{
PIRLMP_CONNECTION pConn;
if (*pOptionLen < (int)sizeof(DWORD))
{
Status = WSAEFAULT;
goto done;
}
pConn = GETCONN(TdiConnectionObjectHandle);
if (pConn == NULL)
{
Status = WSAEFAULT;
goto done;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (pConn->Use9WireMode)
*(int *) pOptionValue = pConn->SendMaxPDU - 1;
else
*(int *) pOptionValue = pConn->SendMaxPDU;
FREE_CONN_LOCK(pConn);
REFDELCONN(pConn);
Status = NO_ERROR;
}
if (Level == SOL_IRLMP && OptionName == IRLMP_ENUMDEVICES)
{
if (*pOptionLen < (int)sizeof(DWORD))
{
Status = WSAEFAULT;
goto done;
}
Status = TdiEnumDevices(
(PDEVICELIST)pOptionValue,
(*pOptionLen - sizeof(DWORD))/sizeof(IRDA_DEVICE_INFO)
);
}
if (Level == SOL_IRLMP && OptionName == IRLMP_IAS_QUERY)
{
if (*pOptionLen < (int)(sizeof(IAS_QUERY) - 4))
{
Status = WSAEFAULT;
goto done;
}
Status = TdiIasQuery(
(PIAS_QUERY)pOptionValue,
*pOptionLen);
}
done:
return(Status);
}
/*****************************************************************************
*
* @func INT | IRLMP_SetSocketInformation |
* Called by the Winsock DLL when a level/option name combination
* is passed to setsockopt() that the winsock DLL does not understand.
*
* @rdesc
* NO_ERROR (winerror.h) on success, or (winsock.h)
* @errors
* @ecode WSAEINVAL | Unsupported level.
* @ecode WSAEFAULT | pOptionLen in invalid.
* @ecode WSAENOBUFS | No memory.
* @ecode WSAENOPROTOOPT | Unsupported option.
*
* @parm PVOID | pHelperDllSocketContext |
* Pointer to the IRLMP_SOCKET_CONTEXT returned by IRLMP_OpenSocket().
* @parm SOCKET | SocketHandle |
* Handle of the socket for which we're getting information.
* @parm HANDLE | TdiAddressObjectHandle |
* TDI address object of the socket, or NULL.
* @parm HANDLE | TdiConnectionObjectHandle |
* TDI connection object of the socket, or NULL.
* @parm INT | Level |
* level, from setsockopt().
* @parm INT | OptionName |
* optname, from setsockopt().
* @parm PCHAR | pOptionValue |
* optval, from setsockopt().
* @parm INT | OptionLen |
* optlen, from setsockopt().
*/
INT
IRLMP_SetSocketInformation(IN PVOID pHelperDllSocketContext,
IN SOCKET SocketHandle,
IN HANDLE TdiAddressObjectHandle,
IN HANDLE TdiConnectionObjectHandle,
IN INT Level,
IN INT OptionName,
IN PCHAR pOptionValue,
IN INT OptionLen)
{
PIRLMP_SOCKET_CONTEXT pContext =
(PIRLMP_SOCKET_CONTEXT) pHelperDllSocketContext;
PIAS_SET pIASSet = (PIAS_SET) pOptionValue;
IRDA_MSG IrDAMsg;
int rc;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_SetSocketInformation(0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"),
pHelperDllSocketContext,
(unsigned) SocketHandle,
(unsigned) TdiAddressObjectHandle,
(unsigned) TdiConnectionObjectHandle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -