Utopia-Canteen-System/Services/Logging/InteractiveUserPath.cs

59 lines
1.8 KiB
C#

using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace UtopiaCanteenSystem.Services.Logging;
/// <summary>
/// Resolves the logged-on Windows user's profile paths when the app runs as a service (SYSTEM).
/// </summary>
internal static class InteractiveUserPath
{
public static string? TryGetLocalAppDataPath()
{
var profile = TryGetProfileDirectory();
if (string.IsNullOrWhiteSpace(profile))
return null;
var localAppData = Path.Combine(profile, "AppData", "Local");
return Directory.Exists(localAppData) ? localAppData : null;
}
private static string? TryGetProfileDirectory()
{
var sessionId = WTSGetActiveConsoleSessionId();
if (sessionId == 0xFFFFFFFF)
return null;
if (!WTSQueryUserToken(sessionId, out var userToken) || userToken == IntPtr.Zero)
return null;
try
{
var sb = new StringBuilder(512);
var size = sb.Capacity;
if (!GetUserProfileDirectory(userToken, sb, ref size, out _))
return null;
var path = sb.ToString();
return string.IsNullOrWhiteSpace(path) ? null : path;
}
finally
{
CloseHandle(userToken);
}
}
[DllImport("kernel32.dll")]
private static extern uint WTSGetActiveConsoleSessionId();
[DllImport("wtsapi32.dll", SetLastError = true)]
private static extern bool WTSQueryUserToken(uint sessionId, out IntPtr phToken);
[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool GetUserProfileDirectory(IntPtr hToken, StringBuilder lpProfileDir, ref int lpcchSize, out int lpDwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
}