You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1268 lines
36 KiB
1268 lines
36 KiB
//---------------------------------------------------------------
|
|
// 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 <userenv.h>
|
|
#include <time.h>
|
|
#include <malloc.h>
|
|
#include <shlwapi.h>
|
|
|
|
#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<dwBytesToWrite; i++)
|
|
{
|
|
pBuffer[i] = pBuffer[i+m_dwJpegOffset-m_dwUpfBytes];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwBytesToWrite = 0;
|
|
}
|
|
|
|
//
|
|
// When we start writing the JPEG file we want to cut off the
|
|
// file save writes once we've written out the m_dwJpegSize
|
|
// bytes that are the JPEG image inside of the UPF file.
|
|
//
|
|
if (!m_fSaveAsUPF)
|
|
{
|
|
if (m_dwBytesWritten < m_dwJpegSize)
|
|
{
|
|
if ((m_dwBytesWritten+dwBytesToWrite) > 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; i<m_dwMapSize; i++)
|
|
{
|
|
m_pMap[i].Socket = INVALID_SOCKET;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::Lookup()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::Lookup( IN SOCKET Socket )
|
|
{
|
|
DWORD i;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket == Socket)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
return m_pMap[i].pConnection;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::LookupByServiceName()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::LookupByServiceName( IN char *pszServiceName )
|
|
{
|
|
DWORD i;
|
|
CCONNECTION *pConnection;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
if ( (pConnection)
|
|
&& (pConnection->GetServiceName())
|
|
&& (!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; i++)
|
|
{
|
|
if (m_pMap[i].Socket == INVALID_SOCKET)
|
|
{
|
|
m_pMap[i].Socket = Socket;
|
|
m_pMap[i].pConnection = pConnection;
|
|
LeaveCriticalSection(&m_cs);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// The table is full, expand it...
|
|
DWORD dwNewMapSize = 3*m_dwMapSize/2; // 50% bigger.
|
|
CONNECTION_MAP_ENTRY *pMap = (CONNECTION_MAP_ENTRY*)AllocateMemory( dwNewMapSize*sizeof(CONNECTION_MAP_ENTRY) );
|
|
|
|
if (!pMap)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
return FALSE; // Out of memory...
|
|
}
|
|
|
|
memset(pMap,0,dwNewMapSize*sizeof(CONNECTION_MAP_ENTRY));
|
|
for (i=0; i<dwNewMapSize; i++)
|
|
{
|
|
pMap[i].Socket = INVALID_SOCKET;
|
|
}
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
pMap[i].Socket = m_pMap[i].Socket;
|
|
pMap[i].pConnection = m_pMap[i].pConnection;
|
|
}
|
|
|
|
pMap[i].Socket = Socket;
|
|
pMap[i].pConnection = pConnection;
|
|
|
|
FreeMemory(m_pMap);
|
|
m_pMap = pMap;
|
|
m_dwMapSize = dwNewMapSize;
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::Remove()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::Remove( IN SOCKET Socket )
|
|
{
|
|
DWORD i;
|
|
CCONNECTION *pConnection;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket == Socket)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
m_pMap[i].Socket = INVALID_SOCKET;
|
|
m_pMap[i].pConnection = 0;
|
|
LeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::RemoveConnection()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::RemoveConnection( IN CCONNECTION *pConnection )
|
|
{
|
|
DWORD i;
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].pConnection == pConnection)
|
|
{
|
|
m_pMap[i].Socket = INVALID_SOCKET;
|
|
m_pMap[i].pConnection = 0;
|
|
LeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::RemoveNext()
|
|
//
|
|
// Walk through the connection map and get the next entry, remove the
|
|
// entry from the map as well.
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::RemoveNext()
|
|
{
|
|
DWORD i;
|
|
CCONNECTION *pConnection;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
m_pMap[i].Socket = INVALID_SOCKET;
|
|
m_pMap[i].pConnection = 0;
|
|
LeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::ReturnNext()
|
|
//
|
|
// Walk through the connection map returning 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 NULL;
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::ReturnNext( IN OUT DWORD *pdwState )
|
|
{
|
|
CCONNECTION *pConnection = NULL;
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if (*pdwState >= 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;
|
|
}
|
|
|