windows-nt/Source/XPSP1/NT/base/win32/winnls/csrlocal.c
2020-09-26 16:20:57 +08:00

508 lines
15 KiB
C

/*++
Copyright (c) 1998-2000, Microsoft Corporation All rights reserved.
Module Name:
csrlocal.c
Abstract:
This module implements functions that are used by the functions in locale.c
to communicate with csrss.
Author:
Michael Zoran (mzoran) 21-Jun-1998
Revision History:
--*/
//
// Include Files.
//
#include "nls.h"
#include "ntwow64n.h"
////////////////////////////////////////////////////////////////////////////
//
// CsrBasepNlsSetUserInfo
//
// Parameters:
// LCType The type of locale information to be set.
// pData The buffer which contains the information to be set.
// This is usually an Unicode string.
// DataLength The length of pData in BYTE.
//
// Return:
// STATUS_SUCCESS if the locale information is set correctly.
// Otherwise, a proper NTSTATUS error code is returned.
//
// Note:
// When kernel32.dll is complied for the WOW64 layer, we will call
// a thunk function NtWow64CsrBasepNlsSetUserInfo(), and it will
// in turn call the corresponding 64-bit version of this function.
//
////////////////////////////////////////////////////////////////////////////
NTSTATUS CsrBasepNlsSetUserInfo(
IN LCTYPE LCType,
IN LPWSTR pData,
IN ULONG DataLength)
{
#if defined(BUILD_WOW6432)
return (NtWow64CsrBasepNlsSetUserInfo( LCType,
pData,
DataLength ));
#else
BASE_API_MSG m;
PBASE_NLS_SET_USER_INFO_MSG a = &m.u.NlsSetUserInfo;
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 1, DataLength );
if (CaptureBuffer == NULL)
{
return (STATUS_NO_MEMORY);
}
if (CsrAllocateMessagePointer(CaptureBuffer, DataLength, (PVOID *)&(a->pData)) == 0)
{
goto exit;
}
RtlCopyMemory (a->pData, pData, DataLength);
//
// Save the pointer to the cache string.
//
a->LCType = LCType;
//
// Save the length of the data in the msg structure.
//
a->DataLength = DataLength;
//
// Call the server to set the registry value.
//
CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
BasepNlsSetUserInfo ),
sizeof(*a) );
exit:
//
// Free the capture buffer.
//
if (CaptureBuffer != NULL)
{
CsrFreeCaptureBuffer(CaptureBuffer);
}
return (m.ReturnValue);
#endif
}
////////////////////////////////////////////////////////////////////////////
//
// CsrBasepNlsGetUserInfo
//
// This function uses LPC to call into server side (csrss.exe) to retrieve
// the locale setting from the registry cache.
//
// Parameters
// Locale The locale to be retrived. Note that this could be different from
// the current user locale stored in the registry cache.
// If that's the case, this function will return FALSE.
// CacheOffset The offset in BYTE for the field in the NLS_USER_INFO cache to retrieve.
// FIELD_OFFSET(NLS_USER_INFO, fieldName) should be used to get the offset.
// pData The pointer which points to the target buffer
// DataLength The size of the target buffer in BYTE (the NULL terminator is included in the count)
//
// BIGNOTE BIGNOTE
// This function follows the convention of CsrBasepNlsSetUserInfo to use
// DataLength in BYTE.
//
////////////////////////////////////////////////////////////////////////////
NTSTATUS CsrBasepNlsGetUserInfo(
IN LCID Locale,
IN SIZE_T CacheOffset,
IN LPWSTR pData,
IN ULONG DataLength)
{
#if defined(BUILD_WOW6432)
return (NtWow64CsrBasepNlsGetUserInfo( Locale, CacheOffset,
pData,
DataLength ));
#else
BASE_API_MSG m;
PBASE_NLS_GET_USER_INFO_MSG a = &m.u.NlsGetUserInfo;
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
NTSTATUS rc;
// Check the following:
// 1. Make sure that the CacheOffset can not be greater than the offset of the last field. The assumption here is that
// UserLocaleId the FIRST field after any field that contains strings.
// 2. Make sure that CacheOffset is always aligned in WCHAR and is aligned with the beginning of each field.
// 3. DataLength can not be greater than the maximum length in BYTE.
// 4. The pointer to the data is not NULL.
//
// There is a duplicated check in BaseSrvNlsGetUserInfo().
if ((CacheOffset > FIELD_OFFSET(NLS_USER_INFO, UserLocaleId) - sizeof(WCHAR) * MAX_REG_VAL_SIZE) ||
((CacheOffset % (sizeof(WCHAR) * MAX_REG_VAL_SIZE)) != 0) ||
(DataLength > MAX_REG_VAL_SIZE * sizeof(WCHAR)) ||
(pData == NULL))
{
return (STATUS_INVALID_PARAMETER);
}
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 1, DataLength );
if (CaptureBuffer == NULL)
{
return (STATUS_NO_MEMORY);
}
CsrCaptureMessageBuffer( CaptureBuffer,
NULL,
DataLength,
(PVOID *)&a->pData );
a->Locale = Locale;
a->CacheOffset = CacheOffset;
//
// Save the length of the data in the msg structure.
//
a->DataLength = DataLength;
//
// Call the server to set the registry value.
//
rc = CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
BasepNlsGetUserInfo ),
sizeof(*a) );
if (NT_SUCCESS(rc))
{
// NOTE: DataLength is in BYTE.
wcsncpy(pData, a->pData, DataLength/sizeof(WCHAR));
}
//
// Free the capture buffer.
//
if (CaptureBuffer != NULL)
{
CsrFreeCaptureBuffer(CaptureBuffer);
}
return (rc);
#endif
}
////////////////////////////////////////////////////////////////////////////
//
// CsrBasepNlsSetMultipleUserInfo
//
////////////////////////////////////////////////////////////////////////////
NTSTATUS CsrBasepNlsSetMultipleUserInfo(
IN DWORD dwFlags,
IN int cchData,
IN LPCWSTR pPicture,
IN LPCWSTR pSeparator,
IN LPCWSTR pOrder,
IN LPCWSTR pTLZero,
IN LPCWSTR pTimeMarkPosn)
{
#if defined(BUILD_WOW6432)
return (NtWow64CsrBasepNlsSetMultipleUserInfo( dwFlags,
cchData,
pPicture,
pSeparator,
pOrder,
pTLZero,
pTimeMarkPosn ));
#else
ULONG CaptureLength; // length of capture buffer
ULONG Length; // temp storage for length of string
BASE_API_MSG m;
PBASE_NLS_SET_MULTIPLE_USER_INFO_MSG a = &m.u.NlsSetMultipleUserInfo;
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
//
// Initialize the msg structure to NULL.
//
RtlZeroMemory(a, sizeof(BASE_NLS_SET_MULTIPLE_USER_INFO_MSG));
//
// Save the flags and the length of the data in the msg structure.
//
a->Flags = dwFlags;
a->DataLength = cchData * sizeof(WCHAR);
//
// Save the appropriate strings in the msg structure.
//
switch (dwFlags)
{
case ( LOCALE_STIMEFORMAT ) :
{
//
// Get the length of the capture buffer.
//
Length = wcslen(pSeparator) + 1;
CaptureLength = (cchData + Length + 2 + 2 + 2) * sizeof(WCHAR);
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 5,
CaptureLength );
if (CaptureBuffer != NULL)
{
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pPicture,
cchData * sizeof(WCHAR),
(PVOID *)&a->pPicture );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pSeparator,
Length * sizeof(WCHAR),
(PVOID *)&a->pSeparator );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pOrder,
2 * sizeof(WCHAR),
(PVOID *)&a->pOrder );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pTLZero,
2 * sizeof(WCHAR),
(PVOID *)&a->pTLZero );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pTimeMarkPosn,
2 * sizeof(WCHAR),
(PVOID *)&a->pTimeMarkPosn );
}
break;
}
case ( LOCALE_STIME ) :
{
//
// Get the length of the capture buffer.
//
Length = wcslen(pPicture) + 1;
CaptureLength = (Length + cchData) * sizeof(WCHAR);
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 2,
CaptureLength );
if (CaptureBuffer != NULL)
{
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pPicture,
Length * sizeof(WCHAR),
(PVOID *)&a->pPicture );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pSeparator,
cchData * sizeof(WCHAR),
(PVOID *)&a->pSeparator );
}
break;
}
case ( LOCALE_ITIME ) :
{
//
// Get the length of the capture buffer.
//
Length = wcslen(pPicture) + 1;
CaptureLength = (Length + cchData) * sizeof(WCHAR);
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 2,
CaptureLength );
if (CaptureBuffer != NULL)
{
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pPicture,
Length * sizeof(WCHAR),
(PVOID *)&a->pPicture );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pOrder,
cchData * sizeof(WCHAR),
(PVOID *)&a->pOrder );
}
break;
}
case ( LOCALE_SSHORTDATE ) :
{
//
// Get the length of the capture buffer.
//
Length = wcslen(pSeparator) + 1;
CaptureLength = (cchData + Length + 2) * sizeof(WCHAR);
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 3,
CaptureLength );
if (CaptureBuffer != NULL)
{
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pPicture,
cchData * sizeof(WCHAR),
(PVOID *)&a->pPicture );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pSeparator,
Length * sizeof(WCHAR),
(PVOID *)&a->pSeparator );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pOrder,
2 * sizeof(WCHAR),
(PVOID *)&a->pOrder );
}
break;
}
case ( LOCALE_SDATE ) :
{
//
// Get the length of the capture buffer.
//
Length = wcslen(pPicture) + 1;
CaptureLength = (Length + cchData) * sizeof(WCHAR);
//
// Get the capture buffer for the strings.
//
CaptureBuffer = CsrAllocateCaptureBuffer( 2,
CaptureLength );
if (CaptureBuffer != NULL)
{
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pPicture,
Length * sizeof(WCHAR),
(PVOID *)&a->pPicture );
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR)pSeparator,
cchData * sizeof(WCHAR),
(PVOID *)&a->pSeparator );
}
break;
}
}
//
// Make sure the CaptureBuffer was created and filled in.
//
if (CaptureBuffer == NULL)
{
return (STATUS_NO_MEMORY);
}
//
// Call the server to set the registry values.
//
CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
BasepNlsSetMultipleUserInfo ),
sizeof(*a) );
//
// Free the capture buffer.
//
if (CaptureBuffer != NULL)
{
CsrFreeCaptureBuffer(CaptureBuffer);
}
return (m.ReturnValue);
#endif
}
////////////////////////////////////////////////////////////////////////////
//
// CsrBasepNlsUpdateCacheCount
//
////////////////////////////////////////////////////////////////////////////
NTSTATUS CsrBasepNlsUpdateCacheCount()
{
#if defined(BUILD_WOW6432)
return (NtWow64CsrBasepNlsUpdateCacheCount());
#else
BASE_API_MSG m;
PBASE_NLS_UPDATE_CACHE_COUNT_MSG a = &m.u.NlsCacheUpdateCount;
a->Reserved = 0L;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
BasepNlsUpdateCacheCount ),
sizeof(*a) );
return (m.ReturnValue);
#endif
}