VOID NTAPI BaseSrvNLSInit(IN PBASE_STATIC_SERVER_DATA StaticData) { /* Initialize the lock */ RtlInitializeCriticalSection(&NlsCacheCriticalSection); /* Initialize the data with all F's */ pNlsRegUserInfo = &StaticData->NlsUserInfo; RtlFillMemory(&StaticData->NlsUserInfo, sizeof(StaticData->NlsUserInfo), 0xFF); /* Set empty LCID */ pNlsRegUserInfo->UserLocaleId = 0; /* Reset the cache update counter */ RtlEnterCriticalSection(&NlsCacheCriticalSection); pNlsRegUserInfo->ulCacheUpdateCount = 0; RtlLeaveCriticalSection(&NlsCacheCriticalSection); /* Get the LCID */ NtQueryDefaultLocale(0, &pNlsRegUserInfo->UserLocaleId); }
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 ); }
/********************************************************************** * find_entry * * Find a resource entry */ NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info, ULONG level, void **ret, int want_dir ) { ULONG size; void *root; IMAGE_RESOURCE_DIRECTORY *resdirptr; USHORT list[9]; /* list of languages to try */ int i, pos = 0; LCID user_lcid, system_lcid; root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size ); if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; resdirptr = root; if (!level--) goto done; if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level ))) return STATUS_RESOURCE_TYPE_NOT_FOUND; if (!level--) return STATUS_SUCCESS; resdirptr = *ret; if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level ))) return STATUS_RESOURCE_NAME_NOT_FOUND; if (!level--) return STATUS_SUCCESS; if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */ /* 1. specified language */ pos = push_language( list, pos, info->Language ); /* 2. specified language with neutral sublanguage */ pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) ); /* 3. neutral language with neutral sublanguage */ pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); /* if no explicitly specified language, try some defaults */ if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) { /* user defaults, unless SYS_DEFAULT sublanguage specified */ if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT) { /* 4. current thread locale language */ pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) ); if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid))) { /* 5. user locale language */ pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) ); /* 6. user locale language with neutral sublanguage */ pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) ); } } /* now system defaults */ if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid))) { /* 7. system locale language */ pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) ); /* 8. system locale language with neutral sublanguage */ pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) ); } /* 9. English */ pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) ); } resdirptr = *ret; for (i = 0; i < pos; i++) if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS; /* if no explicitly specified language, return the first entry */ if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) { if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS; } return STATUS_RESOURCE_LANG_NOT_FOUND; done: *ret = resdirptr; return STATUS_SUCCESS; }
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 ); }
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 ); }