diff --git a/src/User32/PublicAPI.Unshipped.txt b/src/User32/PublicAPI.Unshipped.txt
index 88a32dcc..b721a61f 100644
--- a/src/User32/PublicAPI.Unshipped.txt
+++ b/src/User32/PublicAPI.Unshipped.txt
@@ -44,4 +44,12 @@ static extern PInvoke.User32.EnumDisplaySettings(char* lpszDeviceName, uint iMod
static extern PInvoke.User32.EnumDisplaySettingsEx(char* lpszDeviceName, uint iModeNum, PInvoke.DEVMODE* lpDevMode, PInvoke.User32.EnumDisplaySettingsExFlags dwFlags) -> bool
static extern PInvoke.User32.LoadString(System.IntPtr hInstance, uint uID, char* lpBuffer, int cchBufferMax) -> int
static extern PInvoke.User32.UnregisterClass(string lpClassName, System.IntPtr hInstance) -> bool
-static readonly PInvoke.User32.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED -> System.IntPtr
\ No newline at end of file
+static readonly PInvoke.User32.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED -> System.IntPtr
+static PInvoke.User32.GetLastInputInfo(System.IntPtr plii) -> bool
+static PInvoke.User32.GetLastInputInfo(out PInvoke.User32.LASTINPUTINFO plii) -> bool
+static extern PInvoke.User32.GetLastInputInfo(PInvoke.User32.LASTINPUTINFO* plii) -> bool
+PInvoke.User32.LASTINPUTINFO
+PInvoke.User32.LASTINPUTINFO.LASTINPUTINFO() -> void
+PInvoke.User32.LASTINPUTINFO.cbSize -> int
+PInvoke.User32.LASTINPUTINFO.dwTime -> uint
+static PInvoke.User32.LASTINPUTINFO.Create() -> PInvoke.User32.LASTINPUTINFO
\ No newline at end of file
diff --git a/src/User32/User32+LASTINPUTINFO.cs b/src/User32/User32+LASTINPUTINFO.cs
new file mode 100644
index 00000000..c39a3f5a
--- /dev/null
+++ b/src/User32/User32+LASTINPUTINFO.cs
@@ -0,0 +1,36 @@
+// Copyright © .NET Foundation and Contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace PInvoke
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Contains the nested type.
+ ///
+ public partial class User32
+ {
+ ///
+ /// Contains the time of the last input. It is used with the function.
+ ///
+ public struct LASTINPUTINFO
+ {
+ ///
+ /// The size of the structure, in bytes. This member must be set to sizeof(LASTINPUTINFO).
+ ///
+ public int cbSize;
+
+ ///
+ /// The tick count when the last input event was received.
+ ///
+ public uint dwTime;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// An initialized instance of the struct.
+ public static unsafe LASTINPUTINFO Create() => new LASTINPUTINFO { cbSize = sizeof(LASTINPUTINFO) };
+ }
+ }
+}
diff --git a/src/User32/User32.cs b/src/User32/User32.cs
index 20c59971..16afeb47 100644
--- a/src/User32/User32.cs
+++ b/src/User32/User32.cs
@@ -3944,6 +3944,27 @@ public static unsafe extern uint MsgWaitForMultipleObjectsEx(
WakeMask dwWakeMask,
MsgWaitForMultipleObjectsExFlags dwFlags);
+ ///
+ /// Retrieves the time of the last input event.
+ ///
+ /// A pointer to a structure that receives the time of the last input event.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero.
+ ///
+ ///
+ /// This function is useful for input idle detection. However, GetLastInputInfo does not provide system-wide
+ /// user input information across all running sessions. Rather, GetLastInputInfo provides session-specific user input
+ /// information for only the session that invoked the function.
+ /// The tick count when the last input event was received (see ) is not guaranteed to be incremental.
+ /// In some cases, the value might be less than the tick count of a prior event. For example, this can be caused by
+ /// a timing gap between the raw input thread and the desktop thread or an event raised by SendInput, which supplies its own tick count.
+ ///
+ [DllImport(nameof(User32))]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern unsafe bool GetLastInputInfo(
+ [Friendly(FriendlyFlags.Out)] LASTINPUTINFO* plii);
+
///
/// The BeginPaint function prepares the specified window for painting and fills a structure with information about the painting.
///