diff mbox series

[FFmpeg-devel,v2] gdigrab: Allow capturing a window by its handle

Message ID 20231212135956.20801-2-lena@nihil.gay
State New
Headers show
Series [FFmpeg-devel,v2] gdigrab: Allow capturing a window by its handle | expand

Checks

Context Check Description
andriy/commit_msg_x86 warning Please wrap lines in the body of the commit message between 60 and 72 characters.
yinshiyou/commit_msg_loongarch64 warning Please wrap lines in the body of the commit message between 60 and 72 characters.
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Lena Dec. 12, 2023, 1:59 p.m. UTC
Added the change to the documentation and added error checking on `strtol`, according to the stdlib documentation.

The documentation for `strtol` says that on error, 0 is returned. This makes it impossible to specify a window handle of 0 (the whole desktop), but that case is already covered by the "desktop" input filename, so it should be fine.


x11grab can capture windows by their ID, but gdigrab can only capture windows by their names, internally calling FindWindowW to lookup its handle.

This patch simply allows the user to specify a window handle directly.
Signed-off-by: Lena <lena@nihil.gay>
---
 doc/indevs.texi       |  8 ++++++--
 libavdevice/gdigrab.c | 13 ++++++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

Comments

Nicolas George Dec. 12, 2023, 2:07 p.m. UTC | #1
Lena via ffmpeg-devel (12023-12-12):
> The documentation for `strtol` says that on error, 0 is returned. This
> makes it impossible to specify a window handle of 0 (the whole
> desktop), but that case is already covered by the "desktop" input
> filename, so it should be fine.

The correct way to test for error in strtol is to check the endptr.

But just use a single sscanf() and %n to see if it reached the end of
the string.

> -There are two options for the input filename:
> +There are three options for the input filename:

“Amongst options for the imput filenames are such elements as:”

;-)

Regards,
Rémi Denis-Courmont Dec. 12, 2023, 3:31 p.m. UTC | #2
Le 12 décembre 2023 16:07:28 GMT+02:00, Nicolas George <george@nsup.org> a écrit :
>Lena via ffmpeg-devel (12023-12-12):
>> The documentation for `strtol` says that on error, 0 is returned. This
>> makes it impossible to specify a window handle of 0 (the whole
>> desktop), but that case is already covered by the "desktop" input
>> filename, so it should be fine.
>
>The correct way to test for error in strtol is to check the endptr.

...and test for overflow errors in errno.m (which shall have been zeroed beforehand). AFAIK, you need to do both if you want strict error detection.

>
>But just use a single sscanf() and %n to see if it reached the end of
>the string.

Don't some distros forbid the use of the n specifier for (debatable) "security reasons"? Or is that only for formatting, and not in scanning?

>> -There are two options for the input filename:
>> +There are three options for the input filename:
>
>“Amongst options for the imput filenames are such elements as:”
>
>;-)
>
>Regards,
>
>-- 
>  Nicolas George
>_______________________________________________
>ffmpeg-devel mailing list
>ffmpeg-devel@ffmpeg.org
>https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>To unsubscribe, visit link above, or email
>ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Nicolas George Dec. 13, 2023, 10:03 a.m. UTC | #3
Rémi Denis-Courmont (12023-12-12):
> ...and test for overflow errors in errno.m (which shall have been
> zeroed beforehand). AFAIK, you need to do both if you want strict
> error detection.

Or we can consider that 30064771114 is just another valid way if writing
42 = 042 = 0x2a. It would be better to check, but it is less critical
than checking for garbage at the and, which itself is less critical than
checking that the number is entirely absent.

> Don't some distros forbid the use of the n specifier for (debatable)
> "security reasons"? Or is that only for formatting, and not in
> scanning?

First time I ear of that. We use %n in quite a few places — not only
code by me — and we did not have a problem.

If there is a real security consideration about %n, I would like a
pointer to the explanations; but I strongly doubt there are, it is just
another conversion specifier with all the usual caveats. If not, and
there are distros who forbid it for no valid reason, then I say to hell
with them.

Regards,
Rémi Denis-Courmont Dec. 14, 2023, 10:52 a.m. UTC | #4
Le 13 décembre 2023 12:03:55 GMT+02:00, Nicolas George <george@nsup.org> a écrit :
>Rémi Denis-Courmont (12023-12-12):
>> ...and test for overflow errors in errno.m (which shall have been
>> zeroed beforehand). AFAIK, you need to do both if you want strict
>> error detection.
>
>Or we can consider that 30064771114 is just another valid way if writing
>42 = 042 = 0x2a. It would be better to check, but it is less critical
>than checking for garbage at the and, which itself is less critical than
>checking that the number is entirely absent.

That's completely arbitrary, TBH. Both cases are syntax errors, and there are no particular reasons to tolerate one but not the other. And even if it constitued a sensible distinction, that's simply not how strtoul() handles overflow: it returns ULONG_MAX, not a wrapped-around value.

In this case, both error cases are strong signs of a typing error or corruption.
diff mbox series

Patch

diff --git a/doc/indevs.texi b/doc/indevs.texi
index 863536a34d..6da0ccac62 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -722,7 +722,7 @@  Win32 GDI-based screen capture device.
 
 This device allows you to capture a region of the display on Windows.
 
-There are two options for the input filename:
+There are three options for the input filename:
 @example
 desktop
 @end example
@@ -730,9 +730,13 @@  or
 @example
 title=@var{window_title}
 @end example
+or
+@example
+hwnd=@var{window_hwnd}
+@end example
 
 The first option will capture the entire desktop, or a fixed region of the
-desktop. The second option will instead capture the contents of a single
+desktop. The second and third options will instead capture the contents of a single
 window, regardless of its position on the screen.
 
 For example, to grab the entire desktop using @command{ffmpeg}:
diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c
index c069232472..f310d8f3d7 100644
--- a/libavdevice/gdigrab.c
+++ b/libavdevice/gdigrab.c
@@ -273,9 +273,20 @@  gdigrab_read_header(AVFormatContext *s1)
         }
     } else if (!strcmp(filename, "desktop")) {
         hwnd = NULL;
+    } else if (!strncmp(filename, "hwnd=", 5)) {
+        name = filename + 5;
+        
+        hwnd = strtol(name, NULL, 0);
+
+        if (hwnd == NULL) {
+            av_log(s1, AV_LOG_ERROR,
+               "Invalid window handle.\n");
+            ret = AVERROR(EINVAL);
+            goto error;
+        }
     } else {
         av_log(s1, AV_LOG_ERROR,
-               "Please use \"desktop\" or \"title=<windowname>\" to specify your target.\n");
+               "Please use \"desktop\", \"title=<windowname>\" or \"hwnd=<hwnd>\" to specify your target.\n");
         ret = AVERROR(EIO);
         goto error;
     }