mirror of https://github.com/tongzx/nt5src
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.
1484 lines
43 KiB
1484 lines
43 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
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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_hIoCompletionPort = hIoCP;
|
|
m_ListenSocket = INVALID_SOCKET;
|
|
m_Socket = Socket;
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
m_pwszPathPlusFileName = 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)
|
|
{
|
|
m_ExecutionState
|
|
= SetThreadExecutionState( ES_SYSTEM_REQUIRED|ES_CONTINUOUS );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::~CCONNECTION()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION::~CCONNECTION()
|
|
{
|
|
#if FALSE
|
|
DbgPrint("CCONNECTION::~CCONNECTION(): Kind: %s Socket: %d\n",
|
|
(m_dwKind == PACKET_KIND_LISTEN)?"Listen":"Read",
|
|
(m_dwKind == PACKET_KIND_LISTEN)?m_ListenSocket:m_Socket);
|
|
#endif
|
|
|
|
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_pwszPathPlusFileName)
|
|
{
|
|
FreeMemory(m_pwszPathPlusFileName);
|
|
}
|
|
|
|
// Tell the system that it can go to sleep now if it wants
|
|
// to...
|
|
if (m_dwKind != PACKET_KIND_LISTEN)
|
|
{
|
|
SetThreadExecutionState( m_ExecutionState );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::operator new()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
void *CCONNECTION::operator new( IN size_t Size )
|
|
{
|
|
void *pObj = AllocateMemory(Size);
|
|
|
|
#ifdef DBG_MEM
|
|
if (pObj)
|
|
{
|
|
InterlockedIncrement(&g_lCConnectionCount);
|
|
}
|
|
|
|
DbgPrint("new CCONNECTION: Count: %d\n",g_lCConnectionCount);
|
|
#endif
|
|
|
|
return pObj;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::operator delete()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
void CCONNECTION::operator delete( IN void *pObj,
|
|
IN size_t Size )
|
|
{
|
|
if (pObj)
|
|
{
|
|
DWORD dwStatus = FreeMemory(pObj);
|
|
|
|
#ifdef DBG_MEM
|
|
if (dwStatus)
|
|
{
|
|
DbgPrint("IrXfer: IrTran-P: CCONNECTION::delete Failed: %d\n",
|
|
dwStatus );
|
|
}
|
|
|
|
InterlockedDecrement(&g_lCConnectionCount);
|
|
|
|
if (g_lCConnectionCount < 0)
|
|
{
|
|
DbgPrint("IrXfer: IrTran-P: CCONNECTION::delete: Count: %d\n",
|
|
g_lCConnectionCount);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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();
|
|
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();
|
|
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();
|
|
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;
|
|
}
|
|
|
|
hIoCP = CreateIoCompletionPort( (void*)m_ListenSocket,
|
|
hIoCP,
|
|
m_ListenSocket,
|
|
0 );
|
|
|
|
m_hIoCompletionPort = hIoCP;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::PostMoreIos()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::PostMoreIos( CIOPACKET *pIoPacket )
|
|
{
|
|
DWORD dwStatus;
|
|
LONG lNumPendingReads;
|
|
|
|
#ifdef DBG_IO
|
|
if (m_dwKind == PACKET_KIND_LISTEN)
|
|
{
|
|
DbgPrint("CCONNECTION::PostMoreIos(): Listen: Socket: %d PendingReads: %d MaxPendingReads: %d\n",
|
|
m_ListenSocket, m_lPendingReads, m_lMaxPendingReads );
|
|
}
|
|
else if (m_dwKind == PACKET_KIND_READ)
|
|
{
|
|
DbgPrint("CCONNECTION::PostMoreIos(): Read: Socket: %d PendingReads: %d MaxPendingReads: %d\n",
|
|
m_Socket, m_lPendingReads, m_lMaxPendingReads );
|
|
}
|
|
#endif
|
|
|
|
while (m_lPendingReads < m_lMaxPendingReads)
|
|
{
|
|
if (!pIoPacket)
|
|
{
|
|
pIoPacket = new CIOPACKET;
|
|
if (!pIoPacket)
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("new CIOPACKET failed.\n");
|
|
#endif
|
|
dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwStatus = pIoPacket->Initialize( GetKind(),
|
|
GetListenSocket(),
|
|
GetSocket(),
|
|
GetIoCompletionPort() );
|
|
}
|
|
|
|
dwStatus = pIoPacket->PostIo();
|
|
if (dwStatus != NO_ERROR)
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("pNewIoPacket->PostIo() failed: %d\n", dwStatus );
|
|
#endif
|
|
delete pIoPacket;
|
|
break;
|
|
}
|
|
|
|
// Increment the count of the number of pending reads on
|
|
// this connection:
|
|
lNumPendingReads = IncrementPendingReads();
|
|
ASSERT(lNumPendingReads > 0);
|
|
|
|
pIoPacket = 0; // don't delete this line... this is a loop...
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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_IRTRANP_OUT_OF_MEMORY;
|
|
}
|
|
|
|
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);
|
|
|
|
if (dwStatus != NO_ERROR)
|
|
{
|
|
delete pIoPacket;
|
|
}
|
|
else
|
|
{
|
|
*ppIoPacket = pIoPacket;
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::ShutdownSocket()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::ShutdownSocket()
|
|
{
|
|
#define SHUTDOWN_WAIT_TIME 3000
|
|
DWORD dwStatus = NO_ERROR;
|
|
WSAEVENT hEvent;
|
|
|
|
if (m_Socket != INVALID_SOCKET)
|
|
{
|
|
if (SOCKET_ERROR == shutdown(m_Socket,SD_BOTH))
|
|
{
|
|
dwStatus = WSAGetLastError();
|
|
return dwStatus;
|
|
}
|
|
|
|
#if FALSE
|
|
// Since I'm using IO completion ports, I shouldn't need
|
|
// to do all this stuff, the close should just "come to me".
|
|
hEvent = WSACreateEvent();
|
|
if (hEvent == WAS_INVALID_EVENT)
|
|
{
|
|
dwStatus = WSAGetLastError();
|
|
this->CloseSocket();
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
if (SOCKET_ERROR == WSAEventSelect(m_Socket,hEvent,FD_CLOSE))
|
|
{
|
|
dwStatus = WSAGetLastError();
|
|
WSACloseEvent(hEvent);
|
|
this->CloseSocket();
|
|
return dwStatus;
|
|
}
|
|
|
|
dwStatus = WaitForSingleObject(hEvent,SHUTDOWN_WAIT_TIME);
|
|
|
|
if (dwStatus == WAIT_OBJECT_0)
|
|
{
|
|
dwStatus = NO_ERROR;
|
|
}
|
|
|
|
this->CloseSocket();
|
|
#endif
|
|
}
|
|
else if (m_ListenSocket != INVALID_SOCKET)
|
|
{
|
|
if (SOCKET_ERROR == shutdown(m_ListenSocket,SD_BOTH))
|
|
{
|
|
dwStatus = WSAGetLastError();
|
|
return dwStatus;
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
void CCONNECTION::CleanupDateString( IN OUT WCHAR *pwszDateStr )
|
|
{
|
|
if (pwszDateStr)
|
|
{
|
|
while (*pwszDateStr)
|
|
{
|
|
if ((*pwszDateStr == L'/') || (*pwszDateStr == L'\\'))
|
|
{
|
|
*pwszDateStr = L'-';
|
|
}
|
|
else if (*pwszDateStr < 30)
|
|
{
|
|
*pwszDateStr = L'_';
|
|
}
|
|
|
|
pwszDateStr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::ConstructPicturesSubDirectory()
|
|
//
|
|
// Generate the path for the directory where pictures will be stored
|
|
// in.
|
|
//
|
|
// The return path string should be free'd using FreeMemory().
|
|
//------------------------------------------------------------------------
|
|
WCHAR *CCONNECTION::ConstructPicturesSubDirectory(
|
|
IN DWORD dwExtraChars )
|
|
{
|
|
# define MAX_DATE 64
|
|
DWORD dwStatus = NO_ERROR;
|
|
DWORD dwSize;
|
|
DWORD dwLen;
|
|
DWORD dwUserDirectoryLen = 0;
|
|
DWORD dwDateLen = 0;
|
|
WCHAR *pwszDirectoryName = 0;
|
|
WCHAR *pwszUserDirectory = 0;
|
|
WCHAR wszDate[MAX_DATE];
|
|
HANDLE hUserToken = ::GetUserToken();
|
|
|
|
//
|
|
// Get the target directory (~\My Documents\My Pictures):
|
|
//
|
|
pwszUserDirectory = GetUserDirectory();
|
|
if (!pwszUserDirectory)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
dwUserDirectoryLen = wcslen(pwszUserDirectory);
|
|
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::ConstructPicturesSubDirectory(): User Directory: %S\n",
|
|
pwszUserDirectory);
|
|
#endif
|
|
|
|
//
|
|
// Make sure the ~\My Pictures\ directory exists:
|
|
//
|
|
if (!CreateDirectory(pwszUserDirectory,0))
|
|
{
|
|
dwStatus = GetLastError();
|
|
if ( (dwStatus == ERROR_ALREADY_EXISTS)
|
|
|| (dwStatus == ERROR_ACCESS_DENIED) )
|
|
{
|
|
dwStatus = NO_ERROR;
|
|
}
|
|
else if (dwStatus != NO_ERROR)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Create a subdirectory under ~\My Pictures\ which is the current
|
|
// date (i.e. MM-DD-YY), this is where the pictures will actually
|
|
// be saved to:
|
|
|
|
time_t now;
|
|
struct tm *pTime;
|
|
|
|
time(&now);
|
|
pTime = localtime(&now);
|
|
|
|
// NOTE: Use "%#x" for long date.
|
|
if ( (pTime) && (wcsftime(wszDate,sizeof(wszDate),TEXT("%x"),pTime)) )
|
|
{
|
|
CleanupDateString(wszDate);
|
|
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::ConstructPicturesSubDirectory(): Date: %S\n",
|
|
wszDate );
|
|
#endif
|
|
|
|
dwDateLen = wcslen(wszDate);
|
|
|
|
pwszDirectoryName = (WCHAR*)AllocateMemory( sizeof(WCHAR)
|
|
* (2
|
|
+dwUserDirectoryLen
|
|
+dwDateLen
|
|
+dwExtraChars) );
|
|
// NOTE: The extra 2 is for the '\' and a trailing zero.
|
|
if (!pwszDirectoryName)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
wcscpy(pwszDirectoryName,pwszUserDirectory);
|
|
if (pwszUserDirectory[dwUserDirectoryLen-1] != L'\\')
|
|
{
|
|
wcscat(pwszDirectoryName,TEXT("\\"));
|
|
}
|
|
wcscat(pwszDirectoryName,wszDate);
|
|
|
|
dwStatus = NO_ERROR;
|
|
|
|
if (!CreateDirectory(pwszDirectoryName,0))
|
|
{
|
|
dwStatus = GetLastError();
|
|
if (dwStatus == ERROR_ALREADY_EXISTS)
|
|
{
|
|
dwStatus = NO_ERROR;
|
|
}
|
|
#ifdef DBG_ERROR
|
|
else if (dwStatus != NO_ERROR)
|
|
{
|
|
DbgPrint("CCONNECTION::ConstructPicturesSubDirectory(): CreateDirectory(%S) failed: %d\n", pwszDirectoryName,dwStatus );
|
|
FreeMemory(pwszDirectoryName);
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (dwStatus == NO_ERROR)
|
|
{
|
|
SetThumbnailView(pwszUserDirectory,pwszDirectoryName);
|
|
}
|
|
}
|
|
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::ConstructPicturesSubDirectory(): Directory: %S\n",
|
|
pwszDirectoryName);
|
|
#endif
|
|
|
|
return pwszDirectoryName;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::SetThumbnailView()
|
|
//
|
|
// Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
|
|
// {8BEBB290-52D0-11D0-B7F4-00C04FD706EC}={8BEBB290-52D0-11D0-B7F4-00C04FD706EC}
|
|
// {5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
|
|
// [{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
|
|
// PersistMoniker=d:\winnt5\web\imgview.htt
|
|
// PersistMonikerPreview=d:\winnt5\web\preview.bmp
|
|
// [.ShellClassInfo]
|
|
// ConfirmFileOp=0
|
|
//
|
|
//------------------------------------------------------------------------
|
|
BOOL CCONNECTION::SetThumbnailView( IN WCHAR *pwszParentDirectoryName,
|
|
IN WCHAR *pwszDirectoryName )
|
|
{
|
|
//
|
|
// Configure the folder to have a "desktop.ini" file.
|
|
//
|
|
DWORD dwStatus = 0;
|
|
BOOL fStatus = PathMakeSystemFolderW(pwszDirectoryName);
|
|
|
|
#ifdef DBG_ERROR
|
|
if (!fStatus)
|
|
{
|
|
|
|
DbgPrint("CCONNECTION::SetThumbnailView(): PathMakeSystemFolderW() failed: %d\n",GetLastError());
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Create the "desktop.ini" file. First, try top copy it from the parent
|
|
// directory (My Pictures). If that fails, then we will create it
|
|
// ourselves (Picture Preview w/Thumbnail view on).
|
|
//
|
|
# define DESKTOP_INI TEXT("desktop.ini")
|
|
HANDLE hFile;
|
|
UINT uiSystemDirectorySize;
|
|
WCHAR *pwszIniFile;
|
|
WCHAR *pwszParentIniFile;
|
|
BOOL fFailIfExists = TRUE;
|
|
|
|
pwszIniFile = (WCHAR*)_alloca( sizeof(DESKTOP_INI)
|
|
+ sizeof(WCHAR) * (1 + wcslen(pwszDirectoryName)) );
|
|
wcscpy(pwszIniFile,pwszDirectoryName);
|
|
wcscat(pwszIniFile,TEXT("\\"));
|
|
wcscat(pwszIniFile,DESKTOP_INI);
|
|
|
|
pwszParentIniFile = (WCHAR*)_alloca( sizeof(DESKTOP_INI)
|
|
+ sizeof(WCHAR) * (1 + wcslen(pwszParentDirectoryName)) );
|
|
wcscpy(pwszParentIniFile,pwszParentDirectoryName);
|
|
wcscat(pwszParentIniFile,TEXT("\\"));
|
|
wcscat(pwszParentIniFile,DESKTOP_INI);
|
|
|
|
//
|
|
// Try to get desktop.ini from the parent directory (My Pictures usually).
|
|
//
|
|
if (!CopyFileW(pwszParentIniFile,pwszIniFile,fFailIfExists))
|
|
{
|
|
dwStatus = GetLastError();
|
|
#ifdef DBG_ERROR
|
|
if (dwStatus != ERROR_FILE_EXISTS)
|
|
{
|
|
DbgPrint("CCONNECTION::SetThumbnailView(): copy %S to %S failed: dwStatus: %d\n", pwszParentIniFile, pwszIniFile, dwStatus );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (dwStatus == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
uiSystemDirectorySize = GetWindowsDirectoryA(NULL,0);
|
|
ASSERT(uiSystemDirectorySize > 0);
|
|
// Note: that in this case GetWindowsDirectoryA() is returning the
|
|
// size, not the length...
|
|
|
|
char *pszSystemDirectory = (char*)_alloca(uiSystemDirectorySize);
|
|
|
|
UINT uiLen = GetWindowsDirectoryA(pszSystemDirectory,uiSystemDirectorySize);
|
|
if (uiSystemDirectorySize != 1+uiLen)
|
|
{
|
|
#ifdef DBG_ERROR
|
|
dwStatus = GetLastError();
|
|
DbgPrint("CCONNECTION::ConstructPicturesSubDirectory(): GetWindowsDirectoryA() failed: %d\n",dwStatus);
|
|
DbgPrint(" pszSystemDirectory: %s\n",pszSystemDirectory);
|
|
DbgPrint(" uiSystemDirectorySize: %d\n",uiSystemDirectorySize);
|
|
DbgPrint(" uiLen: %d\n",uiLen);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
# define FILE_CONTENTS_1 "[ExtShellFolderViews]\nDefault={5984FFE0-28D4-11CF-AE66-08002B2E1262}\n{8BEBB290-52D0-11D0-B7F4-00C04FD706EC}={8BEBB290-52D0-11D0-B7F4-00C04FD706EC}\n{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}\n[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]\nPersistMoniker="
|
|
|
|
# define FILE_CONTENTS_2 "\\web\\imgview.htt\nPersistMonikerPreview="
|
|
|
|
# define FILE_CONTENTS_3 "\\web\\preview.bmp\n[.ShellClassInfo]\nConfirmFileOp=0\n"
|
|
|
|
|
|
hFile = CreateFileW( pwszIniFile,
|
|
GENERIC_WRITE, // dwAccess
|
|
0, // dwShareMode (no sharing).
|
|
NULL, // pSecurityAttributes
|
|
CREATE_NEW, // dwDisposition
|
|
FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
|
|
NULL ); // hTemplate
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
char *pszFileContents = (char*)_alloca( sizeof(FILE_CONTENTS_1)
|
|
+ sizeof(FILE_CONTENTS_2)
|
|
+ sizeof(FILE_CONTENTS_3)
|
|
+ 2*uiSystemDirectorySize );
|
|
strcpy(pszFileContents,FILE_CONTENTS_1);
|
|
strcat(pszFileContents,pszSystemDirectory);
|
|
strcat(pszFileContents,FILE_CONTENTS_2);
|
|
strcat(pszFileContents,pszSystemDirectory);
|
|
strcat(pszFileContents,FILE_CONTENTS_3);
|
|
|
|
DWORD dwBytes = strlen(pszFileContents);
|
|
DWORD dwBytesWritten = 0;
|
|
|
|
WriteFile(hFile,pszFileContents,dwBytes,&dwBytesWritten,NULL);
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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.
|
|
//------------------------------------------------------------------------
|
|
WCHAR *CCONNECTION::ConstructFullFileName( IN DWORD dwCopyCount )
|
|
{
|
|
# define MAX_DATE 64
|
|
# define MAX_PREFIX 64
|
|
DWORD dwLen;
|
|
DWORD dwFileNameLen;
|
|
DWORD dwPrefixStrLen;
|
|
DWORD dwExtraChars;
|
|
WCHAR *pwszFullFileName = 0; // Path + file name.
|
|
WCHAR *pwszFileName = 0; // File name only.
|
|
WCHAR wszPrefixStr[MAX_PREFIX];
|
|
|
|
if (!m_pScepConnection)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pwszFileName = m_pScepConnection->GetFileName();
|
|
if (!pwszFileName)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
dwFileNameLen = wcslen(pwszFileName);
|
|
|
|
if (dwCopyCount == 0)
|
|
{
|
|
dwExtraChars = 1 + dwFileNameLen; // Extra 1 for the "\".
|
|
}
|
|
else
|
|
{
|
|
_itow(dwCopyCount,wszPrefixStr,10);
|
|
wcscat(wszPrefixStr,TEXT("_"));
|
|
dwPrefixStrLen = wcslen(wszPrefixStr);
|
|
dwExtraChars = 1 + dwFileNameLen + dwPrefixStrLen;
|
|
}
|
|
|
|
|
|
pwszFullFileName = CCONNECTION::ConstructPicturesSubDirectory(dwExtraChars);
|
|
if (!pwszFullFileName)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (dwCopyCount == 0)
|
|
{
|
|
wcscat(pwszFullFileName,TEXT("\\"));
|
|
wcscat(pwszFullFileName,pwszFileName);
|
|
}
|
|
else
|
|
{
|
|
wcscat(pwszFullFileName,TEXT("\\"));
|
|
wcscat(pwszFullFileName,wszPrefixStr);
|
|
wcscat(pwszFullFileName,pwszFileName);
|
|
}
|
|
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::ConstructFullFileName(): return: %S\n",
|
|
pwszFullFileName);
|
|
#endif
|
|
|
|
return pwszFullFileName;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::Impersonate()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::Impersonate()
|
|
{
|
|
DWORD dwStatus = NO_ERROR;
|
|
HANDLE hToken = ::GetUserToken();
|
|
|
|
if (hToken)
|
|
{
|
|
if (!ImpersonateLoggedOnUser(hToken))
|
|
{
|
|
dwStatus = GetLastError();
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("IrXfer: IrTran-P: CreatePictureFile(): Impersonate Failed: %d\n",dwStatus);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
m_fImpersonating = TRUE;
|
|
#ifdef DBG_IMPERSONATE
|
|
DbgPrint("CCONNECTION::Impersonate(): Impersonate\n");
|
|
#endif
|
|
}
|
|
}
|
|
#ifdef DBG_IMPERSONATE
|
|
else
|
|
{
|
|
DbgPrint("CCONNECTION::Impersonate(): No token to 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;
|
|
#ifdef DBG_IMPERSONATE
|
|
DbgPrint("CCONNECTION::RevertToSelf(): RevertToSelf\n");
|
|
#endif
|
|
}
|
|
#ifdef DBG_IMPERSONATE
|
|
else
|
|
{
|
|
DbgPrint("CCONNECTION::RevertToSelf(): No impersonation\n");
|
|
}
|
|
#endif
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::CreatePictureFile()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::CreatePictureFile()
|
|
{
|
|
DWORD dwStatus = NO_ERROR;
|
|
DWORD dwFlags = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED;
|
|
WCHAR *pwszFile;
|
|
WCHAR *pwszPathPlusFileName = 0;
|
|
HANDLE hIoCP;
|
|
|
|
// 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++)
|
|
{
|
|
pwszPathPlusFileName = ConstructFullFileName(dwCopyCount);
|
|
if (!pwszPathPlusFileName)
|
|
{
|
|
return ERROR_SCEP_CANT_CREATE_FILE;
|
|
}
|
|
|
|
// Try to create new image (JPEG) file:
|
|
m_hFile = CreateFile( pwszPathPlusFileName,
|
|
GENERIC_WRITE,
|
|
0, // Share mode (none).
|
|
0, // Security attribute.
|
|
CREATE_NEW, // Open mode.
|
|
dwFlags, // Attributes.
|
|
0 ); // Template file (none).
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
// Successfully created the file, now associate it with
|
|
// our IO completion port:
|
|
|
|
hIoCP = CreateIoCompletionPort( m_hFile,
|
|
m_hIoCompletionPort,
|
|
(DWORD)m_Socket,
|
|
0 );
|
|
if (!hIoCP)
|
|
{
|
|
dwStatus = GetLastError();
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("CCONNECTION::CreatePictureFile(): CreateIoCompletionPort() failed: %d\n",dwStatus);
|
|
#endif
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
FreeMemory(pwszPathPlusFileName);
|
|
break;
|
|
}
|
|
|
|
// This is the success exit point.
|
|
m_pwszPathPlusFileName = pwszPathPlusFileName;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
dwStatus = GetLastError();
|
|
if (dwStatus != ERROR_FILE_EXISTS)
|
|
{
|
|
#ifdef DBG_TARGET_DIR
|
|
DbgPrint("CCONNECTION::CreatePictureFile(): CreateFile(): %S Failed: %d\n",pwszPathPlusFileName,dwStatus);
|
|
#endif
|
|
FreeMemory(pwszPathPlusFileName);
|
|
break;
|
|
}
|
|
|
|
// If we get here, then then a picture file by that name
|
|
// alreay exists, so try again...
|
|
FreeMemory(pwszPathPlusFileName);
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::SetPictureFileTime()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::SetPictureFileTime( IN FILETIME *pFileTime )
|
|
{
|
|
DWORD dwStatus = NO_ERROR;
|
|
|
|
if (!pFileTime)
|
|
{
|
|
#ifdef DBG_DATE
|
|
DbgPrint("IrTranP: SetFileTime(): no time to set\n");
|
|
#endif
|
|
return dwStatus; // Empty case, no time to set.
|
|
}
|
|
|
|
if (!SetFileTime(m_hFile,pFileTime,pFileTime,pFileTime))
|
|
{
|
|
dwStatus = GetLastError();
|
|
#ifdef DBG_DATE
|
|
DbgPrint("IrTranP: SetFileTime() Failed: %d\n",dwStatus);
|
|
#endif
|
|
}
|
|
|
|
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_IRTRANP_OUT_OF_MEMORY;
|
|
}
|
|
|
|
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();
|
|
ASSERT( lPendingWrites > 0 );
|
|
|
|
m_dwBytesWritten += dwBytesToWrite;
|
|
|
|
*ppIoPacket = pIoPacket;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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_pwszPathPlusFileName)
|
|
{
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::DeletePictureFile(): Delete: %S\n",
|
|
m_pwszPathPlusFileName );
|
|
#endif
|
|
DeleteFile(m_pwszPathPlusFileName);
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION::ClosePictureFile()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
DWORD CCONNECTION::ClosePictureFile()
|
|
{
|
|
DWORD dwStatus = NO_ERROR;
|
|
|
|
if (m_pwszPathPlusFileName)
|
|
{
|
|
FreeMemory(m_pwszPathPlusFileName);
|
|
m_pwszPathPlusFileName = 0;
|
|
}
|
|
|
|
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);
|
|
#ifdef DBG_IO
|
|
DbgPrint("CCONNECTION::IncompleteFile(): Written: %d JPEG Size: %d\n",
|
|
m_dwBytesWritten, m_dwJpegSize );
|
|
#endif
|
|
}
|
|
|
|
return fIncomplete;
|
|
}
|
|
|
|
//************************************************************************
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::CCONNECTION_MAP()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION_MAP::CCONNECTION_MAP()
|
|
{
|
|
m_dwMapSize = 0;
|
|
m_pMap = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::~CCONNECTION_MAP()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION_MAP::~CCONNECTION_MAP()
|
|
{
|
|
if (m_pMap)
|
|
{
|
|
NTSTATUS Status = RtlDeleteCriticalSection(&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);
|
|
|
|
#ifdef DBG_MEM
|
|
if (dwStatus)
|
|
{
|
|
DbgPrint("IrXfer: IrTran-P: CCONNECTION_MAP::delete Failed: %d\n",
|
|
dwStatus );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
NTSTATUS Status = RtlInitializeCriticalSection(&m_cs);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
FreeMemory(m_pMap);
|
|
m_pMap = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
m_dwMapSize = dwNewMapSize;
|
|
|
|
memset(m_pMap,0,m_dwMapSize*sizeof(CONNECTION_MAP_ENTRY));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::Lookup()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::Lookup( IN SOCKET Socket )
|
|
{
|
|
DWORD i;
|
|
NTSTATUS Status;
|
|
|
|
if (m_dwMapSize == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket == Socket)
|
|
{
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return m_pMap[i].pConnection;
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::LookupByServiceName()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::LookupByServiceName( IN char *pszServiceName )
|
|
{
|
|
DWORD i;
|
|
NTSTATUS Status;
|
|
CCONNECTION *pConnection;
|
|
|
|
if (m_dwMapSize == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
if ( (pConnection)
|
|
&& (pConnection->GetServiceName())
|
|
&& (!strcmp(pConnection->GetServiceName(),pszServiceName)))
|
|
{
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&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;
|
|
}
|
|
|
|
NTSTATUS Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
// Look for an empty place in the table:
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket == 0)
|
|
{
|
|
m_pMap[i].Socket = Socket;
|
|
m_pMap[i].pConnection = pConnection;
|
|
Status = RtlLeaveCriticalSection(&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)
|
|
{
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return FALSE; // Out of memory...
|
|
}
|
|
|
|
memset(pMap,0,dwNewMapSize*sizeof(CONNECTION_MAP_ENTRY));
|
|
|
|
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;
|
|
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::Remove()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::Remove( IN SOCKET Socket )
|
|
{
|
|
DWORD i;
|
|
CCONNECTION *pConnection;
|
|
|
|
NTSTATUS Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket == Socket)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
m_pMap[i].Socket = 0;
|
|
m_pMap[i].pConnection = 0;
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// CCONNECTION_MAP::RemoveConnection()
|
|
//
|
|
//------------------------------------------------------------------------
|
|
CCONNECTION *CCONNECTION_MAP::RemoveConnection( IN CCONNECTION *pConnection )
|
|
{
|
|
DWORD i;
|
|
NTSTATUS Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].pConnection == pConnection)
|
|
{
|
|
m_pMap[i].Socket = 0;
|
|
m_pMap[i].pConnection = 0;
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&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;
|
|
|
|
NTSTATUS Status = RtlEnterCriticalSection(&m_cs);
|
|
|
|
for (i=0; i<m_dwMapSize; i++)
|
|
{
|
|
if (m_pMap[i].Socket)
|
|
{
|
|
pConnection = m_pMap[i].pConnection;
|
|
m_pMap[i].Socket = 0;
|
|
m_pMap[i].pConnection = 0;
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
return pConnection;
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&m_cs);
|
|
|
|
return 0;
|
|
}
|
|
|