NT4/private/windows/base/server/srvnls.c

1034 lines
29 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
srvnls.c
Abstract:
This file contains the NLS Server-Side routines.
Author:
Julie Bennett (JulieB) 02-Dec-1992
Revision History:
--*/
#include "basesrv.h"
/*
* Constant Declarations.
*/
#define MAX_PATH_LEN 512 /* max length of path name */
#define MAX_KEY_VALUE_PARTINFO \
( FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data ) + MAX_REG_VAL_SIZE )
#define NLS_VALUE_STIMEFORMAT L"sTimeFormat"
#define NLS_VALUE_STIME L"sTime"
#define NLS_VALUE_ITIME L"iTime"
#define NLS_VALUE_ITLZERO L"iTLZero"
#define NLS_VALUE_ITIMEMARKPOSN L"iTimePrefix"
#define NLS_VALUE_SSHORTDATE L"sShortDate"
#define NLS_VALUE_SDATE L"sDate"
#define NLS_VALUE_IDATE L"iDate"
/*
* Typedef Declarations.
*/
/*
* These MUST remain in the same order as the NLS_USER_INFO structure.
*/
LPWSTR pCPanelRegValues[] =
{
L"sLanguage",
L"iCountry",
L"sCountry",
L"sList",
L"iMeasure",
L"sDecimal",
L"sThousand",
L"sGrouping",
L"iDigits",
L"iLZero",
L"iNegNumber",
L"sCurrency",
L"sMonDecimalSep",
L"sMonThousandSep",
L"sMonGrouping",
L"iCurrDigits",
L"iCurrency",
L"iNegCurr",
L"sPositiveSign",
L"sNegativeSign",
L"sTimeFormat",
L"sTime",
L"iTime",
L"iTLZero",
L"iTimePrefix",
L"s1159",
L"s2359",
L"sShortDate",
L"sDate",
L"iDate",
L"sLongDate",
L"iCalendarType",
L"iFirstDayOfWeek",
L"iFirstWeekOfYear",
L"Locale"
};
int NumCPanelRegValues = ( sizeof(pCPanelRegValues) / sizeof(LPWSTR) );
/*
* Global Variables.
*/
HANDLE hNlsCacheMutant;
HANDLE hCPanelIntlKeyRead = NULL;
HANDLE hCPanelIntlKeyWrite = NULL;
PNLS_USER_INFO pNlsRegUserInfo = NULL;
ULONG NlsChangeBuffer;
IO_STATUS_BLOCK IoStatusBlock;
/*
* Forward Declarations.
*/
ULONG
NlsSetRegAndCache(
LPWSTR pValue,
LPWSTR pCacheString,
LPWSTR pData,
ULONG DataLength);
VOID
NlsUpdateCacheInfo(VOID);
ULONG
CreateSecurityDescriptor(
ULONG *pSecurityDescriptor,
PSID *ppWorldSid,
ACCESS_MASK AccessMask);
/***************************************************************************\
* BaseSrvNLSInit
*
* This routine creates the shared heap for the nls information.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
NTSTATUS
BaseSrvNLSInit(
PBASE_STATIC_SERVER_DATA pStaticServerData)
{
ULONG rc; /* return code */
/*
* Create a mutant to protect the cache.
*/
rc = NtCreateMutant( &hNlsCacheMutant,
MUTANT_ALL_ACCESS,
NULL,
FALSE );
if (!NT_SUCCESS( rc ))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Create Cache Mutex - %lx.\n", rc));
return ( rc );
}
/*
* Initialize the cache to zero.
*/
pNlsRegUserInfo = &(pStaticServerData->NlsUserInfo);
RtlZeroMemory( pNlsRegUserInfo, sizeof(NLS_USER_INFO) );
/*
* Make the system locale the user locale.
*/
NtQueryDefaultLocale( FALSE, &(pNlsRegUserInfo->UserLocaleId) );
/*
* Return success.
*/
return ( STATUS_SUCCESS );
}
/***************************************************************************\
* BaseSrvNLSConnect
*
* This routine duplicates the mutant handle for the client.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
NTSTATUS
BaseSrvNlsConnect(
PCSR_PROCESS Process,
PVOID pConnectionInfo,
PULONG pConnectionInfoLength)
{
/*
* Duplicate the mutant handle.
*/
return ( NtDuplicateObject(NtCurrentProcess(),
hNlsCacheMutant,
Process->ProcessHandle,
(PHANDLE)pConnectionInfo,
SYNCHRONIZE,
0L,
0L ) );
}
/***************************************************************************\
* BaseSrvNlsLogon
*
* This routine initializes the heap for the nls information. If fLogon is
* TRUE, then it opens registry key, initializes the heap information, and
* registers the key for notification. If fLogon is FALSE, then it
* unregisters the key for notification, zeros out the heap information,
* and closes the registry key.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
NTSTATUS
BaseSrvNlsLogon(
BOOL fLogon)
{
HANDLE hUserHandle; /* HKEY_CURRENT_USER equivalent */
HANDLE hKeyHandle;
OBJECT_ATTRIBUTES ObjA; /* object attributes structure */
UNICODE_STRING ObKeyName; /* key name */
ULONG rc = 0L; /* return code */
if (fLogon)
{
/*
* Logging ON.
* - open keys
*
* NOTE: Registry Notification is done by the RIT in user server.
*/
rc = RtlOpenCurrentUser( MAXIMUM_ALLOWED, &hUserHandle );
if (!NT_SUCCESS( rc ))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Open HKEY_CURRENT_USER - %lx.\n", rc));
return ( rc );
}
RtlInitUnicodeString( &ObKeyName, L"Control Panel\\International" );
InitializeObjectAttributes( &ObjA,
&ObKeyName,
OBJ_CASE_INSENSITIVE,
hUserHandle,
NULL );
/*
* Open key for READ and NOTIFY access.
*/
rc = NtOpenKey( &hCPanelIntlKeyRead,
KEY_READ | KEY_NOTIFY,
&ObjA );
/*
* Open key for WRITE access.
*/
if (!NT_SUCCESS( NtOpenKey( &hCPanelIntlKeyWrite,
KEY_WRITE,
&ObjA ) ))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Open Registry Key %wZ for Write - %lx.\n",
&ObKeyName, rc));
hCPanelIntlKeyWrite = NULL;
}
/*
* Close the handle to the current user (HKEY_CURRENT_USER).
*/
NtClose( hUserHandle );
/*
* Check for error from first NtOpenKey.
*/
if (!NT_SUCCESS( rc ))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Open Registry Key %wZ for Read - %lx.\n",
&ObKeyName, rc));
hCPanelIntlKeyRead = NULL;
if (hCPanelIntlKeyWrite != NULL)
{
NtClose( hCPanelIntlKeyWrite );
hCPanelIntlKeyWrite = NULL;
}
return ( rc );
}
}
else
{
/*
* Logging OFF.
* - close keys
* - zero out info
*/
if (hCPanelIntlKeyRead != NULL)
{
NtClose( hCPanelIntlKeyRead );
hCPanelIntlKeyRead = NULL;
}
if (hCPanelIntlKeyWrite != NULL)
{
NtClose( hCPanelIntlKeyWrite );
hCPanelIntlKeyWrite = NULL;
}
/*
* Get the cache mutant.
*/
NtWaitForSingleObject( hNlsCacheMutant, FALSE, NULL );
/*
* Set the cache to be invalid.
*/
pNlsRegUserInfo->fCacheValid = FALSE;
/*
* Zero out info.
*/
RtlZeroMemory(pNlsRegUserInfo, sizeof(NLS_USER_INFO));
/*
* Make the system locale the user locale.
*/
NtQueryDefaultLocale( FALSE, &(pNlsRegUserInfo->UserLocaleId) );
/*
* Release the cache mutant.
*/
NtReleaseMutant( hNlsCacheMutant, NULL );
}
/*
* Return success.
*/
return ( STATUS_SUCCESS );
}
/***************************************************************************\
* BaseSrvNlsUpdateRegistryCache
*
* This routine updates the NLS cache when a registry notification occurs.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
VOID
BaseSrvNlsUpdateRegistryCache(
PVOID ApcContext,
PIO_STATUS_BLOCK pIoStatusBlock)
{
ULONG rc = 0L; /* return code */
if (hCPanelIntlKeyRead != NULL)
{
/*
* Update the cache information.
*/
NlsUpdateCacheInfo();
/*
* Call NtNotifyChangeKey.
*/
rc = NtNotifyChangeKey( hCPanelIntlKeyRead,
NULL,
(PIO_APC_ROUTINE)BaseSrvNlsUpdateRegistryCache,
NULL,
&IoStatusBlock,
REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
FALSE,
&NlsChangeBuffer,
sizeof(NlsChangeBuffer),
TRUE );
#ifdef DBG
/*
* Check for error from NtNotifyChangeKey.
*/
if (!NT_SUCCESS( rc ))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Set Notification of Control Panel International Registry Key - %lx.\n",
rc));
}
#endif
}
}
/***************************************************************************\
* NlsSetRegAndCache
*
* This routine sets the registry with the appropriate string and then
* updates the cache.
*
* NOTE: Must already own the mutant for the cache before calling this
* routine.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
ULONG
NlsSetRegAndCache(
LPWSTR pValue,
LPWSTR pCacheString,
LPWSTR pData,
ULONG DataLength)
{
UNICODE_STRING ObValueName; /* value name */
ULONG rc; /* return code */
if (hCPanelIntlKeyWrite != NULL)
{
/*
* Set the value in the registry.
*/
RtlInitUnicodeString( &ObValueName, pValue );
rc = NtSetValueKey( hCPanelIntlKeyWrite,
&ObValueName,
0,
REG_SZ,
(PVOID)pData,
DataLength );
/*
* Copy the new string to the cache.
*/
if (NT_SUCCESS( rc ))
{
wcsncpy( pCacheString, pData, DataLength );
pCacheString[DataLength / sizeof(WCHAR)] = 0;
}
/*
* Return the result.
*/
return ( rc );
}
/*
* Return access denied, since the key is not open for write access.
*/
return ( (ULONG)STATUS_ACCESS_DENIED );
}
/***************************************************************************\
* BaseSrvNlsSetUserInfo
*
* This routine sets a particular value in the NLS cache and updates the
* registry entry.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
ULONG
BaseSrvNlsSetUserInfo(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus)
{
PBASE_NLS_SET_USER_INFO_MSG a =
(PBASE_NLS_SET_USER_INFO_MSG)&m->u.ApiMessageData;
ULONG rc; /* return code */
/*
* Get the cache mutant.
*/
NtWaitForSingleObject( hNlsCacheMutant, FALSE, NULL );
/*
* Set the value in the registry and update the cache.
*/
rc = NlsSetRegAndCache( a->pValue,
a->pCacheString,
a->pData,
a->DataLength );
/*
* Release the cache mutant.
*/
NtReleaseMutant( hNlsCacheMutant, NULL );
/*
* Return the result of NtSetValueKey.
*/
return (rc);
ReplyStatus; // get rid of unreferenced parameter warning message
}
/***************************************************************************\
* BaseSrvNlsSetMultipleUserInfo
*
* This routine sets the date/time strings in the NLS cache and updates the
* registry entries.
*
* This call is done so that only one client/server transition is needed
* when setting multiple entries.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
ULONG
BaseSrvNlsSetMultipleUserInfo(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus)
{
PBASE_NLS_SET_MULTIPLE_USER_INFO_MSG a =
(PBASE_NLS_SET_MULTIPLE_USER_INFO_MSG)&m->u.ApiMessageData;
ULONG rc = 0L; /* return code */
/*
* Get the cache mutant.
*/
NtWaitForSingleObject( hNlsCacheMutant, FALSE, NULL );
switch (a->Flags)
{
case ( LOCALE_STIMEFORMAT ) :
{
rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
pNlsRegUserInfo->sTimeFormat,
a->pPicture,
a->DataLength );
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_STIME,
pNlsRegUserInfo->sTime,
a->pSeparator,
(wcslen(a->pSeparator) + 1) * sizeof(WCHAR) );
}
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_ITIME,
pNlsRegUserInfo->iTime,
a->pOrder,
(wcslen(a->pOrder) + 1) * sizeof(WCHAR) );
}
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_ITLZERO,
pNlsRegUserInfo->iTLZero,
a->pTLZero,
(wcslen(a->pTLZero) + 1) * sizeof(WCHAR) );
}
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_ITIMEMARKPOSN,
pNlsRegUserInfo->iTimeMarkPosn,
a->pTimeMarkPosn,
(wcslen(a->pTimeMarkPosn) + 1) * sizeof(WCHAR) );
}
break;
}
case ( LOCALE_STIME ) :
{
rc = NlsSetRegAndCache( NLS_VALUE_STIME,
pNlsRegUserInfo->sTime,
a->pSeparator,
a->DataLength );
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
pNlsRegUserInfo->sTimeFormat,
a->pPicture,
(wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
}
break;
}
case ( LOCALE_ITIME ) :
{
rc = NlsSetRegAndCache( NLS_VALUE_ITIME,
pNlsRegUserInfo->iTime,
a->pOrder,
a->DataLength );
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
pNlsRegUserInfo->sTimeFormat,
a->pPicture,
(wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
}
break;
}
case ( LOCALE_SSHORTDATE ) :
{
rc = NlsSetRegAndCache( NLS_VALUE_SSHORTDATE,
pNlsRegUserInfo->sShortDate,
a->pPicture,
a->DataLength );
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_SDATE,
pNlsRegUserInfo->sDate,
a->pSeparator,
(wcslen(a->pSeparator) + 1) * sizeof(WCHAR) );
}
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_IDATE,
pNlsRegUserInfo->iDate,
a->pOrder,
(wcslen(a->pOrder) + 1) * sizeof(WCHAR) );
}
break;
}
case ( LOCALE_SDATE ) :
{
rc = NlsSetRegAndCache( NLS_VALUE_SDATE,
pNlsRegUserInfo->sDate,
a->pSeparator,
a->DataLength );
if (NT_SUCCESS( rc ))
{
rc = NlsSetRegAndCache( NLS_VALUE_SSHORTDATE,
pNlsRegUserInfo->sShortDate,
a->pPicture,
(wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
}
break;
}
}
/*
* Release the cache mutant.
*/
NtReleaseMutant( hNlsCacheMutant, NULL );
/*
* Return the result.
*/
return (rc);
ReplyStatus; // get rid of unreferenced parameter warning message
}
/***************************************************************************\
* NlsUpdateCacheInfo
*
* This routine updates the NLS cache when a registry notification occurs.
*
* 08-19-94 JulieB Created.
\***************************************************************************/
VOID
NlsUpdateCacheInfo()
{
LCID Locale; /* locale id */
UNICODE_STRING ObKeyName; /* key name */
LPWSTR pTmp; /* tmp string pointer */
int ctr; /* loop counter */
ULONG ResultLength; /* result length */
ULONG rc = 0L; /* return code */
BYTE KeyValuePart[MAX_KEY_VALUE_PARTINFO];
PKEY_VALUE_PARTIAL_INFORMATION pValuePart;
/*
* Get the cache mutant.
*/
NtWaitForSingleObject( hNlsCacheMutant, FALSE, NULL );
/*
* Update the cache information.
*/
pTmp = (LPWSTR)pNlsRegUserInfo;
pValuePart = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValuePart;
for (ctr = 0; ctr < NumCPanelRegValues; ctr++)
{
RtlInitUnicodeString( &ObKeyName, pCPanelRegValues[ctr] );
rc = NtQueryValueKey( hCPanelIntlKeyRead,
&ObKeyName,
KeyValuePartialInformation,
pValuePart,
MAX_KEY_VALUE_PARTINFO,
&ResultLength );
if (NT_SUCCESS( rc ))
{
((LPBYTE)pValuePart)[ResultLength] = UNICODE_NULL;
wcscpy(pTmp, (LPWSTR)(pValuePart->Data));
}
else
{
*pTmp = NLS_INVALID_INFO_CHAR;
*(pTmp + 1) = UNICODE_NULL;
}
/*
* Increment pointer to cache structure.
*/
pTmp += MAX_REG_VAL_SIZE;
}
/*
* Convert the user locale id string to a dword value and store
* it in the cache.
*/
pNlsRegUserInfo->UserLocaleId = (LCID)0;
if ((pNlsRegUserInfo->sLocale)[0] != NLS_INVALID_INFO_CHAR)
{
RtlInitUnicodeString( &ObKeyName, pNlsRegUserInfo->sLocale );
if (NT_SUCCESS(RtlUnicodeStringToInteger( &ObKeyName, 16, &Locale )))
{
pNlsRegUserInfo->UserLocaleId = Locale;
}
}
/*
* Make sure the user locale id was found. Otherwise, set it to
* the system locale.
*/
if (pNlsRegUserInfo->UserLocaleId == 0)
{
NtQueryDefaultLocale( FALSE, &(pNlsRegUserInfo->UserLocaleId) );
}
/*
* Set the cache to be valid.
*/
pNlsRegUserInfo->fCacheValid = TRUE;
/*
* Release the cache mutant.
*/
NtReleaseMutant( hNlsCacheMutant, NULL );
}
/***************************************************************************\
* BaseSrvNlsCreateSortSection
*
* This routine creates a named memory mapped section with the given
* section name, and has both READ and WRITE access. The size of the
* section should be the same as the default section - NLSSECTION_SORTKEY.
*
* 12-02-92 JulieB Created.
\***************************************************************************/
ULONG
BaseSrvNlsCreateSortSection(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus)
{
PBASE_NLS_CREATE_SORT_SECTION_MSG a =
(PBASE_NLS_CREATE_SORT_SECTION_MSG)&m->u.ApiMessageData;
HANDLE hNewSec = (HANDLE)0; /* new section handle */
HANDLE hProcess = (HANDLE)0; /* process handle */
OBJECT_ATTRIBUTES ObjA; /* object attributes structure */
NTSTATUS rc = 0L; /* return code */
ULONG pSecurityDescriptor[MAX_PATH_LEN]; /* security descriptor buffer */
PSID pWorldSid; /* ptr to world SID */
/*
* Set the handles to null.
*/
a->hNewSection = NULL;
/*
* Create the NEW Section for Read and Write access.
* Add a ReadOnly security descriptor so that only the
* initial creating process may write to the section.
*/
if (rc = CreateSecurityDescriptor(pSecurityDescriptor,
&pWorldSid,
GENERIC_READ))
{
return (rc);
}
InitializeObjectAttributes(&ObjA,
&(a->SectionName),
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
NULL,
pSecurityDescriptor);
rc = NtCreateSection(&hNewSec,
SECTION_MAP_READ | SECTION_MAP_WRITE,
&ObjA,
&(a->SectionSize),
PAGE_READWRITE,
SEC_COMMIT,
NULL);
/*
* Check for error from NtCreateSection.
*/
if (!NT_SUCCESS(rc))
{
/*
* If the name has already been created, ignore the error.
*/
if (rc != STATUS_OBJECT_NAME_COLLISION)
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Create Section %wZ - %lx.\n",
&(a->SectionName), rc));
return (rc);
}
}
/*
* Duplicate the new section handle for the client.
* The client will map a view of the section and fill in the data.
*/
InitializeObjectAttributes(&ObjA,
NULL,
0,
NULL,
NULL);
rc = NtOpenProcess(&hProcess,
PROCESS_DUP_HANDLE,
&ObjA,
&m->h.ClientId);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Open Process - %lx.\n", rc));
return (rc);
}
rc = NtDuplicateObject(NtCurrentProcess(),
hNewSec,
hProcess,
&(a->hNewSection),
0L,
0L,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/*
* Return the return value from NtDuplicateObject.
*/
return (rc);
ReplyStatus; // get rid of unreferenced parameter warning message
}
/***************************************************************************\
* BaseSrvNlsPreserveSection
*
* This routine preserves a created section by duplicating the handle
* into CSR and never closing it.
*
* 03-12-93 JulieB Created.
\***************************************************************************/
ULONG
BaseSrvNlsPreserveSection(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus)
{
PBASE_NLS_PRESERVE_SECTION_MSG a =
(PBASE_NLS_PRESERVE_SECTION_MSG)&m->u.ApiMessageData;
HANDLE hSection = (HANDLE)0; /* section handle */
HANDLE hProcess = (HANDLE)0; /* process handle */
OBJECT_ATTRIBUTES ObjA; /* object attributes structure */
NTSTATUS rc = 0L; /* return code */
/*
* Duplicate the section handle for the server.
*/
InitializeObjectAttributes(&ObjA,
NULL,
0,
NULL,
NULL);
rc = NtOpenProcess(&hProcess,
PROCESS_DUP_HANDLE,
&ObjA,
&m->h.ClientId);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Open Process - %lx.\n", rc));
return (rc);
}
/*
* The hSection value will not be used for anything. However,
* it must remain open so that the object remains permanent.
*/
rc = NtDuplicateObject(hProcess,
a->hSection,
NtCurrentProcess(),
&hSection,
0L,
0L,
DUPLICATE_SAME_ACCESS);
/*
* Return the return value from NtDuplicateObject.
*/
return (rc);
ReplyStatus; // get rid of unreferenced parameter warning message
}
/***************************************************************************\
* CreateSecurityDescriptor
*
* This routine creates the security descriptor needed to create the
* memory mapped section for a data file and returns the world SID.
*
* 12-02-92 JulieB Created.
\***************************************************************************/
ULONG CreateSecurityDescriptor(
ULONG *pSecurityDescriptor,
PSID *ppWorldSid,
ACCESS_MASK AccessMask)
{
ULONG rc = 0L; /* return code */
PACL pAclBuffer; /* ptr to ACL buffer */
ULONG SidLength; /* length of SID - 1 sub authority */
PSID pWSid; /* ptr to world SID */
SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_WORLD_SID_AUTHORITY;
/*
* Create World SID.
*/
SidLength = RtlLengthRequiredSid(1);
if ((pWSid = (PSID)RtlAllocateHeap(RtlProcessHeap(),
MAKE_TAG( TMP_TAG ) | HEAP_ZERO_MEMORY,
SidLength)) == NULL)
{
*ppWorldSid = NULL;
KdPrint(("NLSAPI (BaseSrv): Could NOT Allocate SID Buffer.\n"));
return (ERROR_OUTOFMEMORY);
}
*ppWorldSid = pWSid;
RtlInitializeSid(pWSid, &SidAuth, 1);
*(RtlSubAuthoritySid(pWSid, 0)) = SECURITY_WORLD_RID;
/*
* Initialize Security Descriptor.
*/
rc = RtlCreateSecurityDescriptor(pSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Create Security Descriptor - %lx.\n",
rc));
RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pWSid);
return (rc);
}
/*
* Initialize ACL.
*/
pAclBuffer = (PACL)((PBYTE)pSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
rc = RtlCreateAcl((PACL)pAclBuffer,
MAX_PATH_LEN * sizeof(ULONG),
ACL_REVISION2);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Create ACL - %lx.\n", rc));
RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pWSid);
return (rc);
}
/*
* Add an ACE to the ACL that allows World GENERIC_READ to the
* section object.
*/
rc = RtlAddAccessAllowedAce((PACL)pAclBuffer,
ACL_REVISION2,
AccessMask,
pWSid);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Add Access Allowed ACE - %lx.\n",
rc));
RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pWSid);
return (rc);
}
/*
* Assign the DACL to the security descriptor.
*/
rc = RtlSetDaclSecurityDescriptor((PSECURITY_DESCRIPTOR)pSecurityDescriptor,
(BOOLEAN)TRUE,
(PACL)pAclBuffer,
(BOOLEAN)FALSE);
if (!NT_SUCCESS(rc))
{
KdPrint(("NLSAPI (BaseSrv): Could NOT Set DACL Security Descriptor - %lx.\n",
rc));
RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pWSid);
return (rc);
}
/*
* Return success.
*/
return (NO_ERROR);
}