<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 17, 2018 at 10:03 PM, Frediano Ziglio <span dir="ltr"><<a href="mailto:fziglio@redhat.com" target="_blank">fziglio@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">> <br>
> Added implementation of system-dependent operations<br>
> defined in cd-device.h for Windows<br>
> <br>
> Signed-off-by: Yuri Benditovich <<a href="mailto:yuri.benditovich@daynix.com">yuri.benditovich@daynix.com</a>><br>
> ---<br>
>  src/cd-device-win.c | 193<br>
>  ++++++++++++++++++++++++++++++<wbr>++++++++++++++++++++++<br>
>  1 file changed, 193 insertions(+)<br>
>  create mode 100644 src/cd-device-win.c<br>
> <br>
> diff --git a/src/cd-device-win.c b/src/cd-device-win.c<br>
> new file mode 100644<br>
> index 0000000..de7f3f1<br>
> --- /dev/null<br>
> +++ b/src/cd-device-win.c<br>
> @@ -0,0 +1,193 @@<br>
> +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */<br>
> +/*<br>
> +Copyright (C) 2018 Red Hat, Inc.<br>
> +<br>
> +Red Hat Authors:<br>
> +Yuri Benditovich<<a href="mailto:ybendito@redhat.com">ybendito@redhat.<wbr>com</a>><br>
> +<br>
> +This library is free software; you can redistribute it and/or<br>
> +modify it under the terms of the GNU Lesser General Public<br>
> +License as published by the Free Software Foundation; either<br>
> +version 2.1 of the License, or (at your option) any later version.<br>
> +<br>
> +This library is distributed in the hope that it will be useful,<br>
> +but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
> +Lesser General Public License for more details.<br>
> +<br>
> +You should have received a copy of the GNU Lesser General Public<br>
> +License along with this library; if not, see <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank">http://www.gnu.org/licenses/</a>><wbr>.<br>
> +*/<br>
> +<br>
> +#include "config.h"<br>
> +#include <glib-object.h><br>
> +<br>
> +#ifdef G_OS_WIN32<br>
> +#ifdef USE_USBREDIR<br>
> +<br>
> +#include <inttypes.h><br>
> +#include <gio/gio.h><br>
> +#include <windows.h><br>
> +#include <ntddcdrm.h><br>
> +#include <ntddmmc.h><br>
> +#include "cd-device.h"<br>
> +#include "spice-client.h"<br>
> +<br>
> +static gboolean is_device_name(const char *filename)<br>
> +{<br>
> +    gboolean b = strlen(filename) == 2 && filename[1] == ':';<br>
> +    return b;<br>
> +}<br>
> +<br>
> +static HANDLE open_file(const char *filename)<br>
> +{<br>
> +    HANDLE h = CreateFileA(<br>
> +        filename,<br>
> +        GENERIC_READ,<br>
> +        FILE_SHARE_READ | FILE_SHARE_WRITE,<br>
> +        NULL, OPEN_EXISTING,<br>
> +        0,<br>
> +        NULL);<br>
> +    if (h == INVALID_HANDLE_VALUE) {<br>
> +        h = NULL;<br>
> +    }<br>
> +    return h;<br>
> +}<br>
> +<br>
> +static uint32_t ioctl_out(HANDLE h, uint32_t code, void *out_buffer,<br>
> uint32_t out_size)<br>
> +{<br>
> +    uint32_t error;<br>
> +    DWORD ret;<br>
> +    BOOL b = DeviceIoControl(h,<br>
> +        code,<br>
> +        NULL,<br>
> +        0,<br>
> +        out_buffer,<br>
> +        out_size,<br>
> +        &ret,<br>
> +        NULL);<br>
<br>
</div></div>Is it necessary to split that much?<br>
<span class=""><br>
> +        error = b ? 0 : GetLastError();<br>
<br>
</span>wrong indentation.<br></blockquote><div><br></div><div>To be fixed in next round</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5"><br>
> +    return error;<br>
> +}<br>
> +<br>
> +static uint32_t ioctl_none(HANDLE h, uint32_t code)<br>
> +{<br>
> +    return ioctl_out(h, code, NULL, 0);<br>
> +}<br>
> +<br>
> +static gboolean check_device(HANDLE h)<br>
> +{<br>
> +    GET_CONFIGURATION_IOCTL_INPUT cfgIn = { FeatureCdRead,<br>
> SCSI_GET_CONFIGURATION_<wbr>REQUEST_TYPE_ALL };<br>
> +    DWORD ret;<br>
> +    GET_CONFIGURATION_HEADER cfgOut;<br>
> +    return DeviceIoControl(h, IOCTL_CDROM_GET_CONFIGURATION,<br>
> +        &cfgIn, sizeof(cfgIn), &cfgOut, sizeof(cfgOut),<br>
> +        &ret, NULL);<br>
> +}<br>
> +<br>
> +int cd_device_open_stream(<wbr>SpiceCdLU *unit, const char *filename)<br>
> +{<br>
> +    int error = 0;<br>
> +    HANDLE h;<br>
> +    unit->device = 0;<br>
> +    if (!unit->filename && !filename) {<br>
> +        SPICE_DEBUG("%s: unnamed file", __FUNCTION__);<br>
> +        return -1; // TODO<br>
> +    }<br>
> +    if (unit->filename && filename) {<br>
> +        g_free(unit->filename);<br>
> +        unit->filename = NULL;<br>
> +    }<br>
> +    if (!filename) {<br>
> +        // reopening the stream on existing file name<br>
> +    } else if (is_device_name(filename)) {<br>
> +        unit->filename = g_strdup_printf("\\\\.\\%s", filename);<br>
> +    } else {<br>
> +        unit->filename = g_strdup(filename);<br>
> +    }<br>
> +    h = open_file(unit->filename);<br>
> +    if (h) {<br>
> +        LARGE_INTEGER size = { 0 };<br>
> +        if (!GetFileSizeEx(h, &size)) {<br>
> +            uint64_t buffer[256];<br>
> +            unit->device = check_device(h);<br>
> +            SPICE_DEBUG("%s: CD device %srecognized on %s",<br>
> +                __FUNCTION__, unit->device ? "" : "NOT ", unit->filename);<br>
> +            uint32_t res = ioctl_out(h, IOCTL_DISK_GET_DRIVE_GEOMETRY_<wbr>EX,<br>
> +                buffer, sizeof(buffer));<br>
> +            if (!res)<br>
> +            {<br>
> +                DISK_GEOMETRY_EX *pg = (DISK_GEOMETRY_EX *)buffer;<br>
> +                unit->blockSize = pg->Geometry.BytesPerSector;<br>
> +                size = pg->DiskSize;<br>
> +            } else {<br>
> +                SPICE_DEBUG("%s: can't obtain size of %s (error %u)",<br>
> +                    __FUNCTION__, unit->filename, res);<br>
<br>
</div></div>In this path size is not defined, I would add a<br>
<br>
  CloseHandle(h);<br>
  return -1;<br></blockquote><div><br></div><div>If we can't get the size of the CD, this is minor problem, this might be a blank CD.</div><div>Will deal with size of 0. The user will need to replace the CD.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><br>
> +            }<br>
> +        }<br>
> +        unit->size = size.QuadPart;<br>
> +        CloseHandle(h);<br>
> +        if (unit->size) {<br>
> +            unit->file_object = g_file_new_for_path(unit-><wbr>filename);<br>
> +            unit->stream = g_file_read(unit->file_object, NULL, NULL);<br>
> +        }<br>
> +        if (!unit->stream) {<br>
> +            SPICE_DEBUG("%s: can't open stream on %s", __FUNCTION__,<br>
> unit->filename);<br>
> +            g_object_unref(unit->file_<wbr>object);<br>
> +            unit->file_object = NULL;<br>
> +            error = -1; //TODO<br>
> +        }<br>
> +    } else {<br>
> +        SPICE_DEBUG("%s: can't open file %s", __FUNCTION__, unit->filename);<br>
> +        error = -1; //TODO<br>
> +    }<br>
> +    return error;<br>
> +}<br>
> +<br>
> +int cd_device_load(SpiceCdLU *unit, gboolean load)<br>
> +{<br>
> +    int error = 0;<br>
> +    HANDLE h;<br>
> +    if (!unit->device || !unit->filename) {<br>
> +        return -1; //TODO<br>
> +    }<br>
> +    h = open_file(unit->filename);<br>
> +    if (h) {<br>
> +        uint32_t res = ioctl_none(h, load ? IOCTL_STORAGE_LOAD_MEDIA :<br>
> IOCTL_STORAGE_EJECT_MEDIA);<br>
> +        if (res) {<br>
> +            SPICE_DEBUG("%s: can't %sload %s, win error %u",<br>
> +                __FUNCTION__, load ? "" : "un", unit->filename, res);<br>
> +            error = -1; //TODO<br>
> +        } else {<br>
> +            SPICE_DEBUG("%s: device %s [%s]",<br>
> +                __FUNCTION__, load ? "loaded" : "ejected", unit->filename);<br>
> +        }<br>
> +        CloseHandle(h);<br>
> +    }<br>
> +    return error;<br>
> +}<br>
> +<br>
> +int cd_device_check(SpiceCdLU *unit)<br>
> +{<br>
> +    int error = 0;<br>
> +    CDROM_DISK_DATA data;<br>
> +    HANDLE h;<br>
> +    if (!unit->device || !unit->filename) {<br>
> +        return -1; //TODO<br>
> +    }<br>
> +    h = open_file(unit->filename);<br>
> +    if (h) {<br>
> +        uint32_t res = ioctl_none(h, IOCTL_STORAGE_CHECK_VERIFY);<br>
> +        if (!res) {<br>
> +            res = ioctl_out(h, IOCTL_CDROM_DISK_TYPE, &data, sizeof(data));<br>
> +        }<br>
> +        if (res != 0 || data.DiskData != CDROM_DISK_DATA_TRACK) {<br>
> +            error = -1; //TODO<br>
> +        }<br>
> +        CloseHandle(h);<br>
> +    }<br>
> +    return error;<br>
> +}<br>
> +<br>
> +#endif<br>
> +#endif<br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">Frediano<br>
</font></span></blockquote></div><br></div></div>