123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959(** The Qubes wire protocol details. *)(** for more details, see qubes-gui-common/include/qubes-gui-protocol.h *)letof_int32_lei=letb=Bytes.create4inBytes.set_int32_leb0i;Bytes.unsafe_to_stringb(* String.get_* exixt since 4.13, this stub will be removed when the min
Ocaml version will match *)letget_int32_les=Bytes.get_int32_le(Bytes.unsafe_of_strings)letget_int32_bes=Bytes.get_int32_be(Bytes.unsafe_of_strings)letget_uint8s=Bytes.get_uint8(Bytes.unsafe_of_strings)moduletypeFRAMING=sigvalheader_size:intvalbody_size_from_header:string->intendmoduleQrexec=structtypemsg_header={ty:int32;len:int32;}letget_msg_header_tyh=get_int32_leh0(* let set_msg_header_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_header_lenh=get_int32_leh4(* let set_msg_heade.r_len h vString= Bytes.set_int32_le h 4 v *)letsizeof_msg_header=8typepeer_info={version:int32;}letget_peer_info_versionh=get_int32_leh0(* let set_peer_info_version h v = Bytes.set_int32_le h 0 v *)letsizeof_peer_info=4typeexec_params={connect_domain:int32;connect_port:int32;(* rest of message is command line *)}letget_exec_params_connect_domainh=get_int32_leh0(* let set_exec_params_connect_domain h v = Bytes.set_int32_le h 0 v *)letget_exec_params_connect_porth=get_int32_leh4(* let set_exec_params_connect_port h v = Bytes.set_int32_le h 4 v *)letsizeof_exec_params=8typeexit_status={return_code:int32;}letget_exit_status_return_codeh=get_int32_leh0(* let set_exit_status_return_code h v = Bytes.set_int32_le h 0 v *)letsizeof_exit_status=4typetrigger_service_params={service_name:string;(* [@len 64]; *)target_domain:string;(* [@len 32]; *)request_id:string;(* [@len 32] *)}letget_trigger_service_params_service_nameh=String.subh064(* let set_trigger_service_params_service_name v ofs h = Bytes.blit_string v 0 h ofs 64 *)letget_trigger_service_params_target_domainh=String.subh6432(* let set_trigger_service_params_target_domain v ofs h = Bytes.blit_string v 0 h (64+ofs) 32 *)letget_trigger_service_params_request_idh=String.subh9632(* let set_trigger_service_params_request_id v ofs h = Bytes.blit_string v 0 h (96+ofs) 32 *)letsizeof_trigger_service_params=64+32+32typetrigger_service_params3={target_domain:string;(* [@len 64]; *)request_id:string;(* [@len 32] *)(* rest of message is service name *)}letget_trigger_service_params3_target_domainh=String.subh064(* let set_trigger_service_params3_target_domain v ofs h = Bytes.blit_string v 0 h ofs 64 *)letget_trigger_service_params3_request_idh=String.subh6432(* let set_trigger_service_params3_request_id v ofs h = Bytes.blit_string v 0 h (64+ofs) 32 *)letsizeof_trigger_service_params3=64+32typemsg_type=[`Exec_cmdline|`Just_exec|`Service_connect|`Service_refused|`Trigger_service|`Connection_terminated|`Trigger_service3|`Hello|`Data_stdin|`Data_stdout|`Data_stderr|`Data_exit_code]lettype_of_int=function|0x190l->`Data_stdin|0x191l->`Data_stdout|0x192l->`Data_stderr|0x193l->`Data_exit_code|0x200l->`Exec_cmdline|0x201l->`Just_exec|0x202l->`Service_connect|0x203l->`Service_refused|0x210l->`Trigger_service|0x211l->`Connection_terminated|0x212l->`Trigger_service3|0x300l->`Hello|x->`Unknownxletint_of_type=function|`Data_stdin->0x190l|`Data_stdout->0x191l|`Data_stderr->0x192l|`Data_exit_code->0x193l|`Exec_cmdline->0x200l|`Just_exec->0x201l|`Service_connect->0x202l|`Service_refused->0x203l|`Trigger_service->0x210l|`Connection_terminated->0x211l|`Trigger_service3->0x212l|`Hello->0x300l|`Unknownx->xletstring_of_type=function|`Data_stdin->"DATA_STDIN"|`Data_stdout->"DATA_STDOUT"|`Data_stderr->"DATA_STDERR"|`Data_exit_code->"DATA_EXIT_CODE"|`Exec_cmdline->"MSG_EXEC_CMDLINE"|`Just_exec->"MSG_JUST_EXEC"|`Service_connect->"MSG_SERVICE_CONNECT"|`Service_refused->"MSG_SERVICE_REFUSED"|`Trigger_service->"MSG_TRIGGER_SERVICE"|`Connection_terminated->"MSG_CONNECTION_TERMINATED"|`Trigger_service3->"MSG_TRIGGER_SERVICE3"|`Hello->"MSG_HELLO"|`Unknownx->"Unknown message: "^(Int32.to_stringx)typeversion=[`V2|`V3]letversion_of_int=function|2l->`V2|3l->`V3|x->`Unknown_versionxletint_of_version=function|`V2->2l|`V3->3l|`Unknown_versionx->xmoduleFraming=structletheader_size=sizeof_msg_headerletbody_size_from_headerh=get_msg_header_lenh|>Int32.to_intendendmoduleGUI=struct(** https://www.qubes-os.org/doc/gui/ *)(** see qubes-gui-common/include/qubes-gui-protocol.h *)letconst_QUBES_MAIN_WINDOW=1ltypegui_protocol_version={version:int32;}(* let get_gui_protocol_version_version h = Bytes.get_int32_le h 0 *)(* let set_gui_protocol_version_version h v = Bytes.set_int32_le h 0 v *)letsizeof_gui_protocol_version=4(** struct msg_hdr *)typemsg_header={ty:int32;(** type *)window:int32;untrusted_len:int32;}letget_msg_header_tyh=get_int32_leh0(* let set._msg_header_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_header_windowh=get_int32_leh4(* let set_msg_header_window h v = Bytes.set_int32_le h 4 v *)letget_msg_header_untrusted_lenh=get_int32_leh8(* let set_msg_header_untrusted_len h v = Bytes.set_int32_le h 8 v *)letsizeof_msg_header=12(** VM -> Dom0, Dom0 -> VM *)typemsg_map_info={override_redirect:int32;transient_for:int32;}letget_msg_map_info_override_redirecth=get_int32_leh0(* let set_msg_map_info_override_redirect h v = Bytes.set_int32_le h 0 v *)letget_msg_map_info_transient_forh=get_int32_leh4(* let set_msg_map_info_transient_for h v = Bytes.set_int32_le h 4 v *)letsizeof_msg_map_info=8(** Dom0 -> VM, dom0 wants us to reply with a MSG_CLIPBOARD_DATA *)letsizeof_msg_clipboard_req=0(** Dom0 -> VM, VM -> Dom0: MSG_CLIPBOARD_DATA:
a normal header, followed by a uint8 array of size len *)typemsg_clipboard_data={window_id:int32;(* [@big_endian]; *)len:int32;(* followed by a uint8 array of size len *)}letget_msg_clipboard_data_window_idh=get_int32_beh0(* let set_msg_clipboard_data_window_id h v = Bytes.set_int32_be h 0 v *)letget_msg_clipboard_data_lenh=get_int32_leh4(* let set_msg_clipboard_data_len h v = Bytes.set_int32_le h 4 v *)letsizeof_msg_clipboard_data=8(** VM -> Dom0 *)typemsg_create={x:int32;(* position of window, seems to be converted *)y:int32;width:int32;height:int32;(* from qubes src: "size of image" *)parent:int32;override_redirect:int32;}letget_msg_create_xh=get_int32_leh0(* let set_msg_create_x h v = Bytes.set_int32_le h 0 v *)letget_msg_create_yh=get_int32_leh4(* let set_msg_create_y h v = Bytes.set_int32_le h 4 v *)letget_msg_create_widthh=get_int32_leh8(* let set_msg_create_width h v = Bytes.set_int32_le h 8 v *)letget_msg_create_heighth=get_int32_leh12(* let set_msg_create_height h v = Bytes.set_int32_le h 12 v *)letget_msg_create_parenth=get_int32_leh16(* let set_msg_create_parent h v = Bytes.set_int32_le h 16 v *)letget_msg_create_override_redirecth=get_int32_leh20(* let set_msg_create_override_redirect h v = Bytes.set_int32_le h 20 v *)letsizeof_msg_create=24typemsg_keypress_t={ty:int32;(* TODO make bool? XKeyEvent->type, see KeyPressMask/KeyReleaseMask *)x:int32;y:int32;state:int32;(* key mask *)keycode:int32;}(** Dom0 -> VM *)(* https://github.com/drinkcat/chroagh/commit/1d38c2e2422f97b6bf55580c9efc027ecf9f2721 *)(*
type msg_keypress = {
ty : int32;
x : int32;
y : int32;
state : int32; (** 1:down, 0:up *)
keycode : int32;
}
*)letget_msg_keypress_tyh=get_int32_leh0(* let set_msg_keypress_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_keypress_xh=get_int32_leh4(* let set_msg_keypress_x h v = Bytes.set_int32_le h 4 v *)letget_msg_keypress_yh=get_int32_leh8(* let set_msg_keypress_y h v = Bytes.set_int32_le h 8 v *)letget_msg_keypress_stateh=get_int32_leh12(* let set_msg_keypress_state h v = Bytes.set_int32_le h 12 v *)letget_msg_keypress_keycodeh=get_int32_leh16(* let set_msg_keypress_keycode h v = Bytes.set_int32_le h 16 v *)letsizeof_msg_keypress=20typemsg_button_t={ty:int32;(* TODO make bool? ButtonPress / ButtonRelease*)x:int32;y:int32;state:int32;(* button mask *)button:int32;}(*
(** Dom0 -> VM, TODO seems to be mouse buttons? *)
type msg_button = {
ty : int32;
x : int32;
y : int32;
state : int32;
button : int32; (* TODO *)
}
*)letget_msg_button_tyh=get_int32_leh0(* let set_msg_button_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_button_xh=get_int32_leh4(* let set_msg_button_x h v = Bytes.set_int32_le h 4 v *)letget_msg_button_yh=get_int32_leh8(* let set_msg_button_y h v = Bytes.set_int32_le h 8 v *)letget_msg_button_stateh=get_int32_leh12(* let set_msg_button_state h v = Bytes.set_int32_le h 12 v *)letget_msg_button_buttonh=get_int32_leh16(* let set_msg_button_button h v = Bytes.set_int32_le h 16 v *)letsizeof_msg_button=20letdecode_msg_buttonb:msg_button_toption=Some({ty=get_msg_button_tyb;x=get_msg_button_xb;y=get_msg_button_yb;state=get_msg_button_stateb;button=get_msg_button_buttonb;})(* dom0 -> VM, mouse / cursor movement *)typemsg_motion_t={x:int;y:int;state:int32;is_hint:int;}letget_msg_motion_xh=get_int32_leh0letget_msg_motion_yh=get_int32_leh4letget_msg_motion_stateh=get_int32_leh8letget_msg_motion_is_hinth=get_int32_leh12letsizeof_msg_motion=16letdecode_msg_motionstr:msg_motion_toption=(*TODO catch exceptions *)leti32=funf->(fstr|>Int32.to_int)inSome({x=i32get_msg_motion_x;y=i32get_msg_motion_y;state=get_msg_motion_statestr;is_hint=i32get_msg_motion_is_hint}:msg_motion_t)(* Dom0 -> VM, TODO better types *)typemsg_crossing_t={ty:int32;x:int32;y:int32;state:int32;mode:int32;detail:int32;focus:int32;}(*
(** Dom0 -> VM, seems to fire when the mouse is moved over a window border *)
type msg_crossing = {
ty : int32;
x : int32;
y : int32;
state : int32;
mode : int32;
detail : int32;
focus : int32;
}
*)letget_msg_crossing_tyh=get_int32_leh0(* let set_msg_crossing_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_crossing_xh=get_int32_leh4(* let set_msg_crossing_x h v = Bytes.set_int32_le h 4 v *)letget_msg_crossing_yh=get_int32_leh8(* let set_msg_crossing_y h v = Bytes.set_int32_le h 8 v *)letget_msg_crossing_stateh=get_int32_leh12(* let set_msg_crossing_state h v = Bytes.set_int32_le h 12 v *)letget_msg_crossing_modeh=get_int32_leh16(* let set_msg_crossing_mode h v = Bytes.set_int32_le h 16 v *)letget_msg_crossing_detailh=get_int32_leh20(* let set_msg_crossing_detail h v = Bytes.set_int32_le h 20 v *)letget_msg_crossing_focush=get_int32_leh24(* let set_msg_crossing_focus h v = Bytes.set_int32_le h 24 v *)letsizeof_msg_crossing=28letdecode_msg_crossingstr:msg_crossing_toption=(*TODO catch exceptions *)Some({ty=get_msg_crossing_tystr;x=get_msg_crossing_xstr;y=get_msg_crossing_ystr;state=get_msg_crossing_statestr;mode=get_msg_crossing_modestr;detail=get_msg_crossing_detailstr;focus=get_msg_crossing_focusstr}:msg_crossing_t)(** VM -> Dom0, Dom0 -> VM, note that when you send this you must read the
"corrected" MSG_CONFIGURE you get back and use those
values instead of your own *)typemsg_configure_t={x:int32;y:int32;width:int32;height:int32;override_redirect:int32;}(* type msg_configure = {
x : int32;
y : int32;
width : int32;
height : int32;
override_redirect : int32;
}
*)letget_msg_configure_xh=get_int32_leh0(* let set_msg_configure_x h v = Bytes.set_int32_le h 0 v *)letget_msg_configure_yh=get_int32_leh4(* let set_msg_configure_y h v = Bytes.set_int32_le h 4 v *)letget_msg_configure_widthh=get_int32_leh8(* let set_msg_configure_width h v = Bytes.set_int32_le h 8 v *)letget_msg_configure_heighth=get_int32_leh12(* let set_msg_configure_height h v = Bytes.set_int32_le h 12 v *)letget_msg_configure_override_redirecth=get_int32_leh16(* let set_msg_configure_override_redirect h v = Bytes.set_int32_le h 16 v *)letsizeof_msg_configure=20letdecode_msg_configureb:msg_configure_toption=Some({x=get_msg_configure_xb;y=get_msg_configure_yb;width=get_msg_configure_widthb;height=get_msg_configure_heightb;override_redirect=get_msg_configure_override_redirectb;}:msg_configure_t)(** VM -> Dom0 *)typemsg_shmimage={x:int32;y:int32;width:int32;height:int32;}letget_msg_shmimage_xh=get_int32_leh0(* let set_msg_shmimage_x h v = Bytes.set_int32_le h 0 v *)letget_msg_shmimage_yh=get_int32_leh4(* let set_msg_shmimage_y h v = Bytes.set_int32_le h 4 v *)letget_msg_shmimage_widthh=get_int32_leh8(* let set_msg_shmimage_width h v = Bytes.set_int32_le h 8 v *)letget_msg_shmimage_heighth=get_int32_leh12(* let set_msg_shmimage_height h v = Bytes.set_int32_le h 12 v *)letsizeof_msg_shmimage=16typemsg_focus_t={mode:int32;detail:int32;}(** Dom0 -> VM *)typemsg_focus={ty:int32;mode:int32;detail:int32;}letget_msg_focus_tyh=get_int32_leh0(* let set_msg_focus_ty h v = Bytes.set_int32_le h 0 v *)letget_msg_focus_modeh=get_int32_leh4(* let set_msg_focus_mode h v = Bytes.set_int32_le h 4 v *)letget_msg_focus_detailh=get_int32_leh8(* let set_msg_focus_detail h v = Bytes.set_int32_le h 8 v *)letsizeof_msg_focus=12(* Dom0 -> VM *)typemsg_execute={cmd:string;(* uint8_t [@len 255]; *)}(* let get_msg_execute_cmd h = h *)(* let set_msg_execute_cmd h v = Bytes.blit v 0 h 0 255 *)letsizeof_msg_execute=255(** Dom0 -> VM: Xorg conf *)typexconf={w:int32;(** width *)h:int32;(** height *)depth:int32;(** bits per pixel *)mem:int32;(* TODO seemingly unused , could be: MemBase baseaddress
This optional entry specifies the memory base address of a graphics board's
linear frame buffer. This entry is not used by many drivers, and it should
only be specified if the driver-specific documentation recommends it. *)}letget_xconf_wh=get_int32_leh0(* let set_xconf_w h v = Bytes.set_int32_le h 0 v *)letget_xconf_hh=get_int32_leh4(* let set_xconf_h h v = Bytes.set_int32_le h 4 v *)letget_xconf_depthh=get_int32_leh8(* let set_xconf_depth h v = Bytes.set_int32_le h 8 v *)letget_xconf_memh=get_int32_leh12(* let set_xconf_mem h v = Bytes.set_int32_le h 12 v *)letsizeof_xconf=16(* https://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR *)(** VM -> Dom0 *)typemsg_wmname={data:string(*uint8_t [@len 128];*)(* title of the window *)}(* let get_msg_wmname_data h = h *)(* let set_msg_wmname_data h v = Bytes.blit v 0 h 0 128 *)letsizeof_msg_wmname=128(** Dom0 -> VM *)typemsg_keymap_notify={(* this is a 256-bit bitmap of which keys should be enabled*)keys:string(*uint8_t [@len 32];*)}(* let get_msg_keymap_notify_keys h = h *)(* let set_msg_keymap_notify_keys h v = Bytes.blit v 0 h 0 32 *)letsizeof_msg_keymap_notify=32(** VM -> Dom0 *)(* https://standards.freedesktop.org/wm-spec/latest/ *)typemsg_window_hints={flags:int32;min_width:int32;min_height:int32;max_width:int32;max_height:int32;width_inc:int32;height_inc:int32;base_width:int32;base_height:int32;}(* let get_msg_window_hints_flags h = String.get_int32_le h 0 *)(* let set_msg_window_hints_flags h v = Bytes.set_int32_le h 0 v *)(* let get_msg_window_hints_min_width h = String.get_int32_le h 4 *)(* let set_msg_window_hints_min_width h v = Bytes.set_int32_le h 4 v *)(* let get_msg_window_hints_min_height h = String.get_int32_le h 8 *)(* let set_msg_window_hints_min_height h v = Bytes.set_int32_le h 8 v *)(* let get_msg_window_hints_max_width h = String.get_int32_le h 12 *)(* let set_msg_window_hints_max_width h v = Bytes.set_int32_le h 12 v *)(* let get_msg_window_hints_max_height h = String.get_int32_le h 16 *)(* let set_msg_window_hints_max_height h v = Bytes.set_int32_le h 16 v *)(* let get_msg_window_hints_width_inc h = String.get_int32_le h 20 *)(* let set_msg_window_hints_width_inc h v = Bytes.set_int32_le h 20 v *)(* let get_msg_window_hints_height_inc h = String.get_int32_le h 24 *)(* let set_msg_window_hints_height_inc h v = Bytes.set_int32_le h 24 v *)(* let get_msg_window_hints_base_width h = String.get_int32_le h 28 *)(* let set_msg_window_hints_base_width h v = Bytes.set_int32_le h 28 v *)(* let get_msg_window_hints_base_height h = String.get_int32_le h 32 *)(* let set_msg_window_hints_base_height h v = Bytes.set_int32_le h 32 v *)letsizeof_msg_window_hints=36(** VM -> Dom0, Dom0 -> VM *)typemsg_window_flags={(* &1= FULLSCREEN, &2= DEMANDS_ATTENTION, &4=MINIMIZE *)flags_set:int32;flags_unset:int32;}(* let get_msg_window_flags_flags_set h = Bytes.get_int32_le h 0 *)(* let set_msg_window_flags_flags_set h v = Bytes.set_int32_le h 0 v *)(* let get_msg_window_flags_flags_unset h = Bytes.get_int32_le h 4 *)(* let set_msg_window_flags_flags_unset h v = Bytes.set_int32_le h 4 v *)letsizeof_msg_window_flags=8(** VM -> Dom0 *)typeshm_cmd={shmid:int32;width:int32;height:int32;bpp:int32;(* bpp = bits per pixel *)off:int32;num_mfn:int32;(* number of pixels *)domid:int32;(* followed by a variable length buffer of pixels:*)(* uint32_t mfns[0]; *)}(* let get_shm_cmd_shmid h = Bytes.get_int32_le h 0 *)(* let set_shm_cmd_shmid h v = Bytes.set_int32_le h 0 v *)(* let get_shm_cmd_width h = Bytes.get_int32_le h 4 *)(* let set_shm_cmd_width h v = Bytes.set_int32_le h 4 v *)(* let get_shm_cmd_height h = Bytes.get_int32_le h 8 *)(* let set_shm_cmd_height h v = Bytes.set_int32_le h 8 v *)(* let get_shm_cmd_bpp h = Bytes.get_int32_le h 12 *)(* let set_shm_cmd_bpp h v = Bytes.set_int32_le h 12 v *)(* let get_shm_cmd_off h = Bytes.get_int32_le h 16 *)(* let set_shm_cmd_off h v = Bytes.set_int32_le h 16 v *)(* let get_shm_cmd_num_mfn h = Bytes.get_int32_le h 20 *)(* let set_shm_cmd_num_mfn h v = Bytes.set_int32_le h 20 v *)(* let get_shm_cmd_domid h = Bytes.get_int32_le h 24 *)(* let set_shm_cmd_domid h v = Bytes.set_int32_le h 24 v *)letsizeof_shm_cmd=28(** VM -> Dom0 *)typemsg_wmclass={res_class:string;(* uint8_t [@len 64]; *)res_name:string;(* uint8_t [@len 64]; *)}(* let get_msg_wmclass_res_class h = Bytes.sub h 0 64 *)(* let set_msg_wmclass_res_class h v = Bytes.blit v 0 h 0 64 *)(* let get_msg_wmclass_res_name h = Bytes.sub h 64 64 *)(* let set_msg_wmclass_res_name h v = Bytes.blit v 0 h 64 64 *)letsizeof_msg_wmclass=128typemsg_type=(*| MSG_MIN [@id 123l] (* 0x7b_l *) *)|MSG_KEYPRESS(*[@id 124_l]*)(* 0x7c_l *)|MSG_BUTTON|MSG_MOTION|MSG_CROSSING|MSG_FOCUS(*| MSG_RESIZE - DEPRECATED; NOT IMPLEMENTED *)|MSG_CREATE(*[@id 130_l]*)(* 0x82_l *)|MSG_DESTROY|MSG_MAP|MSG_UNMAP|MSG_CONFIGURE|MSG_MFNDUMP|MSG_SHMIMAGE|MSG_CLOSE|MSG_EXECUTE|MSG_CLIPBOARD_REQ|MSG_CLIPBOARD_DATA|MSG_WMNAME|MSG_KEYMAP_NOTIFY|MSG_DOCK|MSG_WINDOW_HINTS|MSG_WINDOW_FLAGS|MSG_WMCLASS(*| MSG_MAX [@id 147l]*)letmsg_type_size=function|MSG_BUTTON->Somesizeof_msg_button|MSG_CLIPBOARD_REQ->Somesizeof_msg_clipboard_req|MSG_CLIPBOARD_DATA->None|MSG_CLOSE->Some0(* user clicked [X] or pressed Alt-F4 or similar *)|MSG_CONFIGURE->Somesizeof_msg_configure|MSG_CREATE->Somesizeof_msg_create|MSG_CROSSING->Somesizeof_msg_crossing|MSG_DESTROY->None(* this is the "prepare to shutdown your VM" message, no payload *)|MSG_DOCK->None(* TODO *)|MSG_EXECUTE->Somesizeof_msg_execute|MSG_FOCUS->Somesizeof_msg_focus|MSG_KEYMAP_NOTIFY->Somesizeof_msg_keymap_notify|MSG_KEYPRESS->Somesizeof_msg_keypress|MSG_MAP->None(* TODO *)|MSG_MFNDUMP->None(* TODO *)|MSG_MOTION->Somesizeof_msg_motion|MSG_SHMIMAGE->Somesizeof_msg_shmimage|MSG_UNMAP->None(* TODO *)|MSG_WINDOW_FLAGS->Somesizeof_msg_window_flags|MSG_WINDOW_HINTS->Somesizeof_msg_window_hints|MSG_WMCLASS->Somesizeof_msg_wmclass|MSG_WMNAME->Somesizeof_msg_wmname(* window title *)letmsg_type_to_int=function(*| MSG_MIN -> 123l [@id 123l] (* 0x7b_l *) *)|MSG_KEYPRESS->124l(*[@id 124_l]*)(* 0x7c_l *)|MSG_BUTTON->125l|MSG_MOTION->126l|MSG_CROSSING->127l|MSG_FOCUS->128l(*| MSG_RESIZE -> - DEPRECATED; NOT IMPLEMENTED *)|MSG_CREATE->130l(*[@id 130_l]*)(* 0x82_l *)|MSG_DESTROY->131l|MSG_MAP->132l|MSG_UNMAP->133l|MSG_CONFIGURE->134l|MSG_MFNDUMP->135l|MSG_SHMIMAGE->136l|MSG_CLOSE->137l|MSG_EXECUTE->138l|MSG_CLIPBOARD_REQ->139l|MSG_CLIPBOARD_DATA->140l|MSG_WMNAME->141l|MSG_KEYMAP_NOTIFY->142l|MSG_DOCK->143l|MSG_WINDOW_HINTS->144l|MSG_WINDOW_FLAGS->145l|MSG_WMCLASS->146l(*| MSG_MAX [@id 147l]*)letint_to_msg_type=function(*| 123l -> Some MSG_MIN [@id 123l] (* 0x7b_l *) *)|124l->SomeMSG_KEYPRESS(*[@id 124_l]*)(* 0x7c_l *)|125l->SomeMSG_BUTTON|126l->SomeMSG_MOTION|127l->SomeMSG_CROSSING|128l->SomeMSG_FOCUS(*| 124l -> Some MSG_RESIZE - DEPRECATED; NOT IMPLEMENTED *)|130l->SomeMSG_CREATE(*[@id 130_l]*)(* 0x82_l *)|131l->SomeMSG_DESTROY|132l->SomeMSG_MAP|133l->SomeMSG_UNMAP|134l->SomeMSG_CONFIGURE|135l->SomeMSG_MFNDUMP|136l->SomeMSG_SHMIMAGE|137l->SomeMSG_CLOSE|138l->SomeMSG_EXECUTE|139l->SomeMSG_CLIPBOARD_REQ|140l->SomeMSG_CLIPBOARD_DATA|141l->SomeMSG_WMNAME|142l->SomeMSG_KEYMAP_NOTIFY|143l->SomeMSG_DOCK|144l->SomeMSG_WINDOW_HINTS|145l->SomeMSG_WINDOW_FLAGS|146l->SomeMSG_WMCLASS(*| 147l -> Some MSG_MAX [@id 147l]*)|_->None(** "MFN: machine frame number - actual hw addresses"
http://ccrc.web.nthu.edu.tw/ezfiles/16/1016/img/598/v14n_xen.pdf
*)(* type mfn : uint32_t; big-endian 24-bit RGB pixel *)letmake_with_header~window~ty~body_lenbody=(* see qubes-gui-agent-linux/include/txrx.h:#define write_message *)String.concat""[of_int32_le(msg_type_to_intty);of_int32_lewindow;of_int32_lebody_len;body]letmake_msg_mfndump~window~width~height~mfns=(* n.b. must be followed by a MSG_SHMIMAGE to actually repaint *)letnum_mfn=List.lengthmfnsinletoffset=0x0lin(* TODO let n = (4 * width * height + offset
+ (XC_PAGE_SIZE-1)) / XC_PAGE_SIZE; *)letcmds=mfns|>List.mapi(funi->fun_->of_int32_le(Int32.of_int(sizeof_shm_cmd+i*4)))inletbody=String.concat""@@List.append[of_int32_lewidth;of_int32_leheight;of_int32_le24l;(* bits per pixel *)of_int32_leoffset;of_int32_le@@Int32.of_int(num_mfn);]cmdsin(* From https://www.qubes-os.org/doc/gui/
>> "shmid" and "domid" parameters are just placeholders (to be filled
>> by *qubes_guid* ), so that we can use the same structure when talking
>> to shmoverride.so **)letbody_len=Int32.of_int(sizeof_shm_cmd+num_mfn*4)inmake_with_header~window~ty:MSG_MFNDUMP~body_lenbodyletmake_msg_shmimage~window~x~y~width~height=letbody=String.concat""[of_int32_lex;of_int32_ley;of_int32_lewidth;of_int32_leheight;]inletbody_len=Int32.of_intsizeof_msg_shmimageinmake_with_header~window~ty:MSG_SHMIMAGE~body_lenbodyletmake_msg_create~window~width~height~x~y~override_redirect~parent=letbody=String.concat""[of_int32_lewidth;of_int32_leheight;of_int32_lex;of_int32_ley;of_int32_leoverride_redirect;of_int32_leparent;]inletbody_len=Int32.of_intsizeof_msg_createinmake_with_header~window~ty:MSG_CREATE~body_lenbodyletmake_msg_map_info~window~override_redirect~transient_for=letbody=of_int32_leoverride_redirect^of_int32_letransient_forinletbody_len=Int32.of_intsizeof_msg_map_infoinmake_with_header~window~ty:MSG_MAP~body_lenbodyletmake_msg_wmname~window~wmname=letbody=wmname^String.make(sizeof_msg_wmname-String.(lengthwmname))'\000';(* padding to sizeof_msg_wmname *)inletbody_len=Int32.of_intsizeof_msg_wmnameinmake_with_header~window~ty:MSG_WMNAME~body_lenbodyletmake_msg_window_hints~window~width~height=letbody=String.concat""[of_int32_le@@Int32.(16lor32|>of_int);(*^-- PMinSize | PMaxSize *)of_int32_lewidth;(* min width *)of_int32_leheight;(* min height *)of_int32_lewidth;(* max width *)of_int32_leheight;(* max height *)]inletbody_len=Int32.of_intsizeof_msg_window_hintsinmake_with_header~window~ty:MSG_WINDOW_HINTS~body_lenbodyletmake_msg_configure~window~x~y~width~height=letbody=String.concat""[of_int32_lex;of_int32_ley;(* x and y are from qs->window_x and window_y*)of_int32_lewidth;of_int32_leheight;of_int32_le0l;(* override_redirect *)]inletbody_len=Int32.of_intsizeof_msg_window_hintsinmake_with_header~window~ty:MSG_CONFIGURE~body_lenbodymoduleFraming=structletheader_size=sizeof_msg_headerletbody_size_from_header_h=get_msg_header_untrusted_len_h|>Int32.to_intendendmoduleQubesDB=structtypeqdb_msg=|QDB_CMD_READ|QDB_CMD_WRITE|QDB_CMD_MULTIREAD|QDB_CMD_LIST|QDB_CMD_RM|QDB_CMD_WATCH|QDB_CMD_UNWATCH|QDB_RESP_OK|QDB_RESP_ERROR_NOENT|QDB_RESP_ERROR|QDB_RESP_READ|QDB_RESP_MULTIREAD|QDB_RESP_LIST|QDB_RESP_WATCHletqdb_msg_to_int=function|QDB_CMD_READ->0|QDB_CMD_WRITE->1|QDB_CMD_MULTIREAD->2|QDB_CMD_LIST->3|QDB_CMD_RM->4|QDB_CMD_WATCH->5|QDB_CMD_UNWATCH->6|QDB_RESP_OK->7|QDB_RESP_ERROR_NOENT->8|QDB_RESP_ERROR->9|QDB_RESP_READ->10|QDB_RESP_MULTIREAD->11|QDB_RESP_LIST->12|QDB_RESP_WATCH->13letint_to_qdb_msg=function|0->SomeQDB_CMD_READ|1->SomeQDB_CMD_WRITE|2->SomeQDB_CMD_MULTIREAD|3->SomeQDB_CMD_LIST|4->SomeQDB_CMD_RM|5->SomeQDB_CMD_WATCH|6->SomeQDB_CMD_UNWATCH|7->SomeQDB_RESP_OK|8->SomeQDB_RESP_ERROR_NOENT|9->SomeQDB_RESP_ERROR|10->SomeQDB_RESP_READ|11->SomeQDB_RESP_MULTIREAD|12->SomeQDB_RESP_LIST|13->SomeQDB_RESP_WATCH|_->Noneletqdb_msg_to_string=function|QDB_CMD_READ->"QDB_CMD_READ"|QDB_CMD_WRITE->"QDB_CMD_WRITE"|QDB_CMD_MULTIREAD->"QDB_CMD_MULTIREAD"|QDB_CMD_LIST->"QDB_CMD_LIST"|QDB_CMD_RM->"QDB_CMD_RM"|QDB_CMD_WATCH->"QDB_CMD_WATCH"|QDB_CMD_UNWATCH->"QDB_CMD_UNWATCH"|QDB_RESP_OK->"QDB_RESP_OK"|QDB_RESP_ERROR_NOENT->"QDB_RESP_ERROR_NOENT"|QDB_RESP_ERROR->"QDB_RESP_ERROR"|QDB_RESP_READ->"QDB_RESP_READ"|QDB_RESP_MULTIREAD->"QDB_RESP_MULTIREAD"|QDB_RESP_LIST->"QDB_RESP_LIST"|QDB_RESP_WATCH->"QDB_RESP_WATCH"typemsg_header={ty:int;path:string;(* [@len 64]; *)padding:string;(* [@len 3]; *)data_len:int32;(* rest of message is data *)}letget_msg_header_tyh=get_uint8h0(* let set_msg_header_ty h v = Bytes.set_uint8 h 0 v *)letget_msg_header_pathh=String.subh164(* let set_msg_header_path h v = Bytes.blit_string v 0 h 1 (min (String.length v) 64) *)letget_msg_header_data_lenh=get_int32_leh68(* let set_msg_header_data_len h v = Bytes.set_int32_le h 68 v *)letsizeof_msg_header=72letmake_msg_header~ty~path~data_len=assert(String.lengthpath<=64);String.concat""[String.make1(Char.chr(qdb_msg_to_intty));(* int8 *)path;String.make(3+64-String.lengthpath)'\000';(* padding=3 and max size of path=64 *)of_int32_le(Int32.of_intdata_len);]moduleFraming=structletheader_size=sizeof_msg_headerletbody_size_from_headerh=get_msg_header_data_lenh|>Int32.to_intendendmoduleRpc_filecopy=struct(* see qubes-linux-utils/qrexec-lib/libqubes-rpc-filecopy.h
* and qubes-core-agent-windows/src/qrexec-services/common/filecopy.h*)typefile_header={namelen:int32;mode:int32;filelen:int64;atime:int32;atime_nsec:int32;mtime:int32;mtime_nsec:int32;}(* followed by filename[namelen] and data[filelen] *)(* let get_file_header_namelen h = Bytes.get_int32_le h 0 *)(* let set_file_header_namelen h v = Bytes.set_int32_le h 0 v *)(* let get_file_header_mode h = Bytes.get_int32_le h 4 *)(* let set_file_header_mode h v = Bytes.set_int32_le h 4 v *)(* let get_file_header_filelen h = Bytes.get_int64_le h 8 *)(* let set_file_header_filelen h v = Bytes.set_int64_le h 8 v *)(* let get_file_header_atime h = Bytes.get_int32_le h 16 *)(* let set_file_header_atime h v = Bytes.set_int32_le h 16 v *)(* let get_file_header_atime_nsec h = Bytes.get_int32_le h 20 *)(* let set_file_header_atime_nsec h v = Bytes.set_int32_le h 20 v *)(* let get_file_header_mtime h = Bytes.get_int32_le h 24 *)(* let set_file_header_mtime h v = Bytes.set_int32_le h 24 v *)(* let get_file_header_mtime_nsec h = Bytes.get_int32_le h 28 *)(* let set_file_header_mtime_nsec h v = Bytes.set_int32_le h 28 v *)letsizeof_file_header=32typeresult_header={error_code:int32;_pad:int32;crc32:int64;}(* let get_result_header_error_code h = Bytes.get_int32_le h 0 *)(* let set_result_header_error_code h v = Bytes.set_int32_le h 0 v *)(* let get_result_header__pad h = Bytes.get_int32_le h 4 *)(* let set_result_header__pad h v = Bytes.set_int32_le h 4 v *)(* let get_result_header_crc32 h = Bytes.get_int64_le h 8 *)(* let set_result_header_crc32 h v = Bytes.set_int64_le h 8 v *)letsizeof_result_header=16typeresult_header_ext={last_namelen:int32;(* TODO char last_name[0]; variable length[last_namelen] *)}(* let get_result_header_ext_last_namelen h = Bytes.get_int32_le h 0 *)(* let set_result_header_ext_last_namelen h v = Bytes.set_int32_le h 0 v *)letsizeof_result_header_ext=4(*
let make_result_header_ext last_filename =
let namelen = Bytes.length last_filename in
of_int32_le @@ (Int32.of_int namelen) ^ last_filename
*)end