[PATCH 1/2] avicap32: Build with msvcrt.

Zebediah Figura zfigura at codeweavers.com
Wed Sep 1 15:56:46 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
There's a good chance that we'll want to move v4l handling to a kernel streaming
infrastructure, which is the main reason I hadn't bothered converting avicap32
yet, but I'm not likely to get the time to do that research in the near future.

 dlls/avicap32/Makefile.in     |   7 +-
 dlls/avicap32/avicap32_main.c | 135 +++++++--------------------------
 dlls/avicap32/unixlib.h       |  33 ++++++++
 dlls/avicap32/v4l.c           | 137 ++++++++++++++++++++++++++++++++++
 4 files changed, 201 insertions(+), 111 deletions(-)
 create mode 100644 dlls/avicap32/unixlib.h
 create mode 100644 dlls/avicap32/v4l.c

diff --git a/dlls/avicap32/Makefile.in b/dlls/avicap32/Makefile.in
index 8f5a1089d5c..a899a6207b0 100644
--- a/dlls/avicap32/Makefile.in
+++ b/dlls/avicap32/Makefile.in
@@ -1,4 +1,9 @@
 MODULE    = avicap32.dll
 IMPORTLIB = avicap32
+EXTRALIBS = -Wl,--subsystem,unixlib
 
-C_SRCS = avicap32_main.c
+EXTRADLLFLAGS = -mno-cygwin
+
+C_SRCS = \
+	avicap32_main.c \
+	v4l.c
diff --git a/dlls/avicap32/avicap32_main.c b/dlls/avicap32/avicap32_main.c
index 9e2a99d4c7c..d4608138d8b 100644
--- a/dlls/avicap32/avicap32_main.c
+++ b/dlls/avicap32/avicap32_main.c
@@ -17,45 +17,20 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-
 #include <stdarg.h>
-#include <stdio.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_ASM_TYPES_H
-# include <asm/types.h>
-#endif
-#ifdef HAVE_LINUX_VIDEODEV2_H
-# include <linux/videodev2.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
 #include "vfw.h"
-#include "winnls.h"
 #include "winternl.h"
 #include "wine/debug.h"
 
-#define CAP_DESC_MAX 32
+#include "unixlib.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(avicap);
 
+static unixlib_handle_t unix_handle;
 
 /***********************************************************************
  *             capCreateCaptureWindowW   (AVICAP32.@)
@@ -88,81 +63,6 @@ HWND VFWAPI capCreateCaptureWindowA(LPCSTR lpszWindowName, DWORD dwStyle, INT x,
     return retW;
 }
 
-#ifdef HAVE_LINUX_VIDEODEV2_H
-
-static int xioctl(int fd, int request, void * arg)
-{
-   int r;
-
-   do r = ioctl (fd, request, arg);
-   while (-1 == r && EINTR == errno);
-
-   return r;
-}
-
-static BOOL query_video_device(int devnum, char *name, int namesize, char *version, int versionsize)
-{
-   int fd;
-   char device[16];
-   struct stat st;
-   struct v4l2_capability caps;
-
-   snprintf(device, sizeof(device), "/dev/video%i", devnum);
-
-   if (stat (device, &st) == -1) {
-      /* This is probably because the device does not exist */
-      WARN("%s: %s\n", device, strerror(errno));
-      return FALSE;
-   }
-
-   if (!S_ISCHR (st.st_mode)) {
-      ERR("%s: Not a device\n", device);
-      return FALSE;
-   }
-
-   fd = open(device, O_RDWR | O_NONBLOCK);
-   if (fd == -1) {
-      ERR("%s: Failed to open: %s\n", device, strerror(errno));
-      return FALSE;
-   }
-
-   memset(&caps, 0, sizeof(caps));
-   if (xioctl(fd, VIDIOC_QUERYCAP, &caps) != -1) {
-      BOOL isCaptureDevice;
-#ifdef V4L2_CAP_DEVICE_CAPS
-      if (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
-         isCaptureDevice = caps.device_caps & V4L2_CAP_VIDEO_CAPTURE;
-      else
-#endif
-         isCaptureDevice = caps.capabilities & V4L2_CAP_VIDEO_CAPTURE;
-      if (isCaptureDevice) {
-         lstrcpynA(name, (char *)caps.card, namesize);
-         snprintf(version, versionsize, "%s v%u.%u.%u", (char *)caps.driver, (caps.version >> 16) & 0xFF,
-                             (caps.version >> 8) & 0xFF, caps.version & 0xFF);
-      }
-      close(fd);
-      return isCaptureDevice;
-   }
-
-   if (errno != EINVAL && errno != 515)
-/* errno 515 is used by some webcam drivers for unknown IOICTL command */
-      ERR("%s: Querying failed: %s\n", device, strerror(errno));
-   else ERR("%s: Querying failed: Not a V4L compatible device\n", device);
-
-   close(fd);
-   return FALSE;
-}
-
-#else /* HAVE_LINUX_VIDEODEV2_H */
-
-static BOOL query_video_device(int devnum, char *name, int namesize, char *version, int versionsize)
-{
-   ERR("Video 4 Linux support not enabled\n");
-   return FALSE;
-}
-
-#endif /* HAVE_LINUX_VIDEODEV2_H */
-
 /***********************************************************************
  *             capGetDriverDescriptionA   (AVICAP32.@)
  */
@@ -183,15 +83,30 @@ BOOL VFWAPI capGetDriverDescriptionA(WORD wDriverIndex, LPSTR lpszName,
 /***********************************************************************
  *             capGetDriverDescriptionW   (AVICAP32.@)
  */
-BOOL VFWAPI capGetDriverDescriptionW(WORD wDriverIndex, LPWSTR lpszName,
-                                     INT cbName, LPWSTR lpszVer, INT cbVer)
+BOOL VFWAPI capGetDriverDescriptionW(WORD index, WCHAR *name, int name_len, WCHAR *version, int version_len)
 {
-   char devname[CAP_DESC_MAX], devver[CAP_DESC_MAX];
+    struct get_device_desc_params params;
 
-   if (!query_video_device(wDriverIndex, devname, CAP_DESC_MAX, devver, CAP_DESC_MAX)) return FALSE;
+    params.index = index;
+    if (__wine_unix_call(unix_handle, unix_get_device_desc, &params))
+        return FALSE;
 
-   MultiByteToWideChar(CP_UNIXCP, 0, devname, -1, lpszName, cbName);
-   MultiByteToWideChar(CP_UNIXCP, 0, devver, -1, lpszVer, cbVer);
-   TRACE("Version: %s - Name: %s\n", debugstr_w(lpszVer), debugstr_w(lpszName));
-   return TRUE;
+    TRACE("Found device name %s, version %s.\n", debugstr_w(params.name), debugstr_w(params.version));
+    lstrcpynW(name, params.name, name_len);
+    lstrcpynW(version, params.version, version_len);
+    return TRUE;
+}
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
+{
+    switch (reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            NtQueryVirtualMemory(GetCurrentProcess(), instance,
+                    MemoryWineUnixFuncs, &unix_handle, sizeof(unix_handle), NULL);
+            DisableThreadLibraryCalls(instance);
+            break;
+    }
+
+    return TRUE;
 }
diff --git a/dlls/avicap32/unixlib.h b/dlls/avicap32/unixlib.h
new file mode 100644
index 00000000000..89ef1cc93f9
--- /dev/null
+++ b/dlls/avicap32/unixlib.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/unixlib.h"
+
+#define CAP_DESC_MAX 32
+
+struct get_device_desc_params
+{
+    WORD index;
+    WCHAR name[CAP_DESC_MAX];
+    WCHAR version[CAP_DESC_MAX];
+};
+
+enum unix_funcs
+{
+    unix_get_device_desc,
+};
diff --git a/dlls/avicap32/v4l.c b/dlls/avicap32/v4l.c
new file mode 100644
index 00000000000..ab2694ae041
--- /dev/null
+++ b/dlls/avicap32/v4l.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2002 Dmitry Timoshkov for CodeWeavers
+ * Copyright 2005 Maarten Lankhorst
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_LINUX_VIDEODEV2_H
+# include <linux/videodev2.h>
+#endif
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "wine/debug.h"
+
+#include "unixlib.h"
+
+#ifdef HAVE_LINUX_VIDEODEV2_H
+
+WINE_DEFAULT_DEBUG_CHANNEL(avicap);
+
+static int xioctl(int fd, int request, void *arg)
+{
+    int ret;
+
+    do
+        ret = ioctl(fd, request, arg);
+    while (ret < 0 && errno == EINTR);
+
+    return ret;
+}
+
+static void v4l_umbstowcs(const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen)
+{
+    DWORD ret = ntdll_umbstowcs(src, srclen, dst, dstlen - 1);
+
+    dst[ret] = 0;
+}
+
+static NTSTATUS get_device_desc(void *args)
+{
+    struct get_device_desc_params *params = args;
+    struct v4l2_capability caps = {{0}};
+    char device[16];
+    struct stat st;
+    int fd;
+
+    snprintf(device, sizeof(device), "/dev/video%u", params->index);
+
+    if (stat(device, &st) < 0)
+    {
+        /* This is probably because the device does not exist */
+        WARN("Failed to stat %s: %s\n", device, strerror(errno));
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+    if (!S_ISCHR(st.st_mode))
+    {
+        ERR("%s is not a character device.\n", device);
+        return STATUS_OBJECT_TYPE_MISMATCH;
+    }
+
+    if ((fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
+    {
+        ERR("%s: Failed to open: %s\n", device, strerror(errno));
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (!xioctl(fd, VIDIOC_QUERYCAP, &caps))
+    {
+        BOOL is_capture_device;
+#ifdef V4L2_CAP_DEVICE_CAPS
+        if (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
+            is_capture_device = caps.device_caps & V4L2_CAP_VIDEO_CAPTURE;
+        else
+#endif
+            is_capture_device = caps.capabilities & V4L2_CAP_VIDEO_CAPTURE;
+        if (is_capture_device)
+        {
+            char version[CAP_DESC_MAX];
+            int ret;
+
+            v4l_umbstowcs((char *)caps.card, strlen((char *)caps.card),
+                    params->name, ARRAY_SIZE(params->name));
+
+            ret = snprintf(version, ARRAY_SIZE(version), "%s v%u.%u.%u", (char *)caps.driver,
+                    (caps.version >> 16) & 0xff, (caps.version >> 8) & 0xff, caps.version & 0xff);
+            v4l_umbstowcs(version, ret, params->version, ARRAY_SIZE(params->version));
+        }
+        close(fd);
+        return is_capture_device;
+    }
+
+    /* errno 515 is used by some webcam drivers for unknown IOCTL commands. */
+    ERR("Failed to get capabilities for %s: %s\n", device, strerror(errno));
+
+    close(fd);
+    return FALSE;
+}
+
+const unixlib_entry_t __wine_unix_call_funcs[] =
+{
+    get_device_desc,
+};
+
+#endif /* HAVE_LINUX_VIDEODEV_2 */
-- 
2.33.0




More information about the wine-devel mailing list