123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156(*
* Copyright (C) 2016 Docker Inc
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)typet=Unix.file_descrtypevmid=|Wildcard|Children|Loopback|Parent|IdofUuidm.ttypeserviceid=stringtypesockaddr={vmid:vmid;serviceid:serviceid;}letstring_of_sockaddr{vmid;serviceid}=letvmid=matchvmidwith|Wildcard->"Wildcard"|Children->"Children"|Loopback->"Loopback"|Parent->"Parent"|Idx->Uuidm.to_stringxinPrintf.sprintf"AF_HYPERV { vmid = %s; serviceid = %s }"vmidserviceidexternalget_wildcard:unit->string="stub_hvsock_wildcard"letwildcard=get_wildcard()externalget_children:unit->string="stub_hvsock_children"letchildren=get_children()externalget_loopback:unit->string="stub_hvsock_loopback"letloopback=get_loopback()externalget_parent:unit->string="stub_hvsock_parent"letparent=get_parent()letstring_of_vmid=function|Wildcard->wildcard|Children->children|Loopback->loopback|Parent->parent|Idx->Uuidm.to_stringxletvmid_of_stringx=ifx=wildcardthenWildcardelseifx=childrenthenChildrenelseifx=loopbackthenLoopbackelseifx=parentthenParentelsematchUuidm.of_stringxwith|Somex->Idx|None->failwith("Failed to parse VM GUID: "^x)externaldo_socket:unit->Unix.file_descr="stub_hvsock_socket"externaldo_bind:Unix.file_descr->string->string->unit="stub_hvsock_bind"externaldo_accept:Unix.file_descr->Unix.file_descr*string*string="stub_hvsock_accept"externaldo_connect_blocking:Unix.file_descr->string->string->unit="stub_hvsock_connect_blocking"externaldo_connect_nonblocking:int->Unix.file_descr->string->string->unit="stub_hvsock_connect_nonblocking"letcreate=do_socketletbindfd{vmid;serviceid}=do_bindfd(string_of_vmidvmid)serviceidletacceptfd=letnew_fd,vmid,serviceid=do_acceptfdinletvmid=vmid_of_stringvmidinnew_fd,{vmid;serviceid}letconnect?timeout_msfd{vmid;serviceid}=(matchtimeout_mswith|None->do_connect_blocking|Somet->do_connect_nonblockingt)fd(string_of_vmidvmid)serviceidletread_into=Af_common.read_intoletwritev=Af_common.writevletshutdown_readfd=Unix.shutdownfdUnix.SHUTDOWN_RECEIVEletshutdown_writefd=Unix.shutdownfdUnix.SHUTDOWN_SENDletclose=Unix.closeletlisten=Unix.listenletwith_powershellscriptf=(* Avoid escaping problems by base64-encoding the script *)letencoded=letb=Buffer.create100infori=0toString.lengthscript-1doUutf.Buffer.add_utf_16leb(Uchar.of_charscript.[i])done;matchBase64.encode(Buffer.contentsb)with|Okx->x|Error(`Msgy)->failwith("Base64.encode failed unexpectedly: "^y)inletic=Unix.open_process_in("powershell.exe -Sta -NonInteractive -ExecutionPolicy RemoteSigned -EncodedCommand "^encoded)inletclosed=reffalseintryletresult=ficinbeginmatchUnix.close_process_inicwith|Unix.WEXITED0->result|_->closed:=true;Printf.fprintfstderr"Failed to run powershell script:\n%s\n"script;failwith"Failed to run powershell"endwithe->ifnot(!closed)thenignore(Unix.close_process_inic);raiseeletvmid_of_namename=with_powershell(Printf.sprintf"(Get-VM %s).Id"name)(funic->(* If not adminstrator this will fail with:
Get-VM : You do not have the required permission to complete this task. Contact the administrator of the authorization
*)letline=String.trim@@input_lineicinifline<>""thenfailwithline;letline=String.trim@@input_lineicinifline<>"Guid"thenfailwithline;letline=String.trim@@input_lineicinifline<>"----"thenfailwithline;letline=String.trim@@input_lineicinmatchUuidm.of_stringlinewith|None->failwith("Failed to discover VM GUID of "^name)|Somex->x)letregister_serviceidserviceid=letscript=String.concat"\n"[(* Get-Item with a regexp doesn't spam the output if the key doesn't exist.
Note [S]OFTWARE only matches SOFTWARE *)Printf.sprintf"if (!(Get-Item -Path \"HKLM:\\[S]OFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Virtualization\\GuestCommunicationServices\\%s\")) {"serviceid;Printf.sprintf" $service = New-Item -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Virtualization\\GuestCommunicationServices\" -Name %s"serviceid;" # Set a friendly name";" $service.SetValue(\"ElementName\", \"https://github.com/mirage/ocaml-hvsock\")";"}";]inwith_powershellscript(fun_ic->())