//--------------------------------------------------------------- // Copyright (c)1998 Microsoft Corporation, All Rights Reserved. // // conn.cpp // // Connection mapping between sockets and CCONNECTION objects. // // Author: // // Edward Reus (edwardr) 02-26-98 Initial coding. // //--------------------------------------------------------------- #include "precomp.h" #include #include #include #include #ifdef DBG_MEM static LONG g_lCConnectionCount = 0; #endif extern HINSTANCE g_hInst; // Instance of ircamera.dll //------------------------------------------------------------------------ // CCONNECTION::CCONNECTION() // //------------------------------------------------------------------------ CCONNECTION::CCONNECTION( IN DWORD dwKind, IN SOCKET Socket, IN HANDLE hIoCP, IN CSCEP_CONNECTION *pScepConnection, IN BOOL fSaveAsUPF ) { this->SetKind(dwKind); m_pszServiceName = 0; m_ListenSocket = INVALID_SOCKET; m_Socket = Socket; m_hFile = INVALID_HANDLE_VALUE; m_pszPathPlusFileName = 0; m_dwFileBytesWritten = 0; m_lPendingReads = 0; // m_lMaxPendingReads is set in SetKind(). m_lPendingWrites = 0; // m_lMaxPendingWrites is set in SetKind(). m_dwJpegOffset = 0; m_fSaveAsUPF = fSaveAsUPF; m_dwUpfBytes = 0; m_dwBytesWritten = 0; m_fReceiveComplete = FALSE; m_fImpersonating = FALSE; m_pScepConnection = pScepConnection; // If the new connection is to a camera, then tell the system that // we don't want it to hibrenate while the connection is active. if (m_dwKind != PACKET_KIND_LISTEN) { #ifdef USE_WINNT_CALLS m_ExecutionState = SetThreadExecutionState( ES_SYSTEM_REQUIRED|ES_CONTINUOUS ); #else #pragma message("Missing important call: SetThreadExecutionState on Windows9x ") #endif } } //------------------------------------------------------------------------ // CCONNECTION::~CCONNECTION() // //------------------------------------------------------------------------ CCONNECTION::~CCONNECTION() { if (m_pszServiceName) { FreeMemory(m_pszServiceName); } if ( (m_dwKind == PACKET_KIND_LISTEN) && (m_ListenSocket != INVALID_SOCKET)) { closesocket(m_ListenSocket); } if (m_Socket != INVALID_SOCKET) { closesocket(m_Socket); } if (m_pScepConnection) { delete m_pScepConnection; } if (m_hFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); } if (m_pszPathPlusFileName) { FreeMemory(m_pszPathPlusFileName); } // Tell the system that it can go to sleep now if it wants // to... if (m_dwKind != PACKET_KIND_LISTEN) { #ifdef USE_WINNT_CALLS SetThreadExecutionState( m_ExecutionState ); #else #pragma message("Missing important call SetThreadExecutionState on Windows9x ") #endif } } //------------------------------------------------------------------------ // CCONNECTION::operator new() // //------------------------------------------------------------------------ void *CCONNECTION::operator new( IN size_t Size ) { void *pObj = AllocateMemory(Size); return pObj; } //------------------------------------------------------------------------ // CCONNECTION::operator delete() // //------------------------------------------------------------------------ void CCONNECTION::operator delete( IN void *pObj, IN size_t Size ) { if (pObj) { DWORD dwStatus = FreeMemory(pObj); } } //------------------------------------------------------------------------ // CCONNECTION::InitializeForListen() // //------------------------------------------------------------------------ DWORD CCONNECTION::InitializeForListen( IN char *pszServiceName, IN BOOL fIsIrCOMM, IN HANDLE hIoCP ) { DWORD dwStatus = NO_ERROR; SOCKADDR_IRDA AddrLocal; BYTE bIASSetBuffer[sizeof(IAS_SET) - 3 + IAS_SET_ATTRIB_MAX_LEN]; int iIASSetSize = sizeof(bIASSetBuffer); IAS_SET *pIASSet = (IAS_SET*)bIASSetBuffer; int iEnable9WireMode = 1; // Connections are initialized in listen mode: SetKind(PACKET_KIND_LISTEN); // Save the service name for listen sockets: m_pszServiceName = (char*)AllocateMemory(1+strlen(pszServiceName)); if (m_pszServiceName) { strcpy(m_pszServiceName,pszServiceName); } // Create a socket that we will listen on: m_ListenSocket = socket(AF_IRDA,SOCK_STREAM,IPPROTO_IP); if (m_ListenSocket == INVALID_SOCKET) { dwStatus = WSAGetLastError(); #ifdef DBG_ERROR WIAS_ERROR((g_hInst,"InitializeForListen(%s): socket() Failed: %d\n",pszServiceName,dwStatus)); #endif return dwStatus; } // If this is IrCOMM, the we need to do a little extra work. if (fIsIrCOMM) { // Fill in the 9-wire attributes: memset(pIASSet,0,iIASSetSize); memcpy(pIASSet->irdaClassName,IRCOMM_9WIRE,sizeof(IRCOMM_9WIRE)); memcpy(pIASSet->irdaAttribName,IRDA_PARAMETERS,sizeof(IRDA_PARAMETERS)); pIASSet->irdaAttribType = IAS_ATTRIB_OCTETSEQ; pIASSet->irdaAttribute.irdaAttribOctetSeq.Len = OCTET_SEQ_SIZE; memcpy(pIASSet->irdaAttribute.irdaAttribOctetSeq.OctetSeq,OCTET_SEQ,OCTET_SEQ_SIZE); // Add IrCOMM IAS attributes for 3-wire cooked and 9-wire // raw modes (see the IrCOMM spec)... if (SOCKET_ERROR == setsockopt(m_ListenSocket, SOL_IRLMP, IRLMP_IAS_SET, (const char*)pIASSet, iIASSetSize)) { dwStatus = WSAGetLastError(); #ifdef DBG_ERROR WIAS_TRACE((g_hInst,"InitializeForListen(%s): setsockopt(IRLMP_IAS_SET) Failed: %d",pszServiceName,dwStatus)); #endif closesocket(m_ListenSocket); m_ListenSocket = INVALID_SOCKET; return dwStatus; } // Need to enable 9-wire mode before the bind(): if (SOCKET_ERROR == setsockopt(m_ListenSocket, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char*)&iEnable9WireMode, sizeof(iEnable9WireMode))) { dwStatus = WSAGetLastError(); #ifdef DBG_ERROR WIAS_TRACE((g_hInst,"InitializeForListen(%s): setsockopt(IRLMP_9WIRE_MODE) Failed: %d",pszServiceName,dwStatus)); #endif closesocket(m_ListenSocket); m_ListenSocket = INVALID_SOCKET; return dwStatus; } } // Setup the local address for the bind(): memset(&AddrLocal,0,sizeof(AddrLocal)); AddrLocal.irdaAddressFamily = AF_IRDA; strcpy(AddrLocal.irdaServiceName,pszServiceName); // Note: AddrLocal.irdaDeviceID ignored by server applications... if (SOCKET_ERROR == bind( m_ListenSocket, (struct sockaddr *)&AddrLocal, sizeof(AddrLocal)) ) { dwStatus = WSAGetLastError(); closesocket(m_ListenSocket); m_ListenSocket = INVALID_SOCKET; return dwStatus; } if (SOCKET_ERROR == listen(m_ListenSocket,2)) { dwStatus = WSAGetLastError(); closesocket(m_ListenSocket); m_ListenSocket = INVALID_SOCKET; return dwStatus; } #ifdef USE_IOCOMPLETION // // If this is NT, then associate the listen socket with // an IO completion port (not supported in Windows98). // hIoCP = CreateIoCompletionPort( (void*)m_ListenSocket, hIoCP, m_ListenSocket, 0 ); m_hIoCompletionPort = hIoCP; #endif return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::PostMoreIos() // //------------------------------------------------------------------------ #if FALSE DWORD CCONNECTION::PostMoreIos( CIOPACKET *pIoPacket ) { DWORD dwStatus = S_OK; LONG lNumPendingReads; while (m_lPendingReads < m_lMaxPendingReads) { if (!pIoPacket) { pIoPacket = new CIOPACKET; if (!pIoPacket) { WIAS_ERROR((g_hInst,"new CIOPACKET failed.")); dwStatus = ERROR_OUTOFMEMORY; break; } dwStatus = pIoPacket->Initialize( GetKind(), GetListenSocket(), GetSocket(), GetIoCompletionPort() ); } dwStatus = pIoPacket->PostIo(); if (dwStatus != NO_ERROR) { WIAS_ERROR((g_hInst,"pNewIoPacket->PostIo() failed: %d\n", dwStatus )); delete pIoPacket; break; } // Increment the count of the number of pending reads on // this connection: lNumPendingReads = IncrementPendingReads(); WIAS_ASSERT(g_hInst,lNumPendingReads > 0); pIoPacket = 0; // don't delete this line... this is a loop... } return dwStatus; } #endif //------------------------------------------------------------------------ // CCONNECTION::SendPdu() // //------------------------------------------------------------------------ DWORD CCONNECTION::SendPdu( IN SCEP_HEADER *pPdu, IN DWORD dwPduSize, OUT CIOPACKET **ppIoPacket ) { DWORD dwStatus = NO_ERROR; CIOPACKET *pIoPacket = new CIOPACKET; *ppIoPacket = 0; if (!pIoPacket) { return ERROR_OUTOFMEMORY; } dwStatus = pIoPacket->Initialize( PACKET_KIND_WRITE_SOCKET, INVALID_SOCKET, // ListenSocket GetSocket(), GetIoCompletionPort() ); if (dwStatus != NO_ERROR) { delete pIoPacket; return dwStatus; } dwStatus = pIoPacket->PostIoWrite(pPdu,dwPduSize,0); delete pIoPacket; return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::ShutdownSocket() // //------------------------------------------------------------------------ DWORD CCONNECTION::ShutdownSocket() { this->CloseSocket(); return NO_ERROR; } //------------------------------------------------------------------------ // CCONNECTION::CloseSocket() // //------------------------------------------------------------------------ void CCONNECTION::CloseSocket() { if (m_Socket != INVALID_SOCKET) { closesocket(m_Socket); m_Socket = INVALID_SOCKET; } } //------------------------------------------------------------------------ // CCONNECTION::CloseListenSocket() // //------------------------------------------------------------------------ void CCONNECTION::CloseListenSocket() { if (m_ListenSocket != INVALID_SOCKET) { closesocket(m_ListenSocket); m_ListenSocket = INVALID_SOCKET; } } //------------------------------------------------------------------------ // CCONNECTION::CleanupDateString() // // Make sure that the specified date string doesn't contain any slashes // which could be confused as subdirectories if the date is used as part // of a path. //------------------------------------------------------------------------ void CCONNECTION::CleanupDateString( IN OUT CHAR *pszDateStr ) { if (pszDateStr) { while (*pszDateStr) { if ((*pszDateStr == '/') || (*pszDateStr == '\\')) { *pszDateStr = '-'; } else if (*pszDateStr < 30) { *pszDateStr = '_'; } pszDateStr++; } } } //------------------------------------------------------------------------ // CCONNECTION::ConstructPicturesSubDirectory() // // Generate the path for the directory where pictures will be stored // in. // // The return path string should be free'd using FreeMemory(). //------------------------------------------------------------------------ char *CCONNECTION::ConstructPicturesSubDirectory( IN DWORD dwExtraChars ) { char *pszTempDirectory = 0; char *psz = ::GetImageDirectory(); if (psz) { pszTempDirectory = (char*)AllocateMemory( strlen(psz) + dwExtraChars + 2 ); } if (pszTempDirectory) { strcpy(pszTempDirectory,psz); } // Don't try to free psz !!. return pszTempDirectory; } //------------------------------------------------------------------------ // CCONNECTION::ConstructFullFileName() // // Generate the path + file name that the picture will be stored // in. If dwCopyCount is zero, then its just a straight file name. // If dwCopyCount is N, then "N_" is prefixed to the file name. //------------------------------------------------------------------------ CHAR *CCONNECTION::ConstructFullFileName( IN DWORD dwCopyCount ) { # define MAX_DATE 64 # define MAX_PREFIX 64 DWORD dwLen; DWORD dwFileNameLen; DWORD dwPrefixStrLen; DWORD dwExtraChars; CHAR *pszFullFileName = 0; // Path + file name. CHAR *pszFileName = 0; // File name only. CHAR szPrefixStr[MAX_PREFIX]; if (!m_pScepConnection) { return 0; } pszFileName = m_pScepConnection->GetFileName(); if (!pszFileName) { return 0; } dwFileNameLen = strlen(pszFileName); if (dwCopyCount == 0) { dwExtraChars = 1 + dwFileNameLen; // Extra 1 for the "\". } else { _itoa(dwCopyCount,szPrefixStr,10); strcat(szPrefixStr,SZ_UNDERSCORE); dwPrefixStrLen = strlen(szPrefixStr); dwExtraChars = 1 + dwFileNameLen + dwPrefixStrLen; } pszFullFileName = CCONNECTION::ConstructPicturesSubDirectory(dwExtraChars); if (!pszFullFileName) { return 0; } if (dwCopyCount == 0) { strcat(pszFullFileName,SZ_SLASH); strcat(pszFullFileName,pszFileName); } else { strcat(pszFullFileName,SZ_SLASH); strcat(pszFullFileName,szPrefixStr); strcat(pszFullFileName,pszFileName); } #ifdef DBG_IO WIAS_TRACE((g_hInst,"CCONNECTION::ConstructFullFileName(): return: %s",pszFullFileName)); #endif return pszFullFileName; } //------------------------------------------------------------------------ // CCONNECTION::Impersonate() // //------------------------------------------------------------------------ DWORD CCONNECTION::Impersonate() { DWORD dwStatus = NO_ERROR; HANDLE hToken = ::GetUserToken(); if (hToken) { if (!ImpersonateLoggedOnUser(hToken)) { dwStatus = GetLastError(); #ifdef DBG_ERROR WIAS_ERROR((g_hInst,"IrXfer: IrTran-P: CreatePictureFile(): Impersonate Failed: %d\n",dwStatus)); #endif } else { m_fImpersonating = TRUE; #ifdef DBG_IMPERSONATE WIAS_ERROR((g_hInst,"CCONNECTION::Impersonate(): Impersonate\n")); #endif } } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::RevertToSelf() // //------------------------------------------------------------------------ DWORD CCONNECTION::RevertToSelf() { DWORD dwStatus = NO_ERROR; HANDLE hToken = ::GetUserToken(); if ((hToken) && (m_fImpersonating)) { ::RevertToSelf(); m_fImpersonating = FALSE; } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::CreatePictureFile() // //------------------------------------------------------------------------ DWORD CCONNECTION::CreatePictureFile() { DWORD dwStatus = NO_ERROR; CHAR *pszFile; CHAR *pszPathPlusFileName = 0; DWORD dwFlags = FILE_ATTRIBUTE_NORMAL; // Make sure that the counters start at zero: m_dwUpfBytes = 0; m_dwBytesWritten = 0; // See if we already have an image file open, if yes then // close it. if (m_hFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); } // Get the full path + name for the file we will create. // Note, that ConstructFullFileName() may create a subdirectory, // so it needs to be done after the impersonation... // This is important if we have a remoted \My Documents\ // directory. DWORD dwCopyCount; for (dwCopyCount=0; dwCopyCount<=MAX_COPYOF_TRIES; dwCopyCount++) { pszPathPlusFileName = ConstructFullFileName(dwCopyCount); if (!pszPathPlusFileName) { return ERROR_SCEP_CANT_CREATE_FILE; } // // Try to create new image (JPEG) file: // m_hFile = CreateFile( pszPathPlusFileName, GENERIC_WRITE, FILE_SHARE_READ, // Share mode. 0, // Security attr (BUGBUG). CREATE_NEW, // Open mode. dwFlags, // Attributes. 0 ); // Template file (none). if (m_hFile != INVALID_HANDLE_VALUE) { // This is the success exit point. m_pszPathPlusFileName = pszPathPlusFileName; break; } else { dwStatus = GetLastError(); if (dwStatus != ERROR_FILE_EXISTS) { #ifdef DBG_TARGET_DIR WIAS_ERROR((g_hInst,"CCONNECTION::CreatePictureFile(): CreateFile(): %s Failed: %d",pszPathPlusFileName,dwStatus)); #endif FreeMemory(pszPathPlusFileName); break; } // If we get here, then then a picture file by that name // alreay exists, so try again... FreeMemory(pszPathPlusFileName); } } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::SetPictureFileTime() // //------------------------------------------------------------------------ DWORD CCONNECTION::SetPictureFileTime( IN FILETIME *pFileTime ) { DWORD dwStatus = NO_ERROR; if (!pFileTime) { return dwStatus; // Empty case, no time to set. } if (!SetFileTime(m_hFile,pFileTime,pFileTime,pFileTime)) { dwStatus = GetLastError(); WIAS_ERROR((g_hInst,"IrTranP: SetFileTime() Failed: %d",dwStatus)); } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::WritePictureFile() // //------------------------------------------------------------------------ DWORD CCONNECTION::WritePictureFile( IN UCHAR *pBuffer, IN DWORD dwBufferSize, OUT CIOPACKET **ppIoPacket ) { DWORD dwStatus = NO_ERROR; DWORD dwOffset = m_dwBytesWritten; DWORD dwBytesToWrite; LONG lPendingWrites; *ppIoPacket = 0; CIOPACKET *pIoPacket = new CIOPACKET; if (!pIoPacket) { return ERROR_OUTOFMEMORY; } dwStatus = pIoPacket->Initialize( PACKET_KIND_WRITE_FILE, INVALID_SOCKET, // ListenSocket INVALID_SOCKET, // Camera... GetIoCompletionPort() ); if (dwStatus != NO_ERROR) { delete pIoPacket; return dwStatus; } pIoPacket->SetFileHandle(m_hFile); // // If we are writing just the JPEG image out of the UPF file, // then we don't want to write the first m_dwJpegOffset bytes // of the UPF file. // if ((m_dwUpfBytes >= m_dwJpegOffset) || (m_fSaveAsUPF)) { dwBytesToWrite = dwBufferSize; } else if ((m_dwUpfBytes + dwBufferSize) > m_dwJpegOffset) { dwBytesToWrite = (m_dwUpfBytes + dwBufferSize) - m_dwJpegOffset; for (DWORD i=0; i m_dwJpegSize) { dwBytesToWrite = m_dwJpegSize - m_dwBytesWritten; } } else { dwBytesToWrite = 0; } } // // If there are bytes to actually write, then let's do it. // if (dwBytesToWrite > 0) { dwStatus = pIoPacket->PostIoWrite(pBuffer,dwBytesToWrite,dwOffset); if (dwStatus == NO_ERROR) { lPendingWrites = IncrementPendingWrites(); WIAS_ASSERT(g_hInst, lPendingWrites > 0 ); m_dwBytesWritten += dwBytesToWrite; *ppIoPacket = pIoPacket; } } delete pIoPacket; m_dwUpfBytes += dwBufferSize; return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::DeletePictureFile() // //------------------------------------------------------------------------ DWORD CCONNECTION::DeletePictureFile() { DWORD dwStatus = NO_ERROR; if (m_hFile == INVALID_HANDLE_VALUE) { return NO_ERROR; } CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; if (m_pszPathPlusFileName) { DeleteFile(m_pszPathPlusFileName); } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::ClosePictureFile() // //------------------------------------------------------------------------ DWORD CCONNECTION::ClosePictureFile() { DWORD dwStatus = NO_ERROR; #if FALSE if (m_pszPathPlusFileName) { FreeMemory(m_pszPathPlusFileName); m_pszPathPlusFileName = 0; } #endif if (m_hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(m_hFile)) { dwStatus = GetLastError(); } m_hFile = INVALID_HANDLE_VALUE; } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::IncompleteFile() // // Check to see if we have a complete picture file, if yes, then return // FALSE, else return TRUE. //------------------------------------------------------------------------ BOOL CCONNECTION::IncompleteFile() { BOOL fIncomplete = FALSE; if (m_fSaveAsUPF) { // Note: currently save the .UPF file, even if its incomplete. // This file mode is set in the registry and is for testing // only... fIncomplete = FALSE; } else if (!m_fReceiveComplete) { fIncomplete = (m_dwBytesWritten < m_dwJpegSize); } return fIncomplete; } //------------------------------------------------------------------------ // CCONNECTION::StartProgress() // // Startup the progress bar for the incomming JPEG. //------------------------------------------------------------------------ DWORD CCONNECTION::StartProgress() { DWORD dwStatus = 0; if (!m_pIrProgress) { m_pIrProgress = new CIrProgress; if (m_pIrProgress) { dwStatus = m_pIrProgress->Initialize(g_hInst,IDR_TRANSFER_AVI); } else { return E_OUTOFMEMORY; } } if (m_pIrProgress) { dwStatus = m_pIrProgress->StartProgressDialog(); } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::UpdateProgress() // // Update the progress bar's completion display. //------------------------------------------------------------------------ DWORD CCONNECTION::UpdateProgress() { DWORD dwStatus = 0; if (m_pIrProgress) { dwStatus = m_pIrProgress->UpdateProgressDialog( m_dwBytesWritten, m_dwJpegSize ); } return dwStatus; } //------------------------------------------------------------------------ // CCONNECTION::EndProgress() // // File transfer complete, hide the progress bar. //------------------------------------------------------------------------ DWORD CCONNECTION::EndProgress() { DWORD dwStatus = 0; if (m_pIrProgress) { dwStatus = m_pIrProgress->EndProgressDialog(); delete m_pIrProgress; m_pIrProgress = NULL; } return dwStatus; } //************************************************************************ //------------------------------------------------------------------------ // CCONNECTION_MAP::CCONNECTION_MAP() // //------------------------------------------------------------------------ CCONNECTION_MAP::CCONNECTION_MAP() { m_dwMapSize = 0; m_pMap = 0; ZeroMemory(&m_cs, sizeof(m_cs)); } //------------------------------------------------------------------------ // CCONNECTION_MAP::~CCONNECTION_MAP() // //------------------------------------------------------------------------ CCONNECTION_MAP::~CCONNECTION_MAP() { if (m_pMap) { DeleteCriticalSection(&m_cs); FreeMemory(m_pMap); } } //------------------------------------------------------------------------ // CCONNECTION_MAP::operator new() // //------------------------------------------------------------------------ void *CCONNECTION_MAP::operator new( IN size_t Size ) { void *pObj = AllocateMemory(Size); return pObj; } //------------------------------------------------------------------------ // CCONNECTION_MAP::operator delete() // //------------------------------------------------------------------------ void CCONNECTION_MAP::operator delete( IN void *pObj, IN size_t Size ) { if (pObj) { DWORD dwStatus = FreeMemory(pObj); } } //------------------------------------------------------------------------ // CCONNECTION_MAP::Initialize() // //------------------------------------------------------------------------ BOOL CCONNECTION_MAP::Initialize( IN DWORD dwNewMapSize ) { if (!dwNewMapSize) { return FALSE; } if (!m_dwMapSize) { m_pMap = (CONNECTION_MAP_ENTRY*)AllocateMemory( dwNewMapSize*sizeof(CONNECTION_MAP_ENTRY) ); if (!m_pMap) { return FALSE; } __try { if(!InitializeCriticalSectionAndSpinCount(&m_cs, MINLONG)) { FreeMemory(m_pMap); m_pMap = NULL; return FALSE; } } __except(EXCEPTION_EXECUTE_HANDLER) { FreeMemory(m_pMap); m_pMap = NULL; return FALSE; } m_dwMapSize = dwNewMapSize; memset(m_pMap,0,m_dwMapSize*sizeof(CONNECTION_MAP_ENTRY)); for (DWORD i=0; iGetServiceName()) && (!strcmp(pConnection->GetServiceName(),pszServiceName))) { LeaveCriticalSection(&m_cs); return pConnection; } } LeaveCriticalSection(&m_cs); return 0; } //------------------------------------------------------------------------ // CCONNECTION_MAP::Add() // //------------------------------------------------------------------------ BOOL CCONNECTION_MAP::Add( IN CCONNECTION *pConnection, IN SOCKET Socket ) { DWORD i; // Only add entries that look valid... if ((Socket == 0)||(Socket==INVALID_SOCKET)||(pConnection == 0)) { return FALSE; } EnterCriticalSection(&m_cs); // Look for an empty place in the table: for (i=0; i= m_dwMapSize) { LeaveCriticalSection(&m_cs); return NULL; } while ((pConnection == NULL) && (*pdwState < m_dwMapSize)) { pConnection = m_pMap[(*pdwState)++].pConnection; } LeaveCriticalSection(&m_cs); return pConnection; } //------------------------------------------------------------------------ // CCONNECTION_MAP::ReturnNextSocket() // // Walk through the connection map returning the SOCKET associated with // the next entry. To start at the "begining", pass in state equal zero. // When you get to the end of the list of connections, return // INVALID_SOCKET. //------------------------------------------------------------------------ SOCKET CCONNECTION_MAP::ReturnNextSocket( IN OUT DWORD *pdwState ) { SOCKET Socket = INVALID_SOCKET; EnterCriticalSection(&m_cs); if (*pdwState >= m_dwMapSize) { LeaveCriticalSection(&m_cs); return INVALID_SOCKET; } while ((Socket == INVALID_SOCKET) && (*pdwState < m_dwMapSize)) { Socket = m_pMap[(*pdwState)++].Socket; } LeaveCriticalSection(&m_cs); return Socket; }