NTSTATUS NTAPI NtQueryValueKey( HANDLE KeyHandle, PUNICODE_STRING ValueName, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG KeyValueInformationLength, PULONG ResultLength ) { unicode_string_t us; NTSTATUS r; ULONG len; regkey_t *key; regval_t *val; trace("%p %p %d %p %lu %p\n", KeyHandle, ValueName, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, ResultLength ); r = check_key_value_info_class( KeyValueInformationClass ); if (r < STATUS_SUCCESS) return r; r = object_from_handle( key, KeyHandle, KEY_QUERY_VALUE ); if (r < STATUS_SUCCESS) return r; r = us.copy_from_user( ValueName ); if (r < STATUS_SUCCESS) return r; r = verify_for_write( ResultLength, sizeof *ResultLength ); if (r < STATUS_SUCCESS) return r; trace("%pus\n", &us ); val = key_find_value( key, &us ); if (!val) return STATUS_OBJECT_NAME_NOT_FOUND; r = reg_query_value( val, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, len ); copy_to_user( ResultLength, &len, sizeof len ); return r; }
NTSTATUS NTAPI NtEnumerateValueKey( HANDLE KeyHandle, ULONG Index, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG KeyValueInformationLength, PULONG ResultLength ) { regkey_t *key; ULONG len = 0; NTSTATUS r = STATUS_SUCCESS; trace("%p %lu %u %p %lu %p\n", KeyHandle, Index, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, ResultLength ); r = object_from_handle( key, KeyHandle, KEY_QUERY_VALUE ); if (r < STATUS_SUCCESS) return r; r = verify_for_write( ResultLength, sizeof *ResultLength ); if (r < STATUS_SUCCESS) return r; regval_iter i(key->values); for ( ; i && Index; i.next()) Index--; if (!i) return STATUS_NO_MORE_ENTRIES; r = reg_query_value( i, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, len ); copy_to_user( ResultLength, &len, sizeof len ); return r; }
static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi) { static const WCHAR Time_ZonesW[] = { 'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s',' ','N','T','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'T','i','m','e',' ','Z','o','n','e','s',0 }; static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 }; static const WCHAR fmtW[] = { '%','d',0 }; HANDLE hkey; ULONG idx; OBJECT_ATTRIBUTES attr, attrDynamic; UNICODE_STRING nameW, nameDynamicW; WCHAR buf[128], yearW[16]; sprintfW(yearW, fmtW, tzi->DaylightDate.wYear); attrDynamic.Length = sizeof(attrDynamic); attrDynamic.RootDirectory = 0; /* will be replaced later */ attrDynamic.ObjectName = &nameDynamicW; attrDynamic.Attributes = 0; attrDynamic.SecurityDescriptor = NULL; attrDynamic.SecurityQualityOfService = NULL; RtlInitUnicodeString(&nameDynamicW, Dynamic_DstW); attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString(&nameW, Time_ZonesW); if (NtOpenKey(&hkey, KEY_READ, &attr)) { WARN("Unable to open the time zones key\n"); return; } idx = 0; nameW.Buffer = buf; nameW.Length = sizeof(buf); nameW.MaximumLength = sizeof(buf); while (!RtlpNtEnumerateSubKey(hkey, &nameW, idx++)) { static const WCHAR stdW[] = { 'S','t','d',0 }; static const WCHAR dltW[] = { 'D','l','t',0 }; static const WCHAR tziW[] = { 'T','Z','I',0 }; RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; HANDLE hSubkey, hSubkeyDynamicDST; BOOL is_dynamic = FALSE; struct tz_reg_data { LONG bias; LONG std_bias; LONG dlt_bias; RTL_SYSTEM_TIME std_date; RTL_SYSTEM_TIME dlt_date; } tz_data; attr.Length = sizeof(attr); attr.RootDirectory = hkey; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; if (NtOpenKey(&hSubkey, KEY_READ, &attr)) { WARN("Unable to open subkey %s\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR))); continue; } #define get_value(hkey, name, type, data, len) \ if (!reg_query_value(hkey, name, type, data, len)) \ { \ WARN("can't read data from %s\n", debugstr_w(name)); \ NtClose(hkey); \ continue; \ } get_value(hSubkey, stdW, REG_SZ, reg_tzi.StandardName, sizeof(reg_tzi.StandardName)); get_value(hSubkey, dltW, REG_SZ, reg_tzi.DaylightName, sizeof(reg_tzi.DaylightName)); memcpy(reg_tzi.TimeZoneKeyName, nameW.Buffer, nameW.Length); reg_tzi.TimeZoneKeyName[nameW.Length/sizeof(WCHAR)] = 0; /* Check for Dynamic DST entry first */ attrDynamic.RootDirectory = hSubkey; if (!NtOpenKey(&hSubkeyDynamicDST, KEY_READ, &attrDynamic)) { is_dynamic = reg_query_value(hSubkeyDynamicDST, yearW, REG_BINARY, &tz_data, sizeof(tz_data)); NtClose(hSubkeyDynamicDST); } if (!is_dynamic) get_value(hSubkey, tziW, REG_BINARY, &tz_data, sizeof(tz_data)); #undef get_value reg_tzi.Bias = tz_data.bias; reg_tzi.StandardBias = tz_data.std_bias; reg_tzi.DaylightBias = tz_data.dlt_bias; reg_tzi.StandardDate = tz_data.std_date; reg_tzi.DaylightDate = tz_data.dlt_date; TRACE("%s: bias %d\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR)), reg_tzi.Bias); TRACE("std (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", reg_tzi.StandardDate.wDay, reg_tzi.StandardDate.wMonth, reg_tzi.StandardDate.wYear, reg_tzi.StandardDate.wDayOfWeek, reg_tzi.StandardDate.wHour, reg_tzi.StandardDate.wMinute, reg_tzi.StandardDate.wSecond, reg_tzi.StandardDate.wMilliseconds, reg_tzi.StandardBias); TRACE("dst (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", reg_tzi.DaylightDate.wDay, reg_tzi.DaylightDate.wMonth, reg_tzi.DaylightDate.wYear, reg_tzi.DaylightDate.wDayOfWeek, reg_tzi.DaylightDate.wHour, reg_tzi.DaylightDate.wMinute, reg_tzi.DaylightDate.wSecond, reg_tzi.DaylightDate.wMilliseconds, reg_tzi.DaylightBias); NtClose(hSubkey); if (match_tz_info(tzi, ®_tzi)) { *tzi = reg_tzi; NtClose(hkey); return; } /* reset len */ nameW.Length = sizeof(buf); nameW.MaximumLength = sizeof(buf); } NtClose(hkey); FIXME("Can't find matching timezone information in the registry for " "bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n", tzi->Bias, tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear, tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear); }
/*********************************************************************** * TIME_GetSpecificTimeZoneInfo * * Returns time zone information for the given time zone and year. * * PARAMS * key_name [in] The time zone name. * year [in] The year, if Dynamic DST is used. * dynamic [in] Whether to use Dynamic DST. * result [out] The time zone information. * * RETURNS * TRUE if successful. */ static BOOL TIME_GetSpecificTimeZoneInfo( const WCHAR *key_name, WORD year, BOOL dynamic, DYNAMIC_TIME_ZONE_INFORMATION *tzinfo ) { static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 }; static const WCHAR fmtW[] = { '%','d',0 }; static const WCHAR stdW[] = { 'S','t','d',0 }; static const WCHAR dltW[] = { 'D','l','t',0 }; static const WCHAR tziW[] = { 'T','Z','I',0 }; HANDLE time_zone_key, dynamic_dst_key; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; WCHAR yearW[16]; BOOL got_reg_data = FALSE; struct tz_reg_data { LONG bias; LONG std_bias; LONG dlt_bias; SYSTEMTIME std_date; SYSTEMTIME dlt_date; } tz_data; if (!TIME_GetSpecificTimeZoneKey( key_name, &time_zone_key )) return FALSE; if (!reg_query_value( time_zone_key, stdW, REG_SZ, tzinfo->StandardName, sizeof(tzinfo->StandardName)) || !reg_query_value( time_zone_key, dltW, REG_SZ, tzinfo->DaylightName, sizeof(tzinfo->DaylightName))) { NtClose( time_zone_key ); return FALSE; } lstrcpyW(tzinfo->TimeZoneKeyName, key_name); if (dynamic) { attr.Length = sizeof(attr); attr.RootDirectory = time_zone_key; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &nameW, Dynamic_DstW ); if (!NtOpenKey( &dynamic_dst_key, KEY_READ, &attr )) { sprintfW( yearW, fmtW, year ); got_reg_data = reg_query_value( dynamic_dst_key, yearW, REG_BINARY, &tz_data, sizeof(tz_data) ); NtClose( dynamic_dst_key ); } } if (!got_reg_data) { if (!reg_query_value( time_zone_key, tziW, REG_BINARY, &tz_data, sizeof(tz_data) )) { NtClose( time_zone_key ); return FALSE; } } tzinfo->Bias = tz_data.bias; tzinfo->StandardBias = tz_data.std_bias; tzinfo->DaylightBias = tz_data.dlt_bias; tzinfo->StandardDate = tz_data.std_date; tzinfo->DaylightDate = tz_data.dlt_date; tzinfo->DynamicDaylightTimeDisabled = !dynamic; NtClose( time_zone_key ); return TRUE; }