868 lines
25 KiB
C
868 lines
25 KiB
C
/*++
|
|
|
|
Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
security.c
|
|
|
|
Abstract:
|
|
|
|
This file handles the management of the NLS per-thread and process cache.
|
|
The cache is only established when hitting an API that needs it. The process
|
|
NLS cache is used when accessing NLS info for a process NOT running in the
|
|
context of the interactive logged on user. The per-thread NLS cache is used
|
|
when accssing NLS info and the thread is doing a user impersonation.
|
|
|
|
External Routines found in this file:
|
|
NlsFlushProcessCache
|
|
NlsGetCurrentUserNlsInfo
|
|
NlsIsInteractiveUserProcess
|
|
NlsCheckForInteractiveUser
|
|
NlsGetUserLocale
|
|
|
|
Revision History:
|
|
|
|
03-29-1999 SamerA Created.
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include "nls.h"
|
|
#include "nlssafe.h"
|
|
|
|
|
|
|
|
|
|
//
|
|
// Global Variables.
|
|
//
|
|
|
|
//
|
|
// Process Nls Cache.
|
|
//
|
|
PNLS_LOCAL_CACHE gpNlsProcessCache;
|
|
|
|
//
|
|
// Whether the current running process is the same as the
|
|
// interactive logged on user.
|
|
//
|
|
BOOL gInteractiveLogonUserProcess = (BOOL)-1;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Forward Declarations.
|
|
//
|
|
|
|
NTSTATUS FASTCALL
|
|
NlsGetCacheBuffer(
|
|
PNLS_USER_INFO pNlsUserInfo,
|
|
LCTYPE LCType,
|
|
PWSTR *ppCache);
|
|
|
|
void FASTCALL
|
|
NlsInvalidateCache(
|
|
PNLS_USER_INFO pNlsUserInfo);
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
// EXTERNAL ROUTINES //
|
|
//-------------------------------------------------------------------------//
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsFlushProcessCache
|
|
//
|
|
// Invalidates an entry in the NLS process cache.
|
|
//
|
|
// 05-22-99 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsFlushProcessCache(
|
|
LCTYPE LCType)
|
|
{
|
|
PWSTR pOutputCache;
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
|
|
|
|
//
|
|
// If there is no thread impersonation, then flush the
|
|
// process entry cache.
|
|
//
|
|
if (NtCurrentTeb()->IsImpersonating != 0)
|
|
{
|
|
return (NtStatus);
|
|
}
|
|
|
|
if (gpNlsProcessCache)
|
|
{
|
|
NtStatus = NlsGetCacheBuffer( &gpNlsProcessCache->NlsInfo,
|
|
LCType,
|
|
&pOutputCache );
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
RtlEnterCriticalSection(&gcsNlsProcessCache);
|
|
|
|
pOutputCache[0] = NLS_INVALID_INFO_CHAR;
|
|
|
|
RtlLeaveCriticalSection(&gcsNlsProcessCache);
|
|
}
|
|
}
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsGetCurrentUserNlsInfo
|
|
//
|
|
// Retreive the NLS info correponding to the current security context.
|
|
//
|
|
// 03-29-99 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsGetCurrentUserNlsInfo(
|
|
LCID Locale,
|
|
LCTYPE LCType,
|
|
PWSTR RegistryValue,
|
|
PWSTR pOutputBuffer,
|
|
size_t cchOutputBuffer,
|
|
BOOL IgnoreLocaleValue)
|
|
{
|
|
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
|
|
PNLS_LOCAL_CACHE pNlsThreadCache;
|
|
PWSTR pOutputCache;
|
|
|
|
//
|
|
// Possible NtCurrentTeb()->IsImpersonating values :
|
|
//
|
|
// 0 : Thread isn't impersonating any user.
|
|
//
|
|
// 1 : Thread has just started to do impersonation.
|
|
// Per thread cache needs to be allocated now.
|
|
//
|
|
// 2 : Thread is calling the NLS apis while its
|
|
// a context other than the interactive logged on user.
|
|
//
|
|
switch (NtCurrentTeb()->IsImpersonating)
|
|
{
|
|
case ( 0 ) :
|
|
{
|
|
//
|
|
// Thread is NOT impersonating any user. We check if the process
|
|
// belongs to the interactive user, then we retreive the info from
|
|
// the NLS cache in CSR. Otherwise if the process is running in
|
|
// the context of a different user, then we retreive the NLS info
|
|
// from the process cache.
|
|
//
|
|
if (gInteractiveLogonUserProcess == (BOOL)-1)
|
|
{
|
|
NlsIsInteractiveUserProcess();
|
|
}
|
|
|
|
if (gInteractiveLogonUserProcess == FALSE)
|
|
{
|
|
if ((IgnoreLocaleValue) ||
|
|
(GetUserDefaultLCID() == Locale))
|
|
{
|
|
if (!gpNlsProcessCache)
|
|
{
|
|
//
|
|
// Allocate and invalidate the NLS process cache.
|
|
//
|
|
RtlEnterCriticalSection(&gcsNlsProcessCache);
|
|
|
|
if (!gpNlsProcessCache)
|
|
{
|
|
gpNlsProcessCache = RtlAllocateHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
sizeof(NLS_LOCAL_CACHE) );
|
|
if (gpNlsProcessCache)
|
|
{
|
|
NlsInvalidateCache(&gpNlsProcessCache->NlsInfo);
|
|
gpNlsProcessCache->CurrentUserKeyHandle = NULL;
|
|
}
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&gcsNlsProcessCache);
|
|
}
|
|
|
|
if (gpNlsProcessCache)
|
|
{
|
|
NtStatus = NlsGetCacheBuffer( &gpNlsProcessCache->NlsInfo,
|
|
LCType,
|
|
&pOutputCache);
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
//
|
|
// See if it is a valid cache.
|
|
//
|
|
if (pOutputCache[0] == NLS_INVALID_INFO_CHAR)
|
|
{
|
|
RtlEnterCriticalSection(&gcsNlsProcessCache);
|
|
|
|
if (GetUserInfoFromRegistry( RegistryValue,
|
|
pOutputCache,
|
|
MAX_REG_VAL_SIZE, 0 ) == FALSE)
|
|
{
|
|
NtStatus = STATUS_UNSUCCESSFUL;
|
|
pOutputCache[0] = NLS_INVALID_INFO_CHAR;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&gcsNlsProcessCache);
|
|
}
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if(FAILED((StringCchCopyW(pOutputBuffer, cchOutputBuffer, pOutputCache))))
|
|
{
|
|
NtStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( 1 ) :
|
|
{
|
|
//
|
|
// Thread started to do impersonation.
|
|
//
|
|
pNlsThreadCache = NtCurrentTeb()->NlsCache;
|
|
|
|
if (!pNlsThreadCache)
|
|
{
|
|
pNlsThreadCache = RtlAllocateHeap( RtlProcessHeap(),
|
|
0,
|
|
sizeof(NLS_LOCAL_CACHE) );
|
|
if (pNlsThreadCache)
|
|
{
|
|
pNlsThreadCache->CurrentUserKeyHandle = NULL;
|
|
}
|
|
|
|
NtCurrentTeb()->NlsCache = (PVOID) pNlsThreadCache;
|
|
}
|
|
|
|
if (pNlsThreadCache)
|
|
{
|
|
NlsInvalidateCache(&pNlsThreadCache->NlsInfo);
|
|
}
|
|
|
|
NtCurrentTeb()->IsImpersonating = 2;
|
|
|
|
//
|
|
// Fall Thru...
|
|
//
|
|
}
|
|
case ( 2 ) :
|
|
{
|
|
//
|
|
// Thread is impersonating a particular user.
|
|
//
|
|
pNlsThreadCache = NtCurrentTeb()->NlsCache;
|
|
|
|
if (pNlsThreadCache)
|
|
{
|
|
|
|
if ((IgnoreLocaleValue) ||
|
|
(GetUserDefaultLCID() == Locale))
|
|
{
|
|
NtStatus = NlsGetCacheBuffer( &pNlsThreadCache->NlsInfo,
|
|
LCType,
|
|
&pOutputCache );
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if (pOutputCache[0] == NLS_INVALID_INFO_CHAR)
|
|
{
|
|
//
|
|
// Don't cache key handles - this will break
|
|
// profile unload.
|
|
//
|
|
OPEN_CPANEL_INTL_KEY( pNlsThreadCache->CurrentUserKeyHandle,
|
|
STATUS_UNSUCCESSFUL,
|
|
KEY_READ );
|
|
|
|
NtStatus = NlsQueryCurrentUserInfo( pNlsThreadCache,
|
|
RegistryValue,
|
|
pOutputCache,
|
|
MAX_REG_VAL_SIZE );
|
|
|
|
CLOSE_REG_KEY(pNlsThreadCache->CurrentUserKeyHandle);
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
pOutputCache[0] = NLS_INVALID_INFO_CHAR;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if(FAILED((StringCchCopyW(pOutputBuffer, cchOutputBuffer, pOutputCache))))
|
|
{
|
|
NtStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsIsInteractiveUserProcess
|
|
//
|
|
// Read the process's authetication id out of its access token object and
|
|
// cache it since it never changes.
|
|
//
|
|
// 12-27-98 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsIsInteractiveUserProcess()
|
|
{
|
|
NTSTATUS NtStatus;
|
|
TOKEN_STATISTICS TokenInformation;
|
|
HANDLE TokenHandle;
|
|
ULONG BytesRequired;
|
|
BOOL IsInteractiveProcess = TRUE;
|
|
|
|
|
|
//
|
|
// Get the process access token.
|
|
//
|
|
NtStatus = NtOpenProcessToken( NtCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&TokenHandle );
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
//
|
|
// Get the LUID.
|
|
//
|
|
NtStatus = NtQueryInformationToken( TokenHandle,
|
|
TokenStatistics,
|
|
&TokenInformation,
|
|
sizeof(TokenInformation),
|
|
&BytesRequired );
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if (RtlEqualLuid( &pNlsUserInfo->InteractiveUserLuid,
|
|
&TokenInformation.AuthenticationId ) == FALSE)
|
|
{
|
|
IsInteractiveProcess = FALSE;
|
|
}
|
|
}
|
|
|
|
NtClose(TokenHandle);
|
|
}
|
|
|
|
gInteractiveLogonUserProcess = IsInteractiveProcess;
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsCheckForInteractiveUser
|
|
//
|
|
// This function makes sure that the current thread isn't impersonating
|
|
// anybody, but the interactive. It compares the authentication-id of the
|
|
// interactive user -cached in CSRSS at logon time- with the
|
|
// authentication-id of the current thread or process. It returns failure
|
|
// ONLY if the current security context -session- isn't the same as the
|
|
// interactive logged-on user.
|
|
//
|
|
// 12-16-98 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsCheckForInteractiveUser()
|
|
{
|
|
NTSTATUS NtStatus, ReturnStatus = STATUS_SUCCESS;
|
|
TOKEN_STATISTICS TokenInformation;
|
|
HANDLE TokenHandle;
|
|
ULONG BytesRequired;
|
|
PLUID InteractiveUserLuid = &pNlsUserInfo->InteractiveUserLuid;
|
|
|
|
|
|
//
|
|
// Get the Token Handle.
|
|
// Fast optimization to detect if a thread hasn't started to do any
|
|
// impersonation, which is the case for most GUI user apps.
|
|
//
|
|
if (NtCurrentTeb()->IsImpersonating == 0)
|
|
{
|
|
NtStatus = STATUS_NO_TOKEN;
|
|
}
|
|
else
|
|
{
|
|
NtStatus = NtOpenThreadToken( NtCurrentThread(),
|
|
TOKEN_QUERY,
|
|
FALSE,
|
|
&TokenHandle );
|
|
}
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
if (NtStatus != STATUS_NO_TOKEN)
|
|
{
|
|
KdPrint(("NLSAPI: Couldn't retreive thread token - %lx.\n", NtStatus));
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Get the process access token.
|
|
//
|
|
if (gInteractiveLogonUserProcess == (BOOL)-1)
|
|
{
|
|
NtStatus = NlsIsInteractiveUserProcess();
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
KdPrint(("NLSAPI: Couldn't retreive process token - %lx\n", NtStatus));
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
if (gInteractiveLogonUserProcess == FALSE)
|
|
{
|
|
ReturnStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the AuthenticationId of the current thread's security context.
|
|
//
|
|
NtStatus = NtQueryInformationToken( TokenHandle,
|
|
TokenStatistics,
|
|
&TokenInformation,
|
|
sizeof(TokenInformation),
|
|
&BytesRequired );
|
|
|
|
//
|
|
// Close the thread token here.
|
|
//
|
|
NtClose(TokenHandle);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if (RtlEqualLuid( InteractiveUserLuid,
|
|
&TokenInformation.AuthenticationId ) == FALSE)
|
|
{
|
|
ReturnStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (ReturnStatus);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsGetUserLocale
|
|
//
|
|
// Retreives the user locale from the registry of the current security
|
|
// context. It is called ONLY when the running security context is
|
|
// different from the interactive logged-on security context-(user).
|
|
//
|
|
// 12-16-98 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsGetUserLocale(
|
|
LCID *Lcid)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
WCHAR wszLocale[MAX_REG_VAL_SIZE];
|
|
UNICODE_STRING ObLocaleString;
|
|
PNLS_LOCAL_CACHE pNlsCache = NtCurrentTeb()->NlsCache;
|
|
|
|
|
|
//
|
|
// Get the current user locale.
|
|
//
|
|
NtStatus = NlsGetCurrentUserNlsInfo( LOCALE_USER_DEFAULT,
|
|
(LCTYPE)LOCALE_SLOCALE,
|
|
L"Locale",
|
|
wszLocale,
|
|
ARRAYSIZE(wszLocale),
|
|
TRUE );
|
|
if ((NT_SUCCESS(NtStatus)) ||
|
|
(GetUserInfoFromRegistry(L"Locale", wszLocale, ARRAYSIZE(wszLocale), 0)))
|
|
{
|
|
RtlInitUnicodeString(&ObLocaleString, wszLocale);
|
|
NtStatus = RtlUnicodeStringToInteger( &ObLocaleString,
|
|
16,
|
|
(PULONG)Lcid);
|
|
}
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
// INTERNAL ROUTINES //
|
|
//-------------------------------------------------------------------------//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsGetCacheBuffer
|
|
//
|
|
// Get a buffer pointer inside the cache for this LCTYPE.
|
|
//
|
|
// 03-29-99 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS FASTCALL NlsGetCacheBuffer(
|
|
PNLS_USER_INFO pNlsUserInfo,
|
|
LCTYPE LCType,
|
|
PWSTR *ppCache)
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
|
|
switch (LCType)
|
|
{
|
|
case ( LOCALE_SLANGUAGE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sAbbrevLangName;
|
|
break;
|
|
}
|
|
case ( LOCALE_ICOUNTRY ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iCountry;
|
|
break;
|
|
}
|
|
case ( LOCALE_SCOUNTRY ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sCountry;
|
|
break;
|
|
}
|
|
case ( LOCALE_SLIST ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sList;
|
|
break;
|
|
}
|
|
case ( LOCALE_IMEASURE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iMeasure;
|
|
break;
|
|
}
|
|
case ( LOCALE_IPAPERSIZE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iPaperSize;
|
|
break;
|
|
}
|
|
case ( LOCALE_SDECIMAL ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sDecimal;
|
|
break;
|
|
}
|
|
case ( LOCALE_STHOUSAND ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sThousand;
|
|
break;
|
|
}
|
|
case ( LOCALE_SGROUPING ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sGrouping;
|
|
break;
|
|
}
|
|
case ( LOCALE_IDIGITS ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iDigits;
|
|
break;
|
|
}
|
|
case ( LOCALE_ILZERO ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iLZero;
|
|
break;
|
|
}
|
|
case ( LOCALE_INEGNUMBER ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iNegNumber;
|
|
break;
|
|
}
|
|
case ( LOCALE_SNATIVEDIGITS ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sNativeDigits;
|
|
break;
|
|
}
|
|
case ( LOCALE_IDIGITSUBSTITUTION ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iDigitSubstitution;
|
|
break;
|
|
}
|
|
case ( LOCALE_SCURRENCY ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sCurrency;
|
|
break;
|
|
}
|
|
case ( LOCALE_SMONDECIMALSEP ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sMonDecSep;
|
|
break;
|
|
}
|
|
case ( LOCALE_SMONTHOUSANDSEP ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sMonThouSep;
|
|
break;
|
|
}
|
|
case ( LOCALE_SMONGROUPING ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sMonGrouping;
|
|
break;
|
|
}
|
|
case ( LOCALE_ICURRDIGITS ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iCurrDigits;
|
|
break;
|
|
}
|
|
case ( LOCALE_ICURRENCY ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iCurrency;
|
|
break;
|
|
}
|
|
case ( LOCALE_INEGCURR ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iNegCurr;
|
|
break;
|
|
}
|
|
case ( LOCALE_SPOSITIVESIGN ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sPosSign;
|
|
break;
|
|
}
|
|
case ( LOCALE_SNEGATIVESIGN ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sNegSign;
|
|
break;
|
|
}
|
|
case ( LOCALE_STIMEFORMAT ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sTimeFormat;
|
|
break;
|
|
}
|
|
case ( LOCALE_STIME ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sTime;
|
|
break;
|
|
}
|
|
case ( LOCALE_ITIME ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iTime;
|
|
break;
|
|
}
|
|
case ( LOCALE_ITLZERO ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iTLZero;
|
|
break;
|
|
}
|
|
case ( LOCALE_ITIMEMARKPOSN ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iTimeMarkPosn;
|
|
break;
|
|
}
|
|
case ( LOCALE_S1159 ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->s1159;
|
|
break;
|
|
}
|
|
case ( LOCALE_S2359 ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->s2359;
|
|
break;
|
|
}
|
|
case ( LOCALE_SSHORTDATE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sShortDate;
|
|
break;
|
|
}
|
|
case ( LOCALE_SDATE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sDate;
|
|
break;
|
|
}
|
|
case ( LOCALE_IDATE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iDate;
|
|
break;
|
|
}
|
|
case ( LOCALE_SYEARMONTH ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sYearMonth;
|
|
break;
|
|
}
|
|
case ( LOCALE_SLONGDATE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sLongDate;
|
|
break;
|
|
}
|
|
case ( LOCALE_ICALENDARTYPE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iCalType;
|
|
break;
|
|
}
|
|
case ( LOCALE_IFIRSTDAYOFWEEK ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iFirstDay;
|
|
break;
|
|
}
|
|
case ( LOCALE_IFIRSTWEEKOFYEAR ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->iFirstWeek;
|
|
break;
|
|
}
|
|
case ( LOCALE_SLOCALE ) :
|
|
{
|
|
*ppCache = pNlsUserInfo->sLocale;
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
NtStatus = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsQueryCurrentUserInfo
|
|
//
|
|
// Retreive the NLS info from the registry using a cached key.
|
|
//
|
|
// 04-07-99 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS NlsQueryCurrentUserInfo(
|
|
PNLS_LOCAL_CACHE pNlsCache,
|
|
LPWSTR pValue,
|
|
LPWSTR pOutput,
|
|
size_t cchOutput)
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION pKeyValueFull; // ptr to query info
|
|
BYTE pStatic[MAX_KEY_VALUE_FULLINFO]; // ptr to static buffer
|
|
ULONG rc;
|
|
|
|
|
|
//
|
|
// Initialize the output string.
|
|
//
|
|
*pOutput = 0;
|
|
|
|
//
|
|
// Query the registry value.
|
|
//
|
|
pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
|
|
rc = QueryRegValue( pNlsCache->CurrentUserKeyHandle,
|
|
pValue,
|
|
&pKeyValueFull,
|
|
MAX_KEY_VALUE_FULLINFO,
|
|
NULL );
|
|
|
|
//
|
|
// If the query failed or if the output buffer is not large enough,
|
|
// then return failure.
|
|
//
|
|
if ((rc != NO_ERROR) ||
|
|
(pKeyValueFull->DataLength > (MAX_REG_VAL_SIZE * sizeof(WCHAR))))
|
|
{
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
//
|
|
// Save the string in pOutput.
|
|
//
|
|
if(FAILED(StringCchCopyW(pOutput, MAX_REG_VAL_SIZE, GET_VALUE_DATA_PTR(pKeyValueFull))))
|
|
{
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsInvalidateCache
|
|
//
|
|
// Invalidate an NLS Cache.
|
|
//
|
|
// 03-29-99 SamerA Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FASTCALL NlsInvalidateCache(
|
|
PNLS_USER_INFO pNlsUserInfo)
|
|
{
|
|
pNlsUserInfo->sAbbrevLangName[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iCountry[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sCountry[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sList[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iMeasure[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iPaperSize[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sDecimal[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sThousand[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sGrouping[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iDigits[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iLZero[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iNegNumber[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sNativeDigits[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iDigitSubstitution[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sCurrency[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sMonDecSep[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sMonThouSep[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sMonGrouping[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iCurrDigits[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iCurrency[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iNegCurr[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sPosSign[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sNegSign[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sTimeFormat[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sTime[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iTime[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iTLZero[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iTimeMarkPosn[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->s1159[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->s2359[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sShortDate[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sDate[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iDate[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sYearMonth[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sLongDate[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iCalType[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iFirstDay[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->iFirstWeek[0] = NLS_INVALID_INFO_CHAR;
|
|
pNlsUserInfo->sLocale[0] = NLS_INVALID_INFO_CHAR;
|
|
|
|
return;
|
|
}
|