Leaked source code of windows server 2003
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.
 
 
 
 
 
 

363 lines
7.5 KiB

//--------------------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation, 1996
//
// Description:
//
// Microsoft Internet LDAP Client
//
//
// Authors:
//
// Umesh Madan
// Robert Carney 4/17/96 Created from ChatSock library.
// davidsan 04-25-96 hacked into tiny bits for my own devious purposes
//
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
//
// INCLUDES
//
//--------------------------------------------------------------------------------------------
#include "ldappch.h"
//--------------------------------------------------------------------------------------------
//
// PROTOTYPES
//
//--------------------------------------------------------------------------------------------
DWORD __stdcall DwReadThread(PVOID pvData);
//--------------------------------------------------------------------------------------------
//
// GLOBALS
//
//--------------------------------------------------------------------------------------------
BOOL g_fInitedWinsock = FALSE;
//--------------------------------------------------------------------------------------------
//
// FUNCTIONS
//
//--------------------------------------------------------------------------------------------
BOOL FInitSocketDLL()
{
WORD wVer;
WSADATA wsaData;
int err;
wVer = MAKEWORD(1, 1); // use Winsock 1.1
if (WSAStartup(wVer, &wsaData))
return FALSE;
return TRUE;
}
void FreeSocketDLL()
{
WSACleanup();
}
//--------------------------------------------------------------------------------------------
//
// CLASSES
//
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
//
// CLdapWinsock
//
// Wrapper that implements a socket based connection.
//
//--------------------------------------------------------------------------------------------
CLdapWinsock::CLdapWinsock()
{
m_sc = INVALID_SOCKET;
m_pfnReceive = NULL;
m_pvCookie = NULL;
m_pbBuf = NULL;
m_cbBuf = 0;
m_cbBufMax = 0;
m_fConnected = FALSE;
m_hthread = NULL;
InitializeCriticalSection(&m_cs);
}
CLdapWinsock::~CLdapWinsock(void)
{
if (m_pbBuf)
delete [] m_pbBuf;
DeleteCriticalSection(&m_cs);
}
//
// Open a connection the named server, and connect to the port 'usPort' (host byte order)
// Can block
//
STDMETHODIMP
CLdapWinsock::HrConnect(PFNRECEIVEDATA pfnReceive, PVOID pvCookie, CHAR *szServer, USHORT usPort)
{
SOCKADDR_IN sin;
struct hostent *phe;
HRESULT hr;
if (!pfnReceive || !szServer || !usPort)
return E_INVALIDARG;
Assert(!m_pbBuf);
if (!m_pbBuf)
{
m_cbBufMax = CBBUFFERGROW;
m_pbBuf = new BYTE[m_cbBufMax];
m_cbBuf = 0;
if (!m_pbBuf)
return E_OUTOFMEMORY;
}
FillMemory(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(usPort);
if (szServer[0] >= '1' && szServer[0] <= '9')
{
sin.sin_addr.s_addr = inet_addr(szServer);
if (sin.sin_addr.s_addr == INADDR_NONE)
{
delete [] m_pbBuf;
m_pbBuf = NULL;
return LDAP_E_HOSTNOTFOUND;
}
}
else
{
phe = gethostbyname(szServer);
if (!phe)
{
delete [] m_pbBuf;
m_pbBuf = NULL;
return LDAP_E_HOSTNOTFOUND;
}
CopyMemory(&sin.sin_addr, phe->h_addr, phe->h_length);
}
::EnterCriticalSection(&m_cs);
if (m_fConnected)
this->HrDisconnect();
m_sc = socket(PF_INET, SOCK_STREAM, 0);
if (m_sc < 0)
{
delete [] m_pbBuf;
m_pbBuf = NULL;
::LeaveCriticalSection(&m_cs);
return LDAP_E_INVALIDSOCKET;
}
if (connect(m_sc, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
delete [] m_pbBuf;
m_pbBuf = NULL;
::LeaveCriticalSection(&m_cs);
return LDAP_E_CANTCONNECT;
}
hr = this->HrCreateReadThread();
if (SUCCEEDED(hr))
m_fConnected = TRUE;
else
{
delete [] m_pbBuf;
m_pbBuf = NULL;
}
::LeaveCriticalSection(&m_cs);
m_pfnReceive = pfnReceive;
m_pvCookie = pvCookie;
return hr;
}
STDMETHODIMP
CLdapWinsock::HrDisconnect()
{
HRESULT hr = NOERROR;
if (!m_fConnected)
return NOERROR;
::EnterCriticalSection(&m_cs);
m_fConnected = FALSE;
closesocket(m_sc);
::LeaveCriticalSection(&m_cs);
WaitForSingleObject(m_hthread, INFINITE);
::EnterCriticalSection(&m_cs);
delete [] m_pbBuf;
m_cbBuf = 0;
m_cbBufMax = 0;
m_pbBuf = NULL;
::LeaveCriticalSection(&m_cs);
return hr;
}
HRESULT
CLdapWinsock::HrCreateReadThread()
{
HRESULT hr = NOERROR;
::EnterCriticalSection(&m_cs);
m_hthread = ::CreateThread(
NULL,
0,
::DwReadThread,
(LPVOID)this,
0,
&m_dwTid
);
if (!m_hthread)
hr = E_OUTOFMEMORY;
::LeaveCriticalSection(&m_cs);
return hr;
}
//
// Write pvData out to the current socket/connection.
// can block
//
HRESULT
CLdapWinsock::HrSend(PVOID pv, int cb)
{
HRESULT hr = NOERROR;
if (!pv || cb <= 0)
return E_INVALIDARG;
if (send(m_sc, (const char *)pv, cb, 0) == SOCKET_ERROR)
hr = this->HrLastWinsockError();
return hr;
}
HRESULT
CLdapWinsock::HrGrowBuffer()
{
BYTE *pb;
Assert(m_cbBufMax == m_cbBuf);
pb = new BYTE[m_cbBufMax + CBBUFFERGROW];
if (!pb)
return E_OUTOFMEMORY;
CopyMemory(pb, m_pbBuf, m_cbBuf);
delete [] m_pbBuf;
m_pbBuf = pb;
m_cbBufMax += CBBUFFERGROW;
return NOERROR;
}
void
CLdapWinsock::Receive(PVOID pv, int cb, int *pcbReceived)
{
if (m_pfnReceive)
m_pfnReceive(m_pvCookie, pv, cb, pcbReceived);
}
//$ TODO: Find a way to pass memory errors back to the API
DWORD
CLdapWinsock::DwReadThread()
{
int cbRead;
int cbLeft;
int cbReceived;
while (1)
{
// at the beginning of this loop: any unprocessed data is in m_pbBuf[0..m_cbBuf].
Assert(m_cbBuf <= m_cbBufMax);
if (m_cbBuf == m_cbBufMax)
{
if (FAILED(this->HrGrowBuffer()))
return 0xFFFFFFFF;
}
cbLeft = m_cbBufMax - m_cbBuf;
cbRead = recv(m_sc, (LPSTR)&(m_pbBuf[m_cbBuf]), cbLeft, 0);
if (cbRead == 0 || cbRead == SOCKET_ERROR)
return 0;
// note: i don't know why this is happening, but it is...
if (cbRead < 0)
return 0;
m_cbBuf += cbRead;
do
{
this->Receive(m_pbBuf, m_cbBuf, &cbReceived);
if (cbReceived)
{
m_cbBuf -= cbReceived;
CopyMemory(m_pbBuf, &m_pbBuf[cbReceived], m_cbBuf);
}
}
while (cbReceived && m_cbBuf);
}
}
HRESULT
CLdapWinsock::HrIsConnected(void)
{
return m_fConnected ? NOERROR : S_FALSE;
}
//$ TODO: Are there other errors that i need to handle here?
HRESULT
CLdapWinsock::HrLastWinsockError()
{
int idErr;
HRESULT hr = E_FAIL;
idErr = WSAGetLastError();
switch (idErr)
{
default:
break;
case WSANOTINITIALISED:
AssertSz(0,"socket not initialized!");
hr = E_FAIL;
break;
case WSAENETDOWN:
hr = LDAP_E_NETWORKDOWN;
break;
case WSAENETRESET:
hr = LDAP_E_LOSTCONNECTION;
break;
case WSAENOTCONN:
AssertSz(0,"Not connected!");
hr = E_FAIL;
break;
case WSAESHUTDOWN:
hr = LDAP_E_SOCKETCLOSED;
break;
case WSAECONNRESET:
hr = LDAP_E_HOSTDROPPED;
break;
}
return hr;
}
DWORD __stdcall DwReadThread(PVOID pvData)
{
PSOCK psock = (PSOCK)pvData;
Assert(pvData);
return psock->DwReadThread();
}