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

  1. //--------------------------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation, 1996
  4. //
  5. // Description:
  6. //
  7. // Microsoft Internet LDAP Client
  8. //
  9. //
  10. // Authors:
  11. //
  12. // Umesh Madan
  13. // Robert Carney 4/17/96 Created from ChatSock library.
  14. // davidsan 04-25-96 hacked into tiny bits for my own devious purposes
  15. //
  16. //--------------------------------------------------------------------------------------------
  17. //--------------------------------------------------------------------------------------------
  18. //
  19. // INCLUDES
  20. //
  21. //--------------------------------------------------------------------------------------------
  22. #include "ldappch.h"
  23. //--------------------------------------------------------------------------------------------
  24. //
  25. // PROTOTYPES
  26. //
  27. //--------------------------------------------------------------------------------------------
  28. DWORD __stdcall DwReadThread(PVOID pvData);
  29. //--------------------------------------------------------------------------------------------
  30. //
  31. // GLOBALS
  32. //
  33. //--------------------------------------------------------------------------------------------
  34. BOOL g_fInitedWinsock = FALSE;
  35. //--------------------------------------------------------------------------------------------
  36. //
  37. // FUNCTIONS
  38. //
  39. //--------------------------------------------------------------------------------------------
  40. BOOL FInitSocketDLL()
  41. {
  42. WORD wVer;
  43. WSADATA wsaData;
  44. int err;
  45. wVer = MAKEWORD(1, 1); // use Winsock 1.1
  46. if (WSAStartup(wVer, &wsaData))
  47. return FALSE;
  48. return TRUE;
  49. }
  50. void FreeSocketDLL()
  51. {
  52. WSACleanup();
  53. }
  54. //--------------------------------------------------------------------------------------------
  55. //
  56. // CLASSES
  57. //
  58. //--------------------------------------------------------------------------------------------
  59. //--------------------------------------------------------------------------------------------
  60. //
  61. // CLdapWinsock
  62. //
  63. // Wrapper that implements a socket based connection.
  64. //
  65. //--------------------------------------------------------------------------------------------
  66. CLdapWinsock::CLdapWinsock()
  67. {
  68. m_sc = INVALID_SOCKET;
  69. m_pfnReceive = NULL;
  70. m_pvCookie = NULL;
  71. m_pbBuf = NULL;
  72. m_cbBuf = 0;
  73. m_cbBufMax = 0;
  74. m_fConnected = FALSE;
  75. m_hthread = NULL;
  76. InitializeCriticalSection(&m_cs);
  77. }
  78. CLdapWinsock::~CLdapWinsock(void)
  79. {
  80. if (m_pbBuf)
  81. delete [] m_pbBuf;
  82. DeleteCriticalSection(&m_cs);
  83. }
  84. //
  85. // Open a connection the named server, and connect to the port 'usPort' (host byte order)
  86. // Can block
  87. //
  88. STDMETHODIMP
  89. CLdapWinsock::HrConnect(PFNRECEIVEDATA pfnReceive, PVOID pvCookie, CHAR *szServer, USHORT usPort)
  90. {
  91. SOCKADDR_IN sin;
  92. struct hostent *phe;
  93. HRESULT hr;
  94. if (!pfnReceive || !szServer || !usPort)
  95. return E_INVALIDARG;
  96. Assert(!m_pbBuf);
  97. if (!m_pbBuf)
  98. {
  99. m_cbBufMax = CBBUFFERGROW;
  100. m_pbBuf = new BYTE[m_cbBufMax];
  101. m_cbBuf = 0;
  102. if (!m_pbBuf)
  103. return E_OUTOFMEMORY;
  104. }
  105. FillMemory(&sin, 0, sizeof(sin));
  106. sin.sin_family = AF_INET;
  107. sin.sin_port = htons(usPort);
  108. if (szServer[0] >= '1' && szServer[0] <= '9')
  109. {
  110. sin.sin_addr.s_addr = inet_addr(szServer);
  111. if (sin.sin_addr.s_addr == INADDR_NONE)
  112. {
  113. delete [] m_pbBuf;
  114. m_pbBuf = NULL;
  115. return LDAP_E_HOSTNOTFOUND;
  116. }
  117. }
  118. else
  119. {
  120. phe = gethostbyname(szServer);
  121. if (!phe)
  122. {
  123. delete [] m_pbBuf;
  124. m_pbBuf = NULL;
  125. return LDAP_E_HOSTNOTFOUND;
  126. }
  127. CopyMemory(&sin.sin_addr, phe->h_addr, phe->h_length);
  128. }
  129. ::EnterCriticalSection(&m_cs);
  130. if (m_fConnected)
  131. this->HrDisconnect();
  132. m_sc = socket(PF_INET, SOCK_STREAM, 0);
  133. if (m_sc < 0)
  134. {
  135. delete [] m_pbBuf;
  136. m_pbBuf = NULL;
  137. ::LeaveCriticalSection(&m_cs);
  138. return LDAP_E_INVALIDSOCKET;
  139. }
  140. if (connect(m_sc, (struct sockaddr *)&sin, sizeof(sin)) < 0)
  141. {
  142. delete [] m_pbBuf;
  143. m_pbBuf = NULL;
  144. ::LeaveCriticalSection(&m_cs);
  145. return LDAP_E_CANTCONNECT;
  146. }
  147. hr = this->HrCreateReadThread();
  148. if (SUCCEEDED(hr))
  149. m_fConnected = TRUE;
  150. else
  151. {
  152. delete [] m_pbBuf;
  153. m_pbBuf = NULL;
  154. }
  155. ::LeaveCriticalSection(&m_cs);
  156. m_pfnReceive = pfnReceive;
  157. m_pvCookie = pvCookie;
  158. return hr;
  159. }
  160. STDMETHODIMP
  161. CLdapWinsock::HrDisconnect()
  162. {
  163. HRESULT hr = NOERROR;
  164. if (!m_fConnected)
  165. return NOERROR;
  166. ::EnterCriticalSection(&m_cs);
  167. m_fConnected = FALSE;
  168. closesocket(m_sc);
  169. ::LeaveCriticalSection(&m_cs);
  170. WaitForSingleObject(m_hthread, INFINITE);
  171. ::EnterCriticalSection(&m_cs);
  172. delete [] m_pbBuf;
  173. m_cbBuf = 0;
  174. m_cbBufMax = 0;
  175. m_pbBuf = NULL;
  176. ::LeaveCriticalSection(&m_cs);
  177. return hr;
  178. }
  179. HRESULT
  180. CLdapWinsock::HrCreateReadThread()
  181. {
  182. HRESULT hr = NOERROR;
  183. ::EnterCriticalSection(&m_cs);
  184. m_hthread = ::CreateThread(
  185. NULL,
  186. 0,
  187. ::DwReadThread,
  188. (LPVOID)this,
  189. 0,
  190. &m_dwTid
  191. );
  192. if (!m_hthread)
  193. hr = E_OUTOFMEMORY;
  194. ::LeaveCriticalSection(&m_cs);
  195. return hr;
  196. }
  197. //
  198. // Write pvData out to the current socket/connection.
  199. // can block
  200. //
  201. HRESULT
  202. CLdapWinsock::HrSend(PVOID pv, int cb)
  203. {
  204. HRESULT hr = NOERROR;
  205. if (!pv || cb <= 0)
  206. return E_INVALIDARG;
  207. if (send(m_sc, (const char *)pv, cb, 0) == SOCKET_ERROR)
  208. hr = this->HrLastWinsockError();
  209. return hr;
  210. }
  211. HRESULT
  212. CLdapWinsock::HrGrowBuffer()
  213. {
  214. BYTE *pb;
  215. Assert(m_cbBufMax == m_cbBuf);
  216. pb = new BYTE[m_cbBufMax + CBBUFFERGROW];
  217. if (!pb)
  218. return E_OUTOFMEMORY;
  219. CopyMemory(pb, m_pbBuf, m_cbBuf);
  220. delete [] m_pbBuf;
  221. m_pbBuf = pb;
  222. m_cbBufMax += CBBUFFERGROW;
  223. return NOERROR;
  224. }
  225. void
  226. CLdapWinsock::Receive(PVOID pv, int cb, int *pcbReceived)
  227. {
  228. if (m_pfnReceive)
  229. m_pfnReceive(m_pvCookie, pv, cb, pcbReceived);
  230. }
  231. //$ TODO: Find a way to pass memory errors back to the API
  232. DWORD
  233. CLdapWinsock::DwReadThread()
  234. {
  235. int cbRead;
  236. int cbLeft;
  237. int cbReceived;
  238. while (1)
  239. {
  240. // at the beginning of this loop: any unprocessed data is in m_pbBuf[0..m_cbBuf].
  241. Assert(m_cbBuf <= m_cbBufMax);
  242. if (m_cbBuf == m_cbBufMax)
  243. {
  244. if (FAILED(this->HrGrowBuffer()))
  245. return 0xFFFFFFFF;
  246. }
  247. cbLeft = m_cbBufMax - m_cbBuf;
  248. cbRead = recv(m_sc, (LPSTR)&(m_pbBuf[m_cbBuf]), cbLeft, 0);
  249. if (cbRead == 0 || cbRead == SOCKET_ERROR)
  250. return 0;
  251. // note: i don't know why this is happening, but it is...
  252. if (cbRead < 0)
  253. return 0;
  254. m_cbBuf += cbRead;
  255. do
  256. {
  257. this->Receive(m_pbBuf, m_cbBuf, &cbReceived);
  258. if (cbReceived)
  259. {
  260. m_cbBuf -= cbReceived;
  261. CopyMemory(m_pbBuf, &m_pbBuf[cbReceived], m_cbBuf);
  262. }
  263. }
  264. while (cbReceived && m_cbBuf);
  265. }
  266. }
  267. HRESULT
  268. CLdapWinsock::HrIsConnected(void)
  269. {
  270. return m_fConnected ? NOERROR : S_FALSE;
  271. }
  272. //$ TODO: Are there other errors that i need to handle here?
  273. HRESULT
  274. CLdapWinsock::HrLastWinsockError()
  275. {
  276. int idErr;
  277. HRESULT hr = E_FAIL;
  278. idErr = WSAGetLastError();
  279. switch (idErr)
  280. {
  281. default:
  282. break;
  283. case WSANOTINITIALISED:
  284. AssertSz(0,"socket not initialized!");
  285. hr = E_FAIL;
  286. break;
  287. case WSAENETDOWN:
  288. hr = LDAP_E_NETWORKDOWN;
  289. break;
  290. case WSAENETRESET:
  291. hr = LDAP_E_LOSTCONNECTION;
  292. break;
  293. case WSAENOTCONN:
  294. AssertSz(0,"Not connected!");
  295. hr = E_FAIL;
  296. break;
  297. case WSAESHUTDOWN:
  298. hr = LDAP_E_SOCKETCLOSED;
  299. break;
  300. case WSAECONNRESET:
  301. hr = LDAP_E_HOSTDROPPED;
  302. break;
  303. }
  304. return hr;
  305. }
  306. DWORD __stdcall DwReadThread(PVOID pvData)
  307. {
  308. PSOCK psock = (PSOCK)pvData;
  309. Assert(pvData);
  310. return psock->DwReadThread();
  311. }