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.

1348 lines
33 KiB

  1. /*++
  2. * File name:
  3. * queues.c
  4. * Contents:
  5. * Supports the linked lists for the clients
  6. * and events
  7. * Two linked lists:
  8. * g_pClientQHead - list of all clients running within smclient
  9. * g_pWaitQHead - all events we are waiting for from smclient
  10. *
  11. * Copyright (C) 1998-1999 Microsoft Corp.
  12. --*/
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <malloc.h>
  16. #include <process.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20. #include "tclient.h"
  21. #include "protocol.h"
  22. #include "gdata.h"
  23. #include "bmpcache.h"
  24. /*
  25. *
  26. * ClientQ functions
  27. *
  28. */
  29. /*++
  30. * Function:
  31. * _AddToClientQ
  32. * Description:
  33. * Adds a client on the top of the list
  34. * Arguments:
  35. * pClient - the client context
  36. * Called by:
  37. * SCConnect
  38. --*/
  39. VOID _AddToClientQ(PCONNECTINFO pClient)
  40. {
  41. EnterCriticalSection(g_lpcsGuardWaitQueue);
  42. pClient->pNext = g_pClientQHead;
  43. g_pClientQHead = pClient;
  44. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  45. }
  46. /*++
  47. * Function:
  48. * _RemoveFromClientQ
  49. * Description:
  50. * Removes a client context from the list
  51. * Arguments:
  52. * pClient - the client context
  53. * Return value:
  54. * TRUE on success
  55. * Called by:
  56. * SCDisconnect
  57. --*/
  58. BOOL _RemoveFromClientQ(PCONNECTINFO pClient)
  59. {
  60. PCONNECTINFO pIter, pPrev = NULL;
  61. EnterCriticalSection(g_lpcsGuardWaitQueue);
  62. pIter = g_pClientQHead;
  63. while (pIter && pIter != pClient) {
  64. pPrev = pIter;
  65. pIter = pIter->pNext;
  66. }
  67. if (pIter) {
  68. if (!pPrev) g_pClientQHead = pIter->pNext;
  69. else pPrev->pNext = pIter->pNext;
  70. pIter->pNext = NULL;
  71. }
  72. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  73. return (pIter != NULL);
  74. }
  75. /*++
  76. * Function:
  77. * _SetClientDead
  78. * Description:
  79. * Marks a client context as dead
  80. * Arguments:
  81. * dwClientProcessId - ID for the client process
  82. * Return value:
  83. * TRUE on success
  84. * Called by:
  85. * _FeedbackWndProc within feedback thread
  86. --*/
  87. BOOL _SetClientDead(LONG_PTR lClientProcessId)
  88. {
  89. PCONNECTINFO pIter;
  90. EnterCriticalSection(g_lpcsGuardWaitQueue);
  91. pIter = g_pClientQHead;
  92. while (pIter && pIter->lProcessId != lClientProcessId)
  93. {
  94. pIter = pIter->pNext;
  95. }
  96. if (pIter) pIter->dead = TRUE;
  97. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  98. return (pIter != NULL);
  99. }
  100. /*++
  101. * Function:
  102. * _ReplaceProcessId
  103. * Description:
  104. * the client notifys that the control is in anther process
  105. * we have to close the old handles and open handles to
  106. * the new pid
  107. *
  108. * Arguments:
  109. * lOldPid - the old pid
  110. * lNewPid - the pid to replace with
  111. * Return value:
  112. * TRUE on success
  113. * Called by:
  114. * _FeedbackWndProc within feedback thread
  115. --*/
  116. BOOL
  117. _ReplaceProcessId(
  118. LONG_PTR lOldPid,
  119. LONG_PTR lNewPid
  120. )
  121. {
  122. BOOL rv = FALSE;
  123. HANDLE hNewProcess = NULL;
  124. PCONNECTINFO pIter;
  125. PWAIT4STRING pWait;
  126. hNewProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE,
  127. PtrToLong((PVOID) lNewPid ));
  128. if ( NULL == hNewProcess )
  129. {
  130. TRACE((ERROR_MESSAGE, "_ReplaceProcessId: can't open a handle to "
  131. "the new process. GetLastError=%d\n", GetLastError()));
  132. goto exitpt;
  133. }
  134. //
  135. // find the entry with the old process id
  136. //
  137. EnterCriticalSection(g_lpcsGuardWaitQueue);
  138. pIter = g_pClientQHead;
  139. while (pIter && pIter->lProcessId != lOldPid)
  140. {
  141. pIter = pIter->pNext;
  142. }
  143. if ( NULL == pIter )
  144. {
  145. TRACE((WARNING_MESSAGE, "_ReplaceProcessId: can't find old pid\n" ));
  146. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  147. goto exitpt;
  148. }
  149. if ( NULL != pIter->hProcess )
  150. CloseHandle( pIter->hProcess );
  151. if ( NULL != pIter->hThread )
  152. CloseHandle( pIter->hThread );
  153. pIter->lProcessId = lNewPid;
  154. pIter->hProcess = hNewProcess;
  155. pIter->hThread = 0;
  156. //
  157. // process all waiters
  158. //
  159. pWait = g_pWaitQHead;
  160. while(pWait)
  161. {
  162. if (pWait->lProcessId == lOldPid)
  163. pWait->lProcessId = lNewPid;
  164. pWait = pWait->pNext;
  165. }
  166. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  167. rv = TRUE;
  168. exitpt:
  169. if ( !rv && NULL != hNewProcess )
  170. CloseHandle( hNewProcess );
  171. return rv;
  172. }
  173. /*++
  174. * Function:
  175. * _CheckIsAcceptable
  176. * Description:
  177. * Checks if we can accept feedback from this RDP client
  178. * i.e. if this client is member of the client queue
  179. * Arguments:
  180. * dwProcessId - clients process Id
  181. * Return value:
  182. * Pointer to connection context. NULL if not found
  183. * Called by:
  184. * _FeedbackWndProc within feedback thread
  185. --*/
  186. PCONNECTINFO _CheckIsAcceptable(LONG_PTR lProcessId, BOOL bRClxType)
  187. {
  188. PCONNECTINFO pIter;
  189. UNREFERENCED_PARAMETER(bRClxType);
  190. EnterCriticalSection(g_lpcsGuardWaitQueue);
  191. pIter = g_pClientQHead;
  192. while(pIter &&
  193. (pIter->lProcessId != lProcessId
  194. #ifdef _RCLX
  195. || pIter->RClxMode != bRClxType
  196. #endif // _RCLX
  197. ))
  198. {
  199. pIter = pIter->pNext;
  200. }
  201. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  202. return (pIter);
  203. }
  204. /*++
  205. * Function:
  206. * _AddStrToClientBuffer
  207. * Description:
  208. * Add a string to the clients history buffer
  209. * When smclient calls Wait4Str it first checks that buffer
  210. * Arguments:
  211. * str - the string
  212. * dwProcessId - the client process Id
  213. * Called by:
  214. * _CheckForWaitingWorker
  215. --*/
  216. VOID _AddStrToClientBuffer(LPCWSTR str, LONG_PTR lProcessId)
  217. {
  218. PCONNECTINFO pIter;
  219. EnterCriticalSection(g_lpcsGuardWaitQueue);
  220. pIter = g_pClientQHead;
  221. while(pIter && pIter->lProcessId != lProcessId)
  222. {
  223. pIter = pIter->pNext;
  224. }
  225. if (pIter)
  226. {
  227. INT_PTR strsize = wcslen(str);
  228. if (strsize >= MAX_STRING_LENGTH) strsize = MAX_STRING_LENGTH-1;
  229. wcsncpy( pIter->Feedback[pIter->nFBend],
  230. str,
  231. strsize);
  232. pIter->Feedback[pIter->nFBend][strsize] = 0;
  233. pIter->nFBend++;
  234. pIter->nFBend %= FEEDBACK_SIZE;
  235. if (pIter->nFBsize < FEEDBACK_SIZE)
  236. pIter->nFBsize++;
  237. }
  238. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  239. }
  240. /*
  241. *
  242. * WaitQ functions
  243. *
  244. */
  245. /*++
  246. * Function:
  247. * _AddToWaitQNoCheck
  248. * Description:
  249. * Adds an waiting event to the list with checking in the history list
  250. * Arguments:
  251. * pCI - client context
  252. * pWait - the event
  253. * Called by:
  254. * RegisterChat
  255. --*/
  256. VOID _AddToWaitQNoCheck(PCONNECTINFO pCI, PWAIT4STRING pWait)
  257. {
  258. ASSERT(pCI);
  259. EnterCriticalSection(g_lpcsGuardWaitQueue);
  260. pWait->pNext = g_pWaitQHead;
  261. g_pWaitQHead = pWait;
  262. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  263. }
  264. /*++
  265. * Function:
  266. * _AddToWaitQueue
  267. * Description:
  268. * Add an event to the list. If the event is waiting for string(s)
  269. * the history buffer is checked first
  270. * Arguments:
  271. * pCI - client context
  272. * pWait - the event
  273. * Called by:
  274. * _WaitSomething
  275. --*/
  276. VOID _AddToWaitQueue(PCONNECTINFO pCI, PWAIT4STRING pWait)
  277. {
  278. BOOL bDone = FALSE;
  279. int i, strn;
  280. ASSERT(pCI);
  281. // exit if we are dead
  282. if (
  283. #ifdef _RCLX
  284. !pWait->waitstr[0] &&
  285. #endif // _RCLX
  286. pCI->dead)
  287. {
  288. SetEvent(pWait->evWait);
  289. goto exitpt;
  290. }
  291. EnterCriticalSection(g_lpcsGuardWaitQueue);
  292. // Check if we're already received this feedback
  293. if (pWait->WaitType == WAIT_STRING)
  294. // look if the string already came
  295. for(i = 0; !bDone && i < pCI->nFBsize; i++)
  296. {
  297. strn = (FEEDBACK_SIZE + pCI->nFBend - i - 1) % FEEDBACK_SIZE;
  298. if (!pCI->Feedback[strn][0]) continue;
  299. bDone = (wcsstr(pCI->Feedback[strn], pWait->waitstr) != NULL);
  300. }
  301. // In case of waiting multiple strings
  302. else if (pWait->WaitType == WAIT_MSTRINGS)
  303. {
  304. for(i = 0; !bDone && i < pCI->nFBsize; i++)
  305. {
  306. WCHAR *wszComp = pWait->waitstr;
  307. WCHAR *wszLast = pWait->waitstr + pWait->strsize;
  308. int idx = 0;
  309. strn = (FEEDBACK_SIZE + pCI->nFBend - i - 1) % FEEDBACK_SIZE;
  310. if (!pCI->Feedback[strn][0]) continue;
  311. while (wszComp < wszLast && *wszComp && !bDone)
  312. {
  313. if (wcsstr(pCI->Feedback[strn], wszComp))
  314. {
  315. int j;
  316. // Save the string
  317. for(j = 0; wszComp[j]; j++)
  318. pCI->szWait4MultipleStrResult[j] = (char)wszComp[j];
  319. // and the index
  320. pCI->szWait4MultipleStrResult[j] = 0;
  321. pCI->nWait4MultipleStrResult = idx;
  322. bDone = TRUE;
  323. }
  324. else
  325. {
  326. // Advance to next string
  327. wszComp += wcslen(wszComp) + 1;
  328. idx ++;
  329. }
  330. }
  331. }
  332. }
  333. else if (pWait->WaitType == WAIT_CLIPBOARD
  334. #ifdef _RCLX
  335. &&
  336. pWait->pOwner->bRClxClipboardReceived
  337. #endif // _RCLX
  338. )
  339. {
  340. bDone = TRUE;
  341. }
  342. else if (pWait->WaitType == WAIT_DATA
  343. #ifdef _RCLX
  344. &&
  345. pWait->pOwner->pRClxDataChain
  346. #endif // _RCLX
  347. )
  348. {
  349. bDone = TRUE;
  350. }
  351. // The string (or anything else) is in the history list
  352. // Set the event
  353. if (bDone)
  354. {
  355. SetEvent(pWait->evWait);
  356. pCI->nFBsize = pCI->nFBend = 0;
  357. }
  358. pWait->pNext = g_pWaitQHead;
  359. g_pWaitQHead = pWait;
  360. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  361. exitpt:
  362. ;
  363. }
  364. /*++
  365. * Function:
  366. * _RemoveFromWaitQueue
  367. * Description:
  368. * Removes an event from the list
  369. * Arguments:
  370. * pWait - the event
  371. * Return value:
  372. * TRUE if the event is found and removed
  373. * Called by:
  374. * _WaitSomething, _RemoveFromWaitQIndirect
  375. --*/
  376. BOOL _RemoveFromWaitQueue(PWAIT4STRING pWait)
  377. {
  378. PWAIT4STRING pIter, pPrev = NULL;
  379. EnterCriticalSection(g_lpcsGuardWaitQueue);
  380. pIter = g_pWaitQHead;
  381. while (pIter && pIter != pWait) {
  382. pPrev = pIter;
  383. pIter = pIter->pNext;
  384. }
  385. if (pIter) {
  386. if (!pPrev) g_pWaitQHead = pIter->pNext;
  387. else pPrev->pNext = pIter->pNext;
  388. pIter->pNext = NULL;
  389. }
  390. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  391. return (pIter != NULL);
  392. }
  393. /*++
  394. * Function:
  395. * _RemoveFromWaitQIndirect
  396. * Description:
  397. * Same as _RemoveFromWaitQueue but identifies the event
  398. * by client context and waited string
  399. * Arguments:
  400. * pCI - the client context
  401. * lpszWait4 - the string
  402. * Return value:
  403. * the event
  404. * Called by:
  405. * UnregisterChat
  406. --*/
  407. PWAIT4STRING _RemoveFromWaitQIndirect(PCONNECTINFO pCI, LPCWSTR lpszWait4)
  408. {
  409. PWAIT4STRING pIter;
  410. ASSERT(pCI);
  411. // Search the list
  412. EnterCriticalSection(g_lpcsGuardWaitQueue);
  413. pIter = g_pWaitQHead;
  414. while (pIter &&
  415. (pIter->pOwner != pCI ||
  416. wcscmp(pIter->waitstr, lpszWait4))
  417. )
  418. pIter = pIter->pNext;
  419. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  420. if (pIter)
  421. {
  422. _RemoveFromWaitQueue(pIter);
  423. }
  424. return pIter;
  425. }
  426. /*++
  427. * Function:
  428. * _RetrieveFromWaitQByEvent
  429. * Description:
  430. * Searches the waiting list by event handler
  431. * Arguments:
  432. * hEvent - the handler
  433. * Return value:
  434. * The event structure
  435. * Called by:
  436. * _WaitSomething when responds on chat sequence
  437. --*/
  438. PWAIT4STRING _RetrieveFromWaitQByEvent(HANDLE hEvent)
  439. {
  440. PWAIT4STRING pIter;
  441. EnterCriticalSection(g_lpcsGuardWaitQueue);
  442. pIter = g_pWaitQHead;
  443. while (pIter &&
  444. pIter->evWait != hEvent)
  445. pIter = pIter->pNext;
  446. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  447. return pIter;
  448. }
  449. /*++
  450. * Function:
  451. * _RetrieveFromWaitQByOwner
  452. * Description:
  453. * Searches the waiting list by owner record
  454. * Arguments:
  455. * pCI - pointer to the owner context
  456. * Return value:
  457. * The event structure
  458. * Called by:
  459. * RClx_MsgReceived
  460. --*/
  461. PWAIT4STRING
  462. _RetrieveFromWaitQByOwner(PCONNECTINFO pCI)
  463. {
  464. PWAIT4STRING pIter;
  465. EnterCriticalSection(g_lpcsGuardWaitQueue);
  466. pIter = g_pWaitQHead;
  467. while (pIter &&
  468. pIter->pOwner != pCI)
  469. pIter = pIter->pNext;
  470. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  471. return pIter;
  472. }
  473. /*++
  474. * Function:
  475. * _FlushFromWaitQ
  476. * Description:
  477. * Flush everithing that we are waiting for from the list
  478. * the client is going to DIE
  479. * Arguments:
  480. * pCI - client context
  481. * Called by:
  482. * _CloseConnectInfo
  483. --*/
  484. VOID _FlushFromWaitQ(PCONNECTINFO pCI)
  485. {
  486. PWAIT4STRING pIter, pPrev, pNext;
  487. ASSERT(pCI);
  488. pPrev = NULL;
  489. EnterCriticalSection(g_lpcsGuardWaitQueue);
  490. pIter = g_pWaitQHead;
  491. do {
  492. while (pIter && pIter->pOwner != pCI) {
  493. pPrev = pIter;
  494. pIter = pIter->pNext;
  495. }
  496. if (pIter) {
  497. if (!pPrev) g_pWaitQHead = pIter->pNext;
  498. else pPrev->pNext = pIter->pNext;
  499. pNext = pIter->pNext;
  500. pIter->pNext = NULL;
  501. // Important stuff
  502. if (pIter->evWait)
  503. {
  504. CloseHandle(pIter->evWait);
  505. pIter->evWait = NULL;
  506. }
  507. free(pIter);
  508. pIter = pNext;
  509. }
  510. } while (pIter);
  511. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  512. }
  513. /*++
  514. * Function:
  515. * _CheckForWaitingWorker
  516. * Description:
  517. * Check the received string against the waited events
  518. * Arguments:
  519. * wszFeed - the received string
  520. * dwProcessId - Id of the sender
  521. * Return value:
  522. * TRUE if an event is found and signaled
  523. * Called by:
  524. * _TextOutReceived, _GlyphReceived
  525. --*/
  526. BOOL _CheckForWaitingWorker(LPCWSTR wszFeed, LONG_PTR lProcessId)
  527. {
  528. PWAIT4STRING pIter;
  529. BOOL bRun;
  530. CHAR szBuff[ MAX_STRING_LENGTH ];
  531. CHAR *szPBuff;
  532. DWORD dwBuffLen;
  533. LPCWSTR wszPFeed;
  534. //
  535. // Apply translation if specified
  536. //
  537. if ( g_bTranslateStrings )
  538. {
  539. UINT i;
  540. UINT j;
  541. UINT_PTR len;
  542. LPWSTR szStr2;
  543. len = wcslen( wszFeed );
  544. __try {
  545. szStr2 = (LPWSTR) _alloca( (len+1)*sizeof( *szStr2 ) );
  546. }
  547. __except ((GetExceptionCode() == STATUS_STACK_OVERFLOW)?
  548. EXCEPTION_EXECUTE_HANDLER:
  549. EXCEPTION_CONTINUE_SEARCH)
  550. {
  551. _resetstkoflw();
  552. szStr2 = NULL;
  553. }
  554. if ( NULL == szStr2 )
  555. return FALSE;
  556. for ( i = 0, j = 0; i < len + 1; j += (szStr2[j] != L' ')?1:0, i++ )
  557. {
  558. if ( wszFeed[i] >= 3 && wszFeed[i] < 0x63 )
  559. {
  560. szStr2[j] = wszFeed[i] + L' ' - 3;
  561. } else {
  562. szStr2[j] = wszFeed[i];
  563. }
  564. }
  565. wszFeed = szStr2;
  566. }
  567. if ( NULL != g_pfnPrintMessage )
  568. {
  569. wszPFeed = wszFeed;
  570. while ( *wszPFeed )
  571. {
  572. if ( (unsigned short)(*wszPFeed) > 0xff )
  573. break;
  574. wszPFeed ++;
  575. }
  576. if ( *wszPFeed )
  577. {
  578. szBuff[0] = '\\';
  579. szBuff[1] = 'u';
  580. szPBuff = szBuff + 2;
  581. wszPFeed = wszFeed;
  582. dwBuffLen = MAX_STRING_LENGTH - 3;
  583. while ( 4 <= dwBuffLen &&
  584. 0 != *wszPFeed)
  585. {
  586. DWORD dwLen;
  587. if ( dwBuffLen < 4 )
  588. break;
  589. dwLen = _snprintf( szPBuff, dwBuffLen + 1, "%02x",
  590. (BYTE)((*wszPFeed) & 0xff ));
  591. szPBuff += dwLen;
  592. dwBuffLen -= dwLen;
  593. dwLen = _snprintf( szPBuff, dwBuffLen + 1, "%02x",
  594. (BYTE)(((*wszPFeed) >> 8) & 0xff ));
  595. szPBuff += dwLen;
  596. dwBuffLen -= dwLen;
  597. wszPFeed ++;
  598. dwBuffLen--;
  599. }
  600. *szPBuff = 0;
  601. TRACE((ALIVE_MESSAGE, "Received: %s\n", szBuff));
  602. } else {
  603. TRACE((ALIVE_MESSAGE, "Received: %S\n", wszFeed));
  604. }
  605. }
  606. _AddStrToClientBuffer(wszFeed, lProcessId);
  607. EnterCriticalSection(g_lpcsGuardWaitQueue);
  608. pIter = g_pWaitQHead;
  609. bRun = TRUE;
  610. while(pIter && bRun)
  611. {
  612. if (pIter->lProcessId == lProcessId)
  613. {
  614. // Check for expected string (one)
  615. if (pIter->WaitType == WAIT_STRING &&
  616. wcsstr(wszFeed, pIter->waitstr))
  617. bRun = FALSE;
  618. else
  619. // Check for expected strings (many)
  620. if (pIter->WaitType == WAIT_MSTRINGS)
  621. {
  622. WCHAR *wszComp = pIter->waitstr;
  623. WCHAR *wszLast = pIter->waitstr + pIter->strsize;
  624. int idx = 0;
  625. while (wszComp < wszLast && *wszComp && bRun)
  626. {
  627. if (wcsstr(wszFeed, wszComp))
  628. {
  629. int i;
  630. PCONNECTINFO pOwner = pIter->pOwner;
  631. // Save the string
  632. for(i = 0; wszComp[i]; i++)
  633. pOwner->szWait4MultipleStrResult[i] = (char)wszComp[i];
  634. pOwner->szWait4MultipleStrResult[i] = 0;
  635. pOwner->nWait4MultipleStrResult = idx;
  636. bRun = FALSE;
  637. }
  638. else
  639. {
  640. // Advance to next string
  641. wszComp += wcslen(wszComp) + 1;
  642. idx ++;
  643. }
  644. }
  645. }
  646. }
  647. // Advance to the next pointer
  648. if (bRun)
  649. pIter = pIter->pNext;
  650. }
  651. if (pIter)
  652. {
  653. SetEvent(pIter->evWait);
  654. }
  655. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  656. return (pIter != NULL);
  657. }
  658. /*++
  659. * Function:
  660. * _TextOutReceived
  661. * Description:
  662. * TextOut order is received from the client, the string is
  663. * in shared memory. Unmaps the memory and checks if the
  664. * strings is waited by anybody. Also adds the string
  665. * to the client history buffer
  666. * Arguments:
  667. * dwProcessId - senders Id
  668. * hMapF - handle to shared memory, which contains the string
  669. * Return value:
  670. * TRUE if a client is found and signaled
  671. * Called by:
  672. * _FeedbackWndProc within feedback thread
  673. --*/
  674. BOOL _TextOutReceived(LONG_PTR lProcessId, HANDLE hMapF)
  675. {
  676. PFEEDBACKINFO pView = NULL;
  677. PCONNECTINFO pIterCl;
  678. HANDLE hDupMapF = NULL;
  679. BOOL rv = FALSE;
  680. EnterCriticalSection(g_lpcsGuardWaitQueue);
  681. pIterCl = g_pClientQHead;
  682. while(pIterCl && pIterCl->lProcessId != lProcessId)
  683. pIterCl = pIterCl->pNext;
  684. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  685. if (!pIterCl)
  686. goto exitpt;
  687. if ( NULL == pIterCl->hProcess ||
  688. !DuplicateHandle(pIterCl->hProcess,
  689. hMapF,
  690. GetCurrentProcess(),
  691. &hDupMapF,
  692. FILE_MAP_READ,
  693. FALSE,
  694. 0))
  695. {
  696. pView = (PFEEDBACKINFO) MapViewOfFile( hMapF,
  697. FILE_MAP_READ,
  698. 0,
  699. 0,
  700. sizeof(*pView));
  701. } else
  702. pView = (PFEEDBACKINFO) MapViewOfFile(hDupMapF,
  703. FILE_MAP_READ,
  704. 0,
  705. 0,
  706. sizeof(*pView));
  707. if (!pView)
  708. {
  709. TRACE((ALIVE_MESSAGE,
  710. "TEXTOUT:Can't map a view, GetLastError = %d\n",
  711. GetLastError()));
  712. goto exitpt1;
  713. }
  714. rv = _CheckForWaitingWorker(pView->string, lProcessId);
  715. exitpt1:
  716. if ( NULL != pView )
  717. UnmapViewOfFile(pView);
  718. if ( NULL != hDupMapF )
  719. CloseHandle(hDupMapF);
  720. exitpt:
  721. return rv;
  722. }
  723. /*++
  724. * Function:
  725. * _GlyphReceived
  726. * Description:
  727. * Same as _TextOutReceived but for GlyphOut order
  728. * the glyph is in shared memory. It is converted to
  729. * string by calling Glyph2String!bmpcache.c
  730. * Arguments:
  731. * dwProcessId - senders Id
  732. * hMapF - handle to shared memory
  733. * Return value:
  734. * TRUE if a client is found and signaled
  735. * Called by:
  736. * _FeedbackWndProc within feedback thread
  737. --*/
  738. BOOL _GlyphReceived(LONG_PTR lProcessId, HANDLE hMapF)
  739. {
  740. WCHAR wszFeed[MAX_STRING_LENGTH];
  741. BOOL rv = FALSE;
  742. PBMPFEEDBACK pView;
  743. PCONNECTINFO pIterCl;
  744. HANDLE hDupMapF;
  745. UINT nSize;
  746. EnterCriticalSection(g_lpcsGuardWaitQueue);
  747. pIterCl = g_pClientQHead;
  748. while(pIterCl && pIterCl->lProcessId != lProcessId)
  749. pIterCl = pIterCl->pNext;
  750. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  751. if (!pIterCl)
  752. goto exitpt;
  753. if ( NULL == pIterCl->hProcess ||
  754. !DuplicateHandle( pIterCl->hProcess,
  755. hMapF,
  756. GetCurrentProcess(),
  757. &hDupMapF,
  758. FILE_MAP_READ,
  759. FALSE,
  760. 0))
  761. {
  762. TRACE((ERROR_MESSAGE,
  763. "GLYPH:Can't dup file handle, GetLastError = %d\n",
  764. GetLastError()));
  765. goto exitpt;
  766. }
  767. pView = (PBMPFEEDBACK) MapViewOfFile(hDupMapF,
  768. FILE_MAP_READ,
  769. 0,
  770. 0,
  771. sizeof(*pView));
  772. if (!pView)
  773. {
  774. TRACE((ERROR_MESSAGE,
  775. "GLYPH:Can't map a view, GetLastError = %d\n",
  776. GetLastError()));
  777. goto exitpt1;
  778. }
  779. // Get bitmap size
  780. nSize = pView->bmpsize;
  781. if (!nSize)
  782. goto exitpt1;
  783. // unmap
  784. UnmapViewOfFile(pView);
  785. // remap the whole structure
  786. pView = (PBMPFEEDBACK) MapViewOfFile(hDupMapF,
  787. FILE_MAP_READ,
  788. 0,
  789. 0,
  790. sizeof(*pView) + nSize);
  791. if (!pView)
  792. {
  793. TRACE((ERROR_MESSAGE,
  794. "GLYPH:Can't map a view, GetLastError = %d\n",
  795. GetLastError()));
  796. goto exitpt1;
  797. }
  798. if (!Glyph2String(pView, wszFeed, sizeof(wszFeed)/sizeof(WCHAR)))
  799. {
  800. goto exitpt1;
  801. }
  802. rv = _CheckForWaitingWorker(wszFeed, lProcessId);
  803. exitpt1:
  804. if ( NULL != pView )
  805. {
  806. UnmapViewOfFile(pView);
  807. }
  808. CloseHandle(hDupMapF);
  809. exitpt:
  810. return rv;
  811. }
  812. /*++
  813. * Function:
  814. * _CheckForWorkerWaitingDisconnect
  815. * Description:
  816. * Signals a worker (client thread) wich waits for a disconnect event
  817. * Arguments:
  818. * dwProcessId - clients Id
  819. * Return value:
  820. * TRUE if a client is found and signaled
  821. * Called by:
  822. * _FeedbackWndProc within feedback thread
  823. --*/
  824. BOOL _CheckForWorkerWaitingDisconnect(LONG_PTR lProcessId)
  825. {
  826. PWAIT4STRING pIter;
  827. EnterCriticalSection(g_lpcsGuardWaitQueue);
  828. pIter = g_pWaitQHead;
  829. while(pIter &&
  830. (pIter->WaitType != WAIT_DISC ||
  831. pIter->lProcessId != lProcessId))
  832. {
  833. pIter = pIter->pNext;
  834. }
  835. if (pIter)
  836. {
  837. SetEvent(pIter->evWait);
  838. }
  839. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  840. return (pIter != NULL);
  841. }
  842. /*++
  843. * Function:
  844. * _CheckForWorkerWaitingConnect
  845. * Description:
  846. * Signals a worker waiting for a connection
  847. * Arguments:
  848. * hwndClient - clients window handle, this is needed for
  849. * sending messages to the client
  850. * dwProcessId - client Id
  851. * Return value:
  852. * TRUE if a client is found and signaled
  853. * Called by:
  854. * _FeedbackWndProc within feedback thread
  855. --*/
  856. BOOL _CheckForWorkerWaitingConnect(HWND hwndClient, LONG_PTR lProcessId)
  857. {
  858. PWAIT4STRING pIter;
  859. EnterCriticalSection(g_lpcsGuardWaitQueue);
  860. pIter = g_pWaitQHead;
  861. while(pIter &&
  862. (pIter->WaitType != WAIT_CONN ||
  863. pIter->lProcessId != lProcessId))
  864. {
  865. pIter = pIter->pNext;
  866. }
  867. if (pIter)
  868. {
  869. PCONNECTINFO pOwner = pIter->pOwner;
  870. if (pOwner)
  871. {
  872. pOwner->hClient = hwndClient;
  873. pOwner->dead = FALSE;
  874. } else
  875. TRACE((WARNING_MESSAGE, "FEED: WAIT4 w/o owner structure"));
  876. SetEvent(pIter->evWait);
  877. }
  878. if ( NULL == pIter )
  879. {
  880. PCONNECTINFO pCon;
  881. //
  882. // in autoreconnect the dead field might be TRUE
  883. //
  884. pCon = g_pClientQHead;
  885. while ( NULL != pCon && pCon->lProcessId != lProcessId)
  886. {
  887. pCon = pCon->pNext;
  888. }
  889. if ( NULL != pCon)
  890. {
  891. pCon->dead = FALSE;
  892. }
  893. }
  894. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  895. return (pIter != NULL);
  896. }
  897. #ifdef _RCLX
  898. /*++
  899. * Function:
  900. * _CheckForWorkerWaitingConnectAndSetId
  901. * Description:
  902. * This is intended for RCLX mode. dwProcessId is zero
  903. * so this function look for such a client and sets its dwProcessId
  904. * Signals a worker waiting for a connection
  905. * Arguments:
  906. * hwndClient - clients window handle, this is needed for
  907. * sending messages to the client
  908. * dwProcessId - client Id
  909. * Return value:
  910. * connection context, NULL if not found
  911. * Called by:
  912. * _FeedbackWndProc within feedback thread
  913. --*/
  914. PCONNECTINFO
  915. _CheckForWorkerWaitingConnectAndSetId(HWND hwndClient, LONG_PTR lProcessId)
  916. {
  917. PWAIT4STRING pIter;
  918. PCONNECTINFO pOwner = NULL;
  919. EnterCriticalSection(g_lpcsGuardWaitQueue);
  920. pIter = g_pWaitQHead;
  921. while(pIter &&
  922. (pIter->WaitType != WAIT_CONN ||
  923. pIter->lProcessId))
  924. {
  925. pIter = pIter->pNext;
  926. }
  927. if (pIter)
  928. {
  929. pOwner = pIter->pOwner;
  930. if (pOwner)
  931. {
  932. ASSERT(pOwner->RClxMode);
  933. pOwner->hClient = hwndClient;
  934. pOwner->lProcessId = lProcessId;
  935. pIter->lProcessId = lProcessId; // Disable next lookup in
  936. // the same entry
  937. }
  938. else
  939. TRACE((WARNING_MESSAGE, "FEED: WAIT4 w/o owner structure"));
  940. SetEvent(pIter->evWait);
  941. }
  942. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  943. return (pOwner);
  944. }
  945. /*++
  946. * Function:
  947. * _CheckForWorkerWaitingReconnectAndSetNewId
  948. * Description:
  949. * This is intended for RCLX mode. When mstsc wants to reconnect
  950. * looks for dwLookupId as an ID to reconnect
  951. * then sets the new ID
  952. * then gets
  953. * Arguments:
  954. * hwndClient - clients window handle, this is needed for
  955. * sending messages to the client
  956. * dwLookupId, dwNewId
  957. * Return value:
  958. * connection context, NULL if not found
  959. * Called by:
  960. * _FeedbackWndProc within feedback thread
  961. --*/
  962. PCONNECTINFO
  963. _CheckForWorkerWaitingReconnectAndSetNewId(
  964. HWND hwndClient,
  965. DWORD dwLookupId,
  966. LONG_PTR lNewId)
  967. {
  968. PWAIT4STRING pIter;
  969. PCONNECTINFO pOwner = NULL;
  970. EnterCriticalSection(g_lpcsGuardWaitQueue);
  971. pIter = g_pWaitQHead;
  972. while(pIter &&
  973. (pIter->WaitType != WAIT_CONN ||
  974. !pIter->pOwner ||
  975. pIter->pOwner->dwThreadId != dwLookupId ||
  976. !(pIter->pOwner->bWillCallAgain)))
  977. {
  978. pIter = pIter->pNext;
  979. }
  980. if (pIter)
  981. {
  982. pOwner = pIter->pOwner;
  983. if (pOwner)
  984. {
  985. ASSERT(pOwner->RClxMode);
  986. pOwner->hClient = hwndClient;
  987. pOwner->lProcessId = lNewId;
  988. pIter->lProcessId = lNewId; // Disable next lookup in
  989. // the same entry
  990. pOwner->bWillCallAgain = FALSE;
  991. }
  992. else
  993. TRACE((WARNING_MESSAGE, "FEED: WAIT4 w/o owner structure"));
  994. SetEvent(pIter->evWait);
  995. }
  996. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  997. return (pOwner);
  998. }
  999. #endif // _RCLX
  1000. /*++
  1001. * Function:
  1002. * _CancelWaitingWorker
  1003. * Description:
  1004. * Releases a worker waiting for any event.
  1005. * Eventualy the client is disconnected
  1006. * Arguments:
  1007. * dwProcessId - client Id
  1008. * Return value:
  1009. * TRUE if a client is found and signaled
  1010. * Called by:
  1011. * _FeedbackWndProc within feedback thread
  1012. --*/
  1013. BOOL _CancelWaitingWorker(LONG_PTR lProcessId)
  1014. {
  1015. PWAIT4STRING pIter;
  1016. EnterCriticalSection(g_lpcsGuardWaitQueue);
  1017. pIter = g_pWaitQHead;
  1018. while(pIter &&
  1019. pIter->lProcessId != lProcessId)
  1020. {
  1021. pIter = pIter->pNext;
  1022. }
  1023. if (pIter)
  1024. {
  1025. SetEvent(pIter->evWait);
  1026. }
  1027. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  1028. return (pIter != NULL);
  1029. }
  1030. #ifdef _RCLX
  1031. /*++
  1032. * Function:
  1033. * _CheckForWorkerWaitingClipboard
  1034. * Description:
  1035. * Releases a worker waiting for client's clipboard content.
  1036. * Arguments:
  1037. * dwProcessId - client Id
  1038. * Return value:
  1039. * TRUE if a client is found and signaled
  1040. * Called by:
  1041. * _FeedbackWndProc within feedback thread
  1042. --*/
  1043. BOOL _CheckForWorkerWaitingClipboard(
  1044. PCONNECTINFO pRClxOwner,
  1045. UINT uiFormat,
  1046. UINT nSize,
  1047. PVOID pClipboard,
  1048. LONG_PTR lProcessId)
  1049. {
  1050. PWAIT4STRING pIter = NULL;
  1051. HGLOBAL ghNewClipboard = NULL;
  1052. LPVOID pNewClipboard = NULL;
  1053. ASSERT(pRClxOwner);
  1054. TRACE((ALIVE_MESSAGE, "Clipboard received, FormatID=%d, Size=%d\n",
  1055. uiFormat, nSize));
  1056. if (nSize)
  1057. {
  1058. // Copy the clipboard content to new buffer
  1059. ghNewClipboard = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, nSize);
  1060. if (!ghNewClipboard)
  1061. {
  1062. TRACE((ERROR_MESSAGE, "_CheckForWorkerWaitingClipboard: can't allocate %d bytes\n", nSize));
  1063. goto exitpt;
  1064. }
  1065. pNewClipboard = GlobalLock(ghNewClipboard);
  1066. if (!pNewClipboard)
  1067. {
  1068. TRACE((ERROR_MESSAGE, "_CheckForWorkerWaitingClipboard: can't lock global memory\n"));
  1069. goto exitpt;
  1070. }
  1071. memcpy(pNewClipboard, pClipboard, nSize);
  1072. // Unlock the clipboard buffer
  1073. GlobalUnlock(ghNewClipboard);
  1074. pNewClipboard = NULL;
  1075. } else {
  1076. pClipboard = NULL;
  1077. }
  1078. EnterCriticalSection(g_lpcsGuardWaitQueue);
  1079. pIter = g_pWaitQHead;
  1080. while(pIter &&
  1081. (pIter->lProcessId != lProcessId ||
  1082. pIter->WaitType != WAIT_CLIPBOARD))
  1083. {
  1084. pIter = pIter->pNext;
  1085. }
  1086. if (pIter)
  1087. {
  1088. PCONNECTINFO pOwner = pIter->pOwner;
  1089. // Put the buffer in the worker's context
  1090. if (pOwner)
  1091. {
  1092. ASSERT(pOwner->RClxMode);
  1093. ASSERT(pOwner == pRClxOwner);
  1094. // pOwner->ghClipboard should be NULL
  1095. ASSERT(pOwner->ghClipboard == NULL);
  1096. pOwner->ghClipboard = ghNewClipboard;
  1097. pOwner->uiClipboardFormat = uiFormat;
  1098. pOwner->nClipboardSize = nSize;
  1099. }
  1100. else
  1101. TRACE((WARNING_MESSAGE, "FEED: WAIT4 w/o owner structure"));
  1102. SetEvent(pIter->evWait);
  1103. } else {
  1104. // Can't find anybody waiting, add it to the context owner
  1105. pRClxOwner->ghClipboard = ghNewClipboard;
  1106. pRClxOwner->uiClipboardFormat = uiFormat;
  1107. pRClxOwner->nClipboardSize = nSize;
  1108. }
  1109. pRClxOwner->bRClxClipboardReceived = TRUE;
  1110. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  1111. exitpt:
  1112. if (!pIter)
  1113. // worker not found, clear the allocated buffer
  1114. {
  1115. if (ghNewClipboard)
  1116. GlobalFree(ghNewClipboard);
  1117. }
  1118. return (pIter != NULL);
  1119. }
  1120. #endif // _RCLX
  1121. BOOL
  1122. _SetSessionID(LONG_PTR lProcessId, UINT uSessionId)
  1123. {
  1124. PCONNECTINFO pIter;
  1125. // PCONNECTINFO pPrev = NULL;
  1126. EnterCriticalSection(g_lpcsGuardWaitQueue);
  1127. pIter = g_pClientQHead;
  1128. while (pIter &&
  1129. pIter->lProcessId != lProcessId)
  1130. pIter = pIter->pNext;
  1131. if (pIter)
  1132. pIter->uiSessionId = (uSessionId)?uSessionId:-1;
  1133. LeaveCriticalSection(g_lpcsGuardWaitQueue);
  1134. return (pIter != NULL);
  1135. }