yaroslavp Posted August 28, 2010 Share Posted August 28, 2010 Hi all, A script that uses "_Date_Time_SetTimeZoneInformation" works very well in Windows XP. In Windows 7, however, it fails. The precise point of failure (in _Date_Time_SetTimeZoneInformation()) is this call: Local $aResult = DllCall("kernel32.dll", "bool", "SetTimeZoneInformation", "ptr", DllStructGetPtr($tZoneInfo)) which sets the ERROR_PRIVILEGE_NOT_HELD flag. Note that all the previous calls succeed, including the call that enables the required privilege! So I have no idea why the function returns this error. I tried to enable the "SeTimeZonePrivilege" as well, but still failed. AutoIt is executed with local administrator rights. Thanks for any hints or suggestions. Yaroslav Link to comment Share on other sites More sharing options...
PsaltyDS Posted August 30, 2010 Share Posted August 30, 2010 You didn't say what privilege you set or how you set it. Note there are two, depending on your version: MSDN: SetTimeZoneInformation Function RemarksAn application must have the SE_TIME_ZONE_NAME privilege for this function to succeed. This privilege is disabled by default. Use the AdjustTokenPrivileges function to enable the privilege before calling SetTimeZoneInformation, and then to disable the privilege after the SetTimeZoneInformation call. For more information, see Running with Special Privileges. Windows Server 2003 and Windows XP/2000: The application must have the SE_SYSTEMTIME_NAME privilege.To inform Explorer that the time zone has changed, send the WM_SETTINGCHANGE message. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
yaroslavp Posted September 23, 2010 Author Share Posted September 23, 2010 I resolved the problem. Both _Date_Time_SetTimeZoneInformation() and _Security__SetPrivilege() needed modifications to work correctly in Windows 7 (the changes were made according to some code I found elsewhere in these forums). However, after these modifications they cease to work in WinXP! In a nutshell, a different privilege needs to be enabled for changing timezones in Windows 7, and different code is needed to successfully enable a privilege. I didn't quite have time to make a platform-independent version of these functions, so I just switch them based on the current OS. The code of both functions for Windows 7 is attached.tmp.au3 Link to comment Share on other sites More sharing options...
PsaltyDS Posted September 23, 2010 Share Posted September 23, 2010 Thanks for posting your resolution. yaroslavp's posted code mirrored below: expandcollapse popupFunc _tagTOKEN_PRIVILEGES($iPrivilegeCount) If Not ( IsInt($iPrivilegeCount) And $iPrivilegeCount > 0 ) Then Return SetError(-1, 0, "") Local $tagTOKEN_PRIVILEGES = "dword PrivilegeCount;" For $i = 0 To $iPrivilegeCount - 1 $tagTOKEN_PRIVILEGES &= "dword LowPart" & $i & ";long HighPart" & $i & ";dword Attributes" & $i & ";" Next Return StringTrimRight($tagTOKEN_PRIVILEGES, 1) EndFunc Func SetTimeZoneInformation($iBias, $sStdName, $tStdDate, $iStdBias, $sDayName, $tDayDate, $iDayBias) _DebugOut("SetTimeZoneInformation") Local $tStdName = _WinAPI_MultiByteToWideChar($sStdName) Local $tDayName = _WinAPI_MultiByteToWideChar($sDayName) Local $tZoneInfo = DllStructCreate($tagTIME_ZONE_INFORMATION) DllStructSetData($tZoneInfo, "Bias", $iBias) DllStructSetData($tZoneInfo, "StdName", DllStructGetData($tStdName, 1)) _MemMoveMemory(DllStructGetPtr($tStdDate), DllStructGetPtr($tZoneInfo, "StdDate"), DllStructGetSize($tStdDate)) DllStructSetData($tZoneInfo, "StdBias", $iStdBias) DllStructSetData($tZoneInfo, "DayName", DllStructGetData($tDayName, 1)) _MemMoveMemory(DllStructGetPtr($tDayDate), DllStructGetPtr($tZoneInfo, "DayDate"), DllStructGetSize($tDayDate)) DllStructSetData($tZoneInfo, "DayBias", $iDayBias) Local $aResult = DllCall("kernel32.dll", "handle", "GetCurrentProcess") If @error Then _DebugOut("error 1") Return SetError(@error, @extended, False) EndIf Local $proc = $aResult[0] Local $aResult2 = DllCall("advapi32.dll", "int", "OpenProcessToken", "handle", $proc, "dword", BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY), "ptr*", 0) If @error Then _DebugOut("error 2") Return SetError(@error, @extended, False) ENdIf Local $hToken = $aResult2[3] Local $res = SetPrivilege($hToken, "SeTimeZonePrivilege", True) $res = BitAnd($res, SetPrivilege($hToken, "SeSystemTimePrivilege", True)) Local $iError = @error Local $iLastError = @extended Local $iRet = False If Not @error Then ; Set time zone information Local $aResult = DllCall("kernel32.dll", "bool", "SetTimeZoneInformation", "ptr", DllStructGetPtr($tZoneInfo)) If @error Then $iError = @error $iLastError = @extended _DebugOut("error 3 " & $iLastError) ElseIf $aResult[0] Then $iLastError = 0 $iRet = True Else $iError = 1 $iLastError = _WinAPI_GetLastError() _DebugOut("error 4 " & $iLastError) EndIf ; Disable system time privileged mode SetPrivilege($hToken, "SeSystemTimePrivilege", False) SetPrivilege($hToken, "SeTimeZonePrivilege", False) If @error Then $iError = 2 _DebugOut("error 6 " & $iLastError) EndIf Else _DebugOut("error 5 " & $iLastError) EndIf _WinAPI_CloseHandle($hToken) _DebugOut("Errors: " & $iError & ", " & $iLastError & ", " & $iRet) Return SetError($iError, $iLastError, $iRet) EndFunc ;==>_Date_Time_SetTimeZoneInformation Func SetPrivilege($hToken, $sPrivilege, $fEnable) _DebugOut("SetPrivilege") Local $pRequired, $tRequired, $iLUID, $iAttributes, $iCurrState, $pCurrState, $tCurrState, $iPrevState, $pPrevState, $tPrevState $iLUID = _Security__LookupPrivilegeValue("", $sPrivilege) If $iLUID = 0 Then Return SetError(-1, 0, False) $tCurrState = DllStructCreate( _tagTOKEN_PRIVILEGES(1) ) $pCurrState = DllStructGetPtr($tCurrState) $iCurrState = DllStructGetSize($tCurrState) $tPrevState = DllStructCreate( _tagTOKEN_PRIVILEGES(1) ) $pPrevState = DllStructGetPtr($tPrevState) $iPrevState = DllStructGetSize($tPrevState) $tRequired = DllStructCreate("int Data") $pRequired = DllStructGetPtr($tRequired) ; Get current privilege setting DllStructSetData($tCurrState, "PrivilegeCount", 1) DllStructSetData($tCurrState, "LowPart0", $iLUID) If Not _Security__AdjustTokenPrivileges($hToken, False, $pCurrState, $iCurrState, $pPrevState, $pRequired) Then Return SetError(-2, @error, False) EndIf ; Set privilege based on prior setting DllStructSetData($tPrevState, "PrivilegeCount", 1) DllStructSetData($tPrevState, "LowPart0", $iLUID) $iAttributes = DllStructGetData($tPrevState, "Attributes0") If $fEnable Then $iAttributes = BitOR($iAttributes, $SE_PRIVILEGE_ENABLED) Else $iAttributes = BitAND($iAttributes, BitNOT($SE_PRIVILEGE_ENABLED)) EndIf DllStructSetData($tPrevState, "Attributes0", $iAttributes) If Not _Security__AdjustTokenPrivileges($hToken, False, $pPrevState, $iPrevState, $pCurrState, $pRequired) Then Return SetError(-3, @error, False) EndIf Return SetError(0, 0, True) EndFunc ;==>_Security__SetPrivilege Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now