📄 wshirda.c
字号:
*
* @parm PINT | pAddressFamily |
* From socket(AF_IRDA, , ). IrLMP will return this value unchanged.
* @parm PINT | pSocketType |
* From socket( , SOCK_SEQPACKET, ). IrLMP will return this value
* unchanged.
* @parm PINT | pProtocol |
* From socket( , , 0). IrLMP will return this value unchanged.
* @parm PWSTR | pTransportDeviceName |
* IrLMP will copy IRLMP_TRANSPORT_NAME to this address.
* @parm PVOID * | ppHelperDllSocketContext |
* Returns the address of a new IRLMP_SOCKET_CONTEXT. This context
* will be returned by IRLMP_Notify(), IRLMP_OpenConnection(),
* IRLMP_GetWildcardSockaddr(), and IRLMP_SetSocketInformation(),
* and IRLMP_GetSocketInformation().
* @parm PDWORD | pNotificationEvents |
* (tdice.h) Bitmask indicating which Winsock events should result
* in a call to IRLMP_Notify(). IrLMP will set this value to 0.
* <nl> WSH_NOTIFY_BIND
* <nl> WSH_NOTIFY_LISTEN
* <nl> WSH_NOTIFY_CONNECT
* <nl> WSH_NOTIFY_ACCEPT
* <nl> WSH_NOTIFY_SHUTDOWN_RECEIVE
* <nl> WSH_NOTIFY_SHUTDOWN_SEND
* <nl> WSH_NOTIFY_SHUTDOWN_ALL
* <nl> WSH_NOTIFY_CLOSE
* <nl> WSH_NOTIFY_CONNECT_ERROR
*
* @xref <f IRLMP_Notify> <f IRLMP_OpenConnection>
* <f IRLMP_GetWildcardSockaddr> <f IRLMP_SetSocketInformation>
*/
INT
IRLMP_OpenSocket(IN OUT PINT pAddressFamily,
IN OUT PINT pSocketType,
IN OUT PINT pProtocol,
OUT PWSTR pTransportDeviceName,
OUT PVOID * ppHelperDllSocketContext,
OUT PDWORD pNotificationEvents)
{
PIRLMP_SOCKET_CONTEXT pSocket;
UINT rc;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_OpenSocket(0x%X,0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"),
pAddressFamily,
pSocketType,
pProtocol,
pTransportDeviceName,
ppHelperDllSocketContext,
pNotificationEvents));
DUMP_WSHOBJECTS(ZONE_WSHIRDA);
if (*pAddressFamily != (int) IRLMP_Mapping.Mapping[0].AddressFamily)
return(WSAEINVAL);
if (*pSocketType != (int) IRLMP_Mapping.Mapping[0].SocketType)
return(WSAEINVAL);
if (*pProtocol != (int) IRLMP_Mapping.Mapping[0].Protocol)
return(WSAEINVAL);
wcscpy(pTransportDeviceName, IRLMP_TRANSPORT_NAME);
pSocket = IrdaAlloc(sizeof(IRLMP_SOCKET_CONTEXT), MT_WSH_SOCKET_CTXT);
if (pSocket == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IRLMP_OpenSocket() CTEAllocMem() failed\r\n")));
return(WSAENOBUFS);
}
EnterCriticalSection(&g_csWshIrda);
while (g_IrdaLinkState == IRDALINKSTATE_CLOSING)
{
LeaveCriticalSection(&g_csWshIrda);
DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_OpenSocket(0x%x): Wait for IrDA to release link before open...\r\n"), pSocket));
// If we are in the midst of releasing the link, wait until done - then
// we will need to reacquire the link.
rc = WaitForSingleObject(g_hEvWaitToRelLink, IRLMP_OPENSOCKET_MAX_WAIT);
if (rc != WAIT_OBJECT_0) {
//
// Either IRDA has been deinit'd or the process this thread belongs to has been terminated
//
DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_OpenSocket:WaitForSingleObject returned error %d\r\n"), rc));
IrdaFree(pSocket);
return (WSASYSNOTREADY);
}
EnterCriticalSection(&g_csWshIrda);
}
*ppHelperDllSocketContext = pSocket;
OpenSocketCnt++;
DEBUGMSG(ZONE_SOCKETCNT, (TEXT("IrDA: Open sockets = %d -> %d.\r\n"),
OpenSocketCnt - 1, OpenSocketCnt));
pSocket->UseExclusiveMode = FALSE;
pSocket->UseIrLPTMode = FALSE;
pSocket->Use9WireMode = FALSE;
pSocket->UseSharpMode = FALSE;
pSocket->pIasAttribs = NULL;
InsertHeadList(&g_SocketList, &pSocket->Linkage);
*pNotificationEvents =
WSH_NOTIFY_CLOSE |
WSH_NOTIFY_BIND |
WSH_NOTIFY_LISTEN;
if (g_IrdaLinkState == IRDALINKSTATE_CLOSED)
{
IRDA_MSG IMsg;
g_IrdaLinkState = IRDALINKSTATE_OPENING;
DEBUGMSG(ZONE_SOCKETCNT, (TEXT("IrDA: Acquire link resources.\r\n")));
IMsg.Prim = IRLMP_LINKCONTROL_REQ;
IMsg.IRDA_MSG_AcquireResources = TRUE;
rc = IrlmpDown(NULL, &IMsg);
if (rc == SUCCESS)
{
g_IrdaLinkState = IRDALINKSTATE_OPENED;
}
else if (rc == IRMAC_ALREADY_INIT)
{
// This happens if a previous process got terminated in the middle of
// calling IRLMP_OpenSocket
DEBUGMSG(ZONE_WARN, (TEXT("IRDASTK:IRLMP_OpenSocket Link already up!\r\n")));
g_IrdaLinkState = IRDALINKSTATE_OPENED;
rc = SUCCESS;
}
else
{
g_IrdaLinkState = IRDALINKSTATE_CLOSED;
// Need to dec. socket count since new AFD will not call
// Notify CLOSE.
OpenSocketCnt--;
DEBUGMSG(ZONE_SOCKETCNT,
(TEXT("IrDA: Acquire resource failure - ")
TEXT("Open sockets = %d -> %d.\r\n"),
OpenSocketCnt + 1, OpenSocketCnt));
}
if (rc == IRMAC_OPEN_PORT_FAILED)
{
DEBUGMSG(ZONE_WARN, (TEXT("IrTdi: Could not open serial port!\r\n")));
rc = WSAEBADF;
}
else if (rc == IRMAC_MALLOC_FAILED)
{
DEBUGMSG(ZONE_ERROR, (TEXT("IrTdi: WSAENOBUFS!\r\n")));
rc = WSAENOBUFS;
}
else if (rc != SUCCESS)
{
ASSERT(FALSE);
DEBUGMSG(ZONE_ERROR, (TEXT("IrTdi: got unexpected error.\r\n")));
rc = WSAEBADF;
}
if (rc != SUCCESS) {
RemoveEntryList(&pSocket->Linkage);
LeaveCriticalSection(&g_csWshIrda);
IrdaFree(pSocket);
return (INT) rc;
}
LeaveCriticalSection(&g_csWshIrda);
}
else
{
ASSERT(g_IrdaLinkState == IRDALINKSTATE_OPENED);
LeaveCriticalSection(&g_csWshIrda);
}
return(NO_ERROR);
}
INT
TdiIasQuery(
PIAS_QUERY pIasQuery,
DWORD cbIasQuery
)
{
INT Status = NO_ERROR;
INT rc;
IRDA_MSG IrDAMsg;
PIAS_QUERY pLocalIasQuery = NULL;
EnterCriticalSection(&csIasQuery);
if (IASQueryInProgress)
{
Status = WSAEINPROGRESS;
goto done;
}
pIASQuery = pIasQuery;
// Need to get around this damn thing for proc permissions.
pLocalIasQuery = IrdaAlloc(cbIasQuery, 0);
if (pLocalIasQuery == NULL)
{
Status = WSAENOBUFS;
goto done;
}
else
{
memcpy(pLocalIasQuery, pIasQuery, cbIasQuery);
}
IrDAMsg.Prim = IRLMP_GETVALUEBYCLASS_REQ;
IrDAMsg.IRDA_MSG_pIasQuery = pLocalIasQuery;
IrDAMsg.IRDA_MSG_AttribLen =
cbIasQuery - offsetof(IAS_QUERY, irdaAttribute.irdaAttribUsrStr.UsrStr);
if (IrDAMsg.IRDA_MSG_AttribLen <= 0)
{
Status = WSAEFAULT;
goto done;
}
IASQueryInProgress = TRUE;
LeaveCriticalSection(&csIasQuery);
rc = IrlmpDown(NULL, &IrDAMsg);
EnterCriticalSection(&csIasQuery);
if (rc != 0)
{
if (rc == IRLMP_LINK_IN_USE)
{
Status = WSAEADDRINUSE;
IASQueryInProgress = FALSE;
goto done;
}
else if (rc == IRLMP_IN_EXCLUSIVE_MODE)
{
Status = WSAEISCONN;
IASQueryInProgress = FALSE;
goto done;
}
else
{
DEBUGMSG (ZONE_ERROR, (TEXT("!IRLMP_GetSocketInfo: Error from IRLMP_DOWN %d\r\n"), rc));
Status = WSAEFAULT;
IASQueryInProgress = FALSE;
goto done;
}
}
LeaveCriticalSection(&csIasQuery);
WaitForSingleObject(IASQueryConfEvent, INFINITE);
EnterCriticalSection(&csIasQuery);
IASQueryInProgress = FALSE;
switch(IASQueryStatus)
{
case IRLMP_IAS_SUCCESS:
Status = NO_ERROR;
break;
case IRLMP_MAC_MEDIA_BUSY:
/* wmz retry the query */
DEBUGMSG (1, (TEXT("TDI:IRLMP_GetSocketinformation, Got IRLMP_MAC_MEDIA_BUSY, returning WSAENETDOWN\r\n")));
Status = WSAENETDOWN;
break;
case IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS:
/* wmz retry the query after DISCOVERY_IND */
DEBUGMSG (1, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:IRLMP_GetSocketinformation\r\n")));
Status = WSAENETDOWN;
break;
case IRLMP_DISC_LSAP:
Status = WSAECONNREFUSED;
break;
case IRLMP_NO_RESPONSE_LSAP:
Status = WSAETIMEDOUT;
break;
case IRLMP_IAS_NO_SUCH_OBJECT:
pLocalIasQuery->irdaAttribType = IAS_ATTRIB_NO_CLASS;
Status = NO_ERROR;
break;
case IRLMP_IAS_NO_SUCH_ATTRIB:
pLocalIasQuery->irdaAttribType = IAS_ATTRIB_NO_ATTRIB;
Status = NO_ERROR;
break;
default:
Status = WSAECONNABORTED;
break;
}
done:
if (pLocalIasQuery != NULL)
{
memcpy(pIasQuery, pLocalIasQuery, cbIasQuery);
IrdaFree(pLocalIasQuery);
}
LeaveCriticalSection(&csIasQuery);
return (Status);
}
#define MAX_ENUM_WAIT_TIME 20000
INT
TdiEnumDevices(
PDEVICELIST pDeviceList,
DWORD cDevices
)
{
INT Status = NO_ERROR;
INT rc;
IRDA_MSG IrDAMsg;
EnterCriticalSection(&csDscv);
if (DscvInProgress)
{
Status = WSAEINPROGRESS;
goto done;
}
DscvInProgress = TRUE;
DscvCallersPermissions = GetCurrentPermissions();
pDscvDevList = pDeviceList;
DscvNumDevices = cDevices;
DscvRepeats = 0;
pDscvDevList->numDevice = 0;
if (DscvNumDevices < 1)
{
DscvInProgress = FALSE;
Status = WSAEFAULT;
goto done;
}
IrDAMsg.Prim = IRLMP_DISCOVERY_REQ;
IrDAMsg.IRDA_MSG_SenseMedia = TRUE;
LeaveCriticalSection(&csDscv);
rc = IrlmpDown(NULL, &IrDAMsg);
ASSERT(rc == 0);
rc = WaitForSingleObject(DscvConfEvent, MAX_ENUM_WAIT_TIME);
EnterCriticalSection(&csDscv);
if (WAIT_TIMEOUT == rc) {
Status = WSAETIMEDOUT;
}
DscvInProgress = FALSE;
done:
LeaveCriticalSection(&csDscv);
return (Status);
}
/*++
Function: DeleteSocketAttribs
Description: Deletes all IAS attributes associated with this socket context.
Arguments:
pSocket - Socket context.
Returns:
None.
Comments:
Assumes g_csWshIrda is held.
--*/
VOID
DeleteSocketAttribs(PIRLMP_SOCKET_CONTEXT pSocket)
{
IRDA_MSG IMsg;
PWSHIRDA_IAS_ATTRIB pIasAttrib;
#ifdef DEBUG
DWORD cAttribs = 0;
#endif
DEBUGMSG(ZONE_WSHIRDA, (TEXT("+DeleteSocketAttributes(%x)\r\n"), pSocket));
while (pSocket->pIasAttribs)
{
#ifdef DEBUG
cAttribs++;
#endif
pIasAttrib = pSocket->pIasAttribs;
pSocket->pIasAttribs = pIasAttrib->pNext;
DEBUGMSG(ZONE_WSHIRDA, (TEXT("Delete attrib %x socket %x\r\n"),
pIasAttrib->AttributeHandle, pSocket));
IMsg.Prim = IRLMP_DELATTRIBUTE_REQ;
IMsg.IRDA_MSG_AttribHandle = pIasAttrib->AttributeHandle;
IrlmpDown(NULL, &IMsg);
IrdaFree(pIasAttrib);
}
DEBUGMSG(ZONE_WSHIRDA, (TEXT("-DeleteSocketAttributes ")
TEXT("[%d IAS attributes deleted]\r\n"), cAttribs));
}
/*++
Function: TdiReleaseLink
Description: Release the link. Called by g_evReleaseLink.
Arguments:
Returns:
Comments:
If we really did correct book-keeping, we know that this function
is thread safe.
1) all sockets are closed, that is why we are releasing the link
2) we won't create any more sockets until g_hEvWaitToRelLink is signalled.
--*/
INT
TdiReleaseLink(
struct CTEEvent *pEvent,
VOID *pvNULL
)
{
IRDA_MSG IMsg;
INT rc;
DEBUGMSG(ZONE_FUNCTION|ZONE_WARN, (TEXT("IRDA:+TdiReleaseLink\r\n")));
EnterCriticalSection(&g_csWshIrda);
if (g_IrdaLinkState == IRDALINKSTATE_CLOSING) {
DEBUGMSG(ZONE_SOCKETCNT, (TEXT("IRDA:TdiReleaseLink releasing link resources\r\n")));
IMsg.Prim = IRLMP_LINKCONTROL_REQ;
IMsg.IRDA_MSG_AcquireResources = FALSE;
LeaveCriticalSection(&g_csWshIrda);
rc = IrlmpDown(NULL, &IMsg);
EnterCriticalSection(&g_csWshIrda);
switch (rc) {
case SUCCESS:
case IRMAC_NOT_INITIALIZED:
g_IrdaLinkState = IRDALINKSTATE_CLOSED;
SetEvent(g_hEvWaitToRelLink);
break;
case IRMAC_MALLOC_FAILED:
// Try again later.
CTEStartTimer(&g_evReleaseLink,
1000,
TdiReleaseLink,
NULL);
break;
default:
ASSERT(FALSE);
}
} else {
ASSERT(FALSE); // Should be at IRDALINKSTATE_CLOSING
}
LeaveCriticalSection(&g_csWshIrda);
DEBUGMSG(ZONE_FUNCTION|ZONE_WARN, (TEXT("IRDA:-TdiReleaseLink\r\n")));
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -