From 1fc2951f227cfa9c7251d7725ff13e006b822c26 Mon Sep 17 00:00:00 2001
From: Daniel Cohen Gindi <danielgindi@gmail.com>
Date: Sat, 20 Sep 2014 17:20:46 +0300
Subject: On windows, use the Win32 calls for directory enumerations.

We also do not need the conversion between UNIX values to Windows values in the RTF_FIND_DATA struct, as we already are on windows.
---
 libvncserver/rfbserver.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 78 insertions(+), 3 deletions(-)

(limited to 'libvncserver')

diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index abe2475..ad76fbc 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -75,8 +75,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+
+#ifndef WIN32
 /* readdir() */
 #include <dirent.h>
+#endif
+
 /* errno */
 #include <errno.h>
 /* strftime() */
@@ -99,6 +103,8 @@
 #else /* MSVC and other windows compilers */
 #define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */
 #endif /* __MINGW32__ else... */
+#define S_ISDIR(m)	(((m) & S_IFDIR) == S_IFDIR)
+#include <direct.h>
 #endif
 
 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
@@ -1299,8 +1305,15 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
     struct stat statbuf;
     RFB_FIND_DATA win32filename;
     int nOptLen = 0, retval=0;
+#ifdef WIN32
+    WIN32_FIND_DATAA winFindData;
+    HANDLE findHandle;
+    int pathLen, basePathLength;
+    char *basePath;
+#else
     DIR *dirp=NULL;
     struct dirent *direntp=NULL;
+#endif
 
     FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
 
@@ -1309,23 +1322,67 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
 
     if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
 
+#ifdef WIN32
+    // Create a search string, like C:\folder\*
+
+    pathLen = strlen(path);
+    basePath = malloc(pathLen + 3);
+    memcpy(basePath, path, pathLen);
+    basePathLength = pathLen;
+    basePath[basePathLength] = '\\';
+    basePath[basePathLength + 1] = '*';
+    basePath[basePathLength + 2] = '\0';
+
+    // Start a search
+    memset(&winFindData, 0, sizeof(winFindData));
+    findHandle = FindFirstFileA(path, &winFindData);
+    free(basePath);
+
+    if (findHandle == INVALID_HANDLE_VALUE)
+#else
     dirp=opendir(path);
     if (dirp==NULL)
+#endif
         return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);
+
     /* send back the path name (necessary for links) */
     if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;
+
+#ifdef WIN32
+    while (findHandle != INVALID_HANDLE_VALUE)
+#else
     for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
+#endif
     {
         /* get stats */
-        snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
+#ifdef WIN32
+    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, winFindData.cFileName);
+#else
+    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
+#endif
         retval = stat(retfilename, &statbuf);
 
         if (retval==0)
         {
             memset((char *)&win32filename, 0, sizeof(win32filename));
+#ifdef WIN32
+            win32filename.dwFileAttributes = winFindData.dwFileAttributes;
+            win32filename.ftCreationTime.dwLowDateTime = winFindData.ftCreationTime.dwLowDateTime;
+            win32filename.ftCreationTime.dwHighDateTime = winFindData.ftCreationTime.dwHighDateTime;
+            win32filename.ftLastAccessTime.dwLowDateTime = winFindData.ftLastAccessTime.dwLowDateTime;
+            win32filename.ftLastAccessTime.dwHighDateTime = winFindData.ftLastAccessTime.dwHighDateTime;
+            win32filename.ftLastWriteTime.dwLowDateTime = winFindData.ftLastWriteTime.dwLowDateTime;
+            win32filename.ftLastWriteTime.dwHighDateTime = winFindData.ftLastWriteTime.dwHighDateTime;
+            win32filename.nFileSizeLow = winFindData.nFileSizeLow;
+            win32filename.nFileSizeHigh = winFindData.nFileSizeHigh;
+            win32filename.dwReserved0 = winFindData.dwReserved0;
+            win32filename.dwReserved1 = winFindData.dwReserved1;
+            strcpy((char *)win32filename.cFileName, winFindData.cFileName);
+            strcpy((char *)win32filename.cAlternateFileName, winFindData.cAlternateFileName);
+#else
             win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
             if (S_ISDIR(statbuf.st_mode))
-              win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
+                win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
             win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime);   /* Intel Order */
             win32filename.ftCreationTime.dwHighDateTime = 0;
             win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
@@ -1340,9 +1397,10 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
             /* If this had the full path, we would need to translate to DOS format ("C:\") */
             /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
             strcpy((char *)win32filename.cFileName, direntp->d_name);
+#endif
             
             /* Do not show hidden files (but show how to move up the tree) */
-            if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.'))
+            if ((strcmp((char *)win32filename.cFileName, "..")==0) || (win32filename.cFileName[0]!='.'))
             {
                 nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
                 /*
@@ -1350,13 +1408,30 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
                 */
                 if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE)
                 {
+#ifdef WIN32
+                    FindClose(findHandle);
+#else
                     closedir(dirp);
+#endif
                     return FALSE;
                 }
             }
         }
+
+        if (FindNextFileA(findHandle, &winFindData) == 0)
+        {
+            FindClose(findHandle);
+            findHandle = INVALID_HANDLE_VALUE;
+        }
     }
+#ifdef WIN32
+    if (findHandle != INVALID_HANDLE_VALUE)
+    {
+        FindClose(findHandle);
+    }
+#else
     closedir(dirp);
+#endif
     /* End of the transfer */
     return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
 }
-- 
cgit v1.2.1