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.

471 lines
12 KiB

  1. #include "precomp.h"
  2. //
  3. // OE.CPP
  4. // Order Encoding
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_ORDER
  9. //
  10. // OE_PartyLeftShare()
  11. //
  12. void ASShare::OE_PartyLeftShare(ASPerson * pasPerson)
  13. {
  14. DebugEntry(ASShare::OE_PartyLeftShare);
  15. ValidatePerson(pasPerson);
  16. //
  17. // Free any font info for this person.
  18. //
  19. if (pasPerson->poeFontInfo)
  20. {
  21. TRACE_OUT(("FREED FONT DATA"));
  22. delete[] pasPerson->poeFontInfo;
  23. pasPerson->poeFontInfo = NULL;
  24. pasPerson->oecFonts = 0;
  25. }
  26. DebugExitVOID(ASShare::OE_PartyLeftShare);
  27. }
  28. //
  29. // OE_RecalcCaps()
  30. //
  31. // Recalculates orders and fonts when somebody joins or leaves the share.
  32. // Unlike the other components, this happens even when we ourselves are not
  33. // hosting, we need this info to interpret data from remote hosts.
  34. //
  35. void ASShare::OE_RecalcCaps(BOOL fJoiner)
  36. {
  37. UINT iOrder;
  38. ASPerson * pasT;
  39. DebugEntry(ASShare::OE_RecalcCaps);
  40. ValidatePerson(m_pasLocal);
  41. //
  42. // Set the initial support to the local support.
  43. //
  44. memcpy(m_aoeOrderSupported, m_pasLocal->cpcCaps.orders.capsOrders,
  45. sizeof(m_pasLocal->cpcCaps.orders.capsOrders));
  46. //
  47. // m_aoeOrderSupported contains more entries than the CAPS_MAX_NUM_ORDERS
  48. // entries in the g_cpcLocalCaps.orders entry. Set the additional values
  49. // to FALSE.
  50. //
  51. for (iOrder = CAPS_MAX_NUM_ORDERS;
  52. iOrder < ORD_NUM_INTERNAL_ORDERS; iOrder++)
  53. {
  54. m_aoeOrderSupported[iOrder] = FALSE;
  55. }
  56. //
  57. // The combined support for the r1.1 font protocol is initially
  58. // whatever the local support is.
  59. //
  60. m_oeCombinedOrderCaps.capsfFonts = m_pasLocal->cpcCaps.orders.capsfFonts;
  61. //
  62. // The combined support for encoding is initially the local values
  63. //
  64. m_oefOE2Negotiable = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
  65. CAPS_ENCODING_OE2_NEGOTIABLE) != 0);
  66. m_oefOE2EncodingOn = !((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
  67. CAPS_ENCODING_OE2_DISABLED) != 0);
  68. m_oeOE2Flag = OE2_FLAG_UNKNOWN;
  69. if (m_oefOE2EncodingOn)
  70. {
  71. m_oeOE2Flag |= OE2_FLAG_SUPPORTED;
  72. }
  73. else
  74. {
  75. m_oeOE2Flag |= OE2_FLAG_NOT_SUPPORTED;
  76. }
  77. m_oefBaseOE = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
  78. CAPS_ENCODING_BASE_OE) != 0);
  79. m_oefAlignedOE = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
  80. CAPS_ENCODING_ALIGNED_OE) != 0);
  81. //
  82. // Loop through the people in the share and examine their order caps
  83. //
  84. for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
  85. {
  86. ValidatePerson(pasT);
  87. //
  88. // Check the orders in the orders capabilities.
  89. //
  90. for (iOrder = 0; iOrder < CAPS_MAX_NUM_ORDERS; iOrder++)
  91. {
  92. if (pasT->cpcCaps.orders.capsOrders[iOrder] < ORD_LEVEL_1_ORDERS)
  93. {
  94. //
  95. // The order is not supported at the level we want to send out
  96. // (currently ORD_LEVEL_1_ORDERS) so set the combined caps to
  97. // say not supported.
  98. //
  99. m_aoeOrderSupported[iOrder] = FALSE;
  100. }
  101. }
  102. m_oeCombinedOrderCaps.capsfFonts &=
  103. (pasT->cpcCaps.orders.capsfFonts | ~CAPS_FONT_AND_FLAGS);
  104. m_oeCombinedOrderCaps.capsfFonts |=
  105. (pasT->cpcCaps.orders.capsfFonts & CAPS_FONT_OR_FLAGS);
  106. //
  107. // Check Order encoding support
  108. //
  109. if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_OE2_NEGOTIABLE))
  110. {
  111. m_oefOE2Negotiable = FALSE;
  112. TRACE_OUT(("OE2 negotiation switched off by person [%d]", pasT->mcsID));
  113. }
  114. if (pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_OE2_DISABLED)
  115. {
  116. m_oefOE2EncodingOn = FALSE;
  117. m_oeOE2Flag |= OE2_FLAG_NOT_SUPPORTED;
  118. TRACE_OUT(("OE2 switched off by person [%d]", pasT->mcsID));
  119. }
  120. else
  121. {
  122. m_oeOE2Flag |= OE2_FLAG_SUPPORTED;
  123. TRACE_OUT(("OE2 supported by person [%d]", pasT->mcsID));
  124. }
  125. if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_BASE_OE))
  126. {
  127. m_oefBaseOE = FALSE;
  128. TRACE_OUT(("Base OE switched off by person [%d]", pasT->mcsID));
  129. }
  130. if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_ALIGNED_OE))
  131. {
  132. m_oefAlignedOE = FALSE;
  133. TRACE_OUT(("Aligned OE switched off by [%d]", pasT->mcsID));
  134. }
  135. }
  136. //
  137. // At 2.x, the DESKSCROLL order support is implied by the SCRBLT
  138. // support.
  139. //
  140. m_aoeOrderSupported[HIWORD(ORD_DESKSCROLL)] = m_aoeOrderSupported[HIWORD(ORD_SCRBLT)];
  141. //
  142. // Turn on the order support now that the table is set up.
  143. //
  144. m_oefSendOrders = TRUE;
  145. //
  146. // Check for incompatible capabilities:
  147. // - OE2 not negotiable but parties don't agree on OE2
  148. // - OE2 not supported but parties don't agree on OE.
  149. // If incompatabilites exist, switch off all order support.
  150. //
  151. if ((!m_oefOE2Negotiable) && (m_oeOE2Flag == OE2_FLAG_MIXED))
  152. {
  153. ERROR_OUT(("OE2 not negotiable but parties don't agree"));
  154. m_oefSendOrders = FALSE;
  155. }
  156. if (!m_oefOE2EncodingOn && !m_oefBaseOE && !m_oefAlignedOE)
  157. {
  158. ERROR_OUT(("None of OE, OE' or OE2 supported"));
  159. m_oefSendOrders = FALSE;
  160. }
  161. FH_DetermineFontSupport();
  162. OECapabilitiesChanged();
  163. DebugExitVOID(ASShare::OE_RecalcCaps);
  164. }
  165. //
  166. // OE_SyncOutgoing()
  167. // Called when share is created or someone new joins the share. Disables
  168. // text orders until we get fonts from all remotes. Broadcasts our local
  169. // supported font list.
  170. //
  171. void ASShare::OE_SyncOutgoing(void)
  172. {
  173. DebugEntry(OE_SyncOutgoing);
  174. //
  175. // Stop sending text orders until the font negotiation is complete.
  176. //
  177. OE_EnableText(FALSE);
  178. //
  179. // Resend font info
  180. //
  181. m_fhLocalInfoSent = FALSE;
  182. DebugExitVOID(ASShare::OE_SyncOutgoing);
  183. }
  184. //
  185. // OE_Periodic - see oe.h
  186. //
  187. void ASShare::OE_Periodic(void)
  188. {
  189. DebugEntry(ASShare::OE_Periodic);
  190. //
  191. // If our local font information has not been sent, then send it now.
  192. //
  193. if (!m_fhLocalInfoSent)
  194. {
  195. FH_SendLocalFontInfo();
  196. }
  197. DebugExitVOID(ASShare::OE_Periodic);
  198. }
  199. //
  200. // OE_EnableText
  201. //
  202. void ASShare::OE_EnableText(BOOL enable)
  203. {
  204. DebugEntry(ASShare::OE_EnableText);
  205. m_oefTextEnabled = (enable != FALSE);
  206. OECapabilitiesChanged();
  207. DebugExitVOID(ASShare::OE_EnableText);
  208. }
  209. //
  210. // OE_RectIntersectsSDA()
  211. //
  212. BOOL ASHost::OE_RectIntersectsSDA(LPRECT pRect)
  213. {
  214. RECT rectVD;
  215. BOOL fIntersection = FALSE;
  216. UINT i;
  217. DebugEntry(ASHost::OE_RectIntersectsSDA);
  218. //
  219. // Copy the supplied rectangle, converting to inclusive Virtual
  220. // Desktop coords.
  221. //
  222. rectVD.left = pRect->left;
  223. rectVD.top = pRect->top;
  224. rectVD.right = pRect->right - 1;
  225. rectVD.bottom = pRect->bottom - 1;
  226. //
  227. // Loop through each of the bounding rectangles checking for
  228. // an intersection with the supplied rectangle.
  229. //
  230. for (i = 0; i < m_baNumRects; i++)
  231. {
  232. if ( (m_abaRects[i].left <= rectVD.right) &&
  233. (m_abaRects[i].top <= rectVD.bottom) &&
  234. (m_abaRects[i].right >= rectVD.left) &&
  235. (m_abaRects[i].bottom >= rectVD.top) )
  236. {
  237. TRACE_OUT(("Rect {%d, %d, %d, %d} intersects SDA {%d, %d, %d, %d}",
  238. rectVD.left, rectVD.top, rectVD.right, rectVD.bottom,
  239. m_abaRects[i].left, m_abaRects[i].top,
  240. m_abaRects[i].right, m_abaRects[i].bottom));
  241. fIntersection = TRUE;
  242. break;
  243. }
  244. }
  245. DebugExitBOOL(ASHost::OE_RectIntersectsSDA, fIntersection);
  246. return(fIntersection);
  247. }
  248. //
  249. // OE_SendAsOrder()
  250. //
  251. BOOL ASShare::OE_SendAsOrder(DWORD order)
  252. {
  253. BOOL rc = FALSE;
  254. DebugEntry(ASShare::OE_SendAsOrder);
  255. //
  256. // Only check the order if we are allowed to send orders in the first
  257. // place!
  258. //
  259. if (m_oefSendOrders)
  260. {
  261. TRACE_OUT(("Orders enabled"));
  262. //
  263. // We are sending some orders, so check individual flags.
  264. //
  265. rc = (m_aoeOrderSupported[HIWORD(order)] != 0);
  266. TRACE_OUT(("Send order 0x%08x HIWORD %hu", order, HIWORD(order)));
  267. }
  268. DebugExitBOOL(ASShare::OE_SendAsOrder, rc);
  269. return(rc);
  270. }
  271. //
  272. // OE_GetStringExtent(..)
  273. //
  274. int OE_GetStringExtent
  275. (
  276. HDC hdc,
  277. PTEXTMETRIC pMetric,
  278. LPSTR lpszString,
  279. UINT cbString,
  280. LPRECT pRect
  281. )
  282. {
  283. SIZE textExtent;
  284. UINT i;
  285. ABC abcSpace;
  286. PTEXTMETRIC pTextMetrics;
  287. int overhang = 0;
  288. TEXTMETRIC metricT;
  289. DebugEntry(OE_GetStringExtent);
  290. //
  291. // If no text metrics supplied, then use the global text metrics.
  292. //
  293. pTextMetrics = (pMetric != (PTEXTMETRIC)NULL)
  294. ? pMetric
  295. : &metricT;
  296. //
  297. // If there are no characters then return a NULL rectangle.
  298. //
  299. pRect->left = 1;
  300. pRect->top = 0;
  301. pRect->right = 0;
  302. pRect->bottom = 0;
  303. if (cbString == 0)
  304. {
  305. TRACE_OUT(( "Zero length string"));
  306. DC_QUIT;
  307. }
  308. if (!GetTextExtentPoint32(hdc, (LPCTSTR)lpszString, cbString, &textExtent))
  309. {
  310. ERROR_OUT(( "Failed to get text extent, rc = %lu",
  311. GetLastError()));
  312. DC_QUIT;
  313. }
  314. pRect->left = 0;
  315. pRect->top = 0;
  316. pRect->right = textExtent.cx;
  317. pRect->bottom = textExtent.cy;
  318. //
  319. // We have the Windows text extent, which is the advance distance
  320. // for the string. However, some fonts (eg TrueType with C spacing
  321. // or italic) may extend beyond this. Add in this extra value here
  322. // if necessary.
  323. //
  324. if (pTextMetrics->tmPitchAndFamily & TMPF_TRUETYPE)
  325. {
  326. //
  327. // Get the ABC spacing of the last character in the string.
  328. //
  329. GetCharABCWidths(hdc, lpszString[cbString-1], lpszString[cbString-1],
  330. &abcSpace );
  331. //
  332. // SFR 2916: Add in (not subtract) the C space of the last
  333. // character from the string extent.
  334. //
  335. overhang = abcSpace.abcC;
  336. }
  337. else
  338. {
  339. //
  340. // The font is not TrueType. Add any global font overhang onto
  341. // the string extent.
  342. //
  343. overhang = pTextMetrics->tmOverhang;
  344. }
  345. pRect->right += overhang;
  346. DC_EXIT_POINT:
  347. DebugExitDWORD(OE_GetStringExtent, overhang);
  348. return(overhang);
  349. }
  350. //
  351. //
  352. // Name: OECapabilitiesChanged
  353. //
  354. // Purpose: Called when the OE capabilities have been renegotiated.
  355. //
  356. // Returns: Nothing
  357. //
  358. // Params: None
  359. //
  360. //
  361. void ASShare::OECapabilitiesChanged(void)
  362. {
  363. DebugEntry(ASShare::OECapabilitiesChanged);
  364. if (g_asCanHost)
  365. {
  366. OE_NEW_CAPABILITIES newCapabilities;
  367. newCapabilities.sendOrders = (m_oefSendOrders != FALSE);
  368. newCapabilities.textEnabled = (m_oefTextEnabled != FALSE);
  369. newCapabilities.baselineTextEnabled =
  370. (m_oeCombinedOrderCaps.capsfFonts & CAPS_FONT_ALLOW_BASELINE) != 0;
  371. newCapabilities.orderSupported = m_aoeOrderSupported;
  372. OSI_FunctionRequest(OE_ESC_NEW_CAPABILITIES, (LPOSI_ESCAPE_HEADER)&newCapabilities,
  373. sizeof(newCapabilities));
  374. }
  375. DebugExitVOID(ASShare::OECapabilitiesChanged);
  376. }