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.

2645 lines
99 KiB

  1. /****************************************************************************/
  2. /* uhapi.cpp */
  3. /* */
  4. /* Update Handler API */
  5. /* */
  6. /* Copyright(C) Microsoft Corporation 1997-1999 */
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_GROUP TRC_GROUP_CORE
  11. #define TRC_FILE "uhapi"
  12. #include <atrcapi.h>
  13. }
  14. #include "autil.h"
  15. #include "uh.h"
  16. #include "op.h"
  17. #include "od.h"
  18. #include "aco.h"
  19. #include "cd.h"
  20. #include "or.h"
  21. #include "cc.h"
  22. #include "wui.h"
  23. #include "sl.h"
  24. extern "C" {
  25. #include <stdio.h>
  26. #ifdef OS_WINNT
  27. #include <shlobj.h>
  28. #endif
  29. }
  30. #ifdef OS_WINCE
  31. #ifdef DC_DEBUG
  32. #include <eosint.h>
  33. #endif
  34. #endif
  35. CUH::CUH(CObjs* objs)
  36. {
  37. _pClientObjects = objs;
  38. }
  39. CUH::~CUH()
  40. {
  41. }
  42. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  43. /****************************************************************************/
  44. // UHGrabPersistentCacheLock
  45. //
  46. // Takes out a lock on the persistent cache directory to make sure no other
  47. // instances of MSTSC on the system can use the cache directory.
  48. // Returns FALSE if the lock could not be grabbed, nonzero if it was grabbed.
  49. /****************************************************************************/
  50. inline BOOL CUH::UHGrabPersistentCacheLock(VOID)
  51. {
  52. BOOL rc = TRUE;
  53. DC_BEGIN_FN("UHGrabPersistentCacheLock");
  54. _UH.hPersistentCacheLock = CreateMutex(NULL, TRUE, _UH.PersistentLockName);
  55. if (_UH.hPersistentCacheLock == NULL ||
  56. GetLastError() == ERROR_ALREADY_EXISTS) {
  57. if (_UH.hPersistentCacheLock != NULL) {
  58. CloseHandle(_UH.hPersistentCacheLock);
  59. _UH.hPersistentCacheLock = NULL;
  60. }
  61. rc = FALSE;
  62. }
  63. DC_END_FN();
  64. return rc;
  65. }
  66. /****************************************************************************/
  67. // UHReleasePersistentCacheLock
  68. //
  69. // Releases the lock taken out with UHGrabPersistentCacheLock().
  70. /****************************************************************************/
  71. inline VOID CUH::UHReleasePersistentCacheLock(VOID)
  72. {
  73. DC_BEGIN_FN("UHReleasePersistentCacheLock");
  74. if (_UH.hPersistentCacheLock != NULL) {
  75. CloseHandle(_UH.hPersistentCacheLock);
  76. _UH.hPersistentCacheLock = NULL;
  77. }
  78. DC_END_FN();
  79. }
  80. /****************************************************************************/
  81. // Wrappers for directory enumeration functions - to translate into Win32
  82. // (non-WinCE) and Win16 enumeration methods.
  83. //
  84. // UHFindFirstFile returns INVALID_FILE_HANDLE on enumeration start failure.
  85. // UHFindNextFile returns TRUE if there are more files to enumerate.
  86. /****************************************************************************/
  87. #if (defined(OS_WINNT) || (defined(OS_WINCE) && defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  88. inline HANDLE CUH::UHFindFirstFile(
  89. const TCHAR *Path,
  90. TCHAR *Filename,
  91. long *pFileSize)
  92. {
  93. HANDLE hSearch;
  94. WIN32_FIND_DATA FindData;
  95. hSearch = FindFirstFile(Path, &FindData);
  96. if (hSearch != INVALID_HANDLE_VALUE) {
  97. Filename[12] = _T('\0');
  98. _tcsncpy(Filename, FindData.cFileName, 12);
  99. *pFileSize = FindData.nFileSizeLow;
  100. }
  101. return hSearch;
  102. }
  103. inline BOOL CUH::UHFindNextFile(
  104. HANDLE hSearch,
  105. TCHAR *Filename,
  106. long *pFileSize)
  107. {
  108. WIN32_FIND_DATA FindData;
  109. if (FindNextFile(hSearch, &FindData)) {
  110. Filename[12] = _T('\0');
  111. _tcsncpy(Filename, FindData.cFileName, 12);
  112. *pFileSize = FindData.nFileSizeLow;
  113. return TRUE;
  114. }
  115. return FALSE;
  116. }
  117. inline void CUH::UHFindClose(HANDLE hSearch)
  118. {
  119. FindClose(hSearch);
  120. }
  121. #endif // OS_WINNT and OS_WINCE
  122. #ifdef OS_WINNT
  123. inline BOOL CUH::UHGetDiskFreeSpace(
  124. TCHAR *pPathName,
  125. ULONG *pSectorsPerCluster,
  126. ULONG *pBytesPerSector,
  127. ULONG *pNumberOfFreeClusters,
  128. ULONG *pTotalNumberOfClusters)
  129. {
  130. return GetDiskFreeSpace(pPathName, pSectorsPerCluster,
  131. pBytesPerSector, pNumberOfFreeClusters,
  132. pTotalNumberOfClusters);
  133. }
  134. #elif defined(OS_WINCE)
  135. #ifdef ENABLE_BMP_CACHING_FOR_WINCE
  136. inline BOOL CUH::UHGetDiskFreeSpace(
  137. TCHAR *pPathName,
  138. ULONG *pSectorsPerCluster,
  139. ULONG *pBytesPerSector,
  140. ULONG *pNumberOfFreeClusters,
  141. ULONG *pTotalNumberOfClusters)
  142. {
  143. ULARGE_INTEGER FreeBytesAvailableToCaller; // receives the number of bytes on
  144. // disk available to the caller
  145. ULARGE_INTEGER TotalNumberOfBytes; // receives the number of bytes on disk
  146. ULARGE_INTEGER TotalNumberOfFreeBytes; // receives the free bytes on disk
  147. BOOL bRet = GetDiskFreeSpaceEx(
  148. pPathName,
  149. &FreeBytesAvailableToCaller,
  150. &TotalNumberOfBytes,
  151. &TotalNumberOfFreeBytes
  152. );
  153. if (bRet) {
  154. // For calculation of free space, we assume that each cluster contains
  155. // one sector, and each sector contains one byte.
  156. *pSectorsPerCluster = 1;
  157. *pBytesPerSector = 1;
  158. *pNumberOfFreeClusters = TotalNumberOfFreeBytes.LowPart;
  159. *pTotalNumberOfClusters = TotalNumberOfBytes.LowPart;
  160. }
  161. return bRet;
  162. }
  163. #endif // ENABLE_BMP_CACHING_FOR_WINCE
  164. #endif // OS_WINNT and OS_WINCE
  165. /***************************************************************************/
  166. // UHSendPersistentBitmapKeyList
  167. //
  168. // Attempts to send a persistent bitmap key PDU
  169. /***************************************************************************/
  170. #define UH_BM_PERSISTENT_LIST_SENDBUFSIZE 1400
  171. VOID DCINTERNAL CUH::UHSendPersistentBitmapKeyList(ULONG_PTR unusedParm)
  172. {
  173. UINT i;
  174. ULONG curEntry;
  175. SL_BUFHND hBuf;
  176. PTS_BITMAPCACHE_PERSISTENT_LIST pList;
  177. // Max entries we can fill into the max PDU size we will be using.
  178. const unsigned MaxPDUEntries = ((UH_BM_PERSISTENT_LIST_SENDBUFSIZE -
  179. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST)) /
  180. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY)) + 1;
  181. DC_BEGIN_FN("UHSendPersistentBitmapKeyList");
  182. DC_IGNORE_PARAMETER(unusedParm);
  183. TRC_ASSERT((_UH.bEnabled), (TB, _T("UH not enabled")));
  184. TRC_ASSERT((_UH.bBitmapKeyEnumComplete), (TB, _T("Enumeration is not complete")));
  185. TRC_NRM((TB, _T("Send Persistent Bitmap Key PDU")));
  186. if (_UH.totalNumKeyEntries == 0) {
  187. for (i = 0; i < _UH.NumBitmapCaches; i++) {
  188. _UH.numKeyEntries[i] = min(_UH.numKeyEntries[i],
  189. _UH.bitmapCache[i].BCInfo.NumVirtualEntries);
  190. _UH.totalNumKeyEntries += _UH.numKeyEntries[i];
  191. }
  192. }
  193. if (_pSl->SL_GetBuffer(UH_BM_PERSISTENT_LIST_SENDBUFSIZE,
  194. (PPDCUINT8)&pList, &hBuf)) {
  195. // Fill in the header information - zero first then set nonzero
  196. // fields.
  197. memset(pList, 0, sizeof(TS_BITMAPCACHE_PERSISTENT_LIST));
  198. pList->shareDataHeader.shareControlHeader.pduType =
  199. TS_PDUTYPE_DATAPDU | TS_PROTOCOL_VERSION;
  200. pList->shareDataHeader.shareControlHeader.pduSource =
  201. _pUi->UI_GetClientMCSID();
  202. pList->shareDataHeader.shareID = _pUi->UI_GetShareID();
  203. pList->shareDataHeader.streamID = TS_STREAM_LOW;
  204. pList->shareDataHeader.pduType2 =
  205. TS_PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST;
  206. // set the first PDU flag
  207. if (_UH.sendNumBitmapKeys == 0)
  208. pList->bFirstPDU = TRUE;
  209. // set the last PDU flag
  210. if (_UH.totalNumKeyEntries - _UH.sendNumBitmapKeys <=
  211. MaxPDUEntries)
  212. pList->bLastPDU = TRUE;
  213. // Copy the total entries.
  214. for (i = 0; i < _UH.NumBitmapCaches; i++)
  215. pList->TotalEntries[i] = (DCUINT16) _UH.numKeyEntries[i];
  216. // Continue the entry enumeration from where we left off.
  217. curEntry = 0;
  218. while (curEntry < MaxPDUEntries &&
  219. _UH.sendBitmapCacheId < _UH.NumBitmapCaches) {
  220. if (_UH.sendBitmapCacheIndex < _UH.numKeyEntries[_UH.sendBitmapCacheId]) {
  221. // set up the Bitmap Page Table
  222. _UH.bitmapCache[_UH.sendBitmapCacheId].PageTable.PageEntries
  223. [_UH.sendBitmapCacheIndex].bmpInfo = _UH.pBitmapKeyDB
  224. [_UH.sendBitmapCacheId][_UH.sendBitmapCacheIndex];
  225. #ifdef DC_DEBUG
  226. UHCacheEntryKeyLoadOnSessionStart(_UH.sendBitmapCacheId,
  227. _UH.sendBitmapCacheIndex);
  228. #endif
  229. // fill the bitmap keys into PDU
  230. pList->Entries[curEntry].Key1 = _UH.bitmapCache
  231. [_UH.sendBitmapCacheId].PageTable.PageEntries
  232. [_UH.sendBitmapCacheIndex].bmpInfo.Key1;
  233. pList->Entries[curEntry].Key2 = _UH.bitmapCache
  234. [_UH.sendBitmapCacheId].PageTable.PageEntries
  235. [_UH.sendBitmapCacheIndex].bmpInfo.Key2;
  236. TRC_NRM((TB,_T("Idx: %d K1: 0x%x K2: 0x%x"),
  237. _UH.sendBitmapCacheIndex,
  238. pList->Entries[curEntry].Key1,
  239. pList->Entries[curEntry].Key2 ));
  240. pList->NumEntries[_UH.sendBitmapCacheId]++;
  241. // move on to the next key
  242. _UH.sendBitmapCacheIndex++;
  243. curEntry++;
  244. }
  245. else {
  246. // move on to next cache
  247. _UH.sendBitmapCacheId++;
  248. _UH.sendBitmapCacheIndex = 0;
  249. }
  250. }
  251. // Send the PDU.
  252. pList->shareDataHeader.shareControlHeader.totalLength =
  253. (TSUINT16)(sizeof(TS_BITMAPCACHE_PERSISTENT_LIST) -
  254. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY) +
  255. (curEntry * sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY)));
  256. _pSl->SL_SendPacket((PDCUINT8)pList,
  257. pList->shareDataHeader.shareControlHeader.totalLength, RNS_SEC_ENCRYPT,
  258. hBuf, _pUi->UI_GetClientMCSID(), _pUi->UI_GetChannelID(), TS_MEDPRIORITY);
  259. TRC_NRM((TB,_T("Sent persistent bitmap key PDU, #keys=%u"),curEntry));
  260. _UH.sendNumBitmapKeys += curEntry;
  261. if (_UH.sendNumBitmapKeys >= _UH.totalNumKeyEntries) {
  262. _UH.bPersistentBitmapKeysSent = TRUE;
  263. //
  264. // now we need to send
  265. // a zero font list PDU
  266. //
  267. _pFs->FS_SendZeroFontList(0);
  268. }
  269. else {
  270. // more key PDU to send
  271. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  272. this, CD_NOTIFICATION_FUNC(CUH,UHSendPersistentBitmapKeyList), 0);
  273. }
  274. }
  275. else {
  276. // On buffer allocation failure, UHSendPersistentBitmapKeyList will
  277. // be retried from UH_BufferAvailable.
  278. TRC_ALT((TB, _T("Unable to allocate buffer to send Bitmap Key PDU")));
  279. }
  280. DC_EXIT_POINT:
  281. DC_END_FN();
  282. } // UHSendPersistentBitmapKeyList
  283. /****************************************************************************/
  284. // UHReadFromCacheFileForEnum
  285. //
  286. // Read a bitmap entry from the cache file for the purpose of
  287. // enumerating keys.
  288. /****************************************************************************/
  289. _inline BOOL DCINTERNAL CUH::UHReadFromCacheFileForEnum(VOID)
  290. {
  291. BOOL rc = FALSE;
  292. BOOL bApiRet = FALSE;
  293. LONG filelen = 0;
  294. DC_BEGIN_FN("UHReadFromCacheFile");
  295. TRC_ASSERT(_UH.bBitmapKeyEnumerating,
  296. (TB,_T("UHReadFromCacheFile should only be called for enum")));
  297. TRC_ASSERT(_UH.currentCopyMultiplier,
  298. (TB,_T("currentCopyMultiplier not set")));
  299. // read the bitmap entry to the bitmap key database
  300. DWORD cbRead;
  301. bApiRet = ReadFile( _UH.currentFileHandle,
  302. &_UH.pBitmapKeyDB[_UH.currentBitmapCacheId]
  303. [_UH.numKeyEntries[_UH.currentBitmapCacheId]],
  304. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY),
  305. &cbRead,
  306. NULL );
  307. if(bApiRet && sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY) == cbRead)
  308. {
  309. if (_UH.pBitmapKeyDB[_UH.currentBitmapCacheId][_UH.numKeyEntries
  310. [_UH.currentBitmapCacheId]].Key1 != 0 &&
  311. _UH.pBitmapKeyDB[_UH.currentBitmapCacheId][_UH.numKeyEntries
  312. [_UH.currentBitmapCacheId]].Key2 != 0) {
  313. // we read a valid entry
  314. _UH.numKeyEntries[_UH.currentBitmapCacheId]++;
  315. rc = TRUE;
  316. // Move onto the next entry in the cache file
  317. if((SetFilePointer(_UH.currentFileHandle,
  318. _UH.numKeyEntries[_UH.currentBitmapCacheId] *
  319. (UH_CellSizeFromCacheIDAndMult(
  320. _UH.currentBitmapCacheId,
  321. _UH.currentCopyMultiplier) +
  322. sizeof(UHBITMAPFILEHDR)),
  323. NULL,
  324. FILE_BEGIN) != INVALID_SET_FILE_POINTER) &&
  325. (_UH.numKeyEntries[_UH.currentBitmapCacheId] <
  326. _UH.maxNumKeyEntries[_UH.currentBitmapCacheId]))
  327. {
  328. DC_QUIT;
  329. }
  330. }
  331. #ifdef DC_HICOLOR
  332. // This needs to be here - or we may try to do an lseek on a file
  333. // that's hit the end
  334. DWORD dwRet = SetFilePointer(_UH.currentFileHandle,
  335. 0,
  336. NULL,
  337. FILE_END);
  338. if(INVALID_SET_FILE_POINTER != dwRet)
  339. {
  340. filelen = dwRet;
  341. }
  342. if (filelen > 0) {
  343. _UH.bitmapCacheSizeInUse += filelen;
  344. }
  345. else {
  346. TRC_ABORT((TB, _T("failed SetFilePointer to end of file")));
  347. }
  348. #endif
  349. }
  350. else {
  351. // end of file or error in cache file.
  352. // Close this cache file and move on to next one
  353. TRC_ERR((TB, _T("ReadFile failed with err 0x%x"),
  354. GetLastError()));
  355. if(GetLastError() == ERROR_HANDLE_EOF)
  356. {
  357. rc = TRUE;
  358. }
  359. }
  360. #ifndef DC_HICOLOR
  361. DWORD dwRet = SetFilePointer(_UH.currentFileHandle,
  362. 0,
  363. NULL,
  364. FILE_END);
  365. if(INVALID_SET_FILE_POINTER != dwRet)
  366. {
  367. filelen = dwRet;
  368. }
  369. if (filelen > 0) {
  370. _UH.bitmapCacheSizeInUse += filelen;
  371. }
  372. else {
  373. TRC_ABORT((TB, _T("failed SetFilePointer to end of file")));
  374. }
  375. #endif //HICOLOR
  376. CloseHandle(_UH.currentFileHandle);
  377. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  378. _UH.currentBitmapCacheId++;
  379. _UH.currentFileHandle = 0;
  380. DC_EXIT_POINT:
  381. DC_END_FN();
  382. return rc;
  383. }
  384. /****************************************************************************/
  385. // UHEnumerateBitmapKeyList
  386. //
  387. // Enumerate the persistent bitmap keys from disk cache
  388. /****************************************************************************/
  389. #define UH_ENUM_PER_POST 50
  390. VOID DCINTERNAL CUH::UHEnumerateBitmapKeyList(ULONG_PTR unusedParm)
  391. {
  392. UINT numEnum;
  393. UINT virtualSize = 0;
  394. HRESULT hr;
  395. DC_BEGIN_FN("UHEnumerateBitmapKeyList");
  396. DC_IGNORE_PARAMETER(unusedParm);
  397. numEnum = 0;
  398. if (_UH.bBitmapKeyEnumComplete)
  399. {
  400. TRC_NRM((TB,_T("Enumeration has completed. Bailing out")));
  401. DC_QUIT;
  402. }
  403. if (!_UH.bBitmapKeyEnumerating)
  404. {
  405. TRC_NRM((TB,_T("Starting new enumeration for copymult:%d"),
  406. _UH.copyMultiplier));
  407. _UH.bBitmapKeyEnumerating = TRUE;
  408. //
  409. // Track enumeration copy-multiplier as _UH.copyMultiplier
  410. // can potentially change during enumeration as a UH_Enable
  411. // call comes in
  412. //
  413. _UH.currentCopyMultiplier = _UH.copyMultiplier;
  414. }
  415. //
  416. // Can't be enumerating while complete
  417. //
  418. TRC_ASSERT(!(_UH.bBitmapKeyEnumerating && _UH.bBitmapKeyEnumComplete),
  419. (TB,_T("Bad state: enumerating while complete")));
  420. // enumerate the bitmap cache directories
  421. while (_UH.currentBitmapCacheId < _UH.RegNumBitmapCaches &&
  422. numEnum < UH_ENUM_PER_POST) {
  423. // See if this cache is marked persistent.
  424. if (_UH.RegBCInfo[_UH.currentBitmapCacheId].bSendBitmapKeys) {
  425. if (_UH.pBitmapKeyDB[_UH.currentBitmapCacheId] == NULL) {
  426. // we haven't allocate key database memory for this cache yet
  427. // determine the max possible key database entries for this cache
  428. virtualSize =
  429. UH_PropVirtualCacheSizeFromMult(_UH.currentCopyMultiplier);
  430. _UH.maxNumKeyEntries[_UH.currentBitmapCacheId] =
  431. virtualSize /
  432. (UH_CellSizeFromCacheIDAndMult(
  433. _UH.currentBitmapCacheId,
  434. _UH.currentCopyMultiplier) +
  435. sizeof(UHBITMAPFILEHDR));
  436. _UH.pBitmapKeyDB[_UH.currentBitmapCacheId] =
  437. (PTS_BITMAPCACHE_PERSISTENT_LIST_ENTRY)
  438. UT_MallocHuge(_pUt,
  439. _UH.maxNumKeyEntries[_UH.currentBitmapCacheId] *
  440. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY));
  441. if (_UH.pBitmapKeyDB[_UH.currentBitmapCacheId] == NULL) {
  442. TRC_ERR((TB, _T("failed to alloc mem for key database")));
  443. _UH.bBitmapKeyEnumComplete = TRUE;
  444. break;
  445. }
  446. }
  447. if (_UH.currentFileHandle != INVALID_HANDLE_VALUE) {
  448. // we already have an open cache file
  449. // read a bitmap's info from the cache file
  450. UHReadFromCacheFileForEnum();
  451. }
  452. else {
  453. // we need to open this cache file
  454. hr = UHSetCurrentCacheFileName(_UH.currentBitmapCacheId,
  455. _UH.currentCopyMultiplier);
  456. if (SUCCEEDED(hr)) {
  457. // Start the file enumeration.
  458. #ifndef OS_WINCE
  459. if (!_UH.fBmpCacheMemoryAlloced)
  460. {
  461. _UH.currentFileHandle = CreateFile( _UH.PersistCacheFileName,
  462. GENERIC_READ,
  463. FILE_SHARE_READ | FILE_SHARE_WRITE,
  464. NULL,
  465. OPEN_EXISTING,
  466. FILE_ATTRIBUTE_NORMAL,
  467. NULL);
  468. }
  469. else
  470. {
  471. //UH_Enable and UHAllocBitmapCacheMemory has been called
  472. //and should have created the bitmap cache files. If we were
  473. //to create file here we'd get a sharing violation so instead
  474. //duplicated the existing handle
  475. HANDLE hCacheFile =
  476. _UH.bitmapCache[_UH.currentBitmapCacheId].PageTable.CacheFileInfo.hCacheFile;
  477. TRC_NRM((TB,_T("About to dup handle to bmp cache file 0x%x"),
  478. hCacheFile));
  479. if (INVALID_HANDLE_VALUE != hCacheFile)
  480. {
  481. HANDLE hCurProc = GetCurrentProcess();
  482. if (hCurProc)
  483. {
  484. if(!DuplicateHandle(hCurProc,
  485. hCacheFile,
  486. hCurProc,
  487. &_UH.currentFileHandle,
  488. GENERIC_READ,
  489. FALSE,
  490. 0))
  491. {
  492. TRC_ERR((TB,_T("Dup handle failed 0x%x"),
  493. GetLastError()));
  494. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  495. }
  496. }
  497. else
  498. {
  499. TRC_ERR((TB,_T("GetCurrentProcess failed 0x%x"),
  500. GetLastError()));
  501. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  502. }
  503. }
  504. else
  505. {
  506. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  507. }
  508. }
  509. #else //OS_WINCE
  510. // CE_FIXNOTE:
  511. // CE doesn't support duplicate handle so on a reconnect
  512. // it is possible the CreateFile will fail with a sharing
  513. // violation. Might need to revisit the logic and on CE only
  514. // create the files with R/W sharing
  515. //
  516. _UH.currentFileHandle = CreateFile( _UH.PersistCacheFileName,
  517. GENERIC_READ | GENERIC_WRITE,
  518. FILE_SHARE_READ,
  519. NULL,
  520. OPEN_EXISTING,
  521. FILE_ATTRIBUTE_NORMAL,
  522. NULL);
  523. #endif
  524. }
  525. else {
  526. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  527. }
  528. if (_UH.currentFileHandle != INVALID_HANDLE_VALUE) {
  529. // First entry of the cache file
  530. UHReadFromCacheFileForEnum();
  531. }
  532. else {
  533. // we can't open the cache file for this cache,
  534. // move on to the next cache
  535. // we also need to clear the cache file
  536. UH_ClearOneBitmapDiskCache(_UH.currentBitmapCacheId,
  537. _UH.currentCopyMultiplier);
  538. _UH.currentBitmapCacheId++;
  539. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  540. }
  541. }
  542. numEnum++;
  543. }
  544. else {
  545. // check next cache
  546. _UH.currentBitmapCacheId++;
  547. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  548. }
  549. } // end of while
  550. if (_UH.currentBitmapCacheId == _UH.RegNumBitmapCaches ||
  551. _UH.bBitmapKeyEnumComplete == TRUE) {
  552. TRC_NRM((TB, _T("Finished bitmap keys enumeration for copymult:%d"),
  553. _UH.currentCopyMultiplier));
  554. _UH.bBitmapKeyEnumComplete = TRUE;
  555. _UH.bBitmapKeyEnumerating = FALSE;
  556. // We need to make sure we have enough disk space for persistent caching
  557. UINT vcacheSize = UH_PropVirtualCacheSizeFromMult(_UH.currentCopyMultiplier);
  558. if (vcacheSize / _UH.BytesPerCluster >= _UH.NumberOfFreeClusters) {
  559. //
  560. // Be careful to correctly map the array index (-1 to go 0 based)
  561. //
  562. _UH.PropBitmapVirtualCacheSize[_UH.currentCopyMultiplier-1] =
  563. min(vcacheSize,(_UH.bitmapCacheSizeInUse +
  564. _UH.NumberOfFreeClusters / 2 *
  565. _UH.BytesPerCluster));
  566. }
  567. // We disable persistent caching if we don't have enough disk space
  568. // We need at least as much as memory cache size
  569. if (UH_PropVirtualCacheSizeFromMult(_UH.currentCopyMultiplier) <
  570. _UH.RegBitmapCacheSize)
  571. {
  572. _UH.bPersistenceDisable = TRUE;
  573. }
  574. // UH is enabled and enumeration is finished, try to send the bitmap
  575. // key PDU now
  576. if (_UH.bEnabled) {
  577. if (_UH.bPersistenceActive && !_UH.bPersistentBitmapKeysSent)
  578. {
  579. if (_UH.currentCopyMultiplier == _UH.copyMultiplier)
  580. {
  581. //Great we've enumerated keys for the correct
  582. //copy multiplier
  583. UHSendPersistentBitmapKeyList(0);
  584. }
  585. else
  586. {
  587. //
  588. // We got connected at a different copy multiplier
  589. // need to enumerate keys again. Reset enumeration state
  590. //
  591. UHResetAndRestartEnumeration();
  592. }
  593. }
  594. }
  595. }
  596. else {
  597. if (_UH.bitmapKeyEnumTimerId == 0) {
  598. TRC_DBG((TB, _T("Calling CD again")));
  599. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT, this,
  600. CD_NOTIFICATION_FUNC(CUH,UHEnumerateBitmapKeyList), 0);
  601. }
  602. }
  603. DC_EXIT_POINT:
  604. if (_UH.bBitmapKeyEnumComplete)
  605. {
  606. _UH.bBitmapKeyEnumerating = FALSE;
  607. }
  608. DC_END_FN();
  609. } //UHEnumerateBitmapKeyList
  610. /****************************************************************************/
  611. // UH_ClearOneBitmapDiskCache
  612. //
  613. // remove all the files under a bitmap disk cache
  614. /****************************************************************************/
  615. VOID DCAPI CUH::UH_ClearOneBitmapDiskCache(UINT cacheId, UINT copyMultiplier)
  616. {
  617. DC_BEGIN_FN("UH_ClearOneBitmapDiskCache");
  618. UHSetCurrentCacheFileName(cacheId, copyMultiplier);
  619. DeleteFile(_UH.PersistCacheFileName);
  620. DC_END_FN();
  621. }
  622. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  623. /****************************************************************************/
  624. // UH_Init
  625. //
  626. // Purpose: Initialize _UH. Called on program init, one or more connections
  627. // may be performed after this and before UH_Term is called.
  628. /****************************************************************************/
  629. DCVOID DCAPI CUH::UH_Init(DCVOID)
  630. {
  631. PDCUINT16 pIndexTable;
  632. DCUINT i;
  633. HRESULT hr;
  634. #ifdef OS_WINCE
  635. BOOL bUseStorageCard = FALSE;
  636. BOOL bSuccess = FALSE;
  637. #endif
  638. DC_BEGIN_FN("UH_Init");
  639. TRC_ASSERT(_pClientObjects, (TB,_T("_pClientObjects is NULL")));
  640. _pClientObjects->AddObjReference(UH_OBJECT_FLAG);
  641. #ifdef DC_DEBUG
  642. _pClientObjects->CheckPointers();
  643. #endif
  644. _pGh = _pClientObjects->_pGHObject;
  645. _pOp = _pClientObjects->_pOPObject;
  646. _pSl = _pClientObjects->_pSlObject;
  647. _pUt = _pClientObjects->_pUtObject;
  648. _pFs = _pClientObjects->_pFsObject;
  649. _pOd = _pClientObjects->_pODObject;
  650. _pIh = _pClientObjects->_pIhObject;
  651. _pCd = _pClientObjects->_pCdObject;
  652. _pUi = _pClientObjects->_pUiObject;
  653. _pCc = _pClientObjects->_pCcObject;
  654. _pClx = _pClientObjects->_pCLXObject;
  655. _pOr = _pClientObjects->_pOrObject;
  656. memset(&_UH, 0, sizeof(_UH));
  657. //
  658. // At UH_Init time the client hasn't connected
  659. // yet so key the color depth off what the user
  660. // has requested
  661. //
  662. switch (_pUi->_UI.colorDepthID)
  663. {
  664. case CO_BITSPERPEL8:
  665. _UH.copyMultiplier = 1;
  666. break;
  667. case CO_BITSPERPEL15:
  668. case CO_BITSPERPEL16:
  669. _UH.copyMultiplier = 2;
  670. break;
  671. case CO_BITSPERPEL24:
  672. _UH.copyMultiplier = 3;
  673. break;
  674. default:
  675. TRC_ERR((TB,_T("Unknown color depth: %d"),
  676. _pUi->UI_GetColorDepth()));
  677. _UH.copyMultiplier = 1;
  678. break;
  679. }
  680. _UH.currentFileHandle = INVALID_HANDLE_VALUE;
  681. _pGh->GH_Init();
  682. /************************************************************************/
  683. // Set up the nonzero invariant fields in the BitmapInfoHeader
  684. // structure. This is used for processing received Bitmap PDUs.
  685. // Note that for WinCE this is required for UHAllocBitmapCacheMemory().
  686. /************************************************************************/
  687. _UH.bitmapInfo.hdr.biSize = sizeof(BITMAPINFOHEADER);
  688. _UH.bitmapInfo.hdr.biPlanes = 1;
  689. _UH.bitmapInfo.hdr.biBitCount = 8;
  690. _UH.bitmapInfo.hdr.biCompression = BMCRGB;
  691. _UH.bitmapInfo.hdr.biXPelsPerMeter = 10000;
  692. _UH.bitmapInfo.hdr.biYPelsPerMeter = 10000;
  693. /************************************************************************/
  694. // Allocate and init the color table cache memory.
  695. // If alloc fails then we will not later allocate and advertise bitmap
  696. // and glyph caching capability.
  697. // Note that bitmap cache memory and capabilities are set up during
  698. // connection.
  699. /************************************************************************/
  700. if (UHAllocColorTableCacheMemory()) {
  701. TRC_NRM((TB, _T("Color table cache memory OK")));
  702. // Init headers with default values.
  703. for (i = 0; i < UH_COLOR_TABLE_CACHE_ENTRIES; i++) {
  704. _UH.pMappedColorTableCache[i].hdr.biSize = sizeof(BITMAPINFOHEADER);
  705. _UH.pMappedColorTableCache[i].hdr.biPlanes = 1;
  706. _UH.pMappedColorTableCache[i].hdr.biBitCount = 8;
  707. _UH.pMappedColorTableCache[i].hdr.biCompression = BMCRGB;
  708. _UH.pMappedColorTableCache[i].hdr.biSizeImage = 0;
  709. _UH.pMappedColorTableCache[i].hdr.biXPelsPerMeter = 10000;
  710. _UH.pMappedColorTableCache[i].hdr.biYPelsPerMeter = 10000;
  711. _UH.pMappedColorTableCache[i].hdr.biClrUsed = 0;
  712. _UH.pMappedColorTableCache[i].hdr.biClrImportant = 0;
  713. }
  714. }
  715. else {
  716. TRC_ERR((TB, _T("Color table cache alloc failed - bitmap caching ")
  717. _T("disabled")));
  718. #ifdef OS_WINCE
  719. //This and other failure paths are added for WINCE because it is difficult to
  720. //recover from an OOM scenario on CE. So we trigger a fatal error and not let
  721. //the connection continue in case any memory allocation fails.
  722. DC_QUIT;
  723. #endif
  724. }
  725. // Allocate the glyph cache memory, set up glyph cache capabilities.
  726. if (UHAllocGlyphCacheMemory())
  727. TRC_NRM((TB, _T("Glyph cache memory OK")));
  728. else
  729. #ifdef OS_WINCE
  730. {
  731. #endif
  732. TRC_ERR((TB, _T("Glyph cache memory allocation failed!")));
  733. #ifdef OS_WINCE
  734. DC_QUIT;
  735. }
  736. #endif
  737. // Allocate the brush cache.
  738. if (UHAllocBrushCacheMemory())
  739. TRC_NRM((TB, _T("Brush cache memory OK")));
  740. else
  741. #ifdef OS_WINCE
  742. {
  743. #endif
  744. TRC_ERR((TB, _T("Brush cache memory allocation failed!")));
  745. #ifdef OS_WINCE
  746. DC_QUIT;
  747. }
  748. #endif
  749. // Allocate the offscreen cache
  750. if (UHAllocOffscreenCacheMemory()) {
  751. TRC_NRM((TB, _T("Offscreen cache memory OK")));
  752. }
  753. else {
  754. TRC_ERR((TB, _T("Offscreen cache memory allocation failed!")));
  755. }
  756. #ifdef DRAW_NINEGRID
  757. // Allocate the drawninegrid cache
  758. if (UHAllocDrawNineGridCacheMemory()) {
  759. TRC_NRM((TB, _T("DrawNineGrid cache memory OK")));
  760. }
  761. else {
  762. TRC_ERR((TB, _T("DrawNineGrid cache memory allocation failed!")));
  763. #ifdef OS_WINCE
  764. DC_QUIT;
  765. #endif
  766. }
  767. #endif
  768. // Preload bitmap cache registry settings.
  769. UHReadBitmapCacheSettings();
  770. _UH.hpalDefault = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  771. _UH.hpalCurrent = _UH.hpalDefault;
  772. _UH.hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
  773. _UH.hrgnUpdateRect = CreateRectRgn(0, 0, 0, 0);
  774. _UH.colorIndicesEnabled = TRUE;
  775. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderFlags |=
  776. TS_ORDERFLAGS_COLORINDEXSUPPORT;
  777. #ifdef DC_DEBUG
  778. /************************************************************************/
  779. /* Initialize the Bitmap Cache Monitor */
  780. /************************************************************************/
  781. UHInitBitmapCacheMonitor();
  782. #endif /* DC_DEBUG */
  783. /************************************************************************/
  784. // We pass received bitmap data to StretchDIBits with the
  785. // CO_DIB_PAL_COLORS option, which requires a table of indices into
  786. // the currently selected palette in place of a color table.
  787. //
  788. // We set up this table here, as we always have a simple 1-1
  789. // mapping. Start from 1 since we zeroed the 1st entry with the memset
  790. // above.
  791. /************************************************************************/
  792. pIndexTable = &(_UH.bitmapInfo.paletteIndexTable[1]);
  793. for (i = 1; i < 256; i++)
  794. *pIndexTable++ = (UINT16)i;
  795. _UH.bitmapInfo.bIdentityPalette = TRUE;
  796. /************************************************************************/
  797. /* Set up the codepage */
  798. /************************************************************************/
  799. _pCc->_ccCombinedCapabilities.orderCapabilitySet.textANSICodePage =
  800. (UINT16)_pUt->UT_GetANSICodePage();
  801. /************************************************************************/
  802. /* Read the update frequency */
  803. /************************************************************************/
  804. _UH.drawThreshold = _pUi->_UI.orderDrawThreshold;
  805. if (_UH.drawThreshold == 0)
  806. {
  807. _UH.drawThreshold = (DCUINT)(-1);
  808. }
  809. TRC_NRM((TB, _T("Draw output every %d orders"), _UH.drawThreshold));
  810. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  811. /************************************************************************/
  812. // Grab the mstsc's executable path for use in managing bitmap caches as
  813. // default. _UH.EndPersistCacheDir points to the '\0' after the path.
  814. /************************************************************************/
  815. #ifdef OS_WINNT
  816. if (_UH.PersistCacheFileName[0] == _T('\0')) {
  817. #define CACHE_PROFILE_NAME _T("\\Microsoft\\Terminal Server Client\\Cache\\")
  818. // for NT5, by default, we should place the cache directory at the user profile
  819. // location instead of where the client is installed
  820. HRESULT hr = E_FAIL;
  821. #ifdef UNIWRAP
  822. //Call the uniwrap SHGetFolderPath, it does the necessary dynamic
  823. //binding and will thunk to ANSI on Win9x
  824. hr = SHGetFolderPathWrapW(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE,
  825. NULL, 0, _UH.PersistCacheFileName);
  826. #else //UNIWRAP not defined
  827. HMODULE hmodSH32DLL;
  828. #ifdef UNICODE
  829. typedef HRESULT (STDAPICALLTYPE FNSHGetFolderPath)(HWND, int, HANDLE, DWORD, LPWSTR);
  830. #else
  831. typedef HRESULT (STDAPICALLTYPE FNSHGetFolderPath)(HWND, int, HANDLE, DWORD, LPSTR);
  832. #endif
  833. FNSHGetFolderPath *pfnSHGetFolderPath;
  834. // get the handle to shell32.dll library
  835. hmodSH32DLL = LoadLibrary(TEXT("SHELL32.DLL"));
  836. if (hmodSH32DLL != NULL) {
  837. // get the proc address for SHGetFolderPath
  838. #ifdef UNICODE
  839. pfnSHGetFolderPath = (FNSHGetFolderPath *)GetProcAddress(hmodSH32DLL, "SHGetFolderPathW");
  840. #else
  841. pfnSHGetFolderPath = (FNSHGetFolderPath *)GetProcAddress(hmodSH32DLL, "SHGetFolderPathA");
  842. #endif
  843. // get the user profile local application data location
  844. if (pfnSHGetFolderPath != NULL) {
  845. hr = (*pfnSHGetFolderPath) (NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE,
  846. NULL, 0, _UH.PersistCacheFileName);
  847. }
  848. FreeLibrary(hmodSH32DLL);
  849. }
  850. #endif //UNIWRAP
  851. if (SUCCEEDED(hr)) // did SHGetFolderPath succeed
  852. {
  853. _UH.EndPersistCacheDir = _tcslen(_UH.PersistCacheFileName);
  854. if (_UH.EndPersistCacheDir +
  855. sizeof(CACHE_PROFILE_NAME)/sizeof(TCHAR) + 1< MAX_PATH) {
  856. //LENGTH is validated above
  857. StringCchCopy(_UH.PersistCacheFileName + _UH.EndPersistCacheDir,
  858. MAX_PATH,
  859. CACHE_PROFILE_NAME);
  860. }
  861. }
  862. }
  863. #endif //OS_WINNT
  864. if (_UH.PersistCacheFileName[0] == _T('\0')) {
  865. #ifdef OS_WINCE
  866. //
  867. // First let's see if there is a storage card.
  868. // and if there is enough space in there, then we will use it.
  869. //
  870. DWORDLONG tmpDiskSize = 0;
  871. UINT32 BytesPerSector = 0, SectorsPerCluster = 0, TotalNumberOfClusters = 0, FreeClusters = 0;
  872. // If we're scaling the bitmap caches by the bit depth, test disk
  873. // space for 24-bit depth, otherwise test simply for 8bpp.
  874. if (UHGetDiskFreeSpace(
  875. WINCE_STORAGE_CARD_DIRECTORY,
  876. (PULONG)&SectorsPerCluster,
  877. (PULONG)&BytesPerSector,
  878. (PULONG)&FreeClusters,
  879. (PULONG)&TotalNumberOfClusters))
  880. {
  881. //The cast is needed to do 64bit math, without it we have
  882. //an overflow problem
  883. tmpDiskSize = (DWORDLONG)BytesPerSector * SectorsPerCluster * FreeClusters;
  884. if(tmpDiskSize >= (_UH.RegBitmapCacheSize *
  885. (_UH.RegScaleBitmapCachesByBPP ? 3 : 1)))
  886. {
  887. bUseStorageCard = TRUE;
  888. _tcscpy(_UH.PersistCacheFileName, WINCE_STORAGE_CARD_DIRECTORY);
  889. _tcscat(_UH.PersistCacheFileName, CACHE_DIRECTORY_NAME);
  890. }
  891. }
  892. else {
  893. #endif
  894. _UH.EndPersistCacheDir = GetModuleFileName(_pUi->UI_GetInstanceHandle(),
  895. _UH.PersistCacheFileName, MAX_PATH - sizeof(CACHE_DIRECTORY_NAME)/sizeof(TCHAR));
  896. if (_UH.EndPersistCacheDir > 0) {
  897. // Strip the module name off the end to leave the executable
  898. // directory path, by looking for the last backslash.
  899. _UH.EndPersistCacheDir--;
  900. while (_UH.EndPersistCacheDir != 0) {
  901. if (_UH.PersistCacheFileName[_UH.EndPersistCacheDir] != _T('\\')) {
  902. _UH.EndPersistCacheDir--;
  903. continue;
  904. }
  905. _UH.EndPersistCacheDir++;
  906. break;
  907. }
  908. // we should set up persistent cache disk directory
  909. _UH.PersistCacheFileName[_UH.EndPersistCacheDir] = _T('\0');
  910. // Check we have enough space for the base path + the dir name
  911. if ((_UH.EndPersistCacheDir +
  912. _tcslen(CACHE_DIRECTORY_NAME) + 1) < MAX_PATH) {
  913. //
  914. // Length checked above
  915. //
  916. StringCchCopy(_UH.PersistCacheFileName + _UH.EndPersistCacheDir,
  917. MAX_PATH,
  918. CACHE_DIRECTORY_NAME);
  919. }
  920. else {
  921. _UH.bPersistenceDisable = TRUE;
  922. }
  923. }
  924. else {
  925. // since we can't find the mstsc path, we can't determine where
  926. // to store the bitmaps on disk. So, we simply disable the
  927. // persistence bitmap here
  928. _UH.bPersistenceDisable = TRUE;
  929. TRC_ERR((TB,_T("GetModuleFileName() error, could not retrieve path")));
  930. }
  931. #ifdef OS_WINCE // OS_WINCE
  932. }
  933. #endif // OS_WINCE
  934. }
  935. _UH.EndPersistCacheDir = _tcslen(_UH.PersistCacheFileName);
  936. // Make sure _UH.PersistCacheFileName ends with a \ for directory name
  937. if (_UH.PersistCacheFileName[_UH.EndPersistCacheDir - 1] != _T('\\')) {
  938. _UH.PersistCacheFileName[_UH.EndPersistCacheDir] = _T('\\');
  939. _UH.PersistCacheFileName[++_UH.EndPersistCacheDir] = _T('\0');
  940. }
  941. // Check that our path is not too long to contain the base path
  942. // plus each cache filename. If so, we can't use the path.
  943. if ((_UH.EndPersistCacheDir + CACHE_FILENAME_LENGTH + 1) >= MAX_PATH) {
  944. TRC_ERR((TB,_T("Base cache path \"%s\" too long, cannot load ")
  945. _T("persistent bitmaps"), _UH.PersistCacheFileName));
  946. _UH.bPersistenceDisable = TRUE;
  947. }
  948. /*********************************************************************/
  949. // To make sure we have enough space to hold the virtual memory cache
  950. // we should check the free disk space
  951. /*********************************************************************/
  952. // make sure we don't have a UNC app path
  953. #ifndef OS_WINCE
  954. if (_UH.PersistCacheFileName[0] != _T('\\')) {
  955. #else
  956. if (_UH.PersistCacheFileName[0] != _T('\0')) { // path in wince is of the form "\Windows\Cache"
  957. #endif
  958. UINT32 BytesPerSector = 0, SectorsPerCluster = 0, TotalNumberOfClusters = 0;
  959. #ifndef OS_WINCE
  960. TCHAR RootPath[4];
  961. _tcsncpy(RootPath, _UH.PersistCacheFileName, 3);
  962. RootPath[3] = _T('\0');
  963. #endif
  964. // Get disk information
  965. if (UHGetDiskFreeSpace(
  966. #ifndef OS_WINCE
  967. RootPath,
  968. #else
  969. (bUseStorageCard) ? WINCE_STORAGE_CARD_DIRECTORY : WINCE_FILE_SYSTEM_ROOT ,
  970. #endif
  971. (PULONG)&SectorsPerCluster,
  972. (PULONG)&BytesPerSector,
  973. &_UH.NumberOfFreeClusters,
  974. (PULONG)&TotalNumberOfClusters)) {
  975. _UH.BytesPerCluster = BytesPerSector * SectorsPerCluster;
  976. }
  977. else {
  978. // we can't get disk info, we have to turn the persistent flag off
  979. _UH.bPersistenceDisable = TRUE;
  980. }
  981. }
  982. else {
  983. // we don't support network disk
  984. _UH.bPersistenceDisable = TRUE;
  985. }
  986. /*********************************************************************/
  987. // If the persistent is not disabled,we need to lock the persistent disk
  988. // cache before another session grabs it. If we failed to get the cache
  989. // lock, persistent caching is not supported for this session
  990. /*********************************************************************/
  991. if (!_UH.bPersistenceDisable) {
  992. unsigned len;
  993. // Compose lock name, it's based on the cache directory name
  994. #if (defined(OS_WINCE))
  995. _tcscpy(_UH.PersistentLockName, TEXT("MSTSC_"));
  996. len = _tcslen(_UH.PersistentLockName);
  997. #else
  998. // For Terminal server platforms, we need to use global in
  999. // persistentlockname to make sure the locking is cross sessions.
  1000. // but on non-terminal server NT platforms, we can't use global
  1001. // as the lock name. (in createmutex)
  1002. if (_pUt->UT_IsTerminalServicesEnabled()) {
  1003. hr = StringCchCopy(_UH.PersistentLockName,
  1004. SIZE_TCHARS(_UH.PersistentLockName),
  1005. TEXT("Global\\MSTSC_"));
  1006. }
  1007. else {
  1008. hr = StringCchCopy(_UH.PersistentLockName,
  1009. SIZE_TCHARS(_UH.PersistentLockName),
  1010. TEXT("MSTSC_"));
  1011. }
  1012. //Lock name should fit since it's a fixed format
  1013. TRC_ASSERT(SUCCEEDED(hr),
  1014. (TB,_T("Error copying persistent lock name: 0x%x"), hr));
  1015. len = _tcslen(_UH.PersistentLockName);
  1016. #endif
  1017. for (i = 0; i < _UH.EndPersistCacheDir; i++) {
  1018. // Tried to use _istalnum for 2nd clause, but CRTDLL doesn't
  1019. // like it.
  1020. if (_UH.PersistCacheFileName[i] == _T('\\'))
  1021. _UH.PersistentLockName[len++] = _T('_');
  1022. else if ((_UH.PersistCacheFileName[i] >= _T('0') &&
  1023. _UH.PersistCacheFileName[i] <= _T('9')) ||
  1024. (_UH.PersistCacheFileName[i] >= _T('A') &&
  1025. _UH.PersistCacheFileName[i] <= _T('Z')) ||
  1026. (_UH.PersistCacheFileName[i] >= _T('a') &&
  1027. _UH.PersistCacheFileName[i] <= _T('z')))
  1028. _UH.PersistentLockName[len++] = _UH.PersistCacheFileName[i];
  1029. }
  1030. _UH.PersistentLockName[len] = _T('\0');
  1031. // try to lock the cache directory for persistent caching
  1032. if (!UHGrabPersistentCacheLock()) {
  1033. _UH.bPersistenceDisable = TRUE;
  1034. }
  1035. }
  1036. /********************************************************************/
  1037. // We need to enumerate the disk to get the bitmap key database
  1038. // The client will always enumerate the keys even the persistent
  1039. // caching option might be changed later on.
  1040. /********************************************************************/
  1041. if (!_UH.bPersistenceDisable) {
  1042. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT, this,
  1043. CD_NOTIFICATION_FUNC(CUH,UHEnumerateBitmapKeyList), 0);
  1044. }
  1045. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1046. #ifdef DRAW_GDIPLUS
  1047. // Initialize fGdipEnabled
  1048. _UH.fGdipEnabled = FALSE;
  1049. #endif
  1050. #ifdef OS_WINCE
  1051. bSuccess = TRUE;
  1052. DC_EXIT_POINT:
  1053. if (!bSuccess)
  1054. {
  1055. _pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT,
  1056. _pUi,
  1057. CD_NOTIFICATION_FUNC(CUI,UI_FatalError),
  1058. (ULONG_PTR) DC_ERR_OUTOFMEMORY);
  1059. }
  1060. #endif
  1061. DC_END_FN();
  1062. } /* UH_Init */
  1063. /****************************************************************************/
  1064. // UH_Term
  1065. //
  1066. // Terminates _UH. Called on app exit.
  1067. /****************************************************************************/
  1068. DCVOID DCAPI CUH::UH_Term(DCVOID)
  1069. {
  1070. DC_BEGIN_FN("UH_Term");
  1071. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1072. // unlock the persistent cache directory if this session locked it earlier
  1073. UHReleasePersistentCacheLock();
  1074. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1075. #ifdef DRAW_GDIPLUS
  1076. UHDrawGdiplusShutdown(0);
  1077. #endif
  1078. /************************************************************************/
  1079. /* Free off any bitmaps that are specific to the connection. */
  1080. /************************************************************************/
  1081. if (NULL != _UH.hShadowBitmap)
  1082. {
  1083. /********************************************************************/
  1084. /* Delete the Shadow Bitmap. */
  1085. /********************************************************************/
  1086. TRC_NRM((TB, _T("Delete the Shadow Bitmap")));
  1087. UHDeleteBitmap(&_UH.hdcShadowBitmap,
  1088. &_UH.hShadowBitmap,
  1089. &_UH.hunusedBitmapForShadowDC);
  1090. }
  1091. if (NULL != _UH.hSaveScreenBitmap)
  1092. {
  1093. /********************************************************************/
  1094. /* Delete the Save Bitmap. */
  1095. /********************************************************************/
  1096. TRC_NRM((TB, _T("Delete save screen bitmap")));
  1097. UHDeleteBitmap(&_UH.hdcSaveScreenBitmap,
  1098. &_UH.hSaveScreenBitmap,
  1099. &_UH.hunusedBitmapForSSBDC);
  1100. }
  1101. if (NULL != _UH.hbmpDisconnectedBitmap) {
  1102. UHDeleteBitmap(&_UH.hdcDisconnected,
  1103. &_UH.hbmpDisconnectedBitmap,
  1104. &_UH.hbmpUnusedDisconnectedBitmap);
  1105. }
  1106. // Delete all the offscreen bitmaps
  1107. if (NULL != _UH.hdcOffscreenBitmap) {
  1108. unsigned i;
  1109. for (i = 0; i < _UH.offscrCacheEntries; i++) {
  1110. if (_UH.offscrBitmapCache[i].offscrBitmap) {
  1111. SelectBitmap(_UH.hdcOffscreenBitmap,
  1112. _UH.hUnusedOffscrBitmap);
  1113. DeleteBitmap(_UH.offscrBitmapCache[i].offscrBitmap);
  1114. }
  1115. }
  1116. }
  1117. #ifdef DRAW_NINEGRID
  1118. // Delete all the drawNineGrid bitmaps
  1119. if (NULL != _UH.hdcDrawNineGridBitmap) {
  1120. unsigned i;
  1121. for (i = 0; i < _UH.drawNineGridCacheEntries; i++) {
  1122. if (_UH.drawNineGridBitmapCache[i].drawNineGridBitmap) {
  1123. SelectBitmap(_UH.hdcDrawNineGridBitmap,
  1124. _UH.hUnusedDrawNineGridBitmap);
  1125. DeleteBitmap(_UH.drawNineGridBitmapCache[i].drawNineGridBitmap);
  1126. }
  1127. }
  1128. }
  1129. #endif
  1130. #ifdef DC_DEBUG
  1131. /************************************************************************/
  1132. /* Terminate the Bitmap Cache Monitor */
  1133. /************************************************************************/
  1134. UHTermBitmapCacheMonitor();
  1135. #endif /* DC_DEBUG */
  1136. DeleteRgn(_UH.hrgnUpdate);
  1137. DeleteRgn(_UH.hrgnUpdateRect);
  1138. UHFreeCacheMemory();
  1139. /************************************************************************/
  1140. // Free the palette (if not the default). This needs to happen after
  1141. // freeing bitmap cache resources so the palettes can be written to disk
  1142. // with the bitmap files.
  1143. /************************************************************************/
  1144. if ((_UH.hpalCurrent != NULL) && (_UH.hpalCurrent != _UH.hpalDefault))
  1145. {
  1146. TRC_NRM((TB, _T("Delete current palette %p"), _UH.hpalCurrent));
  1147. DeletePalette(_UH.hpalCurrent);
  1148. }
  1149. /************************************************************************/
  1150. // If we created a decompression buffer, get rid of it now.
  1151. /************************************************************************/
  1152. if (_UH.bitmapDecompressionBuffer != NULL) {
  1153. UT_Free( _pUt, _UH.bitmapDecompressionBuffer);
  1154. _UH.bitmapDecompressionBuffer = NULL;
  1155. _UH.bitmapDecompressionBufferSize = 0;
  1156. }
  1157. /************************************************************************/
  1158. // Release cached glyph resources
  1159. /************************************************************************/
  1160. if (_UH.hdcGlyph != NULL)
  1161. {
  1162. DeleteDC(_UH.hdcGlyph);
  1163. _UH.hdcGlyph = NULL;
  1164. }
  1165. if (_UH.hbmGlyph != NULL)
  1166. {
  1167. DeleteObject(_UH.hbmGlyph);
  1168. _UH.hbmGlyph = NULL;
  1169. }
  1170. if (_UH.hdcBrushBitmap != NULL)
  1171. {
  1172. DeleteDC(_UH.hdcBrushBitmap);
  1173. _UH.hdcBrushBitmap = NULL;
  1174. }
  1175. // Release the offscreen bitmap DC
  1176. if (_UH.hdcOffscreenBitmap != NULL) {
  1177. DeleteDC(_UH.hdcOffscreenBitmap);
  1178. }
  1179. #ifdef DRAW_NINEGRID
  1180. // Release the drawninegrid bitmap DC
  1181. if (_UH.hdcDrawNineGridBitmap != NULL) {
  1182. DeleteDC(_UH.hdcDrawNineGridBitmap);
  1183. _UH.hdcDrawNineGridBitmap = NULL;
  1184. }
  1185. if (_UH.hDrawNineGridClipRegion != NULL) {
  1186. DeleteObject(_UH.hDrawNineGridClipRegion);
  1187. _UH.hdcDrawNineGridBitmap = NULL;
  1188. }
  1189. if (_UH.drawNineGridDecompressionBuffer != NULL) {
  1190. UT_Free( _pUt, _UH.drawNineGridDecompressionBuffer);
  1191. _UH.drawNineGridDecompressionBuffer = NULL;
  1192. _UH.drawNineGridDecompressionBufferSize = 0;
  1193. }
  1194. if (_UH.drawNineGridAssembleBuffer != NULL) {
  1195. UT_Free( _pUt, _UH.drawNineGridAssembleBuffer);
  1196. _UH.drawNineGridAssembleBuffer = NULL;
  1197. }
  1198. if (_UH.hModuleGDI32 != NULL) {
  1199. FreeLibrary(_UH.hModuleGDI32);
  1200. _UH.hModuleGDI32 = NULL;
  1201. }
  1202. if (_UH.hModuleMSIMG32 != NULL) {
  1203. FreeLibrary(_UH.hModuleMSIMG32);
  1204. _UH.hModuleMSIMG32 = NULL;
  1205. }
  1206. #endif
  1207. _pClientObjects->ReleaseObjReference(UH_OBJECT_FLAG);
  1208. DC_END_FN();
  1209. } /* UH_Term */
  1210. #ifdef DC_DEBUG
  1211. /****************************************************************************/
  1212. /* Name: UH_ChangeDebugSettings */
  1213. /* */
  1214. /* Purpose: Changes the current debug settings. */
  1215. /* */
  1216. /* Params: IN - flags: */
  1217. /* CO_CFG_FLAG_HATCH_BITMAP_PDU_DATA */
  1218. /* CO_CFG_FLAG_HATCH_SSB_ORDER_DATA */
  1219. /* CO_CFG_FLAG_HATCH_MEMBLT_ORDER_DATA */
  1220. /* CO_CFG_FLAG_LABEL_MEMBLT_ORDERS */
  1221. /* CO_CFG_FLAG_BITMAP_CACHE_MONITOR */
  1222. /****************************************************************************/
  1223. DCVOID DCAPI CUH::UH_ChangeDebugSettings(ULONG_PTR flags)
  1224. {
  1225. DC_BEGIN_FN("UH_ChangeDebugSettings");
  1226. TRC_NRM((TB, _T("flags %#x"), flags));
  1227. _UH.hatchBitmapPDUData =
  1228. TEST_FLAG(flags, CO_CFG_FLAG_HATCH_BITMAP_PDU_DATA) ? TRUE : FALSE;
  1229. _UH.hatchIndexPDUData =
  1230. TEST_FLAG(flags, CO_CFG_FLAG_HATCH_INDEX_PDU_DATA) ? TRUE : FALSE;
  1231. _UH.hatchSSBOrderData =
  1232. TEST_FLAG(flags, CO_CFG_FLAG_HATCH_SSB_ORDER_DATA) ? TRUE : FALSE;
  1233. _UH.hatchMemBltOrderData =
  1234. TEST_FLAG(flags, CO_CFG_FLAG_HATCH_MEMBLT_ORDER_DATA) ? TRUE : FALSE;
  1235. _UH.labelMemBltOrders =
  1236. TEST_FLAG(flags, CO_CFG_FLAG_LABEL_MEMBLT_ORDERS) ? TRUE : FALSE;
  1237. _UH.showBitmapCacheMonitor =
  1238. TEST_FLAG(flags, CO_CFG_FLAG_BITMAP_CACHE_MONITOR) ? TRUE : FALSE;
  1239. ShowWindow( _UH.hwndBitmapCacheMonitor,
  1240. _UH.showBitmapCacheMonitor ? SW_SHOWNOACTIVATE :
  1241. SW_HIDE );
  1242. DC_END_FN();
  1243. }
  1244. #endif /* DC_DEBUG */
  1245. /****************************************************************************/
  1246. // UH_SetConnectOptions
  1247. //
  1248. // Called on receive thread at session connect time. Takes some connection
  1249. // flags from CC and does connect-time init.
  1250. //
  1251. // Params: connectFlags - flags used to determine whether to enable
  1252. // the Shadow Bitmap and SaveScreenBitmap order support.
  1253. /****************************************************************************/
  1254. DCVOID DCAPI CUH::UH_SetConnectOptions(ULONG_PTR connectFlags)
  1255. {
  1256. DC_BEGIN_FN("UH_SetConnectOptions");
  1257. /************************************************************************/
  1258. /* Get the flags out. */
  1259. /************************************************************************/
  1260. _UH.shadowBitmapRequested = ((connectFlags &
  1261. CO_CONN_FLAG_SHADOW_BITMAP_ENABLED) ? TRUE : FALSE);
  1262. _UH.dedicatedTerminal = ((connectFlags & CO_CONN_FLAG_DEDICATED_TERMINAL) ?
  1263. TRUE : FALSE);
  1264. TRC_NRM((TB, _T("Flags from CC shadow(%u), terminal(%u)"),
  1265. _UH.shadowBitmapRequested, _UH.dedicatedTerminal));
  1266. /************************************************************************/
  1267. /* Set the capabilities to not support SSB and ScreenBlt orders by */
  1268. /* default. These are only supported if the shadow bitmap is enabled. */
  1269. /************************************************************************/
  1270. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1271. TS_NEG_SAVEBITMAP_INDEX] = 0;
  1272. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1273. TS_NEG_SCRBLT_INDEX] = 0;
  1274. // We have not yet sent the persistent bitmap cache keys in this session.
  1275. _UH.bPersistentBitmapKeysSent = FALSE;
  1276. // We have not yet set up the post-DemandActivePDU capabilities for bitmap
  1277. // caching, nor allocated the caches.
  1278. _UH.bEnabledOnce = FALSE;
  1279. DC_END_FN();
  1280. } /* UH_SetConnectOptions */
  1281. /****************************************************************************/
  1282. // UH_BufferAvailable
  1283. //
  1284. // When there is available buffer, we try to send the persistent keys
  1285. // and the font list
  1286. /****************************************************************************/
  1287. VOID DCAPI CUH::UH_BufferAvailable(VOID)
  1288. {
  1289. DC_BEGIN_FN("UH_BufferAvailable");
  1290. // UH_BufferAvailable is called when there is an available send
  1291. // buffer. If so, it tries to send persistent key list if any,
  1292. // and the font list
  1293. UH_SendPersistentKeysAndFontList();
  1294. DC_END_FN();
  1295. }
  1296. /****************************************************************************/
  1297. // UH_SendPersistentKeysAndFontList
  1298. //
  1299. // Send persistent key list followed by font list if they are ready to be
  1300. // send. If we don't have to send any persistent key list, we simply send
  1301. // font list directly.
  1302. /****************************************************************************/
  1303. void DCAPI CUH::UH_SendPersistentKeysAndFontList(void)
  1304. {
  1305. DC_BEGIN_FN("UH_BufferAvailable");
  1306. if (_UH.bEnabled) {
  1307. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1308. if (_UH.bPersistenceActive) {
  1309. if (_UH.bBitmapKeyEnumComplete) {
  1310. if (!_UH.bPersistentBitmapKeysSent)
  1311. {
  1312. if (_UH.currentCopyMultiplier == _UH.copyMultiplier)
  1313. {
  1314. //Great we've enumerated keys for the correct
  1315. //copy multiplier
  1316. UHSendPersistentBitmapKeyList(0);
  1317. }
  1318. else
  1319. {
  1320. //
  1321. // We got connected at a different copy multiplier
  1322. // need to enumerate keys again. Reset enumeration state
  1323. //
  1324. UHResetAndRestartEnumeration();
  1325. }
  1326. }
  1327. else
  1328. {
  1329. _pFs->FS_SendZeroFontList(0);
  1330. }
  1331. }
  1332. }
  1333. else {
  1334. #endif //((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1335. _pFs->FS_SendZeroFontList(0);
  1336. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1337. }
  1338. #endif //((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1339. }
  1340. DC_END_FN();
  1341. }
  1342. /****************************************************************************/
  1343. // UH_Enable
  1344. //
  1345. // Enables _UH. Called on receive thread after receipt of DemandActivePDU
  1346. // containing the server-side capabilities, but before client caps are
  1347. // returned with a ConfirmActivePDU.
  1348. //
  1349. // Params: IN unused - required by the component decoupler.
  1350. /****************************************************************************/
  1351. void DCAPI CUH::UH_Enable(ULONG_PTR unused)
  1352. {
  1353. HBRUSH hbr;
  1354. RECT rect;
  1355. DCSIZE desktopSize;
  1356. #ifdef DRAW_GDIPLUS
  1357. unsigned ProtocolColorDepth;
  1358. unsigned rc;
  1359. #endif
  1360. #ifdef DC_HICOLOR
  1361. int colorDepth;
  1362. UINT16 FAR *pIndexTable;
  1363. DWORD *pColorTable;
  1364. unsigned i;
  1365. #endif
  1366. DC_BEGIN_FN("UH_Enable");
  1367. DC_IGNORE_PARAMETER(unused);
  1368. if (NULL != _UH.hbmpDisconnectedBitmap) {
  1369. UHDeleteBitmap(&_UH.hdcDisconnected,
  1370. &_UH.hbmpDisconnectedBitmap,
  1371. &_UH.hbmpUnusedDisconnectedBitmap);
  1372. }
  1373. #ifdef DC_HICOLOR
  1374. // Set up the bitmap color format. Has to be first thing we do here!
  1375. colorDepth = _pUi->UI_GetColorDepth();
  1376. if ((colorDepth == 4) || (colorDepth == 8)) {
  1377. TRC_NRM((TB, _T("Low color - use PAL")));
  1378. _UH.DIBFormat = DIB_PAL_COLORS;
  1379. _UH.copyMultiplier = 1;
  1380. _UH.protocolBpp = 8;
  1381. _UH.bitmapBpp = 8;
  1382. _UH.bitmapInfo.hdr.biCompression = BMCRGB;
  1383. _UH.bitmapInfo.hdr.biBitCount = 8;
  1384. _UH.bitmapInfo.hdr.biClrUsed = 0;
  1385. // Update the color table cache - if we've previously connected at
  1386. // a high color depth, the bitcounts will be wrong.
  1387. if (_UH.pMappedColorTableCache) {
  1388. TRC_DBG((TB, _T("Update color table cache to 8bpp")));
  1389. for (i = 0; i < UH_COLOR_TABLE_CACHE_ENTRIES; i++) {
  1390. _UH.pMappedColorTableCache[i].hdr.biBitCount = 8;
  1391. _UH.pMappedColorTableCache[i].hdr.biCompression = BI_RGB;
  1392. _UH.pMappedColorTableCache[i].hdr.biClrUsed = 0;
  1393. pColorTable = (DWORD *)
  1394. _UH.pMappedColorTableCache[i].paletteIndexTable;
  1395. pColorTable[0] = 0;
  1396. pColorTable[1] = 0;
  1397. pColorTable[2] = 0;
  1398. // We default to identity palette flag set for 4 and 8 bits,
  1399. // this may be changed when the server sends a color table.
  1400. _UH.pMappedColorTableCache[i].bIdentityPalette = TRUE;
  1401. }
  1402. }
  1403. // Similarly, a high color connection may have overwritten some
  1404. // entries here too.
  1405. pIndexTable = _UH.bitmapInfo.paletteIndexTable;
  1406. for (i = 0; i < 256; i++)
  1407. *pIndexTable++ = (UINT16)i;
  1408. _UH.bitmapInfo.bIdentityPalette = TRUE;
  1409. }
  1410. else {
  1411. TRC_NRM((TB, _T("Hi color - use RGB")));
  1412. _UH.DIBFormat = DIB_RGB_COLORS;
  1413. _UH.protocolBpp = colorDepth;
  1414. // Since we don't use palettes for these color depths,
  1415. // set the BitmapPDU palette identity flag so UHDIBCopyBits() will
  1416. // always do a straight copy.
  1417. _UH.bitmapInfo.bIdentityPalette = TRUE;
  1418. if (colorDepth == 24) {
  1419. TRC_DBG((TB, _T("24bpp")));
  1420. _UH.bitmapInfo.hdr.biBitCount = 24;
  1421. _UH.bitmapBpp = 24;
  1422. _UH.copyMultiplier = 3;
  1423. _UH.bitmapInfo.hdr.biCompression = BI_RGB;
  1424. _UH.bitmapInfo.hdr.biClrUsed = 0;
  1425. // Update the color table cache - though we won't use the color
  1426. // tables as such, the bitmap info will be used.
  1427. if (_UH.pMappedColorTableCache) {
  1428. TRC_DBG((TB, _T("Update color table cache to 24bpp")));
  1429. for (i = 0; i < UH_COLOR_TABLE_CACHE_ENTRIES; i++)
  1430. {
  1431. _UH.pMappedColorTableCache[i].hdr.biBitCount = 24;
  1432. _UH.pMappedColorTableCache[i].hdr.biCompression = BI_RGB;
  1433. _UH.pMappedColorTableCache[i].hdr.biClrUsed = 0;
  1434. pColorTable = (DWORD *)
  1435. _UH.pMappedColorTableCache[i].paletteIndexTable;
  1436. pColorTable[0] = 0;
  1437. pColorTable[1] = 0;
  1438. pColorTable[2] = 0;
  1439. // Since we don't use palettes for this color depth,
  1440. // set the palettes to identity so UHDIBCopyBits() will
  1441. // always do a straight copy.
  1442. _UH.pMappedColorTableCache[i].bIdentityPalette = TRUE;
  1443. }
  1444. }
  1445. }
  1446. else if (colorDepth == 16) {
  1447. TRC_DBG((TB, _T("16bpp - 565")));
  1448. // 16 bpp uses two bytes, with the color masks defined in the
  1449. // bmiColors field. This is supposedly in the order R, G, B,
  1450. // but as ever we have to swap R & B...
  1451. // - LS 5 bits = blue = 0x001f
  1452. // - next 6 bits = green mask = 0x07e0
  1453. // - next 5 bits = red mask = 0xf800
  1454. _UH.bitmapInfo.hdr.biBitCount = 16;
  1455. _UH.bitmapBpp = 16;
  1456. _UH.copyMultiplier = 2;
  1457. _UH.bitmapInfo.hdr.biCompression = BI_BITFIELDS;
  1458. _UH.bitmapInfo.hdr.biClrUsed = 3;
  1459. pColorTable = (DWORD *)_UH.bitmapInfo.paletteIndexTable;
  1460. pColorTable[0] = TS_RED_MASK_16BPP;
  1461. pColorTable[1] = TS_GREEN_MASK_16BPP;
  1462. pColorTable[2] = TS_BLUE_MASK_16BPP;
  1463. // Update the color table cache - though we won't use the color
  1464. // tables as such, the bitmap info will be used.
  1465. if (_UH.pMappedColorTableCache) {
  1466. TRC_DBG((TB, _T("Update color table cache to 16bpp")));
  1467. for (i = 0; i < UH_COLOR_TABLE_CACHE_ENTRIES; i++) {
  1468. _UH.pMappedColorTableCache[i].hdr.biBitCount = 16;
  1469. _UH.pMappedColorTableCache[i].hdr.biCompression =
  1470. BI_BITFIELDS;
  1471. _UH.pMappedColorTableCache[i].hdr.biClrUsed = 3;
  1472. pColorTable = (DWORD *)
  1473. _UH.pMappedColorTableCache[i].paletteIndexTable;
  1474. pColorTable[0] = TS_RED_MASK_16BPP;
  1475. pColorTable[1] = TS_GREEN_MASK_16BPP;
  1476. pColorTable[2] = TS_BLUE_MASK_16BPP;
  1477. // Since we don't use palettes for this color depth,
  1478. // set the palettes to identity so UHDIBCopyBits() will
  1479. // always do a straight copy.
  1480. _UH.pMappedColorTableCache[i].bIdentityPalette = TRUE;
  1481. }
  1482. }
  1483. }
  1484. else if (colorDepth == 15) {
  1485. TRC_DBG((TB, _T("15bpp - 16bpp & 555")));
  1486. // 15 bpp uses two bytes with - least significant 5 bits = blue
  1487. // - next 5 bits = green - next 5 = red - most significant bit
  1488. // = Not used
  1489. // Note that we still have to claim to be 16 bpp to the bitmap
  1490. // functions...
  1491. _UH.bitmapInfo.hdr.biBitCount = 16;
  1492. _UH.bitmapBpp = 16;
  1493. _UH.copyMultiplier = 2;
  1494. _UH.bitmapInfo.hdr.biCompression = BI_RGB;
  1495. _UH.bitmapInfo.hdr.biClrUsed = 0;
  1496. // Update the color table cache - though we won't use the color
  1497. // tables as such, the bitmap info will be used.
  1498. if (_UH.pMappedColorTableCache)
  1499. {
  1500. TRC_DBG((TB, _T("Update color table cache to 15bpp")));
  1501. for (i = 0; i < UH_COLOR_TABLE_CACHE_ENTRIES; i++)
  1502. {
  1503. _UH.pMappedColorTableCache[i].hdr.biBitCount = 16;
  1504. _UH.pMappedColorTableCache[i].hdr.biCompression = BI_RGB;
  1505. _UH.pMappedColorTableCache[i].hdr.biClrUsed = 0;
  1506. pColorTable = (DWORD *)
  1507. _UH.pMappedColorTableCache[i].paletteIndexTable;
  1508. pColorTable[0] = 0;
  1509. pColorTable[1] = 0;
  1510. pColorTable[2] = 0;
  1511. // Since we don't use palettes for this color depth,
  1512. // set the palettes to identity so UHDIBCopyBits() will
  1513. // always do a straight copy.
  1514. _UH.pMappedColorTableCache[i].bIdentityPalette = TRUE;
  1515. }
  1516. }
  1517. }
  1518. else {
  1519. TRC_ABORT((TB, _T("Unsupported color depth")));
  1520. }
  1521. }
  1522. #endif //HICOLOR
  1523. // Check and see if we have already set up the caps and allocated the
  1524. // memory. If so, don't repeat the work since we are simply reconnecting
  1525. // instead of disconnecting.
  1526. if (!_UH.bEnabledOnce)
  1527. {
  1528. _UH.bEnabledOnce = TRUE;
  1529. TRC_ALT((TB, _T("Doing one-time enabling")));
  1530. // We are connected.
  1531. _UH.bConnected = TRUE;
  1532. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1533. _UH.DontUseShadowBitmap = FALSE;
  1534. #endif
  1535. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1536. // reset flags
  1537. _UH.sendBitmapCacheId = 0;
  1538. _UH.sendBitmapCacheIndex = 0;
  1539. _UH.sendNumBitmapKeys = 0;
  1540. _UH.totalNumKeyEntries = 0;
  1541. _UH.totalNumErrorPDUs = 0;
  1542. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1543. _UH.bWarningDisplayed = FALSE;
  1544. _UH.bPersistentBitmapKeysSent = FALSE;
  1545. // No matter what we have to make sure the capabilities are initialized
  1546. // to empty -- any leftover settings from the previous connection are
  1547. // invalid. Also make sure it's set to rev1 caps so that the server
  1548. // will disable bitmap caching if the bitmap caches cannot be
  1549. // allocated.
  1550. memset(&_pCc->_ccCombinedCapabilities.bitmapCacheCaps, 0,
  1551. sizeof(TS_BITMAPCACHE_CAPABILITYSET));
  1552. _pCc->_ccCombinedCapabilities.bitmapCacheCaps.lengthCapability =
  1553. sizeof(TS_BITMAPCACHE_CAPABILITYSET);
  1554. _pCc->_ccCombinedCapabilities.bitmapCacheCaps.capabilitySetType =
  1555. TS_CAPSETTYPE_BITMAPCACHE;
  1556. // Allocate the bitmap cache memory. This is done during connect time
  1557. // because we depend on the server capabilities already processed in
  1558. // UH_ProcessBCHostSupportCaps. It is also dependent on the color table
  1559. // cache having been allocated on app init.
  1560. if (_UH.pColorTableCache != NULL && _UH.pMappedColorTableCache != NULL) {
  1561. UHAllocBitmapCacheMemory();
  1562. _UH.fBmpCacheMemoryAlloced = TRUE;
  1563. }
  1564. else {
  1565. TRC_ERR((TB,_T("Color table cache did not alloc, not allocating bitmap ")
  1566. _T("cache memory and caps")));
  1567. }
  1568. #ifdef DRAW_GDIPLUS
  1569. // Allocate the drawgdiplus cache
  1570. if (UHAllocDrawGdiplusCacheMemory()) {
  1571. TRC_NRM((TB, _T("DrawGdiplus cache memory OK")));
  1572. }
  1573. else {
  1574. TRC_ALT((TB, _T("DrawGdiplus cache memory allocation failed!")));
  1575. }
  1576. #endif
  1577. #ifdef DC_DEBUG
  1578. // Reset the Bitmap Cache Monitor.
  1579. UHEnableBitmapCacheMonitor();
  1580. #endif /* DC_DEBUG */
  1581. #ifdef DC_HICOLOR
  1582. // Allocate the screen data decompression buffer, allowing enough
  1583. // space for 24bpp regardless of the actual depth, as we might find
  1584. // ourselves shadowing a 24bpp session without the opportunity to
  1585. // reallocate it. We don't check for success here since we can't
  1586. // return an init error. Instead, we check the pointer whenever we
  1587. // decode screen data.
  1588. _UH.bitmapDecompressionBufferSize = max(
  1589. UH_DECOMPRESSION_BUFFER_LENGTH,
  1590. (TS_BITMAPCACHE_0_CELL_SIZE << (2*(_UH.NumBitmapCaches))) * 3);
  1591. _UH.bitmapDecompressionBuffer = (PDCUINT8)UT_Malloc( _pUt, _UH.bitmapDecompressionBufferSize);
  1592. #else
  1593. // Allocate the screen data decompression buffer. We don't check for
  1594. // success here since we can't return an init error. Instead, we
  1595. // check the pointer whenever we decode screen data.
  1596. _UH.bitmapDecompressionBufferSize = max(
  1597. UH_DECOMPRESSION_BUFFER_LENGTH,
  1598. UH_CellSizeFromCacheID(_UH.NumBitmapCaches));
  1599. _UH.bitmapDecompressionBuffer = (PBYTE)UT_Malloc( _pUt, _UH.bitmapDecompressionBufferSize);
  1600. #endif //HICOLOR
  1601. if (NULL == _UH.bitmapDecompressionBuffer) {
  1602. _UH.bitmapDecompressionBufferSize = 0;
  1603. }
  1604. #ifdef OS_WINCE
  1605. if (_UH.bitmapDecompressionBuffer == NULL)
  1606. _pUi->UI_FatalError(DC_ERR_OUTOFMEMORY);
  1607. #endif
  1608. // Get a DC for the Output Window.
  1609. _UH.hdcOutputWindow = GetDC(_pOp->OP_GetOutputWindowHandle());
  1610. TRC_ASSERT(_UH.hdcOutputWindow, (TB,_T("_UH.hdcOutputWindow is NULL, GetDC failed")));
  1611. if (!_UH.hdcOutputWindow)
  1612. _pUi->UI_FatalError(DC_ERR_OUTOFMEMORY);
  1613. // Reset maxColorTableId. We only expect to reset our color cache
  1614. // once in a session.
  1615. _UH.maxColorTableId = -1;
  1616. }
  1617. #ifdef DC_HICOLOR
  1618. else if (_UH.BitmapCacheVersion > TS_BITMAPCACHE_REV1) {
  1619. //
  1620. // If the new color depth doesn't match the one we enumerated
  1621. // keys for the block persitent caching
  1622. //
  1623. if (_UH.currentCopyMultiplier != _UH.copyMultiplier)
  1624. {
  1625. TS_BITMAPCACHE_CAPABILITYSET_REV2 *pRev2Caps;
  1626. pRev2Caps = (TS_BITMAPCACHE_CAPABILITYSET_REV2 *)
  1627. &_pCc->_ccCombinedCapabilities.bitmapCacheCaps;
  1628. for (i = 0; i < _UH.NumBitmapCaches; i++) {
  1629. CALC_NUM_CACHE_ENTRIES(_UH.bitmapCache[i].BCInfo.NumEntries,
  1630. _UH.bitmapCache[i].BCInfo.OrigNumEntries,
  1631. _UH.bitmapCache[i].BCInfo.MemLen - UH_CellSizeFromCacheID(i), i);
  1632. TRC_ALT((TB, _T("Cache %d has %d entries"), i,
  1633. _UH.bitmapCache[i].BCInfo.NumEntries));
  1634. pRev2Caps->CellCacheInfo[i].NumEntries =
  1635. _UH.bitmapCache[i].BCInfo.NumEntries;
  1636. // If we've got persistent caching on, we'd better clear all
  1637. // the cache entries to disk.
  1638. if (_UH.bitmapCache[i].BCInfo.NumVirtualEntries) {
  1639. pRev2Caps->CellCacheInfo[i].NumEntries =
  1640. _UH.bitmapCache[i].BCInfo.NumVirtualEntries;
  1641. UHInitBitmapCachePageTable(i);
  1642. }
  1643. }
  1644. TRC_NRM((TB,_T("Blocking persiten cache (different col depth)")));
  1645. _UH.bPersistenceDisable = TRUE;
  1646. }
  1647. }
  1648. #endif
  1649. /************************************************************************/
  1650. // Following items must be done on each reception of DemandActivePDU.
  1651. /************************************************************************/
  1652. _pUi->UI_GetDesktopSize(&desktopSize);
  1653. // Possibly create the Shadow and Save Screen bitmaps and update the
  1654. // capabilities in CC accordingly.
  1655. UHMaybeCreateShadowBitmap();
  1656. if (_UH.shadowBitmapEnabled ||
  1657. (_UH.dedicatedTerminal &&
  1658. (desktopSize.width <= (unsigned)GetSystemMetrics(SM_CXSCREEN)) &&
  1659. (desktopSize.height <= (unsigned)GetSystemMetrics(SM_CYSCREEN))))
  1660. {
  1661. TRC_NRM((TB, _T("OK to use ScreenBlt orders")));
  1662. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1663. TS_NEG_SCRBLT_INDEX] = 1;
  1664. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1665. TS_NEG_MULTISCRBLT_INDEX] = 1;
  1666. }
  1667. else {
  1668. TRC_NRM((TB, _T("Cannot use ScreenBlt orders")));
  1669. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1670. TS_NEG_SCRBLT_INDEX] = 0;
  1671. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1672. TS_NEG_MULTISCRBLT_INDEX] = 0;
  1673. }
  1674. UHMaybeCreateSaveScreenBitmap();
  1675. if (_UH.hSaveScreenBitmap != NULL) {
  1676. TRC_NRM((TB, _T("Support SaveScreenBits orders")));
  1677. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1678. TS_NEG_SAVEBITMAP_INDEX] = 1;
  1679. }
  1680. else {
  1681. TRC_NRM((TB, _T("Cannot support SaveScreenBits orders")));
  1682. _pCc->_ccCombinedCapabilities.orderCapabilitySet.orderSupport[
  1683. TS_NEG_SAVEBITMAP_INDEX] = 0;
  1684. }
  1685. // Set the value of _UH.hdcDraw according to the value of
  1686. // _UH.shadowBitmapEnabled.
  1687. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1688. _UH.hdcDraw = !_UH.DontUseShadowBitmap ? _UH.hdcShadowBitmap :
  1689. _UH.hdcOutputWindow;
  1690. #else
  1691. _UH.hdcDraw = _UH.shadowBitmapEnabled ? _UH.hdcShadowBitmap :
  1692. _UH.hdcOutputWindow;
  1693. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  1694. #if defined (OS_WINCE)
  1695. _UH.validClipDC = NULL;
  1696. _UH.validBkColorDC = NULL;
  1697. _UH.validBkModeDC = NULL;
  1698. _UH.validROPDC = NULL;
  1699. _UH.validTextColorDC = NULL;
  1700. _UH.validPenDC = NULL;
  1701. _UH.validBrushDC = NULL;
  1702. #endif
  1703. UHResetDCState();
  1704. #ifdef OS_WINCE
  1705. if (g_CEConfig != CE_CONFIG_WBT)
  1706. UHGetPaletteCaps();
  1707. #endif
  1708. TRC_DBG((TB, _T("_UH.shadowBitmapEnabled(%u) _UH.hShadowBitmap(%#hx)"),
  1709. _UH.shadowBitmapEnabled, _UH.hShadowBitmap));
  1710. TRC_DBG((TB, _T("_UH.hSaveScreenBitmap(%#hx)"), _UH.hSaveScreenBitmap));
  1711. TRC_DBG((TB, _T("_UH.hdcDraw(%#hx) _UH.hdcShadowBitmap(%#hx)"),
  1712. _UH.hdcDraw, _UH.hdcShadowBitmap));
  1713. if (_UH.shadowBitmapEnabled) {
  1714. // Fill Shadow Bitmap with black.
  1715. TRC_NRM((TB, _T("Fill with black")));
  1716. #ifndef OS_WINCE
  1717. hbr = CreateSolidBrush(RGB(0,0,0));
  1718. #else
  1719. hbr = CECreateSolidBrush(RGB(0,0,0));
  1720. #endif
  1721. TRC_ASSERT(hbr, (TB,_T("CreateSolidBrush failed")));
  1722. if(hbr)
  1723. {
  1724. rect.left = 0;
  1725. rect.top = 0;
  1726. rect.right = desktopSize.width;
  1727. rect.bottom = desktopSize.height;
  1728. UH_ResetClipRegion();
  1729. FillRect( _UH.hdcShadowBitmap,
  1730. &rect,
  1731. hbr );
  1732. #ifndef OS_WINCE
  1733. DeleteBrush(hbr);
  1734. #else
  1735. CEDeleteBrush(hbr);
  1736. #endif
  1737. }
  1738. }
  1739. // Tell OP and OD that the share is coming up.
  1740. _pOp->OP_Enable();
  1741. _pOd->OD_Enable();
  1742. #ifdef DRAW_GDIPLUS
  1743. if (_UH.pfnGdipPlayTSClientRecord) {
  1744. if (!_UH.fGdipEnabled) {
  1745. rc = _UH.pfnGdipPlayTSClientRecord(_UH.hdcShadowBitmap, DrawTSClientEnable, NULL, 0, NULL);
  1746. _UH.fGdipEnabled = TRUE;
  1747. if (rc != 0) {
  1748. TRC_ERR((TB, _T("Call to GdipPlay:DrawTSClientEnable failed")));
  1749. }
  1750. }
  1751. ProtocolColorDepth = _UH.protocolBpp;
  1752. if (_UH.pfnGdipPlayTSClientRecord(_UH.hdcShadowBitmap, DrawTSClientDisplayChange,
  1753. (BYTE *)&ProtocolColorDepth, sizeof(unsigned int), NULL))
  1754. {
  1755. TRC_ERR((TB, _T("GdipPlay:DrawTSClientDisplayChange failed")));
  1756. }
  1757. }
  1758. #endif
  1759. // We are enabled now.
  1760. _UH.bEnabled = TRUE;
  1761. DC_END_FN();
  1762. }
  1763. /****************************************************************************/
  1764. // UHCommonDisable
  1765. //
  1766. // Encapsulates common disable/disconnect code.
  1767. /****************************************************************************/
  1768. void DCINTERNAL CUH::UHCommonDisable(BOOL fDisplayDisabledBitmap)
  1769. {
  1770. BOOL fUseDisabledBitmap = FALSE;
  1771. DC_BEGIN_FN("UHCommonDisable");
  1772. if (_UH.bEnabled) {
  1773. _UH.bEnabled = FALSE;
  1774. }
  1775. // Tell OP and OD that the share is going down.
  1776. //
  1777. // Pass flag to OP telling it if we are now disconnected
  1778. // this starts all the window dimming stuff
  1779. //
  1780. _pOp->OP_Disable(!_UH.bConnected);
  1781. _pOd->OD_Disable();
  1782. DC_END_FN();
  1783. }
  1784. /****************************************************************************/
  1785. // UH_Disable
  1786. //
  1787. // Disables _UH. Called at reception of DisableAllPDU from server. This
  1788. // function should not be used to do cleanup for the session (see
  1789. // UH_Disconnect), as the server may continue the session on server-side
  1790. // reconnect by starting a new share starting with a new DemandActivePDU.
  1791. //
  1792. // Params: IN unused - required by the component decoupler.
  1793. /****************************************************************************/
  1794. void DCAPI CUH::UH_Disable(ULONG_PTR unused)
  1795. {
  1796. DC_BEGIN_FN("UH_Disable");
  1797. DC_IGNORE_PARAMETER(unused);
  1798. TRC_NRM((TB, _T("Disabling UH")));
  1799. // We don't have anything to do here for bitmap caching. Whether we
  1800. // are communicating with a rev1 or rev2 bitmap caching server, we
  1801. // don't need to repeat work and allocations here. For rev2 servers
  1802. // we cannot change the cache contents on DisableAllPDU since we
  1803. // may actually be reconnecting and the server will assume state was
  1804. // maintained.
  1805. // Do work that needs doing on both UH_Disable() and UH_Disconnect().
  1806. UHCommonDisable(TRUE);
  1807. DC_END_FN();
  1808. }
  1809. /****************************************************************************/
  1810. // UH_Disconnect
  1811. //
  1812. // Disconnects _UH. Called at session end to indicate session cleanup should
  1813. // occur.
  1814. //
  1815. // Params: IN unused - required by the component decoupler.
  1816. /****************************************************************************/
  1817. void DCAPI CUH::UH_Disconnect(ULONG_PTR unused)
  1818. {
  1819. UINT cacheId;
  1820. UINT32 cacheIndex;
  1821. DC_BEGIN_FN("UH_Disconnect");
  1822. DC_IGNORE_PARAMETER(unused);
  1823. TRC_NRM((TB, _T("Disconnecting UH")));
  1824. // We can be called here multiple times. Don't do a lot of extra work.
  1825. if (_UH.bConnected) {
  1826. UHCreateDisconnectedBitmap();
  1827. _UH.bConnected = FALSE;
  1828. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1829. if (_UH.bPersistenceActive) {
  1830. if (!_UH.bWarningDisplayed) {
  1831. UINT32 Key1, Key2;
  1832. for (cacheId = 0; cacheId < _UH.NumBitmapCaches; cacheId++) {
  1833. _UH.numKeyEntries[cacheId] = 0;
  1834. if (_UH.pBitmapKeyDB[cacheId] != NULL) {
  1835. for (cacheIndex = 0; cacheIndex < _UH.bitmapCache[cacheId].
  1836. BCInfo.NumVirtualEntries; cacheIndex++) {
  1837. Key1 = _UH.bitmapCache[cacheId].PageTable.PageEntries[
  1838. cacheIndex].bmpInfo.Key1;
  1839. Key2 = _UH.bitmapCache[cacheId].PageTable.PageEntries[
  1840. cacheIndex].bmpInfo.Key2;
  1841. if (Key1 != 0 && Key2 != 0) {
  1842. // need to reset the bitmap key database to what's in
  1843. // the bitmap cache page table
  1844. _UH.pBitmapKeyDB[cacheId][_UH.numKeyEntries[cacheId]] =
  1845. _UH.bitmapCache[cacheId].PageTable.PageEntries[
  1846. cacheIndex].bmpInfo;
  1847. _UH.numKeyEntries[cacheId]++;
  1848. }
  1849. else {
  1850. break;
  1851. }
  1852. }
  1853. }
  1854. }
  1855. }
  1856. else {
  1857. // we had a persistent caching failure, so we should disable
  1858. // persistent caching for next reconnect
  1859. for (cacheId = 0; cacheId < _UH.NumBitmapCaches; cacheId++) {
  1860. _UH.numKeyEntries[cacheId] = 0;
  1861. UH_ClearOneBitmapDiskCache(cacheId, _UH.copyMultiplier);
  1862. }
  1863. _pUi->UI_SetBitmapPersistence(FALSE);
  1864. }
  1865. _UH.bBitmapKeyEnumComplete = TRUE;
  1866. _UH.bBitmapKeyEnumerating = FALSE;
  1867. }
  1868. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1869. //
  1870. // Reset bitmap cache alloced flag
  1871. //
  1872. _UH.fBmpCacheMemoryAlloced = FALSE;
  1873. // Free bitmap cache info in use.
  1874. for (cacheId = 0; cacheId < _UH.NumBitmapCaches; cacheId++) {
  1875. if (_UH.bitmapCache[cacheId].Header != NULL) {
  1876. UT_Free( _pUt, _UH.bitmapCache[cacheId].Header);
  1877. _UH.bitmapCache[cacheId].Header = NULL;
  1878. }
  1879. if (_UH.bitmapCache[cacheId].Entries != NULL) {
  1880. UT_Free( _pUt, _UH.bitmapCache[cacheId].Entries);
  1881. _UH.bitmapCache[cacheId].Entries = NULL;
  1882. }
  1883. #if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1884. // reset the last time bitmap error pdu sent for all caches
  1885. _UH.lastTimeErrorPDU[cacheId] = 0;
  1886. // Free bitmap page table
  1887. if (_UH.bitmapCache[cacheId].PageTable.PageEntries != NULL) {
  1888. UT_Free( _pUt, _UH.bitmapCache[cacheId].PageTable.PageEntries);
  1889. _UH.bitmapCache[cacheId].PageTable.PageEntries = NULL;
  1890. _UH.bitmapCache[cacheId].BCInfo.NumVirtualEntries = 0;
  1891. }
  1892. // close the file handle for the cache files
  1893. if (INVALID_HANDLE_VALUE !=
  1894. _UH.bitmapCache[cacheId].PageTable.CacheFileInfo.hCacheFile)
  1895. {
  1896. CloseHandle(_UH.bitmapCache[cacheId].PageTable.CacheFileInfo.hCacheFile);
  1897. _UH.bitmapCache[cacheId].PageTable.CacheFileInfo.hCacheFile = INVALID_HANDLE_VALUE;
  1898. #ifdef VM_BMPCACHE
  1899. if (_UH.bitmapCache[cacheId].PageTable.CacheFileInfo.pMappedView)
  1900. {
  1901. if (!UnmapViewOfFile(
  1902. _UH.bitmapCache[cacheId].PageTable.CacheFileInfo.pMappedView))
  1903. {
  1904. TRC_ERR((TB,_T("UnmapViewOfFile failed 0x%d"),
  1905. GetLastError()));
  1906. }
  1907. }
  1908. #endif
  1909. }
  1910. #endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
  1911. }
  1912. _UH.NumBitmapCaches = 0;
  1913. // free the decompression buffer
  1914. if (_UH.bitmapDecompressionBuffer != NULL) {
  1915. UT_Free( _pUt, _UH.bitmapDecompressionBuffer);
  1916. _UH.bitmapDecompressionBuffer = NULL;
  1917. _UH.bitmapDecompressionBufferSize = 0;
  1918. }
  1919. // Delete all the offscreen bitmaps
  1920. if (NULL != _UH.hdcOffscreenBitmap) {
  1921. unsigned i;
  1922. for (i = 0; i < _UH.offscrCacheEntries; i++) {
  1923. if (_UH.offscrBitmapCache[i].offscrBitmap) {
  1924. SelectBitmap(_UH.hdcOffscreenBitmap,
  1925. _UH.hUnusedOffscrBitmap);
  1926. DeleteBitmap(_UH.offscrBitmapCache[i].offscrBitmap);
  1927. _UH.offscrBitmapCache[i].offscrBitmap = 0;
  1928. _UH.offscrBitmapCache[i].cx = 0;
  1929. _UH.offscrBitmapCache[i].cy = 0;
  1930. }
  1931. }
  1932. }
  1933. #ifdef DRAW_NINEGRID
  1934. // Delete all the drawStream bitmaps
  1935. if (NULL != _UH.hdcDrawNineGridBitmap) {
  1936. unsigned i;
  1937. for (i = 0; i < _UH.drawNineGridCacheEntries; i++) {
  1938. if (_UH.drawNineGridBitmapCache[i].drawNineGridBitmap) {
  1939. SelectBitmap(_UH.hdcDrawNineGridBitmap,
  1940. _UH.hUnusedDrawNineGridBitmap);
  1941. DeleteBitmap(_UH.drawNineGridBitmapCache[i].drawNineGridBitmap);
  1942. _UH.drawNineGridBitmapCache[i].drawNineGridBitmap = 0;
  1943. _UH.drawNineGridBitmapCache[i].cx = 0;
  1944. _UH.drawNineGridBitmapCache[i].cy = 0;
  1945. }
  1946. }
  1947. }
  1948. #endif
  1949. #ifdef DC_DEBUG
  1950. // Force a redraw of the bitmap cache monitor, since it cannot any
  1951. // longer display contents from the entries array freed above.
  1952. UHDisconnectBitmapCacheMonitor();
  1953. #endif
  1954. /********************************************************************/
  1955. // We need to free up any resources we might have set up in the draw
  1956. // DC, along with the bitmap used for pattern brushes.
  1957. // We do this by selecting in stock objects - which we don't need to
  1958. // free - and deleting the old object (if any)
  1959. /********************************************************************/
  1960. if (NULL != _UH.hdcDraw) {
  1961. HPEN hPenNew;
  1962. HPEN hPenOld;
  1963. HBRUSH hBrushNew;
  1964. HBRUSH hBrushOld;
  1965. HFONT hFontNew;
  1966. HFONT hFontOld;
  1967. TRC_NRM((TB, _T("tidying DC resources")));
  1968. // First the pen.
  1969. hPenNew = (HPEN)GetStockObject(NULL_PEN);
  1970. hPenOld = SelectPen(_UH.hdcDraw, hPenNew);
  1971. if (NULL != hPenOld) {
  1972. TRC_NRM((TB, _T("Delete old pen")));
  1973. DeleteObject(hPenOld);
  1974. }
  1975. // Now the brush.
  1976. hBrushNew = (HBRUSH)GetStockObject(NULL_BRUSH);
  1977. hBrushOld = SelectBrush(_UH.hdcDraw, hBrushNew);
  1978. if (NULL != hBrushOld) {
  1979. TRC_NRM((TB, _T("Delete old brush")));
  1980. DeleteObject(hBrushOld);
  1981. }
  1982. // Now the font.
  1983. hFontNew = (HFONT)GetStockObject(SYSTEM_FONT);
  1984. hFontOld = SelectFont(_UH.hdcDraw, hFontNew);
  1985. if (NULL != hFontOld) {
  1986. TRC_NRM((TB, _T("Delete old Font")));
  1987. DeleteObject(hFontOld);
  1988. }
  1989. #ifdef OS_WINCE
  1990. //Now the palette.
  1991. //On WinCE when the device is capable of only 8bpp, when you
  1992. //disconnect from a session and return to the main dialog, the
  1993. //palette isnt reset, and the rest of CE screen looks ugly.
  1994. if (NULL != _UH.hpalDefault) {
  1995. SelectPalette(_UH.hdcDraw, _UH.hpalDefault, FALSE );
  1996. RealizePalette(_UH.hdcDraw);
  1997. }
  1998. if ((_UH.hpalCurrent != NULL) && (_UH.hpalCurrent != _UH.hpalDefault))
  1999. {
  2000. TRC_NRM((TB, _T("Delete current palette %p"), _UH.hpalCurrent));
  2001. DeletePalette(_UH.hpalCurrent);
  2002. }
  2003. _UH.hpalCurrent = _UH.hpalDefault;
  2004. #endif
  2005. // Make sure this DC is nulled out to avoid problems if we're
  2006. // called again. This is just a copy of _UH.hdcOutputWindow, which
  2007. // is NULLed below.
  2008. _UH.hdcDraw = NULL;
  2009. }
  2010. /********************************************************************/
  2011. // If we're not using a shadow bitmap, we should release the DC we
  2012. // have to the output window - remembering that it is possible that
  2013. // we didn't successfully connect, in which case UH_OnConnected won't
  2014. // have been called and so we won't have acquired a DC to need
  2015. // releasing!
  2016. /********************************************************************/
  2017. if (NULL != _UH.hdcOutputWindow)
  2018. {
  2019. TRC_NRM((TB, _T("Releasing Output Window HDC")));
  2020. ReleaseDC(_pOp->OP_GetOutputWindowHandle(), _UH.hdcOutputWindow);
  2021. _UH.hdcOutputWindow = NULL;
  2022. }
  2023. }
  2024. // Do work that needs doing on both UH_Disable() and UH_Disconnect().
  2025. UHCommonDisable(TRUE);
  2026. DC_END_FN();
  2027. }
  2028. #ifdef DC_DEBUG
  2029. /****************************************************************************/
  2030. /* Name: UH_HatchRect */
  2031. /* */
  2032. /* Purpose: Draws a hatched rectangle in _UH.hdcOutputWindow in the given */
  2033. /* color. */
  2034. /* */
  2035. /* Params: left - left coord of rect */
  2036. /* top - top coord of rect */
  2037. /* right - right coord of rect */
  2038. /* bottom - bottom coord of rect */
  2039. /* color - color of hatching to draw */
  2040. /* hatchStyle - style of hatching to draw */
  2041. /****************************************************************************/
  2042. DCVOID DCAPI CUH::UH_HatchOutputRect(DCINT left, DCINT top, DCINT right,
  2043. DCINT bottom, COLORREF color, DCUINT hatchStyle)
  2044. {
  2045. DC_BEGIN_FN("UHHatchOutputRect");
  2046. UH_HatchRectDC(_UH.hdcOutputWindow, left, top, right, bottom, color,
  2047. hatchStyle);
  2048. DC_END_FN();
  2049. }
  2050. /****************************************************************************/
  2051. /* Name: UH_HatchRect */
  2052. /* */
  2053. /* Purpose: Draws a hatched rectangle in _UH.hdcDraw in the given color. */
  2054. /* */
  2055. /* Params: left - left coord of rect */
  2056. /* top - top coord of rect */
  2057. /* right - right coord of rect */
  2058. /* bottom - bottom coord of rect */
  2059. /* color - color of hatching to draw */
  2060. /* hatchStyle - style of hatching to draw */
  2061. /****************************************************************************/
  2062. DCVOID DCAPI CUH::UH_HatchRect( DCINT left,
  2063. DCINT top,
  2064. DCINT right,
  2065. DCINT bottom,
  2066. COLORREF color,
  2067. DCUINT hatchStyle )
  2068. {
  2069. DC_BEGIN_FN("UHHatchRect");
  2070. UH_HatchRectDC(_UH.hdcDraw, left, top, right, bottom, color,
  2071. hatchStyle);
  2072. DC_END_FN();
  2073. }
  2074. /****************************************************************************/
  2075. /* Name: UH_HatchRectDC */
  2076. /* */
  2077. /* Purpose: Draws a hatched rectangle in the hDC in the given color. */
  2078. /* */
  2079. /* Params: left - left coord of rect */
  2080. /* top - top coord of rect */
  2081. /* right - right coord of rect */
  2082. /* bottom - bottom coord of rect */
  2083. /* color - color of hatching to draw */
  2084. /* hatchStyle - style of hatching to draw */
  2085. /****************************************************************************/
  2086. DCVOID DCAPI CUH::UH_HatchRectDC(HDC hdc, DCINT left, DCINT top, DCINT right,
  2087. DCINT bottom, COLORREF color, DCUINT hatchStyle)
  2088. {
  2089. HBRUSH hbrHatch;
  2090. DCUINT oldBkMode;
  2091. DCUINT oldRop2;
  2092. DCUINT winHatchStyle = 0;
  2093. POINT oldOrigin;
  2094. RECT rect;
  2095. HRGN hrgn;
  2096. HBRUSH hbrOld;
  2097. HPEN hpen;
  2098. HPEN hpenOld;
  2099. DC_BEGIN_FN("UHHatchRectDC");
  2100. switch (hatchStyle)
  2101. {
  2102. case UH_BRUSHTYPE_FDIAGONAL:
  2103. {
  2104. winHatchStyle = HS_FDIAGONAL;
  2105. }
  2106. break;
  2107. case UH_BRUSHTYPE_DIAGCROSS:
  2108. {
  2109. winHatchStyle = HS_DIAGCROSS;
  2110. }
  2111. break;
  2112. case UH_BRUSHTYPE_HORIZONTAL:
  2113. {
  2114. winHatchStyle = HS_HORIZONTAL;
  2115. }
  2116. break;
  2117. case UH_BRUSHTYPE_VERTICAL:
  2118. {
  2119. winHatchStyle = HS_VERTICAL;
  2120. }
  2121. break;
  2122. default:
  2123. {
  2124. TRC_ABORT((TB, _T("Unspecified hatch type request, %u"), hatchStyle));
  2125. }
  2126. break;
  2127. }
  2128. hbrHatch = CreateHatchBrush(winHatchStyle, color);
  2129. oldBkMode = SetBkMode(hdc, TRANSPARENT);
  2130. oldRop2 = SetROP2(hdc, R2_COPYPEN);
  2131. SetBrushOrgEx(hdc, 0, 0, &oldOrigin);
  2132. rect.left = left;
  2133. rect.top = top;
  2134. rect.right = right;
  2135. rect.bottom = bottom;
  2136. /************************************************************************/
  2137. /* Fill the rectangle with the hatched brush. */
  2138. /************************************************************************/
  2139. hrgn = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
  2140. #ifndef OS_WINCE
  2141. /************************************************************************/
  2142. /* Just draw bounding rectangle on WinCE */
  2143. /************************************************************************/
  2144. FillRgn( hdc,
  2145. hrgn,
  2146. hbrHatch );
  2147. #endif
  2148. DeleteRgn(hrgn);
  2149. DeleteBrush(hbrHatch);
  2150. hbrOld = SelectBrush(hdc, GetStockObject(HOLLOW_BRUSH));
  2151. hpen = CreatePen(PS_SOLID, 1, color);
  2152. hpenOld = SelectPen(hdc, hpen);
  2153. /************************************************************************/
  2154. /* Draw a border around the hatched rectangle. */
  2155. /************************************************************************/
  2156. Rectangle( hdc,
  2157. rect.left,
  2158. rect.top,
  2159. rect.right,
  2160. rect.bottom );
  2161. SelectBrush(hdc, hbrOld);
  2162. SelectPen(hdc, hpenOld);
  2163. DeletePen(hpen);
  2164. /************************************************************************/
  2165. /* Reset the original DC state. */
  2166. /************************************************************************/
  2167. SetBrushOrgEx(hdc, oldOrigin.x, oldOrigin.y, NULL);
  2168. SetROP2(hdc, oldRop2);
  2169. SetBkMode(hdc, oldBkMode);
  2170. DC_END_FN();
  2171. }
  2172. #endif
  2173. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  2174. void DCAPI CUH::UH_SetBBarRect(ULONG_PTR pData)
  2175. {
  2176. RECT *prect = (RECT *)pData;
  2177. _UH.rectBBar.left = prect->left;
  2178. _UH.rectBBar.top = prect->top;
  2179. _UH.rectBBar.right = prect->right;
  2180. _UH.rectBBar.bottom = prect->bottom;
  2181. }
  2182. void DCAPI CUH::UH_SetBBarVisible(ULONG_PTR pData)
  2183. {
  2184. if (0 == (int)pData)
  2185. _UH.fIsBBarVisible = FALSE;
  2186. else
  2187. _UH.fIsBBarVisible = TRUE;
  2188. }
  2189. // Disable use of shadow in full-screen
  2190. void DCAPI CUH::UH_DisableShadowBitmap(ULONG_PTR)
  2191. {
  2192. DC_BEGIN_FN("UH_DisableShadowBitmap");
  2193. _UH.hdcDraw = _UH.hdcOutputWindow;
  2194. _UH.DontUseShadowBitmap = TRUE;
  2195. UHResetDCState();
  2196. DC_END_FN();
  2197. }
  2198. // Enable use of shadow when leaving full-screen
  2199. void DCAPI CUH::UH_EnableShadowBitmap(ULONG_PTR)
  2200. {
  2201. DC_BEGIN_FN("UH_EnableShadowBitmap");
  2202. DCSIZE desktopSize;
  2203. RECT rect;
  2204. if (_UH.DontUseShadowBitmap)
  2205. {
  2206. _pUi->UI_GetDesktopSize(&desktopSize);
  2207. _UH.hdcDraw = _UH.hdcShadowBitmap;
  2208. _UH.DontUseShadowBitmap = FALSE;
  2209. rect.left = 0;
  2210. rect.top = 0;
  2211. rect.right = desktopSize.width;
  2212. rect.bottom = desktopSize.height;
  2213. // Since we have no copy of screen, ask the server to resend
  2214. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  2215. _pOr,
  2216. CD_NOTIFICATION_FUNC(COR,OR_RequestUpdate),
  2217. &rect,
  2218. sizeof(RECT));
  2219. UHResetDCState();
  2220. }
  2221. DC_END_FN();
  2222. return;
  2223. }
  2224. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  2225. #ifdef DRAW_GDIPLUS
  2226. // Ininitalize the gdiplus
  2227. BOOL DCAPI CUH::UHDrawGdiplusStartup(ULONG_PTR unused)
  2228. {
  2229. Gdiplus::GdiplusStartupInput sti;
  2230. unsigned GdipVersion;
  2231. unsigned rc = FALSE;
  2232. DC_BEGIN_FN("UHDrawGdiplusStartup");
  2233. if (_UH.pfnGdiplusStartup(&_UH.gpToken, &sti, NULL) == Gdiplus::Ok) {
  2234. _UH.gpValid = TRUE;
  2235. GdipVersion = _UH.pfnGdipPlayTSClientRecord(NULL, DrawTSClientQueryVersion, NULL, 0, NULL);
  2236. _pCc->_ccCombinedCapabilities.drawGdiplusCapabilitySet.GdipVersion = GdipVersion;
  2237. rc = TRUE;
  2238. }
  2239. else {
  2240. TRC_ERR((TB, _T("Call to GdiplusStartup failed")));
  2241. }
  2242. DC_END_FN();
  2243. return rc;
  2244. }
  2245. // Shutdown the gdiplus
  2246. void DCAPI CUH::UHDrawGdiplusShutdown(ULONG_PTR unused)
  2247. {
  2248. DC_BEGIN_FN("UHDrawGdiplusShutDown");
  2249. if (_UH.pfnGdipPlayTSClientRecord) {
  2250. _UH.pfnGdipPlayTSClientRecord(NULL, DrawTSClientDisable, NULL, 0, NULL);
  2251. }
  2252. if (_UH.gpValid) {
  2253. _UH.pfnGdiplusShutdown(_UH.gpToken);
  2254. }
  2255. if (_UH.hModuleGDIPlus != NULL) {
  2256. FreeLibrary(_UH.hModuleGDIPlus);
  2257. _UH.pfnGdipPlayTSClientRecord = NULL;
  2258. _UH.hModuleGDIPlus = NULL;
  2259. }
  2260. DC_END_FN();
  2261. }
  2262. #endif // DRAW_GDIPLUS