<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="Generator" content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang="CS" link="blue" vlink="#954F72"><div class="WordSection1"><p class="MsoNormal">Hi</p><p class="MsoNormal"> </p><div style="border:none;border-top:solid #e1e1e1 1.0pt;padding:3.0pt 0cm 0cm 0cm"><p class="MsoNormal" style="border:none;padding:0cm"><b>From: </b><a href="mailto:lists@victortoso.com">Victor Toso</a><br><b>Sent: </b>pondělí 2. května 2016 8:45<br><b>To: </b><a href="mailto:lvenhoda@redhat.com">Lukáš Venhoda</a><br><b>Cc: </b><a href="mailto:spice-devel@lists.freedesktop.org">spice-devel@lists.freedesktop.org</a><br><b>Subject: </b>Re: [Spice-devel] [phodav PATCH 1/3 v6] spice-webdavd-windows: Automount shared folder</p></div><p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif"> </span></p><p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif">Hey,</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif"><br><br>On Thu, Apr 21, 2016 at 05:28:07PM +0200, Lukáš Venhoda wrote:<br>> From: Lukas Venhoda <<a href="mailto:lvenhoda@redhat.com">lvenhoda@redhat.com</a>><br>><br>> Try to connect to shared folder automatically on Windows.<br>><br>> On each loop of run_service(), run a GTask, that waits for half a second.<br>> If read_thread() returns, it means, that sharing is not yet connected,<br>> and the map_drive task is cancelled.<br>><br>> If the map_drive task is NOT cancelled, it enumerates free drive letters,<br>> and maps Spice Folder to highest possible (from Z: to A:).<br>><br>> If all drive letters are already assigned, show a critical error, but<br>> don't stop the service. The folder can still be accessed trough other<br>> means.<br><br>This one breaks the build<br><br>spice/spice-webdavd.c: In function 'map_drive_cb':<br>spice/spice-webdavd.c:864:19: error: 'MapDriveData {aka struct _MapDriveData}'<br>has no member named 'drive_letter'<br>   *(map_drive_data->drive_letter) = drive_letter;<br>                      ^<br><br></span></p><p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif">            Oops, I might have forgotten that line while rebasing.</span></p><p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif">            It should be anned in the next commit</span></p><p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif"><br>Reviewed-by: Victor Toso <<a href="mailto:victortoso@redhat.com">victortoso@redhat.com</a>><br><br>> ---<br>> Changes since v5:<br>>  - fixed indentation<br>>  - fixed * indentaion<br>>  - removed return from void functions<br>><br>> Changes since v4:<br>>  - Changed cancel_map to MapDriveData structure<br>>  - Added error checking for GetLogicalDrives()<br>>  - Moved defines and variables around<br>>  - Renamed some functions and variables<br>>  - Better debug messages<br>><br>> Changes since v3:<br>>  - Added init_netresource and clear_netresource functions<br>>     - Should clean up the map_drive function<br>>     - Better handeling of adress to map/unmap<br>>        - Not hardcoded port<br>>  - Syntax cleanup<br>>  - Changed criticals to warnings<br>>  - Better TODO<br>><br>> Changes since v2:<br>>  - Changed for loop to gpoll<br>>  - split map_drive into 2 functions<br>>  - added enum for return values of map_drive<br>>  - added TODO for renaming the drive<br>>  - added explanation for the 0.5 delay into commit log<br>><br>> Changes since v1:<br>>  - Changed GThread to a GTask<br>>  - Only wait half a second, instead of 5<br>><br>> Changes since RFC:<br>>  - Calling WNetAddConnection2() blindly was slow and caause many threads to spawn.<br>>     - Now only call it once, when it is sure, that it will connect.<br>>  - Now connects to a * drive, instead of always Z:<br>>  - Thread is now spawned and joined every time run_service() is called.<br>> ---<br>>  Makefile.am           |   4 ++<br>>  spice/spice-webdavd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++<br>>  2 files changed, 146 insertions(+)<br>><br>> diff --git a/Makefile.am b/Makefile.am<br>> index 6127f93..d8e2d53 100644<br>> --- a/Makefile.am<br>> +++ b/Makefile.am<br>> @@ -87,6 +87,10 @@ spice_webdavd_LDADD =              \<br>>       $(PIE_LDFLAGS)          \<br>>       $(NULL)<br>><br>> +if OS_WIN32<br>> +spice_webdavd_LDADD += -lnetapi32 -lmpr<br>> +endif<br>> +<br>>  deps.txt:<br>>       $(AM_V_GEN)rpm -qa | grep $(host_os) | sort | unix2dos > $@<br>><br>> diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c<br>> index f9c5cf1..88c29d0 100644<br>> --- a/spice/spice-webdavd.c<br>> +++ b/spice/spice-webdavd.c<br>> @@ -737,11 +737,148 @@ open_mux_path (const char *path)<br>>    mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));<br>>  }<br>><br>> +#ifdef G_OS_WIN32<br>> +#define MAX_SHARED_FOLDER_NAME_SIZE 64<br>> +#define MAX_DRIVE_LETTER_SIZE 3<br>> +typedef enum _MapDriveEnum<br>> +{<br>> +  MAP_DRIVE_OK,<br>> +  MAP_DRIVE_TRY_AGAIN,<br>> +  MAP_DRIVE_ERROR<br>> +} MapDriveEnum;<br>> +<br>> +typedef struct _MapDriveData<br>> +{<br>> +  GCancellable *cancel_map;<br>> +} MapDriveData;<br>> +<br>> +static gchar<br>> +get_free_drive_letter(void)<br>> +{<br>> +  const guint32 max_mask = 1 << 25;<br>> +  guint32 drives;<br>> +  gint i;<br>> +<br>> +  drives = GetLogicalDrives ();<br>> +  if (drives == 0)<br>> +    {<br>> +      g_warning ("%s", g_win32_error_message (GetLastError ()));<br>> +      return 0;<br>> +    }<br>> +<br>> +  for (i = 0; i < 26; i++)<br>> +    {<br>> +      guint32 mask = max_mask >> i;<br>> +      if ((drives & mask) == 0)<br>> +        return 'z' - i;<br>> +    }<br>> +<br>> +  return 0;<br>> +}<br>> +<br>> +/* User is required to call netresource_free, when no longer needed. */<br>> +static void<br>> +netresource_init(NETRESOURCE *net_resource, const gchar drive_letter)<br>> +{<br>> +  net_resource->dwType = RESOURCETYPE_DISK;<br>> +  net_resource->lpLocalName = g_strdup_printf("%c:", drive_letter);<br>> +  net_resource->lpRemoteName = g_strdup_printf("http://localhost:%d/", port);<br>> +  net_resource->lpProvider = NULL;<br>> +}<br>> +<br>> +static void<br>> +netresource_free(NETRESOURCE *net_resource)<br>> +{<br>> +  g_free(net_resource->lpLocalName);<br>> +  g_free(net_resource->lpRemoteName);<br>> +}<br>> +<br>> +static MapDriveEnum<br>> +map_drive(const gchar drive_letter)<br>> +{<br>> +  NETRESOURCE net_resource;<br>> +  guint32 errn;<br>> +<br>> +  netresource_init(&net_resource, drive_letter);<br>> +  errn = WNetAddConnection2 (&net_resource, NULL, NULL, CONNECT_TEMPORARY);<br>> +  netresource_free(&net_resource);<br>> +<br>> +  if (errn == NO_ERROR)<br>> +    {<br>> +      g_debug ("Shared folder mapped to %c succesfully", drive_letter);<br>> +      return MAP_DRIVE_OK;<br>> +    }<br>> +  else if (errn == ERROR_ALREADY_ASSIGNED)<br>> +    {<br>> +      g_debug ("Drive letter %c is already assigned", drive_letter);<br>> +      return MAP_DRIVE_TRY_AGAIN;<br>> +    }<br>> +<br>> +  g_warning ("map_drive error %d", errn);<br>> +  return MAP_DRIVE_ERROR;<br>> +}<br>> +<br>> +static void<br>> +map_drive_cb(GTask *task,<br>> +             gpointer source_object,<br>> +             gpointer task_data,<br>> +             GCancellable *cancellable)<br>> +{<br>> +  const guint32 delay = 500; //half a second<br>> +  MapDriveData *map_drive_data = task_data;<br>> +  gchar drive_letter;<br>> +  GPollFD cancel_pollfd;<br>> +  guint32 ret = 0;<br>> +<br>> +  if (!g_cancellable_make_pollfd (map_drive_data->cancel_map, &cancel_pollfd))<br>> +    {<br>> +      g_critical ("GPollFD failed to create.");<br>> +      return;<br>> +    }<br>> +<br>> +  ret = g_poll (&cancel_pollfd, 1, delay);<br>> +  g_cancellable_release_fd (map_drive_data->cancel_map);<br>> +<br>> +  if (ret != 0)<br>> +    {<br>> +      return;<br>> +    }<br>> +<br>> +  while (TRUE)<br>> +    {<br>> +      drive_letter = get_free_drive_letter ();<br>> +      if (drive_letter == 0)<br>> +        {<br>> +          g_warning ("all drive letters already assigned.");<br>> +          break;<br>> +        }<br>> +<br>> +      if (map_drive (drive_letter) != MAP_DRIVE_TRY_AGAIN)<br>> +        {<br>> +          break;<br>> +        }<br>> +      //TODO: After mapping, rename network drive from \\localhost@PORT\DavWWWRoot<br>> +      //      to something like SPICE Shared Folder<br>> +    }<br>> +<br>> +  *(map_drive_data->drive_letter) = drive_letter;<br>> +}<br>> +#endif<br>> +<br>>  static void<br>>  run_service (void)<br>>  {<br>>    g_debug ("Run service");<br>><br>> +#ifdef G_OS_WIN32<br>> +  MapDriveData map_drive_data;<br>> +  map_drive_data.cancel_map = g_cancellable_new ();<br>> +  GTask *map_drive_task = g_task_new (NULL, NULL, NULL, NULL);<br>> +  g_task_set_task_data (map_drive_task, &map_drive_data, NULL);<br>> +  g_task_run_in_thread (map_drive_task, map_drive_cb);<br>> +  g_object_unref (map_drive_task);<br>> +#endif<br>> +<br>>    g_socket_service_start (socket_service);<br>><br>>    cancel = g_cancellable_new ();<br>> @@ -775,6 +912,11 @@ run_service (void)<br>>    g_main_loop_run (loop);<br>>    g_main_loop_unref (loop);<br>><br>> +#ifdef G_OS_WIN32<br>> +  g_cancellable_cancel (map_drive_data.cancel_map);<br>> +  g_object_unref (map_drive_data.cancel_map);<br>> +#endif<br>> +<br>>    g_cancellable_cancel (cancel);<br>><br>>    g_clear_object (&mux_istream);<br><span style="color:#888888">> --<br>> 2.5.5<br>><br>> _______________________________________________<br>> Spice-devel mailing list<br>> <a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>> <a href="https://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">https://lists.freedesktop.org/mailman/listinfo/spice-devel</a></span></span></p><p class="MsoNormal"> </p></div></body></html>