<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>