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.

506 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation
  3. Module Name:
  4. queue.cpp
  5. Abstract:
  6. Implementation of CQueue class.
  7. Revision History:
  8. 06 Dec 2000 manishap
  9. Created.
  10. --*/
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // //
  13. // Include files //
  14. // //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include <Queue.h>
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // //
  19. // CQueue Implementation //
  20. // //
  21. ///////////////////////////////////////////////////////////////////////////////
  22. CQueue::CQueue(
  23. )
  24. /*++
  25. Routine Description:
  26. Constructor for CQueue class.
  27. Arguments:
  28. None.
  29. Return Values:
  30. None.
  31. --*/
  32. {
  33. HKEY hk = NULL;
  34. DWORD dwType = 0,dwSize = 0;
  35. m_pHead = NULL;
  36. m_pTail = NULL;
  37. DWORD dwDisp = 0;
  38. if( !TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_PARAMS_KEY, NULL, NULL,
  39. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0) )
  40. {
  41. if( RegQueryValueEx( hk, L"MaxConnections", NULL, &dwType,
  42. ( LPBYTE )& m_dwMaxUnauthenticatedConnections,&dwSize)
  43. )
  44. {
  45. m_dwMaxUnauthenticatedConnections = DEFAULT_MAX_CONNECTIONS;
  46. }
  47. }
  48. else
  49. {
  50. m_dwMaxUnauthenticatedConnections = DEFAULT_MAX_CONNECTIONS;
  51. }
  52. m_dwNumOfUnauthenticatedConnections = 0;
  53. m_dwMaxIPLimit = 4;
  54. __try
  55. {
  56. InitializeCriticalSection(&m_csQModification);
  57. }
  58. __except(EXCEPTION_EXECUTE_HANDLER)
  59. {
  60. ; // Nothing to do, just don't die.... BaskarK
  61. }
  62. }
  63. CQueue::~CQueue(
  64. )
  65. /*++
  66. Routine Description:
  67. Destructor for CQueue class.
  68. Arguments:
  69. None.
  70. Return Values:
  71. None.
  72. --*/
  73. {
  74. if(m_pHead != NULL && m_pTail != NULL )
  75. {
  76. PQ_LIST_ENTRY pTmp=m_pHead;
  77. while( m_pHead != m_pTail )
  78. {
  79. pTmp = m_pHead;
  80. m_pHead = m_pHead->pQNext;
  81. delete pTmp;
  82. }
  83. delete m_pHead;
  84. }
  85. m_pHead = NULL;
  86. m_pTail = NULL;
  87. DeleteCriticalSection(&m_csQModification);
  88. }
  89. /*++
  90. Routine Description:
  91. Checks whether queue is full. i.e. if the number of entries are equal
  92. to maximum number of unauthenticated connections allowed.
  93. Arguments:
  94. None.
  95. Return Values:
  96. Returns TRUE on success.
  97. --*/
  98. bool
  99. CQueue::IsQFull()
  100. { bool result;
  101. bool bCSOwned = true;
  102. do
  103. {
  104. __try
  105. {
  106. EnterCriticalSection(&m_csQModification);
  107. }
  108. __except(EXCEPTION_EXECUTE_HANDLER)
  109. {
  110. Sleep(1);
  111. bCSOwned = false;
  112. }
  113. }
  114. while(!bCSOwned);
  115. result = (m_dwNumOfUnauthenticatedConnections >= m_dwMaxUnauthenticatedConnections) ? true : false;
  116. LeaveCriticalSection(&m_csQModification);
  117. return result;
  118. }
  119. bool
  120. CQueue::FreeEntry(DWORD dwPid)
  121. /*++
  122. Routine Description:
  123. Frees a particular entry in the queue.
  124. Also modifies the MaxNumOfUnauthenticatedConn.
  125. Arguments:
  126. [in]pId whose entry is to be removed.
  127. Return Values:
  128. Returns TRUE on success.
  129. --*/
  130. {
  131. bool bFound = FALSE;
  132. bool bCSOwned = true;
  133. do
  134. {
  135. __try
  136. {
  137. EnterCriticalSection(&m_csQModification);
  138. }
  139. __except(EXCEPTION_EXECUTE_HANDLER)
  140. {
  141. Sleep(1);
  142. bCSOwned = false;
  143. }
  144. }
  145. while(!bCSOwned);
  146. PQ_LIST_ENTRY pTmp=m_pHead;
  147. while(!bFound && pTmp )
  148. {
  149. if( pTmp->dwPid == dwPid )
  150. {
  151. bFound = TRUE;
  152. }
  153. else if( pTmp != m_pTail )
  154. {
  155. pTmp = pTmp->pQNext;
  156. }
  157. else
  158. {
  159. break;
  160. }
  161. }
  162. if(bFound)
  163. {
  164. if(pTmp == m_pHead )
  165. {
  166. if(m_pHead->pQNext)
  167. {
  168. m_pHead = m_pHead->pQNext;
  169. m_pHead->pQPrev = NULL;
  170. }
  171. else
  172. {
  173. m_pHead = NULL;
  174. m_pTail = NULL;
  175. }
  176. }
  177. else if ( pTmp == m_pTail )
  178. {
  179. m_pTail = m_pTail->pQPrev;
  180. m_pTail->pQNext = NULL;
  181. }
  182. else
  183. {
  184. (pTmp->pQPrev)->pQNext = pTmp->pQNext;
  185. (pTmp->pQNext)->pQPrev = pTmp->pQPrev;
  186. }
  187. m_dwNumOfUnauthenticatedConnections--;
  188. delete pTmp;
  189. }
  190. LeaveCriticalSection(&m_csQModification);
  191. return (bFound);
  192. }
  193. bool
  194. CQueue::Pop(HANDLE *phWritePipe)
  195. /*++
  196. Routine Description:
  197. Frees a head entry in the queue.
  198. Arguments:
  199. Stores the pid and pipe handle. [out]pId, [out]PipeHandle.
  200. Return Values:
  201. Returns TRUE on success.
  202. --*/
  203. {
  204. bool bRet = FALSE;
  205. bool bCSOwned = true;
  206. do
  207. {
  208. __try
  209. {
  210. EnterCriticalSection(&m_csQModification);
  211. }
  212. __except(EXCEPTION_EXECUTE_HANDLER)
  213. {
  214. Sleep(1);
  215. bCSOwned = false;
  216. }
  217. }
  218. while(!bCSOwned);
  219. *phWritePipe = m_pHead->hWritePipe;
  220. bRet = FreeEntry(m_pHead->dwPid);
  221. LeaveCriticalSection(&m_csQModification);
  222. return (bRet);
  223. }
  224. /*++
  225. Routine Description:
  226. Checks whether new entry can be added to the queue. New entry will
  227. be denied when it comes from an IP Address for which the maximum
  228. number of entries allowed per IP Address are already present in the queue
  229. or when the queue is full.
  230. In normal case, when new entry is to be added and the queue is not full,
  231. entry is added at the tail position.
  232. In case of IPLimit Reached, and QueueFull, the bool variable bSendMessage
  233. is set to TRUE, which will be passed back to the caller function, which in turn
  234. will send a message to the session that it ( the session ) has been terminated.
  235. Arguments:
  236. [in]pId ,[in]IP Address , [in/out]PipeHandle of an entry to be added [out]SendMessage. On Input,
  237. it takes the values to be added in the queue. On output, it sends the values of removed
  238. entry in case of IPLimitReached or QueueFull. [out]bSendMessage is set to true if
  239. the queue is full or if the IPlimit is reached. This
  240. flag will be used to notify that particular session that it should terminate.
  241. Return Values:
  242. Returns TRUE if the entry gets added to the queue successfully.
  243. --*/
  244. bool
  245. CQueue::WasTheClientAdded(DWORD dwPid, IP_ADDR *pchIPAddr, HANDLE *phWritePipe, bool *pbSendMessage)
  246. {
  247. bool bRet = FALSE;
  248. HANDLE hHeadWritePipe=NULL;
  249. bool bCSOwned = true;
  250. do
  251. {
  252. __try
  253. {
  254. EnterCriticalSection(&m_csQModification);
  255. }
  256. __except(EXCEPTION_EXECUTE_HANDLER)
  257. {
  258. Sleep(1);
  259. bCSOwned = false;
  260. }
  261. }
  262. while(!bCSOwned);
  263. *pbSendMessage = true;
  264. if((! IsQFull()) && (! IsIPLimitReached(pchIPAddr)))
  265. {
  266. if (Push(dwPid, phWritePipe, pchIPAddr)) // This could fail in low memory
  267. {
  268. bRet = TRUE;
  269. *pbSendMessage = false;
  270. }
  271. }
  272. LeaveCriticalSection(&m_csQModification);
  273. return (bRet);
  274. }
  275. bool
  276. CQueue::OkToProceedWithThisClient(IP_ADDR *pchIPAddr)
  277. {
  278. bool bRet = TRUE;
  279. bool bCSOwned = true;
  280. do
  281. {
  282. __try
  283. {
  284. EnterCriticalSection(&m_csQModification);
  285. }
  286. __except(EXCEPTION_EXECUTE_HANDLER)
  287. {
  288. Sleep(1);
  289. bCSOwned = false;
  290. }
  291. }
  292. while(!bCSOwned);
  293. if (
  294. (IsQFull()) ||
  295. (IsIPLimitReached(pchIPAddr))
  296. )
  297. {
  298. bRet = false;
  299. }
  300. LeaveCriticalSection(&m_csQModification);
  301. return (bRet);
  302. }
  303. /*++
  304. Routine Description:
  305. Checks if the maximum number of entries for a particular IP Address are already
  306. present.
  307. Arguments:
  308. IP address of new entry to be added in the queue.
  309. Return Values:
  310. Returns TRUE if maximum number of entries for a particular IP Address are
  311. already present.
  312. --*/
  313. bool
  314. CQueue::IsIPLimitReached(IP_ADDR *pchIPAddr)
  315. {
  316. bool bReached = FALSE;
  317. DWORD dwCount = 0;
  318. // Request ownership of the critical section.
  319. bool bCSOwned = true;
  320. do
  321. {
  322. __try
  323. {
  324. EnterCriticalSection(&m_csQModification);
  325. }
  326. __except(EXCEPTION_EXECUTE_HANDLER)
  327. {
  328. Sleep(1);
  329. bCSOwned = false;
  330. }
  331. }
  332. while(!bCSOwned);
  333. PQ_LIST_ENTRY pTmp = m_pHead;
  334. while( pTmp )
  335. {
  336. if(strcmp (pTmp->chIPAddr, pchIPAddr) == 0 )
  337. {
  338. dwCount ++;
  339. if(dwCount == m_dwMaxIPLimit)
  340. {
  341. bReached = TRUE;
  342. break;
  343. }
  344. }
  345. pTmp = pTmp->pQNext;
  346. }
  347. // Release ownership of the critical section.
  348. LeaveCriticalSection(&m_csQModification);
  349. return (bReached);
  350. }
  351. bool
  352. CQueue::Push(DWORD dwPid, HANDLE *phWritePipe, IP_ADDR *pchIPAddr)
  353. /*++
  354. Routine Description:
  355. Allocates memory for an entry and adds it in the queue.
  356. Also modifies the MaxNumOfUnauthenticatedConn.
  357. Arguments:
  358. [in]pId and [in]PipeHandle [in]IP Address of an entry to be added.
  359. Return Values:
  360. Returns TRUE on success.
  361. --*/
  362. {
  363. PQ_LIST_ENTRY pNode;
  364. bool bRet = FALSE;
  365. // Request ownership of the critical section.
  366. bool bCSOwned = true;
  367. do
  368. {
  369. __try
  370. {
  371. EnterCriticalSection(&m_csQModification);
  372. }
  373. __except(EXCEPTION_EXECUTE_HANDLER)
  374. {
  375. Sleep(1);
  376. bCSOwned = false;
  377. }
  378. }
  379. while(!bCSOwned);
  380. pNode = (PQ_LIST_ENTRY) new Q_LIST_ENTRY;
  381. if (pNode)
  382. {
  383. pNode->pQNext = NULL;
  384. pNode->pQPrev= NULL;
  385. if(NULL == m_pHead )
  386. {
  387. m_pHead = pNode;
  388. m_pTail = pNode;
  389. }
  390. else
  391. {
  392. m_pTail->pQNext = pNode;
  393. pNode->pQPrev = m_pTail;
  394. m_pTail = pNode;
  395. }
  396. m_pTail->dwPid = dwPid;
  397. m_pTail->hWritePipe = (*phWritePipe);
  398. strncpy(m_pTail->chIPAddr, pchIPAddr, SMALL_STRING - 1);
  399. bRet = TRUE;
  400. m_dwNumOfUnauthenticatedConnections++;
  401. }
  402. // Release ownership of the critical section.
  403. LeaveCriticalSection(&m_csQModification);
  404. return (bRet);
  405. }