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.

364 lines
12 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. bitmap.c
  5. Abstract:
  6. This file implements bitmap video buffer management.
  7. Author:
  8. Therese Stowell (thereses) 4-Sept-1991
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. NTSTATUS
  15. CreateConsoleBitmap(
  16. IN OUT PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsInfo,
  17. IN OUT PSCREEN_INFORMATION ScreenInfo,
  18. OUT PVOID *lpBitmap,
  19. OUT HANDLE *hMutex
  20. )
  21. {
  22. NTSTATUS Status;
  23. LARGE_INTEGER MaximumSize;
  24. SIZE_T ViewSize;
  25. //
  26. // adjust bitmap info
  27. //
  28. if (GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight > 0)
  29. {
  30. #if DBG
  31. DbgPrint("*************** Negating biHeight\n");
  32. #endif
  33. GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight =
  34. -GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight;
  35. }
  36. if (GraphicsInfo->lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
  37. {
  38. #if DBG
  39. DbgPrint("*************** setting Compression to BI_RGB)\n");
  40. #endif
  41. GraphicsInfo->lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
  42. }
  43. //
  44. // allocate screeninfo buffer data and copy it
  45. //
  46. ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo = ConsoleHeapAlloc(BMP_TAG, GraphicsInfo->dwBitMapInfoLength);
  47. if (ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo == NULL) {
  48. return STATUS_NO_MEMORY;
  49. }
  50. ScreenInfo->BufferInfo.GraphicsInfo.BitMapInfoLength = GraphicsInfo->dwBitMapInfoLength;
  51. RtlCopyMemory(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo,
  52. GraphicsInfo->lpBitMapInfo,
  53. GraphicsInfo->dwBitMapInfoLength
  54. );
  55. ASSERT((GraphicsInfo->lpBitMapInfo->bmiHeader.biWidth *
  56. -GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight / 8 *
  57. GraphicsInfo->lpBitMapInfo->bmiHeader.biBitCount) ==
  58. (LONG)GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage);
  59. //
  60. // create bitmap section
  61. //
  62. MaximumSize.QuadPart = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage;
  63. Status = NtCreateSection(&ScreenInfo->BufferInfo.GraphicsInfo.hSection,
  64. SECTION_ALL_ACCESS,
  65. NULL,
  66. &MaximumSize,
  67. PAGE_READWRITE,
  68. SEC_COMMIT,
  69. NULL
  70. );
  71. if (!NT_SUCCESS(Status)) {
  72. ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo);
  73. return Status;
  74. }
  75. //
  76. // map server view of section
  77. //
  78. ViewSize = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage;
  79. ScreenInfo->BufferInfo.GraphicsInfo.BitMap = 0;
  80. Status = NtMapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.hSection,
  81. NtCurrentProcess(),
  82. &ScreenInfo->BufferInfo.GraphicsInfo.BitMap,
  83. 0L,
  84. GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage,
  85. NULL,
  86. &ViewSize,
  87. ViewUnmap,
  88. 0L,
  89. PAGE_READWRITE
  90. );
  91. if (!NT_SUCCESS(Status)) {
  92. ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo);
  93. NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection);
  94. return Status;
  95. }
  96. //
  97. // map client view of section
  98. //
  99. ViewSize = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage;
  100. *lpBitmap = 0;
  101. Status = NtMapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.hSection,
  102. CONSOLE_CLIENTPROCESSHANDLE(),
  103. lpBitmap,
  104. 0L,
  105. GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage,
  106. NULL,
  107. &ViewSize,
  108. ViewUnmap,
  109. 0L,
  110. PAGE_READWRITE
  111. );
  112. if (!NT_SUCCESS(Status)) {
  113. ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo);
  114. NtUnmapViewOfSection(NtCurrentProcess(),ScreenInfo->BufferInfo.GraphicsInfo.BitMap);
  115. NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection);
  116. return Status;
  117. }
  118. ScreenInfo->BufferInfo.GraphicsInfo.ClientProcess = CONSOLE_CLIENTPROCESSHANDLE();
  119. ScreenInfo->BufferInfo.GraphicsInfo.ClientBitMap = *lpBitmap;
  120. //
  121. // create mutex to serialize access to bitmap, then map handle to mutex to client side
  122. //
  123. NtCreateMutant(&ScreenInfo->BufferInfo.GraphicsInfo.hMutex,
  124. MUTANT_ALL_ACCESS, NULL, FALSE);
  125. MapHandle(CONSOLE_CLIENTPROCESSHANDLE(),
  126. ScreenInfo->BufferInfo.GraphicsInfo.hMutex,
  127. hMutex
  128. );
  129. ScreenInfo->BufferInfo.GraphicsInfo.dwUsage = GraphicsInfo->dwUsage;
  130. ScreenInfo->ScreenBufferSize.X = (WORD)GraphicsInfo->lpBitMapInfo->bmiHeader.biWidth;
  131. ScreenInfo->ScreenBufferSize.Y = (WORD)-GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight;
  132. ScreenInfo->Window.Left = 0;
  133. ScreenInfo->Window.Top = 0;
  134. ScreenInfo->Window.Right = (SHORT)(ScreenInfo->Window.Left+ScreenInfo->ScreenBufferSize.X-1);
  135. ScreenInfo->Window.Bottom = (SHORT)(ScreenInfo->Window.Top+ScreenInfo->ScreenBufferSize.Y-1);
  136. return STATUS_SUCCESS;
  137. }
  138. ULONG
  139. SrvInvalidateBitMapRect(
  140. IN OUT PCSR_API_MSG m,
  141. IN OUT PCSR_REPLY_STATUS ReplyStatus
  142. )
  143. /*++
  144. Routine Description:
  145. This routine is called to indicate that the application has modified a region
  146. in the bitmap. We update the region to the screen.
  147. Arguments:
  148. m - message containing api parameters
  149. ReplyStatus - Indicates whether to reply to the dll port.
  150. Return Value:
  151. --*/
  152. {
  153. PCONSOLE_INVALIDATERECT_MSG a = (PCONSOLE_INVALIDATERECT_MSG)&m->u.ApiMessageData;
  154. PCONSOLE_INFORMATION Console;
  155. PHANDLE_DATA HandleData;
  156. NTSTATUS Status;
  157. UINT Codepage;
  158. Status = ApiPreamble(a->ConsoleHandle,
  159. &Console
  160. );
  161. if (!NT_SUCCESS(Status)) {
  162. return Status;
  163. }
  164. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  165. a->OutputHandle,
  166. CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  167. GENERIC_WRITE,
  168. &HandleData
  169. );
  170. if (!NT_SUCCESS(Status)) {
  171. UnlockConsole(Console);
  172. return((ULONG) Status);
  173. }
  174. if (HandleData->HandleType & CONSOLE_OUTPUT_HANDLE) {
  175. //ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
  176. //ASSERT(!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE));
  177. ASSERT(Console->VDMBuffer != NULL);
  178. if (Console->VDMBuffer != NULL) {
  179. //ASSERT(HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X <= Console->VDMBufferSize.X);
  180. //ASSERT(HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y <= Console->VDMBufferSize.Y);
  181. if (HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X <= Console->VDMBufferSize.X &&
  182. HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y <= Console->VDMBufferSize.Y) {
  183. COORD TargetPoint;
  184. TargetPoint.X = a->Rect.Left;
  185. TargetPoint.Y = a->Rect.Top;
  186. // VDM can sometimes get out of sync with window size
  187. //ASSERT(a->Rect.Left >= 0);
  188. //ASSERT(a->Rect.Top >= 0);
  189. //ASSERT(a->Rect.Right < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X);
  190. //ASSERT(a->Rect.Bottom < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y);
  191. //ASSERT(a->Rect.Left <= a->Rect.Right);
  192. //ASSERT(a->Rect.Top <= a->Rect.Bottom);
  193. if ((a->Rect.Left >= 0) &&
  194. (a->Rect.Top >= 0) &&
  195. (a->Rect.Right < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X) &&
  196. (a->Rect.Bottom < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y) &&
  197. (a->Rect.Left <= a->Rect.Right) &&
  198. (a->Rect.Top <= a->Rect.Bottom) ) {
  199. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  200. #if defined(FE_SB)
  201. if (CONSOLE_IS_DBCS_ENABLED() &&
  202. Console->OutputCP != WINDOWSCP )
  203. {
  204. Codepage = USACP;
  205. }
  206. else
  207. #endif
  208. // we want UnicodeOem characters
  209. Codepage = WINDOWSCP;
  210. } else {
  211. #if defined(FE_SB)
  212. if (CONSOLE_IS_DBCS_ENABLED()) {
  213. Codepage = Console->OutputCP;
  214. }
  215. else
  216. #endif
  217. // we want real Unicode characters
  218. Codepage = Console->CP;
  219. }
  220. WriteRectToScreenBuffer((PBYTE)Console->VDMBuffer,
  221. Console->VDMBufferSize, &a->Rect,
  222. HandleData->Buffer.ScreenBuffer, TargetPoint,
  223. Codepage);
  224. WriteToScreen(HandleData->Buffer.ScreenBuffer,&a->Rect);
  225. } else {
  226. Status = STATUS_INVALID_PARAMETER;
  227. }
  228. } else {
  229. Status = STATUS_INVALID_PARAMETER;
  230. }
  231. } else {
  232. Status = STATUS_INVALID_PARAMETER;
  233. }
  234. } else {
  235. //
  236. // write data to screen
  237. //
  238. WriteToScreen(HandleData->Buffer.ScreenBuffer,&a->Rect);
  239. }
  240. UnlockConsole(Console);
  241. return Status;
  242. UNREFERENCED_PARAMETER(ReplyStatus);
  243. }
  244. NTSTATUS
  245. WriteRegionToScreenBitMap(
  246. IN PSCREEN_INFORMATION ScreenInfo,
  247. IN PSMALL_RECT Region
  248. )
  249. {
  250. DWORD NumScanLines;
  251. int Height;
  252. //
  253. // if we have a selection, turn it off.
  254. //
  255. InvertSelection(ScreenInfo->Console,TRUE);
  256. NtWaitForSingleObject(ScreenInfo->BufferInfo.GraphicsInfo.hMutex,
  257. FALSE, NULL);
  258. // The origin of (xSrc, ySrc) passed to SetDIBitsToDevice is located
  259. // at the DIB's bottom-left corner no matter if the DIB is
  260. // a top-down or bottom-up. Thus, if the DIB is a top-down, we have
  261. // to translate ySrc accordingly:
  262. // if (height < 0) { // top-down
  263. // ySrc = abs(height) - rect.Bottom -1;
  264. //
  265. // else
  266. // ySrc = rect.Bottom;
  267. //
  268. Height = ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo->bmiHeader.biHeight;
  269. NumScanLines = SetDIBitsToDevice(ScreenInfo->Console->hDC,
  270. Region->Left - ScreenInfo->Window.Left,
  271. Region->Top - ScreenInfo->Window.Top,
  272. Region->Right - Region->Left + 1,
  273. Region->Bottom - Region->Top + 1,
  274. Region->Left,
  275. Height < 0 ? -Height - Region->Bottom - 1 : Region->Bottom,
  276. 0,
  277. ScreenInfo->ScreenBufferSize.Y,
  278. ScreenInfo->BufferInfo.GraphicsInfo.BitMap,
  279. ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo,
  280. ScreenInfo->BufferInfo.GraphicsInfo.dwUsage
  281. );
  282. NtReleaseMutant(ScreenInfo->BufferInfo.GraphicsInfo.hMutex, NULL);
  283. //
  284. // if we have a selection, turn it on.
  285. //
  286. InvertSelection(ScreenInfo->Console,FALSE);
  287. if (NumScanLines == 0) {
  288. return STATUS_UNSUCCESSFUL;
  289. }
  290. return STATUS_SUCCESS;
  291. }
  292. VOID
  293. FreeConsoleBitmap(
  294. IN PSCREEN_INFORMATION ScreenInfo
  295. )
  296. {
  297. NtUnmapViewOfSection(NtCurrentProcess(),
  298. ScreenInfo->BufferInfo.GraphicsInfo.BitMap);
  299. NtUnmapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.ClientProcess,
  300. ScreenInfo->BufferInfo.GraphicsInfo.ClientBitMap);
  301. NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection);
  302. NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hMutex);
  303. ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo);
  304. }