console.c 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  1. /*
  2. * Server-side console management
  3. *
  4. * Copyright (C) 1998 Alexandre Julliard
  5. * 2001 Eric Pouech
  6. *
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  21. */
  22. #include "config.h"
  23. #include "wine/port.h"
  24. #include <assert.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <unistd.h>
  28. #include <signal.h>
  29. #include "ntstatus.h"
  30. #define WIN32_NO_STATUS
  31. #include "handle.h"
  32. #include "process.h"
  33. #include "request.h"
  34. #include "file.h"
  35. #include "unicode.h"
  36. #include "wincon.h"
  37. #include "winternl.h"
  38. #include "esync.h"
  39. struct screen_buffer;
  40. struct console_input_events;
  41. struct history_line
  42. {
  43. data_size_t len;
  44. WCHAR text[1];
  45. };
  46. struct console_input
  47. {
  48. struct object obj; /* object header */
  49. int num_proc; /* number of processes attached to this console */
  50. struct thread *renderer; /* console renderer thread */
  51. int mode; /* input mode */
  52. struct screen_buffer *active; /* active screen buffer */
  53. int recnum; /* number of input records */
  54. INPUT_RECORD *records; /* input records */
  55. struct console_input_events *evt; /* synchronization event with renderer */
  56. WCHAR *title; /* console title */
  57. data_size_t title_len; /* length of console title */
  58. struct history_line **history; /* lines history */
  59. int history_size; /* number of entries in history array */
  60. int history_index; /* number of used entries in history array */
  61. int history_mode; /* mode of history (non zero means remove doubled strings */
  62. int edition_mode; /* index to edition mode flavors */
  63. int input_cp; /* console input codepage */
  64. int output_cp; /* console output codepage */
  65. user_handle_t win; /* window handle if backend supports it */
  66. struct event *event; /* event to wait on for input queue */
  67. struct fd *fd; /* for bare console, attached input fd */
  68. };
  69. static void console_input_dump( struct object *obj, int verbose );
  70. static void console_input_destroy( struct object *obj );
  71. static struct fd *console_input_get_fd( struct object *obj );
  72. static const struct object_ops console_input_ops =
  73. {
  74. sizeof(struct console_input), /* size */
  75. console_input_dump, /* dump */
  76. no_get_type, /* get_type */
  77. no_add_queue, /* add_queue */
  78. NULL, /* remove_queue */
  79. NULL, /* signaled */
  80. NULL, /* get_esync_fd */
  81. no_satisfied, /* satisfied */
  82. no_signal, /* signal */
  83. console_input_get_fd, /* get_fd */
  84. default_fd_map_access, /* map_access */
  85. default_get_sd, /* get_sd */
  86. default_set_sd, /* set_sd */
  87. no_lookup_name, /* lookup_name */
  88. no_link_name, /* link_name */
  89. NULL, /* unlink_name */
  90. no_open_file, /* open_file */
  91. no_kernel_obj_list, /* get_kernel_obj_list */
  92. no_alloc_handle, /* alloc_handle */
  93. no_close_handle, /* close_handle */
  94. console_input_destroy /* destroy */
  95. };
  96. static void console_input_events_dump( struct object *obj, int verbose );
  97. static void console_input_events_destroy( struct object *obj );
  98. static int console_input_events_signaled( struct object *obj, struct wait_queue_entry *entry );
  99. static int console_input_events_get_esync_fd( struct object *obj, enum esync_type *type );
  100. struct console_input_events
  101. {
  102. struct object obj; /* object header */
  103. int num_alloc; /* number of allocated events */
  104. int num_used; /* number of actually used events */
  105. struct console_renderer_event* events;
  106. int esync_fd; /* esync file descriptor (signalled when events present) */
  107. };
  108. static const struct object_ops console_input_events_ops =
  109. {
  110. sizeof(struct console_input_events), /* size */
  111. console_input_events_dump, /* dump */
  112. no_get_type, /* get_type */
  113. add_queue, /* add_queue */
  114. remove_queue, /* remove_queue */
  115. console_input_events_signaled, /* signaled */
  116. console_input_events_get_esync_fd,/* get_esync_fd */
  117. no_satisfied, /* satisfied */
  118. no_signal, /* signal */
  119. no_get_fd, /* get_fd */
  120. default_fd_map_access, /* map_access */
  121. default_get_sd, /* get_sd */
  122. default_set_sd, /* set_sd */
  123. no_lookup_name, /* lookup_name */
  124. no_link_name, /* link_name */
  125. NULL, /* unlink_name */
  126. no_open_file, /* open_file */
  127. no_kernel_obj_list, /* get_kernel_obj_list */
  128. no_alloc_handle, /* alloc_handle */
  129. no_close_handle, /* close_handle */
  130. console_input_events_destroy /* destroy */
  131. };
  132. struct font_info
  133. {
  134. short int width;
  135. short int height;
  136. short int weight;
  137. short int pitch_family;
  138. WCHAR *face_name;
  139. data_size_t face_len;
  140. };
  141. struct screen_buffer
  142. {
  143. struct object obj; /* object header */
  144. struct list entry; /* entry in list of all screen buffers */
  145. struct console_input *input; /* associated console input */
  146. int mode; /* output mode */
  147. int cursor_size; /* size of cursor (percentage filled) */
  148. int cursor_visible;/* cursor visibility flag */
  149. int cursor_x; /* position of cursor */
  150. int cursor_y; /* position of cursor */
  151. int width; /* size (w-h) of the screen buffer */
  152. int height;
  153. int max_width; /* size (w-h) of the window given font size */
  154. int max_height;
  155. char_info_t *data; /* the data for each cell - a width x height matrix */
  156. unsigned short attr; /* default fill attributes (screen colors) */
  157. unsigned short popup_attr; /* pop-up color attributes */
  158. unsigned int color_map[16]; /* color table */
  159. rectangle_t win; /* current visible window on the screen buffer *
  160. * as seen in wineconsole */
  161. struct font_info font; /* console font information */
  162. struct fd *fd; /* for bare console, attached output fd */
  163. };
  164. static void screen_buffer_dump( struct object *obj, int verbose );
  165. static void screen_buffer_destroy( struct object *obj );
  166. static struct fd *screen_buffer_get_fd( struct object *obj );
  167. static const struct object_ops screen_buffer_ops =
  168. {
  169. sizeof(struct screen_buffer), /* size */
  170. screen_buffer_dump, /* dump */
  171. no_get_type, /* get_type */
  172. no_add_queue, /* add_queue */
  173. NULL, /* remove_queue */
  174. NULL, /* signaled */
  175. NULL, /* get_esync_fd */
  176. NULL, /* satisfied */
  177. no_signal, /* signal */
  178. screen_buffer_get_fd, /* get_fd */
  179. default_fd_map_access, /* map_access */
  180. default_get_sd, /* get_sd */
  181. default_set_sd, /* set_sd */
  182. no_lookup_name, /* lookup_name */
  183. no_link_name, /* link_name */
  184. NULL, /* unlink_name */
  185. no_open_file, /* open_file */
  186. no_kernel_obj_list, /* get_kernel_obj_list */
  187. no_alloc_handle, /* alloc_handle */
  188. no_close_handle, /* close_handle */
  189. screen_buffer_destroy /* destroy */
  190. };
  191. static enum server_fd_type console_get_fd_type( struct fd *fd );
  192. static const struct fd_ops console_fd_ops =
  193. {
  194. default_fd_get_poll_events, /* get_poll_events */
  195. default_poll_event, /* poll_event */
  196. console_get_fd_type, /* get_fd_type */
  197. no_fd_read, /* read */
  198. no_fd_write, /* write */
  199. no_fd_flush, /* flush */
  200. no_fd_get_file_info, /* get_file_info */
  201. no_fd_get_volume_info, /* get_volume_info */
  202. default_fd_ioctl, /* ioctl */
  203. default_fd_queue_async, /* queue_async */
  204. default_fd_reselect_async /* reselect_async */
  205. };
  206. static struct list screen_buffer_list = LIST_INIT(screen_buffer_list);
  207. static const char_info_t empty_char_info = { ' ', 0x000f }; /* white on black space */
  208. static int console_input_is_bare( struct console_input* cin )
  209. {
  210. return cin->evt == NULL;
  211. }
  212. static struct fd *console_input_get_fd( struct object* obj )
  213. {
  214. struct console_input *console_input = (struct console_input*)obj;
  215. assert( obj->ops == &console_input_ops );
  216. if (console_input->fd)
  217. return (struct fd*)grab_object( console_input->fd );
  218. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  219. return NULL;
  220. }
  221. static enum server_fd_type console_get_fd_type( struct fd *fd )
  222. {
  223. return FD_TYPE_CHAR;
  224. }
  225. /* dumps the renderer events of a console */
  226. static void console_input_events_dump( struct object *obj, int verbose )
  227. {
  228. struct console_input_events *evts = (struct console_input_events *)obj;
  229. assert( obj->ops == &console_input_events_ops );
  230. fprintf( stderr, "Console input events: %d/%d events\n",
  231. evts->num_used, evts->num_alloc );
  232. }
  233. /* destroys the renderer events of a console */
  234. static void console_input_events_destroy( struct object *obj )
  235. {
  236. struct console_input_events *evts = (struct console_input_events *)obj;
  237. assert( obj->ops == &console_input_events_ops );
  238. free( evts->events );
  239. }
  240. /* the renderer events list is signaled when it's not empty */
  241. static int console_input_events_signaled( struct object *obj, struct wait_queue_entry *entry )
  242. {
  243. struct console_input_events *evts = (struct console_input_events *)obj;
  244. assert( obj->ops == &console_input_events_ops );
  245. return (evts->num_used != 0);
  246. }
  247. static int console_input_events_get_esync_fd( struct object *obj, enum esync_type *type )
  248. {
  249. struct console_input_events *evts = (struct console_input_events *)obj;
  250. *type = ESYNC_MANUAL_SERVER;
  251. return evts->esync_fd;
  252. }
  253. /* add an event to the console's renderer events list */
  254. static void console_input_events_append( struct console_input* console,
  255. struct console_renderer_event* evt)
  256. {
  257. struct console_input_events* evts;
  258. int collapsed = FALSE;
  259. if (!(evts = console->evt)) return;
  260. /* to be done even when evt has been generated by the renderer ? */
  261. /* try to collapse evt into current queue's events */
  262. if (evts->num_used)
  263. {
  264. struct console_renderer_event* last = &evts->events[evts->num_used - 1];
  265. if (last->event == CONSOLE_RENDERER_UPDATE_EVENT &&
  266. evt->event == CONSOLE_RENDERER_UPDATE_EVENT)
  267. {
  268. /* if two update events overlap, collapse them into a single one */
  269. if (last->u.update.bottom + 1 >= evt->u.update.top &&
  270. evt->u.update.bottom + 1 >= last->u.update.top)
  271. {
  272. last->u.update.top = min(last->u.update.top, evt->u.update.top);
  273. last->u.update.bottom = max(last->u.update.bottom, evt->u.update.bottom);
  274. collapsed = TRUE;
  275. }
  276. }
  277. }
  278. if (!collapsed)
  279. {
  280. if (evts->num_used == evts->num_alloc)
  281. {
  282. evts->num_alloc += 16;
  283. evts->events = realloc( evts->events, evts->num_alloc * sizeof(*evt) );
  284. assert(evts->events);
  285. }
  286. evts->events[evts->num_used++] = *evt;
  287. }
  288. wake_up( &evts->obj, 0 );
  289. }
  290. /* retrieves events from the console's renderer events list */
  291. static void console_input_events_get( struct console_input_events* evts )
  292. {
  293. data_size_t num = get_reply_max_size() / sizeof(evts->events[0]);
  294. if (num > evts->num_used) num = evts->num_used;
  295. set_reply_data( evts->events, num * sizeof(evts->events[0]) );
  296. if (num < evts->num_used)
  297. {
  298. memmove( &evts->events[0], &evts->events[num],
  299. (evts->num_used - num) * sizeof(evts->events[0]) );
  300. }
  301. evts->num_used -= num;
  302. if (do_esync() && !evts->num_used)
  303. esync_clear( evts->esync_fd );
  304. }
  305. static struct console_input_events *create_console_input_events(void)
  306. {
  307. struct console_input_events* evt;
  308. if (!(evt = alloc_object( &console_input_events_ops ))) return NULL;
  309. evt->num_alloc = evt->num_used = 0;
  310. evt->events = NULL;
  311. evt->esync_fd = -1;
  312. if (do_esync())
  313. evt->esync_fd = esync_create_fd( 0, 0 );
  314. return evt;
  315. }
  316. static struct object *create_console_input( struct thread* renderer, int fd )
  317. {
  318. struct console_input *console_input;
  319. if (!(console_input = alloc_object( &console_input_ops )))
  320. {
  321. if (fd != -1) close( fd );
  322. return NULL;
  323. }
  324. console_input->renderer = renderer;
  325. console_input->mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
  326. ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_INSERT_MODE |
  327. ENABLE_EXTENDED_FLAGS;
  328. console_input->num_proc = 0;
  329. console_input->active = NULL;
  330. console_input->recnum = 0;
  331. console_input->records = NULL;
  332. console_input->evt = renderer ? create_console_input_events() : NULL;
  333. console_input->title = NULL;
  334. console_input->title_len = 0;
  335. console_input->history_size = 50;
  336. console_input->history = calloc( console_input->history_size, sizeof(*console_input->history) );
  337. console_input->history_index = 0;
  338. console_input->history_mode = 0;
  339. console_input->edition_mode = 0;
  340. console_input->input_cp = 0;
  341. console_input->output_cp = 0;
  342. console_input->win = 0;
  343. console_input->event = create_event( NULL, NULL, 0, 1, 0, NULL );
  344. console_input->fd = NULL;
  345. if (!console_input->history || (renderer && !console_input->evt) || !console_input->event)
  346. {
  347. if (fd != -1) close( fd );
  348. console_input->history_size = 0;
  349. release_object( console_input );
  350. return NULL;
  351. }
  352. if (fd != -1) /* bare console */
  353. {
  354. if (!(console_input->fd = create_anonymous_fd( &console_fd_ops, fd, &console_input->obj,
  355. FILE_SYNCHRONOUS_IO_NONALERT )))
  356. {
  357. release_object( console_input );
  358. return NULL;
  359. }
  360. allow_fd_caching( console_input->fd );
  361. }
  362. return &console_input->obj;
  363. }
  364. static void generate_sb_initial_events( struct console_input *console_input )
  365. {
  366. struct screen_buffer *screen_buffer = console_input->active;
  367. struct console_renderer_event evt;
  368. evt.event = CONSOLE_RENDERER_ACTIVE_SB_EVENT;
  369. memset(&evt.u, 0, sizeof(evt.u));
  370. console_input_events_append( console_input, &evt );
  371. evt.event = CONSOLE_RENDERER_SB_RESIZE_EVENT;
  372. evt.u.resize.width = screen_buffer->width;
  373. evt.u.resize.height = screen_buffer->height;
  374. console_input_events_append( console_input, &evt );
  375. evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
  376. evt.u.display.left = screen_buffer->win.left;
  377. evt.u.display.top = screen_buffer->win.top;
  378. evt.u.display.width = screen_buffer->win.right - screen_buffer->win.left + 1;
  379. evt.u.display.height = screen_buffer->win.bottom - screen_buffer->win.top + 1;
  380. console_input_events_append( console_input, &evt );
  381. evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
  382. evt.u.update.top = 0;
  383. evt.u.update.bottom = screen_buffer->height - 1;
  384. console_input_events_append( console_input, &evt );
  385. evt.event = CONSOLE_RENDERER_CURSOR_GEOM_EVENT;
  386. evt.u.cursor_geom.size = screen_buffer->cursor_size;
  387. evt.u.cursor_geom.visible = screen_buffer->cursor_visible;
  388. console_input_events_append( console_input, &evt );
  389. evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
  390. evt.u.cursor_pos.x = screen_buffer->cursor_x;
  391. evt.u.cursor_pos.y = screen_buffer->cursor_y;
  392. console_input_events_append( console_input, &evt );
  393. }
  394. static struct screen_buffer *create_console_output( struct console_input *console_input, int fd )
  395. {
  396. struct screen_buffer *screen_buffer;
  397. int i;
  398. if (!(screen_buffer = alloc_object( &screen_buffer_ops )))
  399. {
  400. if (fd != -1) close( fd );
  401. return NULL;
  402. }
  403. screen_buffer->mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
  404. screen_buffer->input = console_input;
  405. screen_buffer->cursor_size = 100;
  406. screen_buffer->cursor_visible = 1;
  407. screen_buffer->width = 80;
  408. screen_buffer->height = 150;
  409. screen_buffer->max_width = 80;
  410. screen_buffer->max_height = 25;
  411. screen_buffer->cursor_x = 0;
  412. screen_buffer->cursor_y = 0;
  413. screen_buffer->attr = 0x0F;
  414. screen_buffer->popup_attr = 0xF5;
  415. screen_buffer->win.left = 0;
  416. screen_buffer->win.right = screen_buffer->max_width - 1;
  417. screen_buffer->win.top = 0;
  418. screen_buffer->win.bottom = screen_buffer->max_height - 1;
  419. screen_buffer->data = NULL;
  420. screen_buffer->font.width = 0;
  421. screen_buffer->font.height = 0;
  422. screen_buffer->font.weight = FW_NORMAL;
  423. screen_buffer->font.pitch_family = FIXED_PITCH | FF_DONTCARE;
  424. screen_buffer->font.face_name = NULL;
  425. screen_buffer->font.face_len = 0;
  426. memset( screen_buffer->color_map, 0, sizeof(screen_buffer->color_map) );
  427. list_add_head( &screen_buffer_list, &screen_buffer->entry );
  428. if (fd == -1)
  429. screen_buffer->fd = NULL;
  430. else
  431. {
  432. if (!(screen_buffer->fd = create_anonymous_fd( &console_fd_ops, fd, &screen_buffer->obj,
  433. FILE_SYNCHRONOUS_IO_NONALERT )))
  434. {
  435. release_object( screen_buffer );
  436. return NULL;
  437. }
  438. allow_fd_caching(screen_buffer->fd);
  439. }
  440. if (!(screen_buffer->data = malloc( screen_buffer->width * screen_buffer->height *
  441. sizeof(*screen_buffer->data) )))
  442. {
  443. release_object( screen_buffer );
  444. return NULL;
  445. }
  446. /* clear the first row */
  447. for (i = 0; i < screen_buffer->width; i++) screen_buffer->data[i] = empty_char_info;
  448. /* and copy it to all other rows */
  449. for (i = 1; i < screen_buffer->height; i++)
  450. memcpy( &screen_buffer->data[i * screen_buffer->width], screen_buffer->data,
  451. screen_buffer->width * sizeof(char_info_t) );
  452. if (!console_input->active)
  453. {
  454. console_input->active = (struct screen_buffer*)grab_object( screen_buffer );
  455. generate_sb_initial_events( console_input );
  456. }
  457. return screen_buffer;
  458. }
  459. /* free the console for this process */
  460. int free_console( struct process *process )
  461. {
  462. struct console_input* console = process->console;
  463. if (!console) return 0;
  464. process->console = NULL;
  465. if (--console->num_proc == 0 && console->renderer)
  466. {
  467. /* all processes have terminated... tell the renderer to terminate too */
  468. struct console_renderer_event evt;
  469. evt.event = CONSOLE_RENDERER_EXIT_EVENT;
  470. memset(&evt.u, 0, sizeof(evt.u));
  471. console_input_events_append( console, &evt );
  472. }
  473. release_object( console );
  474. return 1;
  475. }
  476. /* let process inherit the console from parent... this handle two cases :
  477. * 1/ generic console inheritance
  478. * 2/ parent is a renderer which launches process, and process should attach to the console
  479. * rendered by parent
  480. */
  481. void inherit_console( struct thread *parent_thread, struct process *parent, struct process *process,
  482. obj_handle_t hconin )
  483. {
  484. int done = 0;
  485. /* if parent is a renderer, then attach current process to its console
  486. * a bit hacky....
  487. */
  488. if (hconin && parent_thread)
  489. {
  490. struct console_input *console;
  491. /* FIXME: should we check some access rights ? */
  492. if ((console = (struct console_input *)get_handle_obj( parent, hconin,
  493. 0, &console_input_ops )))
  494. {
  495. if (console->renderer == parent_thread)
  496. {
  497. process->console = (struct console_input *)grab_object( console );
  498. process->console->num_proc++;
  499. done = 1;
  500. }
  501. release_object( console );
  502. }
  503. else clear_error(); /* ignore error */
  504. }
  505. /* otherwise, if parent has a console, attach child to this console */
  506. if (!done && parent->console)
  507. {
  508. process->console = (struct console_input *)grab_object( parent->console );
  509. process->console->num_proc++;
  510. }
  511. }
  512. struct thread *console_get_renderer( struct console_input *console )
  513. {
  514. return console->renderer;
  515. }
  516. static struct console_input* console_input_get( obj_handle_t handle, unsigned access )
  517. {
  518. struct console_input* console = NULL;
  519. if (handle)
  520. console = (struct console_input *)get_handle_obj( current->process, handle,
  521. access, &console_input_ops );
  522. else if (current->process->console)
  523. {
  524. console = (struct console_input *)grab_object( current->process->console );
  525. }
  526. if (!console && !get_error()) set_error(STATUS_INVALID_PARAMETER);
  527. return console;
  528. }
  529. struct console_signal_info
  530. {
  531. struct console_input *console;
  532. process_id_t group;
  533. int signal;
  534. };
  535. static int propagate_console_signal_cb(struct process *process, void *user)
  536. {
  537. struct console_signal_info* csi = (struct console_signal_info*)user;
  538. if (process->console == csi->console && process->running_threads &&
  539. (!csi->group || process->group_id == csi->group))
  540. {
  541. /* find a suitable thread to signal */
  542. struct thread *thread;
  543. LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
  544. {
  545. if (send_thread_signal( thread, csi->signal )) break;
  546. }
  547. }
  548. return FALSE;
  549. }
  550. static void propagate_console_signal( struct console_input *console,
  551. int sig, process_id_t group_id )
  552. {
  553. struct console_signal_info csi;
  554. if (!console)
  555. {
  556. set_error( STATUS_INVALID_PARAMETER );
  557. return;
  558. }
  559. /* FIXME: should support the other events (like CTRL_BREAK) */
  560. if (sig != CTRL_C_EVENT)
  561. {
  562. set_error( STATUS_NOT_IMPLEMENTED );
  563. return;
  564. }
  565. csi.console = console;
  566. csi.signal = SIGINT;
  567. csi.group = group_id;
  568. enum_processes(propagate_console_signal_cb, &csi);
  569. }
  570. static int get_console_mode( obj_handle_t handle )
  571. {
  572. struct object *obj;
  573. int ret = 0;
  574. if ((obj = get_handle_obj( current->process, handle, FILE_READ_PROPERTIES, NULL )))
  575. {
  576. if (obj->ops == &console_input_ops)
  577. {
  578. ret = ((struct console_input *)obj)->mode;
  579. }
  580. else if (obj->ops == &screen_buffer_ops)
  581. {
  582. ret = ((struct screen_buffer *)obj)->mode;
  583. }
  584. else
  585. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  586. release_object( obj );
  587. }
  588. return ret;
  589. }
  590. /* changes the mode of either a console input or a screen buffer */
  591. static int set_console_mode( obj_handle_t handle, int mode )
  592. {
  593. struct object *obj;
  594. int ret = 0;
  595. if (!(obj = get_handle_obj( current->process, handle, FILE_WRITE_PROPERTIES, NULL )))
  596. return 0;
  597. if (obj->ops == &console_input_ops)
  598. {
  599. /* FIXME: if we remove the edit mode bits, we need (???) to clean up the history */
  600. ((struct console_input *)obj)->mode = mode;
  601. ret = 1;
  602. }
  603. else if (obj->ops == &screen_buffer_ops)
  604. {
  605. ((struct screen_buffer *)obj)->mode = mode;
  606. ret = 1;
  607. }
  608. else set_error( STATUS_OBJECT_TYPE_MISMATCH );
  609. release_object( obj );
  610. return ret;
  611. }
  612. /* add input events to a console input queue */
  613. static int write_console_input( struct console_input* console, int count,
  614. const INPUT_RECORD *records )
  615. {
  616. INPUT_RECORD *new_rec;
  617. if (!count) return 0;
  618. if (!(new_rec = realloc( console->records,
  619. (console->recnum + count) * sizeof(INPUT_RECORD) )))
  620. {
  621. set_error( STATUS_NO_MEMORY );
  622. return -1;
  623. }
  624. console->records = new_rec;
  625. memcpy( new_rec + console->recnum, records, count * sizeof(INPUT_RECORD) );
  626. if (console->mode & ENABLE_PROCESSED_INPUT)
  627. {
  628. int i = 0;
  629. while (i < count)
  630. {
  631. if (records[i].EventType == KEY_EVENT &&
  632. records[i].Event.KeyEvent.uChar.UnicodeChar == 'C' - 64 &&
  633. !(records[i].Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
  634. {
  635. if (i != count - 1)
  636. memcpy( &console->records[console->recnum + i],
  637. &console->records[console->recnum + i + 1],
  638. (count - i - 1) * sizeof(INPUT_RECORD) );
  639. count--;
  640. if (records[i].Event.KeyEvent.bKeyDown)
  641. {
  642. /* send SIGINT to all processes attached to this console */
  643. propagate_console_signal( console, CTRL_C_EVENT, 0 );
  644. }
  645. }
  646. else i++;
  647. }
  648. }
  649. if (!console->recnum && count) set_event( console->event );
  650. console->recnum += count;
  651. return count;
  652. }
  653. /* retrieve a pointer to the console input records */
  654. static int read_console_input( obj_handle_t handle, int count, int flush )
  655. {
  656. struct console_input *console;
  657. if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
  658. FILE_READ_DATA, &console_input_ops )))
  659. return -1;
  660. if (!count)
  661. {
  662. /* special case: do not retrieve anything, but return
  663. * the total number of records available */
  664. count = console->recnum;
  665. }
  666. else
  667. {
  668. if (count > console->recnum) count = console->recnum;
  669. set_reply_data( console->records, count * sizeof(INPUT_RECORD) );
  670. }
  671. if (flush)
  672. {
  673. int i;
  674. for (i = count; i < console->recnum; i++)
  675. console->records[i-count] = console->records[i];
  676. if ((console->recnum -= count) > 0)
  677. {
  678. INPUT_RECORD *new_rec = realloc( console->records,
  679. console->recnum * sizeof(INPUT_RECORD) );
  680. if (new_rec) console->records = new_rec;
  681. }
  682. else
  683. {
  684. free( console->records );
  685. console->records = NULL;
  686. reset_event( console->event );
  687. }
  688. }
  689. release_object( console );
  690. return count;
  691. }
  692. /* set misc console input information */
  693. static int set_console_input_info( const struct set_console_input_info_request *req,
  694. const WCHAR *title, data_size_t len )
  695. {
  696. struct console_input *console;
  697. struct console_renderer_event evt;
  698. if (!(console = console_input_get( req->handle, FILE_WRITE_PROPERTIES ))) goto error;
  699. if (console_input_is_bare(console) &&
  700. (req->mask & (SET_CONSOLE_INPUT_INFO_ACTIVE_SB|
  701. SET_CONSOLE_INPUT_INFO_WIN)))
  702. {
  703. set_error( STATUS_UNSUCCESSFUL );
  704. goto error;
  705. }
  706. memset(&evt.u, 0, sizeof(evt.u));
  707. if (req->mask & SET_CONSOLE_INPUT_INFO_ACTIVE_SB)
  708. {
  709. struct screen_buffer *screen_buffer;
  710. screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, req->active_sb,
  711. FILE_WRITE_PROPERTIES, &screen_buffer_ops );
  712. if (!screen_buffer || screen_buffer->input != console)
  713. {
  714. set_error( STATUS_INVALID_HANDLE );
  715. if (screen_buffer) release_object( screen_buffer );
  716. goto error;
  717. }
  718. if (screen_buffer != console->active)
  719. {
  720. if (console->active) release_object( console->active );
  721. console->active = screen_buffer;
  722. generate_sb_initial_events( console );
  723. }
  724. else
  725. release_object( screen_buffer );
  726. }
  727. if (req->mask & SET_CONSOLE_INPUT_INFO_TITLE)
  728. {
  729. WCHAR *new_title = NULL;
  730. len = (len / sizeof(WCHAR)) * sizeof(WCHAR);
  731. if (len && !(new_title = memdup( title, len ))) goto error;
  732. free( console->title );
  733. console->title = new_title;
  734. console->title_len = len;
  735. evt.event = CONSOLE_RENDERER_TITLE_EVENT;
  736. console_input_events_append( console, &evt );
  737. }
  738. if (req->mask & SET_CONSOLE_INPUT_INFO_HISTORY_MODE)
  739. {
  740. console->history_mode = req->history_mode;
  741. }
  742. if ((req->mask & SET_CONSOLE_INPUT_INFO_HISTORY_SIZE) &&
  743. console->history_size != req->history_size)
  744. {
  745. struct history_line **mem = NULL;
  746. int i, delta;
  747. if (req->history_size)
  748. {
  749. if (!(mem = mem_alloc( req->history_size * sizeof(*mem) ))) goto error;
  750. memset( mem, 0, req->history_size * sizeof(*mem) );
  751. }
  752. delta = (console->history_index > req->history_size) ?
  753. (console->history_index - req->history_size) : 0;
  754. for (i = delta; i < console->history_index; i++)
  755. {
  756. mem[i - delta] = console->history[i];
  757. console->history[i] = NULL;
  758. }
  759. console->history_index -= delta;
  760. for (i = 0; i < console->history_size; i++)
  761. free( console->history[i] );
  762. free( console->history );
  763. console->history = mem;
  764. console->history_size = req->history_size;
  765. }
  766. if (req->mask & SET_CONSOLE_INPUT_INFO_EDITION_MODE)
  767. {
  768. console->edition_mode = req->edition_mode;
  769. }
  770. if (req->mask & SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE)
  771. {
  772. console->input_cp = req->input_cp;
  773. }
  774. if (req->mask & SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE)
  775. {
  776. console->output_cp = req->output_cp;
  777. }
  778. if (req->mask & SET_CONSOLE_INPUT_INFO_WIN)
  779. {
  780. console->win = req->win;
  781. }
  782. release_object( console );
  783. return 1;
  784. error:
  785. if (console) release_object( console );
  786. return 0;
  787. }
  788. /* resize a screen buffer */
  789. static int change_screen_buffer_size( struct screen_buffer *screen_buffer,
  790. int new_width, int new_height )
  791. {
  792. int i, old_width, old_height, copy_width, copy_height;
  793. char_info_t *new_data;
  794. if (!(new_data = malloc( new_width * new_height * sizeof(*new_data) )))
  795. {
  796. set_error( STATUS_NO_MEMORY );
  797. return 0;
  798. }
  799. old_width = screen_buffer->width;
  800. old_height = screen_buffer->height;
  801. copy_width = min( old_width, new_width );
  802. copy_height = min( old_height, new_height );
  803. /* copy all the rows */
  804. for (i = 0; i < copy_height; i++)
  805. {
  806. memcpy( &new_data[i * new_width], &screen_buffer->data[i * old_width],
  807. copy_width * sizeof(char_info_t) );
  808. }
  809. /* clear the end of each row */
  810. if (new_width > old_width)
  811. {
  812. /* fill first row */
  813. for (i = old_width; i < new_width; i++) new_data[i] = empty_char_info;
  814. /* and blast it to the other rows */
  815. for (i = 1; i < copy_height; i++)
  816. memcpy( &new_data[i * new_width + old_width], &new_data[old_width],
  817. (new_width - old_width) * sizeof(char_info_t) );
  818. }
  819. /* clear remaining rows */
  820. if (new_height > old_height)
  821. {
  822. /* fill first row */
  823. for (i = 0; i < new_width; i++) new_data[old_height * new_width + i] = empty_char_info;
  824. /* and blast it to the other rows */
  825. for (i = old_height+1; i < new_height; i++)
  826. memcpy( &new_data[i * new_width], &new_data[old_height * new_width],
  827. new_width * sizeof(char_info_t) );
  828. }
  829. free( screen_buffer->data );
  830. screen_buffer->data = new_data;
  831. screen_buffer->width = new_width;
  832. screen_buffer->height = new_height;
  833. return 1;
  834. }
  835. /* set misc screen buffer information */
  836. static int set_console_output_info( struct screen_buffer *screen_buffer,
  837. const struct set_console_output_info_request *req )
  838. {
  839. struct console_renderer_event evt;
  840. data_size_t font_name_len, offset;
  841. WCHAR *font_name;
  842. memset(&evt.u, 0, sizeof(evt.u));
  843. if (req->mask & SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM)
  844. {
  845. if (req->cursor_size < 1 || req->cursor_size > 100)
  846. {
  847. set_error( STATUS_INVALID_PARAMETER );
  848. return 0;
  849. }
  850. if (screen_buffer->cursor_size != req->cursor_size ||
  851. screen_buffer->cursor_visible != req->cursor_visible)
  852. {
  853. screen_buffer->cursor_size = req->cursor_size;
  854. screen_buffer->cursor_visible = req->cursor_visible;
  855. evt.event = CONSOLE_RENDERER_CURSOR_GEOM_EVENT;
  856. evt.u.cursor_geom.size = req->cursor_size;
  857. evt.u.cursor_geom.visible = req->cursor_visible;
  858. console_input_events_append( screen_buffer->input, &evt );
  859. }
  860. }
  861. if (req->mask & SET_CONSOLE_OUTPUT_INFO_CURSOR_POS)
  862. {
  863. if (req->cursor_x < 0 || req->cursor_x >= screen_buffer->width ||
  864. req->cursor_y < 0 || req->cursor_y >= screen_buffer->height)
  865. {
  866. set_error( STATUS_INVALID_PARAMETER );
  867. return 0;
  868. }
  869. if (screen_buffer->cursor_x != req->cursor_x || screen_buffer->cursor_y != req->cursor_y)
  870. {
  871. screen_buffer->cursor_x = req->cursor_x;
  872. screen_buffer->cursor_y = req->cursor_y;
  873. evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
  874. evt.u.cursor_pos.x = req->cursor_x;
  875. evt.u.cursor_pos.y = req->cursor_y;
  876. console_input_events_append( screen_buffer->input, &evt );
  877. }
  878. }
  879. if (req->mask & SET_CONSOLE_OUTPUT_INFO_SIZE)
  880. {
  881. unsigned cc;
  882. /* new screen-buffer cannot be smaller than actual window */
  883. if (req->width < screen_buffer->win.right - screen_buffer->win.left + 1 ||
  884. req->height < screen_buffer->win.bottom - screen_buffer->win.top + 1)
  885. {
  886. set_error( STATUS_INVALID_PARAMETER );
  887. return 0;
  888. }
  889. /* FIXME: there are also some basic minimum and max size to deal with */
  890. if (!change_screen_buffer_size( screen_buffer, req->width, req->height )) return 0;
  891. evt.event = CONSOLE_RENDERER_SB_RESIZE_EVENT;
  892. evt.u.resize.width = req->width;
  893. evt.u.resize.height = req->height;
  894. console_input_events_append( screen_buffer->input, &evt );
  895. evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
  896. evt.u.update.top = 0;
  897. evt.u.update.bottom = screen_buffer->height - 1;
  898. console_input_events_append( screen_buffer->input, &evt );
  899. /* scroll window to display sb */
  900. if (screen_buffer->win.right >= req->width)
  901. {
  902. screen_buffer->win.right -= screen_buffer->win.left;
  903. screen_buffer->win.left = 0;
  904. }
  905. if (screen_buffer->win.bottom >= req->height)
  906. {
  907. screen_buffer->win.bottom -= screen_buffer->win.top;
  908. screen_buffer->win.top = 0;
  909. }
  910. /* reset cursor if needed (normally, if cursor was outside of new sb, the
  911. * window has been shifted so that the new position of the cursor will be
  912. * visible */
  913. cc = 0;
  914. if (screen_buffer->cursor_x >= req->width)
  915. {
  916. screen_buffer->cursor_x = req->width - 1;
  917. cc++;
  918. }
  919. if (screen_buffer->cursor_y >= req->height)
  920. {
  921. screen_buffer->cursor_y = req->height - 1;
  922. cc++;
  923. }
  924. if (cc)
  925. {
  926. evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
  927. evt.u.cursor_pos.x = req->cursor_x;
  928. evt.u.cursor_pos.y = req->cursor_y;
  929. console_input_events_append( screen_buffer->input, &evt );
  930. }
  931. if (screen_buffer == screen_buffer->input->active &&
  932. screen_buffer->input->mode & ENABLE_WINDOW_INPUT)
  933. {
  934. INPUT_RECORD ir;
  935. ir.EventType = WINDOW_BUFFER_SIZE_EVENT;
  936. ir.Event.WindowBufferSizeEvent.dwSize.X = req->width;
  937. ir.Event.WindowBufferSizeEvent.dwSize.Y = req->height;
  938. write_console_input( screen_buffer->input, 1, &ir );
  939. }
  940. }
  941. if (req->mask & SET_CONSOLE_OUTPUT_INFO_ATTR)
  942. {
  943. screen_buffer->attr = req->attr;
  944. }
  945. if (req->mask & SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR)
  946. {
  947. screen_buffer->popup_attr = req->popup_attr;
  948. }
  949. if (req->mask & SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW)
  950. {
  951. if (req->win_left < 0 || req->win_left > req->win_right ||
  952. req->win_right >= screen_buffer->width ||
  953. req->win_top < 0 || req->win_top > req->win_bottom ||
  954. req->win_bottom >= screen_buffer->height)
  955. {
  956. set_error( STATUS_INVALID_PARAMETER );
  957. return 0;
  958. }
  959. if (screen_buffer->win.left != req->win_left || screen_buffer->win.top != req->win_top ||
  960. screen_buffer->win.right != req->win_right || screen_buffer->win.bottom != req->win_bottom)
  961. {
  962. screen_buffer->win.left = req->win_left;
  963. screen_buffer->win.top = req->win_top;
  964. screen_buffer->win.right = req->win_right;
  965. screen_buffer->win.bottom = req->win_bottom;
  966. evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
  967. evt.u.display.left = req->win_left;
  968. evt.u.display.top = req->win_top;
  969. evt.u.display.width = req->win_right - req->win_left + 1;
  970. evt.u.display.height = req->win_bottom - req->win_top + 1;
  971. console_input_events_append( screen_buffer->input, &evt );
  972. }
  973. }
  974. if (req->mask & SET_CONSOLE_OUTPUT_INFO_MAX_SIZE)
  975. {
  976. screen_buffer->max_width = req->max_width;
  977. screen_buffer->max_height = req->max_height;
  978. }
  979. if (req->mask & SET_CONSOLE_OUTPUT_INFO_COLORTABLE)
  980. {
  981. memcpy( screen_buffer->color_map, get_req_data(), min( get_req_data_size(), sizeof(screen_buffer->color_map) ));
  982. }
  983. if (req->mask & SET_CONSOLE_OUTPUT_INFO_FONT)
  984. {
  985. screen_buffer->font.width = req->font_width;
  986. screen_buffer->font.height = req->font_height;
  987. screen_buffer->font.weight = req->font_weight;
  988. screen_buffer->font.pitch_family = req->font_pitch_family;
  989. offset = req->mask & SET_CONSOLE_OUTPUT_INFO_COLORTABLE ? sizeof(screen_buffer->color_map) : 0;
  990. if (get_req_data_size() > offset)
  991. {
  992. font_name_len = (get_req_data_size() - offset) / sizeof(WCHAR) * sizeof(WCHAR);
  993. font_name = mem_alloc( font_name_len );
  994. if (font_name)
  995. {
  996. memcpy( font_name, (char *)get_req_data() + offset, font_name_len );
  997. free( screen_buffer->font.face_name );
  998. screen_buffer->font.face_name = font_name;
  999. screen_buffer->font.face_len = font_name_len;
  1000. }
  1001. }
  1002. }
  1003. return 1;
  1004. }
  1005. /* appends a new line to history (history is a fixed size array) */
  1006. static void console_input_append_hist( struct console_input* console, const WCHAR* buf, data_size_t len )
  1007. {
  1008. struct history_line *ptr;
  1009. if (!console || !console->history_size)
  1010. {
  1011. set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
  1012. return;
  1013. }
  1014. len = (len / sizeof(WCHAR)) * sizeof(WCHAR);
  1015. if (console->history_mode && console->history_index &&
  1016. console->history[console->history_index - 1]->len == len &&
  1017. !memcmp( console->history[console->history_index - 1]->text, buf, len ))
  1018. {
  1019. /* don't duplicate entry */
  1020. set_error( STATUS_ALIAS_EXISTS );
  1021. return;
  1022. }
  1023. if (!(ptr = mem_alloc( offsetof( struct history_line, text[len / sizeof(WCHAR)] )))) return;
  1024. ptr->len = len;
  1025. memcpy( ptr->text, buf, len );
  1026. if (console->history_index < console->history_size)
  1027. {
  1028. console->history[console->history_index++] = ptr;
  1029. }
  1030. else
  1031. {
  1032. free( console->history[0]) ;
  1033. memmove( &console->history[0], &console->history[1],
  1034. (console->history_size - 1) * sizeof(*console->history) );
  1035. console->history[console->history_size - 1] = ptr;
  1036. }
  1037. }
  1038. /* returns a line from the cache */
  1039. static data_size_t console_input_get_hist( struct console_input *console, int index )
  1040. {
  1041. data_size_t ret = 0;
  1042. if (index >= console->history_index) set_error( STATUS_INVALID_PARAMETER );
  1043. else
  1044. {
  1045. ret = console->history[index]->len;
  1046. set_reply_data( console->history[index]->text, min( ret, get_reply_max_size() ));
  1047. }
  1048. return ret;
  1049. }
  1050. /* dumb dump */
  1051. static void console_input_dump( struct object *obj, int verbose )
  1052. {
  1053. struct console_input *console = (struct console_input *)obj;
  1054. assert( obj->ops == &console_input_ops );
  1055. fprintf( stderr, "Console input active=%p evt=%p\n",
  1056. console->active, console->evt );
  1057. }
  1058. static void console_input_destroy( struct object *obj )
  1059. {
  1060. struct console_input* console_in = (struct console_input *)obj;
  1061. struct screen_buffer* curr;
  1062. int i;
  1063. assert( obj->ops == &console_input_ops );
  1064. free( console_in->title );
  1065. free( console_in->records );
  1066. if (console_in->active) release_object( console_in->active );
  1067. console_in->active = NULL;
  1068. LIST_FOR_EACH_ENTRY( curr, &screen_buffer_list, struct screen_buffer, entry )
  1069. {
  1070. if (curr->input == console_in) curr->input = NULL;
  1071. }
  1072. if (console_in->evt)
  1073. {
  1074. release_object( console_in->evt );
  1075. console_in->evt = NULL;
  1076. }
  1077. if (console_in->event)
  1078. release_object( console_in->event );
  1079. if (console_in->fd)
  1080. release_object( console_in->fd );
  1081. for (i = 0; i < console_in->history_size; i++)
  1082. free( console_in->history[i] );
  1083. free( console_in->history );
  1084. }
  1085. static void screen_buffer_dump( struct object *obj, int verbose )
  1086. {
  1087. struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
  1088. assert( obj->ops == &screen_buffer_ops );
  1089. fprintf(stderr, "Console screen buffer input=%p\n", screen_buffer->input );
  1090. }
  1091. static void screen_buffer_destroy( struct object *obj )
  1092. {
  1093. struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
  1094. assert( obj->ops == &screen_buffer_ops );
  1095. list_remove( &screen_buffer->entry );
  1096. if (screen_buffer->input && screen_buffer->input->active == screen_buffer)
  1097. {
  1098. struct screen_buffer *sb;
  1099. screen_buffer->input->active = NULL;
  1100. LIST_FOR_EACH_ENTRY( sb, &screen_buffer_list, struct screen_buffer, entry )
  1101. {
  1102. if (sb->input == screen_buffer->input)
  1103. {
  1104. sb->input->active = sb;
  1105. break;
  1106. }
  1107. }
  1108. }
  1109. if (screen_buffer->fd) release_object( screen_buffer->fd );
  1110. free( screen_buffer->data );
  1111. free( screen_buffer->font.face_name );
  1112. }
  1113. static struct fd *screen_buffer_get_fd( struct object *obj )
  1114. {
  1115. struct screen_buffer *screen_buffer = (struct screen_buffer*)obj;
  1116. assert( obj->ops == &screen_buffer_ops );
  1117. if (screen_buffer->fd)
  1118. return (struct fd*)grab_object( screen_buffer->fd );
  1119. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1120. return NULL;
  1121. }
  1122. /* write data into a screen buffer */
  1123. static int write_console_output( struct screen_buffer *screen_buffer, data_size_t size,
  1124. const void* data, enum char_info_mode mode,
  1125. int x, int y, int wrap )
  1126. {
  1127. unsigned int i;
  1128. char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
  1129. if (y >= screen_buffer->height) return 0;
  1130. if (wrap)
  1131. end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
  1132. else
  1133. end = screen_buffer->data + (y+1) * screen_buffer->width;
  1134. switch(mode)
  1135. {
  1136. case CHAR_INFO_MODE_TEXT:
  1137. {
  1138. const WCHAR *ptr = data;
  1139. for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->ch = ptr[i];
  1140. }
  1141. break;
  1142. case CHAR_INFO_MODE_ATTR:
  1143. {
  1144. const unsigned short *ptr = data;
  1145. for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->attr = ptr[i];
  1146. }
  1147. break;
  1148. case CHAR_INFO_MODE_TEXTATTR:
  1149. {
  1150. const char_info_t *ptr = data;
  1151. for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) *dest = ptr[i];
  1152. }
  1153. break;
  1154. case CHAR_INFO_MODE_TEXTSTDATTR:
  1155. {
  1156. const WCHAR *ptr = data;
  1157. for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++)
  1158. {
  1159. dest->ch = ptr[i];
  1160. dest->attr = screen_buffer->attr;
  1161. }
  1162. }
  1163. break;
  1164. default:
  1165. set_error( STATUS_INVALID_PARAMETER );
  1166. return 0;
  1167. }
  1168. if (i && screen_buffer == screen_buffer->input->active)
  1169. {
  1170. struct console_renderer_event evt;
  1171. evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
  1172. memset(&evt.u, 0, sizeof(evt.u));
  1173. evt.u.update.top = y + x / screen_buffer->width;
  1174. evt.u.update.bottom = y + (x + i - 1) / screen_buffer->width;
  1175. console_input_events_append( screen_buffer->input, &evt );
  1176. }
  1177. return i;
  1178. }
  1179. /* fill a screen buffer with uniform data */
  1180. static int fill_console_output( struct screen_buffer *screen_buffer, char_info_t data,
  1181. enum char_info_mode mode, int x, int y, int count, int wrap )
  1182. {
  1183. int i;
  1184. char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
  1185. if (y >= screen_buffer->height) return 0;
  1186. if (wrap)
  1187. end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
  1188. else
  1189. end = screen_buffer->data + (y+1) * screen_buffer->width;
  1190. if (count > end - dest) count = end - dest;
  1191. switch(mode)
  1192. {
  1193. case CHAR_INFO_MODE_TEXT:
  1194. for (i = 0; i < count; i++) dest[i].ch = data.ch;
  1195. break;
  1196. case CHAR_INFO_MODE_ATTR:
  1197. for (i = 0; i < count; i++) dest[i].attr = data.attr;
  1198. break;
  1199. case CHAR_INFO_MODE_TEXTATTR:
  1200. for (i = 0; i < count; i++) dest[i] = data;
  1201. break;
  1202. case CHAR_INFO_MODE_TEXTSTDATTR:
  1203. for (i = 0; i < count; i++)
  1204. {
  1205. dest[i].ch = data.ch;
  1206. dest[i].attr = screen_buffer->attr;
  1207. }
  1208. break;
  1209. default:
  1210. set_error( STATUS_INVALID_PARAMETER );
  1211. return 0;
  1212. }
  1213. if (count && screen_buffer == screen_buffer->input->active)
  1214. {
  1215. struct console_renderer_event evt;
  1216. evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
  1217. memset(&evt.u, 0, sizeof(evt.u));
  1218. evt.u.update.top = y;
  1219. evt.u.update.bottom = (y * screen_buffer->width + x + count - 1) / screen_buffer->width;
  1220. console_input_events_append( screen_buffer->input, &evt );
  1221. }
  1222. return i;
  1223. }
  1224. /* read data from a screen buffer */
  1225. static void read_console_output( struct screen_buffer *screen_buffer, int x, int y,
  1226. enum char_info_mode mode, int wrap )
  1227. {
  1228. int i;
  1229. char_info_t *end, *src = screen_buffer->data + y * screen_buffer->width + x;
  1230. if (y >= screen_buffer->height) return;
  1231. if (wrap)
  1232. end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
  1233. else
  1234. end = screen_buffer->data + (y+1) * screen_buffer->width;
  1235. switch(mode)
  1236. {
  1237. case CHAR_INFO_MODE_TEXT:
  1238. {
  1239. WCHAR *data;
  1240. int count = min( end - src, get_reply_max_size() / sizeof(*data) );
  1241. if ((data = set_reply_data_size( count * sizeof(*data) )))
  1242. {
  1243. for (i = 0; i < count; i++) data[i] = src[i].ch;
  1244. }
  1245. }
  1246. break;
  1247. case CHAR_INFO_MODE_ATTR:
  1248. {
  1249. unsigned short *data;
  1250. int count = min( end - src, get_reply_max_size() / sizeof(*data) );
  1251. if ((data = set_reply_data_size( count * sizeof(*data) )))
  1252. {
  1253. for (i = 0; i < count; i++) data[i] = src[i].attr;
  1254. }
  1255. }
  1256. break;
  1257. case CHAR_INFO_MODE_TEXTATTR:
  1258. {
  1259. char_info_t *data;
  1260. int count = min( end - src, get_reply_max_size() / sizeof(*data) );
  1261. if ((data = set_reply_data_size( count * sizeof(*data) )))
  1262. {
  1263. for (i = 0; i < count; i++) data[i] = src[i];
  1264. }
  1265. }
  1266. break;
  1267. default:
  1268. set_error( STATUS_INVALID_PARAMETER );
  1269. break;
  1270. }
  1271. }
  1272. /* scroll parts of a screen buffer */
  1273. static void scroll_console_output( struct screen_buffer *screen_buffer, int xsrc, int ysrc, int xdst, int ydst,
  1274. int w, int h )
  1275. {
  1276. int j;
  1277. char_info_t *psrc, *pdst;
  1278. struct console_renderer_event evt;
  1279. if (xsrc < 0 || ysrc < 0 || xdst < 0 || ydst < 0 ||
  1280. xsrc + w > screen_buffer->width ||
  1281. xdst + w > screen_buffer->width ||
  1282. ysrc + h > screen_buffer->height ||
  1283. ydst + h > screen_buffer->height ||
  1284. w == 0 || h == 0)
  1285. {
  1286. set_error( STATUS_INVALID_PARAMETER );
  1287. return;
  1288. }
  1289. if (ysrc < ydst)
  1290. {
  1291. psrc = &screen_buffer->data[(ysrc + h - 1) * screen_buffer->width + xsrc];
  1292. pdst = &screen_buffer->data[(ydst + h - 1) * screen_buffer->width + xdst];
  1293. for (j = h; j > 0; j--)
  1294. {
  1295. memcpy(pdst, psrc, w * sizeof(*pdst) );
  1296. pdst -= screen_buffer->width;
  1297. psrc -= screen_buffer->width;
  1298. }
  1299. }
  1300. else
  1301. {
  1302. psrc = &screen_buffer->data[ysrc * screen_buffer->width + xsrc];
  1303. pdst = &screen_buffer->data[ydst * screen_buffer->width + xdst];
  1304. for (j = 0; j < h; j++)
  1305. {
  1306. /* we use memmove here because when psrc and pdst are the same,
  1307. * copies are done on the same row, so the dst and src blocks
  1308. * can overlap */
  1309. memmove( pdst, psrc, w * sizeof(*pdst) );
  1310. pdst += screen_buffer->width;
  1311. psrc += screen_buffer->width;
  1312. }
  1313. }
  1314. /* FIXME: this could be enhanced, by signalling scroll */
  1315. evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
  1316. memset(&evt.u, 0, sizeof(evt.u));
  1317. evt.u.update.top = min(ysrc, ydst);
  1318. evt.u.update.bottom = max(ysrc, ydst) + h - 1;
  1319. console_input_events_append( screen_buffer->input, &evt );
  1320. }
  1321. /* allocate a console for the renderer */
  1322. DECL_HANDLER(alloc_console)
  1323. {
  1324. obj_handle_t in = 0;
  1325. obj_handle_t evt = 0;
  1326. struct process *process;
  1327. struct thread *renderer;
  1328. struct console_input *console;
  1329. int fd;
  1330. int attach = 0;
  1331. if (req->input_fd != -1)
  1332. {
  1333. if ((fd = thread_get_inflight_fd( current, req->input_fd )) == -1)
  1334. {
  1335. set_error( STATUS_INVALID_PARAMETER );
  1336. return;
  1337. }
  1338. }
  1339. else fd = -1;
  1340. switch (req->pid)
  1341. {
  1342. case 0:
  1343. /* renderer is current, console to be attached to parent process */
  1344. renderer = current;
  1345. if (!(process = get_process_from_id( current->process->parent_id )))
  1346. {
  1347. if (fd != -1) close( fd );
  1348. set_error( STATUS_ACCESS_DENIED );
  1349. return;
  1350. }
  1351. attach = 1;
  1352. break;
  1353. case 0xffffffff:
  1354. /* no renderer, console to be attached to current process */
  1355. renderer = NULL;
  1356. process = current->process;
  1357. grab_object( process );
  1358. attach = 1;
  1359. break;
  1360. default:
  1361. /* renderer is current, console to be attached to req->pid */
  1362. renderer = current;
  1363. if (!(process = get_process_from_id( req->pid )))
  1364. {
  1365. if (fd != -1) close( fd );
  1366. return;
  1367. }
  1368. }
  1369. if (attach && process->console)
  1370. {
  1371. if (fd != -1) close( fd );
  1372. set_error( STATUS_ACCESS_DENIED );
  1373. goto the_end;
  1374. }
  1375. if ((console = (struct console_input*)create_console_input( renderer, fd )))
  1376. {
  1377. if ((in = alloc_handle( current->process, console, req->access, req->attributes )))
  1378. {
  1379. if (!console->evt ||
  1380. (evt = alloc_handle( current->process, console->evt, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, 0 )))
  1381. {
  1382. if (attach)
  1383. {
  1384. process->console = (struct console_input*)grab_object( console );
  1385. console->num_proc++;
  1386. }
  1387. reply->handle_in = in;
  1388. reply->event = evt;
  1389. release_object( console );
  1390. goto the_end;
  1391. }
  1392. close_handle( current->process, in );
  1393. }
  1394. release_object( console );
  1395. }
  1396. the_end:
  1397. release_object( process );
  1398. }
  1399. /* free the console of the current process */
  1400. DECL_HANDLER(free_console)
  1401. {
  1402. free_console( current->process );
  1403. }
  1404. /* let the renderer peek the events it's waiting on */
  1405. DECL_HANDLER(get_console_renderer_events)
  1406. {
  1407. struct console_input_events *evt;
  1408. evt = (struct console_input_events *)get_handle_obj( current->process, req->handle,
  1409. FILE_READ_PROPERTIES, &console_input_events_ops );
  1410. if (!evt) return;
  1411. console_input_events_get( evt );
  1412. release_object( evt );
  1413. }
  1414. /* open a handle to the process console */
  1415. DECL_HANDLER(open_console)
  1416. {
  1417. struct object *obj = NULL;
  1418. reply->handle = 0;
  1419. if (!req->from)
  1420. {
  1421. if (current->process->console)
  1422. obj = grab_object( (struct object*)current->process->console );
  1423. }
  1424. else if (req->from == (obj_handle_t)1)
  1425. {
  1426. if (current->process->console && current->process->console->active)
  1427. obj = grab_object( (struct object*)current->process->console->active );
  1428. }
  1429. else if ((obj = get_handle_obj( current->process, req->from,
  1430. FILE_READ_PROPERTIES|FILE_WRITE_PROPERTIES, &console_input_ops )))
  1431. {
  1432. struct console_input *console = (struct console_input *)obj;
  1433. obj = (console->active) ? grab_object( console->active ) : NULL;
  1434. release_object( console );
  1435. }
  1436. /* FIXME: req->share is not used (as in screen buffer creation) */
  1437. if (obj)
  1438. {
  1439. reply->handle = alloc_handle( current->process, obj, req->access, req->attributes );
  1440. release_object( obj );
  1441. }
  1442. else if (!get_error()) set_error( STATUS_ACCESS_DENIED );
  1443. }
  1444. /* attach to a other process's console */
  1445. DECL_HANDLER(attach_console)
  1446. {
  1447. struct process *process;
  1448. if (current->process->console)
  1449. {
  1450. set_error( STATUS_ACCESS_DENIED );
  1451. return;
  1452. }
  1453. process = get_process_from_id( req->pid == ATTACH_PARENT_PROCESS
  1454. ? current->process->parent_id : req->pid );
  1455. if (!process) return;
  1456. if (process->console && process->console->active)
  1457. {
  1458. reply->std_in = alloc_handle( current->process, process->console, GENERIC_READ, 0 );
  1459. if (!reply->std_in) goto error;
  1460. reply->std_out = alloc_handle( current->process, process->console->active, GENERIC_WRITE, 0 );
  1461. if (!reply->std_out) goto error;
  1462. reply->std_err = alloc_handle( current->process, process->console->active, GENERIC_WRITE, 0 );
  1463. if (!reply->std_err) goto error;
  1464. current->process->console = (struct console_input *)grab_object( process->console );
  1465. current->process->console->num_proc++;
  1466. }
  1467. else
  1468. {
  1469. set_error( STATUS_INVALID_HANDLE );
  1470. }
  1471. release_object( process );
  1472. return;
  1473. error:
  1474. if (reply->std_in) close_handle( current->process, reply->std_in );
  1475. if (reply->std_out) close_handle( current->process, reply->std_out );
  1476. release_object( process );
  1477. }
  1478. /* set info about a console input */
  1479. DECL_HANDLER(set_console_input_info)
  1480. {
  1481. set_console_input_info( req, get_req_data(), get_req_data_size() );
  1482. }
  1483. /* get info about a console (output only) */
  1484. DECL_HANDLER(get_console_input_info)
  1485. {
  1486. struct console_input *console;
  1487. if (!(console = console_input_get( req->handle, FILE_READ_PROPERTIES ))) return;
  1488. if (console->title) set_reply_data( console->title, min( console->title_len, get_reply_max_size() ));
  1489. reply->history_mode = console->history_mode;
  1490. reply->history_size = console->history_size;
  1491. reply->history_index = console->history_index;
  1492. reply->edition_mode = console->edition_mode;
  1493. reply->input_cp = console->input_cp;
  1494. reply->output_cp = console->output_cp;
  1495. reply->win = console->win;
  1496. release_object( console );
  1497. }
  1498. /* get a console mode (input or output) */
  1499. DECL_HANDLER(get_console_mode)
  1500. {
  1501. reply->mode = get_console_mode( req->handle );
  1502. }
  1503. /* set a console mode (input or output) */
  1504. DECL_HANDLER(set_console_mode)
  1505. {
  1506. set_console_mode( req->handle, req->mode );
  1507. }
  1508. /* add input records to a console input queue */
  1509. DECL_HANDLER(write_console_input)
  1510. {
  1511. struct console_input *console;
  1512. reply->written = 0;
  1513. if (!(console = (struct console_input *)get_handle_obj( current->process, req->handle,
  1514. FILE_WRITE_PROPERTIES, &console_input_ops )))
  1515. return;
  1516. reply->written = write_console_input( console, get_req_data_size() / sizeof(INPUT_RECORD),
  1517. get_req_data() );
  1518. release_object( console );
  1519. }
  1520. /* fetch input records from a console input queue */
  1521. DECL_HANDLER(read_console_input)
  1522. {
  1523. int count = get_reply_max_size() / sizeof(INPUT_RECORD);
  1524. reply->read = read_console_input( req->handle, count, req->flush );
  1525. }
  1526. /* appends a string to console's history */
  1527. DECL_HANDLER(append_console_input_history)
  1528. {
  1529. struct console_input *console;
  1530. if (!(console = console_input_get( req->handle, FILE_WRITE_PROPERTIES ))) return;
  1531. console_input_append_hist( console, get_req_data(), get_req_data_size() / sizeof(WCHAR) );
  1532. release_object( console );
  1533. }
  1534. /* appends a string to console's history */
  1535. DECL_HANDLER(get_console_input_history)
  1536. {
  1537. struct console_input *console;
  1538. if (!(console = console_input_get( req->handle, FILE_READ_PROPERTIES ))) return;
  1539. reply->total = console_input_get_hist( console, req->index );
  1540. release_object( console );
  1541. }
  1542. /* creates a screen buffer */
  1543. DECL_HANDLER(create_console_output)
  1544. {
  1545. struct console_input* console;
  1546. struct screen_buffer* screen_buffer;
  1547. int fd;
  1548. if (req->fd != -1)
  1549. {
  1550. if ((fd = thread_get_inflight_fd( current, req->fd )) == -1)
  1551. {
  1552. set_error( STATUS_INVALID_HANDLE );
  1553. return;
  1554. }
  1555. }
  1556. else fd = -1;
  1557. if (!(console = console_input_get( req->handle_in, FILE_WRITE_PROPERTIES )))
  1558. {
  1559. if (fd != -1) close( fd );
  1560. return;
  1561. }
  1562. if (console_input_is_bare( console ) ^ (fd != -1))
  1563. {
  1564. if (fd != -1) close( fd );
  1565. release_object( console );
  1566. set_error( STATUS_INVALID_HANDLE );
  1567. return;
  1568. }
  1569. screen_buffer = create_console_output( console, fd );
  1570. if (screen_buffer)
  1571. {
  1572. /* FIXME: should store sharing and test it when opening the CONOUT$ device
  1573. * see file.c on how this could be done */
  1574. reply->handle_out = alloc_handle( current->process, screen_buffer, req->access, req->attributes );
  1575. release_object( screen_buffer );
  1576. }
  1577. release_object( console );
  1578. }
  1579. /* set info about a console screen buffer */
  1580. DECL_HANDLER(set_console_output_info)
  1581. {
  1582. struct screen_buffer *screen_buffer;
  1583. if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
  1584. FILE_WRITE_PROPERTIES, &screen_buffer_ops)))
  1585. {
  1586. set_console_output_info( screen_buffer, req );
  1587. release_object( screen_buffer );
  1588. }
  1589. }
  1590. /* get info about a console screen buffer */
  1591. DECL_HANDLER(get_console_output_info)
  1592. {
  1593. struct screen_buffer *screen_buffer;
  1594. void *data;
  1595. data_size_t total;
  1596. if ((screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, req->handle,
  1597. FILE_READ_PROPERTIES, &screen_buffer_ops)))
  1598. {
  1599. reply->cursor_size = screen_buffer->cursor_size;
  1600. reply->cursor_visible = screen_buffer->cursor_visible;
  1601. reply->cursor_x = screen_buffer->cursor_x;
  1602. reply->cursor_y = screen_buffer->cursor_y;
  1603. reply->width = screen_buffer->width;
  1604. reply->height = screen_buffer->height;
  1605. reply->attr = screen_buffer->attr;
  1606. reply->popup_attr = screen_buffer->popup_attr;
  1607. reply->win_left = screen_buffer->win.left;
  1608. reply->win_top = screen_buffer->win.top;
  1609. reply->win_right = screen_buffer->win.right;
  1610. reply->win_bottom = screen_buffer->win.bottom;
  1611. reply->max_width = screen_buffer->max_width;
  1612. reply->max_height = screen_buffer->max_height;
  1613. reply->font_width = screen_buffer->font.width;
  1614. reply->font_height = screen_buffer->font.height;
  1615. reply->font_weight = screen_buffer->font.weight;
  1616. reply->font_pitch_family = screen_buffer->font.pitch_family;
  1617. total = min( sizeof(screen_buffer->color_map) + screen_buffer->font.face_len, get_reply_max_size() );
  1618. if (total)
  1619. {
  1620. data = set_reply_data_size( total );
  1621. memcpy( data, screen_buffer->color_map, min( total, sizeof(screen_buffer->color_map) ));
  1622. if (screen_buffer->font.face_len && total > sizeof(screen_buffer->color_map))
  1623. {
  1624. memcpy( (char *)data + sizeof(screen_buffer->color_map), screen_buffer->font.face_name,
  1625. min( total - sizeof(screen_buffer->color_map), screen_buffer->font.face_len ));
  1626. }
  1627. }
  1628. release_object( screen_buffer );
  1629. }
  1630. }
  1631. /* read data (chars & attrs) from a screen buffer */
  1632. DECL_HANDLER(read_console_output)
  1633. {
  1634. struct screen_buffer *screen_buffer;
  1635. if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
  1636. FILE_READ_DATA, &screen_buffer_ops )))
  1637. {
  1638. if (console_input_is_bare( screen_buffer->input ))
  1639. {
  1640. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1641. release_object( screen_buffer );
  1642. return;
  1643. }
  1644. read_console_output( screen_buffer, req->x, req->y, req->mode, req->wrap );
  1645. reply->width = screen_buffer->width;
  1646. reply->height = screen_buffer->height;
  1647. release_object( screen_buffer );
  1648. }
  1649. }
  1650. /* write data (char and/or attrs) to a screen buffer */
  1651. DECL_HANDLER(write_console_output)
  1652. {
  1653. struct screen_buffer *screen_buffer;
  1654. if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
  1655. FILE_WRITE_DATA, &screen_buffer_ops)))
  1656. {
  1657. if (console_input_is_bare( screen_buffer->input ))
  1658. {
  1659. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1660. release_object( screen_buffer );
  1661. return;
  1662. }
  1663. reply->written = write_console_output( screen_buffer, get_req_data_size(), get_req_data(),
  1664. req->mode, req->x, req->y, req->wrap );
  1665. reply->width = screen_buffer->width;
  1666. reply->height = screen_buffer->height;
  1667. release_object( screen_buffer );
  1668. }
  1669. }
  1670. /* fill a screen buffer with constant data (chars and/or attributes) */
  1671. DECL_HANDLER(fill_console_output)
  1672. {
  1673. struct screen_buffer *screen_buffer;
  1674. if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
  1675. FILE_WRITE_DATA, &screen_buffer_ops)))
  1676. {
  1677. if (console_input_is_bare( screen_buffer->input ))
  1678. {
  1679. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1680. release_object( screen_buffer );
  1681. return;
  1682. }
  1683. reply->written = fill_console_output( screen_buffer, req->data, req->mode,
  1684. req->x, req->y, req->count, req->wrap );
  1685. release_object( screen_buffer );
  1686. }
  1687. }
  1688. /* move a rect of data in a screen buffer */
  1689. DECL_HANDLER(move_console_output)
  1690. {
  1691. struct screen_buffer *screen_buffer;
  1692. if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
  1693. FILE_WRITE_DATA, &screen_buffer_ops)))
  1694. {
  1695. if (console_input_is_bare( screen_buffer->input ))
  1696. {
  1697. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1698. release_object( screen_buffer );
  1699. return;
  1700. }
  1701. scroll_console_output( screen_buffer, req->x_src, req->y_src, req->x_dst, req->y_dst,
  1702. req->w, req->h );
  1703. release_object( screen_buffer );
  1704. }
  1705. }
  1706. /* sends a signal to a console (process, group...) */
  1707. DECL_HANDLER(send_console_signal)
  1708. {
  1709. process_id_t group;
  1710. group = req->group_id ? req->group_id : current->process->group_id;
  1711. if (!group)
  1712. set_error( STATUS_INVALID_PARAMETER );
  1713. else
  1714. propagate_console_signal( current->process->console, req->signal, group );
  1715. }
  1716. /* get console which renderer is 'current' */
  1717. static int cgwe_enum( struct process* process, void* user)
  1718. {
  1719. if (process->console && process->console->renderer == current)
  1720. {
  1721. *(struct console_input**)user = (struct console_input *)grab_object( process->console );
  1722. return 1;
  1723. }
  1724. return 0;
  1725. }
  1726. DECL_HANDLER(get_console_wait_event)
  1727. {
  1728. struct console_input* console = NULL;
  1729. struct object *obj;
  1730. if (req->handle)
  1731. {
  1732. if (!(obj = get_handle_obj( current->process, req->handle, FILE_READ_PROPERTIES, NULL ))) return;
  1733. if (obj->ops == &console_input_ops)
  1734. console = (struct console_input *)grab_object( obj );
  1735. else if (obj->ops == &screen_buffer_ops)
  1736. console = (struct console_input *)grab_object( ((struct screen_buffer *)obj)->input );
  1737. else
  1738. set_error( STATUS_OBJECT_TYPE_MISMATCH );
  1739. release_object( obj );
  1740. }
  1741. else if (current->process->console)
  1742. console = (struct console_input *)grab_object( current->process->console );
  1743. else enum_processes(cgwe_enum, &console);
  1744. if (console)
  1745. {
  1746. reply->event = alloc_handle( current->process, console->event, EVENT_ALL_ACCESS, 0 );
  1747. release_object( console );
  1748. }
  1749. else set_error( STATUS_INVALID_PARAMETER );
  1750. }