Auch wenn es im Beispielprogramm keine Rolle spielt; erwähnenswert ist das Thema sicher. Datum und Uhrzeit kann man mit den beiden Funktionen
TSystemTime-Variable, die man vorher mit den neuen Werten "füttern" sollte. Beispielsweise
var st : TSystemTime; begin st.wYear := 2003; st.wMonth := 1; st.wDay := 1; st.wHour := 1; st.wMinute := 0; st.wSecond := 0; st.wMilliseconds := 0;
if(SetLocalTime(st)) then MessageBox(0,'Zeit geändert','SetLocalTime',0); end;
Die Rechtefrage ist der eigentliche Grund dieses Kapitels. Wenn man sich die alte "win32.hlp" ansieht, die Delphi beiliegt, dann steht dort folgendes:
Sinngemäß also: "Wenn der aufrufende Prozess (das Programm z.B.) nicht das Recht SE_SYSTEMTIME_NAME besitzt, scheitert der Aufruf der Funktion und damit das Ändern von Datum und Uhrzeit. Es wird empfohlen, das Recht zu aktivieren, die Funktion auszuführen und das Recht dann wieder zu deaktivieren." Vergleicht man diese Aussage mit neueren Ausgaben des Platform SDK, so liest man:
Hier heißt es zwar auch, dass das Recht SE_SYSTEMTIME_NAME standardmäßig deaktiviert ist. Es steht aber auch da, dass die Funktion dieses Recht wohl selbst holen kann (enables the ... privilege). Das steht im Widerspruch zur Aussage der alten Hilfedatei. Ich bin allerdings geneigt, den neuen Quellen eher zu glauben. Ein Test unter Windows XP ergab nämlich einen ganz anderen Ansatzpunkt.
Doch zuerst führen wir den Ratschlag der alten Hilfedatei aus. Die folgende Funktion stammt aus einem Forum und wurde von mir lediglich etwas erweitert, damit sie auch unter 9x-Plattformen benutzt werden kann:
function SetPrivilege(const pszPrivilege: LPCSTR; bEnablePrivilege: boolean): boolean; var wv : TOSVersionInfo; Token : THandle; tkp : TTokenPrivileges; begin wv.dwOSVersionInfoSize := sizeof(TOSVersionInfo); GetVersionEx(wv);
// da unter 9x jeder alles darf, setzen wir das // Ergebnis in dem Fall auf TRUE Result := (wv.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS);
// jetzt der echte Code für NT-Plattformen if(wv.dwPlatformId = VER_PLATFORM_WIN32_NT) then begin if(not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,Token)) then exit;
try if(not LookupPrivilegeValue(nil, pszPrivilege, tkp.Privileges[0].Luid)) then Exit;
tkp.PrivilegeCount := 1;
if(bEnablePrivilege) then tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED else tkp.Privileges[0].Attributes := 0;
Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^); finally CloseHandle(Token); end; end; end;
Bevor wir also die Zeit und/oder das Datum ändern können, müssen wir uns das dazu erforderliche Recht SE_SYSTEMTIME_NAME holen, was im Code so aussieht:
const SE_SYSTEMTIME_NAME = 'SeSystemtimePrivilege';
{ ... }
if(SetPrivilege(SE_SYSTEMTIME_NAME,true)) then SetLocalTime(st);
So würde das auch funktionieren, wenn ... tja ...
Sagen wir so: bei einem Test mit Benutzerrechten wurde die Zeit auch mit der eben erfolgten Anweisung nicht geändert. Des Rätsels Lösung war eine Einstellung der lokalen Sicherheitsrichtlinien von Windows XP. Hier finden Sie unter "Lokale Richtlinien/Zuweisen von Benutzerrechten" den Punkt "Ändern der Systemzeit", für den standardmäßig nur die Administratoren und Hauptbenutzer eingetragen sind. Geben Sie hier zusätzlich Ihren Benutzernamen an, oder ergänzen Sie die Gruppe, der Sie als Benutzer angehören, dann können Sie auch Datum und Uhrzeit ändern.
Und das klappt dann auch, ohne dass man das Recht SE_SYSTEMTIME_NAME vorher explizit setzen muss. Zumindest war das bei meinem Test unter Windows XP so. Und damit wäre ich wieder bei meiner Behauptung, dass sich die Funktion "SetSystemTime" das Recht ggf. selbst holt (so wie es auch im PSDK gesagt wird). Und da keinerlei Einschränkungen genannt werden, dürfte es bei Windows 2000 und NT ähnlich sein.