0

I have a couple of functions from the Kernel32.dll which I am calling from C# program. I imported the functions as follows:

[System.Runtime.InteropServices.DllImport("Kernel32.dll", EntryPoint = "GetSystemTime", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
private static extern void GetSystemTime(ref SYSTEMTIME lpSystemTime);

[System.Runtime.InteropServices.DllImport("Kernel32.dll", EntryPoint = "SetSystemTime", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
private static extern UInt32 SetSystemTime(ref SYSTEMTIME lpSystemTime);

where SYSTEMTIME is a struct accepted by these methods.

The documentation for SetSystemTime says that it returns 0 if the function fails and call GetLastError to get extended information on the failure. So I imported GetLastError from Kernel32.dll file in the same way as the above functions. Now when I simulate the failure as:

if (SetSystemTime(ref st) == 0) {
      Console.WriteLine(GetLastError() + " Error occurred: SetSystemTime returned zero.");
}

The GetLastError() prints a code of 1314 which is for A required privilege not held by the client. I changed the Local security policy to add the user to the Replace a process level token in the User rights assignment as well but I still get the same code. Is what I am doing correct or am I missing something?

Navjot Singh
  • 678
  • 7
  • 18
  • 1
    Don't import `GetLastError` and call it directly. You must use `SetLastError = true` in your p/invoke declarations, and then use `Marshal.GetLastWin32Error()`. This allows the p/invoke framework to capture the error code immediately after the function call returns. Otherwise the .net framework might call another API call and modify the thread's error code. – David Heffernan Nov 21 '19 at 13:33
  • As is clearly [documented](https://learn.microsoft.com/windows/win32/api/sysinfoapi/nf-sysinfoapi-setsystemtime#requirements), calling `SetSystemTime` requires that the caller holds the `SE_SYSTEMTIME_NAME` privilege, and while the function helpfully obtains the privilege for you when not held, it still requires your account to be able to get it. That means running as administrator (elevated), or having the "change the system time" right explicitly assigned through Local Security Policy. In general, think twice before allowing your program to mess with the system clock. – Jeroen Mostert Nov 21 '19 at 13:37
  • https://stackoverflow.com/questions/2818179/how-do-i-force-my-net-application-to-run-as-administrator – Hans Passant Nov 21 '19 at 14:12
  • @DavidHeffernan The `Marshal.GetLastWin32Error()` also returns the same `1314` code – Navjot Singh Nov 21 '19 at 14:42
  • @NavjotSingh Yes. I was giving you broader advice than the specifics of this question. You are welcome. – David Heffernan Nov 21 '19 at 14:47

1 Answers1

-3

it looks like 'User Right Assignment' caused by UAC.

Try this:

1] Use Local Security Policy

Sometimes it happens because of some admin account conflicts. In this case, you need to open Local Security Policy window. You can either search for the same in the Taskbar search box or Cortana, or you can press Win + R, type secpol.msc and hit the Enter button.

Navigate to Local Policies > Security Options. Locate User Account Control: Run all administrators in Admin Approval Mode and set it to Disable.

  • OR

2] Disable UAC

UAC or User Account Control prevents programs from making any change in the system. However, sometimes it can create a problem as well. Therefore, you can temporarily try disabling UAC and check whether it works or not. To disable User Account Control in Windows, search for User Account Control Settings in the Taskbar search box. You should set UAC to Never Notify.

I hope it helps you.