1c2c66affSColin Finck /* 2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3c2c66affSColin Finck * PROJECT: ReactOS Base API Server DLL 4c2c66affSColin Finck * FILE: subsystems/win/basesrv/nls.c 5c2c66affSColin Finck * PURPOSE: National Language Support (NLS) 6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7c2c66affSColin Finck */ 8c2c66affSColin Finck 9c2c66affSColin Finck /* INCLUDES *******************************************************************/ 10c2c66affSColin Finck 11c2c66affSColin Finck #include "basesrv.h" 12c2c66affSColin Finck 13c2c66affSColin Finck #include <ndk/mmfuncs.h> 14c2c66affSColin Finck 15c2c66affSColin Finck #define NDEBUG 16c2c66affSColin Finck #include <debug.h> 17c2c66affSColin Finck 18c2c66affSColin Finck /* GLOBALS ********************************************************************/ 19c2c66affSColin Finck 20c2c66affSColin Finck RTL_CRITICAL_SECTION NlsCacheCriticalSection; 21c2c66affSColin Finck PNLS_USER_INFO pNlsRegUserInfo; 22c2c66affSColin Finck 23c2c66affSColin Finck BOOLEAN BaseSrvKernel32DelayLoadComplete; 24c2c66affSColin Finck HANDLE BaseSrvKernel32DllHandle; 25c2c66affSColin Finck UNICODE_STRING BaseSrvKernel32DllPath; 26c2c66affSColin Finck 27c2c66affSColin Finck POPEN_DATA_FILE pOpenDataFile; 28c2c66affSColin Finck PVOID /*PGET_DEFAULT_SORTKEY_SIZE */ pGetDefaultSortkeySize; 29c2c66affSColin Finck PVOID /*PGET_LINGUIST_LANG_SIZE*/ pGetLinguistLangSize; 30c2c66affSColin Finck PVOID /*PNLS_CONVERT_INTEGER_TO_STRING*/ pNlsConvertIntegerToString; 31c2c66affSColin Finck PVOID /*PVALIDATE_LCTYPE*/ pValidateLCType; 32c2c66affSColin Finck PVALIDATE_LOCALE pValidateLocale; 33c2c66affSColin Finck PGET_NLS_SECTION_NAME pGetNlsSectionName; 34c2c66affSColin Finck PVOID /*PGET_USER_DEFAULT_LANGID*/ pGetUserDefaultLangID; 35c2c66affSColin Finck PGET_CP_FILE_NAME_FROM_REGISTRY pGetCPFileNameFromRegistry; 36c2c66affSColin Finck PCREATE_NLS_SECURTY_DESCRIPTOR pCreateNlsSecurityDescriptor; 37c2c66affSColin Finck 38c2c66affSColin Finck BASESRV_KERNEL_IMPORTS BaseSrvKernel32Imports[10] = 39c2c66affSColin Finck { 40c2c66affSColin Finck { "OpenDataFile", (PVOID*) &pOpenDataFile }, 41c2c66affSColin Finck { "GetDefaultSortkeySize", (PVOID*) &pGetDefaultSortkeySize }, 42c2c66affSColin Finck { "GetLinguistLangSize", (PVOID*) &pGetLinguistLangSize }, 43c2c66affSColin Finck { "NlsConvertIntegerToString", (PVOID*) &pNlsConvertIntegerToString }, 44c2c66affSColin Finck { "ValidateLCType", (PVOID*) &pValidateLCType }, 45c2c66affSColin Finck { "ValidateLocale", (PVOID*) &pValidateLocale }, 46c2c66affSColin Finck { "GetNlsSectionName", (PVOID*) &pGetNlsSectionName }, 47c2c66affSColin Finck { "GetUserDefaultLangID", (PVOID*) &pGetUserDefaultLangID }, 48c2c66affSColin Finck { "GetCPFileNameFromRegistry", (PVOID*) &pGetCPFileNameFromRegistry }, 49c2c66affSColin Finck { "CreateNlsSecurityDescriptor", (PVOID*) &pCreateNlsSecurityDescriptor }, 50c2c66affSColin Finck }; 51c2c66affSColin Finck 52c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 53c2c66affSColin Finck 54c2c66affSColin Finck NTSTATUS 55c2c66affSColin Finck NTAPI 56c2c66affSColin Finck BaseSrvDelayLoadKernel32(VOID) 57c2c66affSColin Finck { 58c2c66affSColin Finck NTSTATUS Status; 59c2c66affSColin Finck ULONG i; 60c2c66affSColin Finck ANSI_STRING ProcedureName; 61c2c66affSColin Finck 62c2c66affSColin Finck /* Only do this once */ 63c2c66affSColin Finck if (BaseSrvKernel32DelayLoadComplete) return STATUS_SUCCESS; 64c2c66affSColin Finck 65c2c66affSColin Finck /* Loop all imports */ 66c2c66affSColin Finck for (i = 0; i < RTL_NUMBER_OF(BaseSrvKernel32Imports); i++) 67c2c66affSColin Finck { 68c2c66affSColin Finck /* Only look them up once */ 69c2c66affSColin Finck if (!*BaseSrvKernel32Imports[i].FunctionPointer) 70c2c66affSColin Finck { 71c2c66affSColin Finck /* If we haven't loaded the DLL yet, do it now */ 72c2c66affSColin Finck if (!BaseSrvKernel32DllHandle) 73c2c66affSColin Finck { 74c2c66affSColin Finck Status = LdrLoadDll(0, 75c2c66affSColin Finck 0, 76c2c66affSColin Finck &BaseSrvKernel32DllPath, 77c2c66affSColin Finck &BaseSrvKernel32DllHandle); 78c2c66affSColin Finck if (!NT_SUCCESS(Status)) 79c2c66affSColin Finck { 80c2c66affSColin Finck DPRINT1("Failed to load %wZ\n", &BaseSrvKernel32DllPath); 81c2c66affSColin Finck return Status; 82c2c66affSColin Finck } 83c2c66affSColin Finck } 84c2c66affSColin Finck 85c2c66affSColin Finck /* Get the address of the routine being looked up*/ 86c2c66affSColin Finck RtlInitAnsiString(&ProcedureName, BaseSrvKernel32Imports[i].FunctionName); 87c2c66affSColin Finck Status = LdrGetProcedureAddress(BaseSrvKernel32DllHandle, 88c2c66affSColin Finck &ProcedureName, 89c2c66affSColin Finck 0, 90c2c66affSColin Finck BaseSrvKernel32Imports[i].FunctionPointer); 91c2c66affSColin Finck DPRINT1("NLS: Found %Z at 0x%p\n", 92c2c66affSColin Finck &ProcedureName, 93c2c66affSColin Finck BaseSrvKernel32Imports[i].FunctionPointer); 94c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 95c2c66affSColin Finck } 96c2c66affSColin Finck } 97c2c66affSColin Finck 98c2c66affSColin Finck /* Did we find them all? */ 99c2c66affSColin Finck if (i == RTL_NUMBER_OF(BaseSrvKernel32Imports)) 100c2c66affSColin Finck { 101c2c66affSColin Finck /* Excellent */ 102c2c66affSColin Finck BaseSrvKernel32DelayLoadComplete = TRUE; 103c2c66affSColin Finck return STATUS_SUCCESS; 104c2c66affSColin Finck } 105c2c66affSColin Finck 106c2c66affSColin Finck /* Nope, fail */ 107c2c66affSColin Finck return Status; 108c2c66affSColin Finck } 109c2c66affSColin Finck 110c2c66affSColin Finck VOID 111c2c66affSColin Finck NTAPI 112c2c66affSColin Finck BaseSrvNLSInit(IN PBASE_STATIC_SERVER_DATA StaticData) 113c2c66affSColin Finck { 114c2c66affSColin Finck /* Initialize the lock */ 115c2c66affSColin Finck RtlInitializeCriticalSection(&NlsCacheCriticalSection); 116c2c66affSColin Finck 117c2c66affSColin Finck /* Initialize the data with all F's */ 118c2c66affSColin Finck pNlsRegUserInfo = &StaticData->NlsUserInfo; 119c2c66affSColin Finck RtlFillMemory(&StaticData->NlsUserInfo, sizeof(StaticData->NlsUserInfo), 0xFF); 120c2c66affSColin Finck 121c2c66affSColin Finck /* Set empty LCID */ 122c2c66affSColin Finck pNlsRegUserInfo->UserLocaleId = 0; 123c2c66affSColin Finck 124c2c66affSColin Finck /* Reset the cache update counter */ 125c2c66affSColin Finck RtlEnterCriticalSection(&NlsCacheCriticalSection); 126c2c66affSColin Finck pNlsRegUserInfo->ulCacheUpdateCount = 0; 127c2c66affSColin Finck RtlLeaveCriticalSection(&NlsCacheCriticalSection); 128c2c66affSColin Finck 129c2c66affSColin Finck /* Get the LCID */ 130c2c66affSColin Finck NtQueryDefaultLocale(0, &pNlsRegUserInfo->UserLocaleId); 131c2c66affSColin Finck } 132c2c66affSColin Finck 133c2c66affSColin Finck NTSTATUS 134c2c66affSColin Finck NTAPI 135c2c66affSColin Finck BaseSrvNlsConnect(IN PCSR_PROCESS CsrProcess, 136c2c66affSColin Finck IN OUT PVOID ConnectionInfo, 137c2c66affSColin Finck IN OUT PULONG ConnectionInfoLength) 138c2c66affSColin Finck { 139c2c66affSColin Finck /* Does nothing */ 140c2c66affSColin Finck return STATUS_SUCCESS; 141c2c66affSColin Finck } 142c2c66affSColin Finck 143c2c66affSColin Finck /* PUBLIC SERVER APIS *********************************************************/ 144c2c66affSColin Finck 145c2c66affSColin Finck CSR_API(BaseSrvNlsSetUserInfo) 146c2c66affSColin Finck { 147c2c66affSColin Finck DPRINT1("%s not yet implemented\n", __FUNCTION__); 148c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 149c2c66affSColin Finck } 150c2c66affSColin Finck 151c2c66affSColin Finck CSR_API(BaseSrvNlsSetMultipleUserInfo) 152c2c66affSColin Finck { 153c2c66affSColin Finck DPRINT1("%s not yet implemented\n", __FUNCTION__); 154c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 155c2c66affSColin Finck } 156c2c66affSColin Finck 157c2c66affSColin Finck CSR_API(BaseSrvNlsCreateSection) 158c2c66affSColin Finck { 159c2c66affSColin Finck NTSTATUS Status; 160c2c66affSColin Finck HANDLE SectionHandle, ProcessHandle, FileHandle; 161c2c66affSColin Finck ULONG LocaleId; 162c2c66affSColin Finck UNICODE_STRING NlsSectionName; 163c2c66affSColin Finck PWCHAR NlsFileName; 164c2c66affSColin Finck UCHAR SecurityDescriptor[52]; 165c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 166c2c66affSColin Finck WCHAR FileNameBuffer[32]; 167c2c66affSColin Finck WCHAR NlsSectionNameBuffer[32]; 168c2c66affSColin Finck PBASE_NLS_CREATE_SECTION NlsMsg = &((PBASE_API_MESSAGE)ApiMessage)->Data.NlsCreateSection; 169c2c66affSColin Finck 170c2c66affSColin Finck /* Load kernel32 first and import the NLS routines */ 171c2c66affSColin Finck Status = BaseSrvDelayLoadKernel32(); 172c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 173c2c66affSColin Finck 174c2c66affSColin Finck /* Assume failure */ 175c2c66affSColin Finck NlsMsg->SectionHandle = NULL; 176c2c66affSColin Finck 177c2c66affSColin Finck /* Check and validate the locale ID, if one is present */ 178c2c66affSColin Finck LocaleId = NlsMsg->LocaleId; 179c2c66affSColin Finck DPRINT1("NLS: Create Section with LCID: %lx for Type: %d\n", LocaleId, NlsMsg->Type); 180c2c66affSColin Finck if (LocaleId) 181c2c66affSColin Finck { 182c2c66affSColin Finck if (!pValidateLocale(LocaleId)) return STATUS_INVALID_PARAMETER; 183c2c66affSColin Finck } 184c2c66affSColin Finck 185c2c66affSColin Finck /* Check which NLS section is being created */ 186c2c66affSColin Finck switch (NlsMsg->Type) 187c2c66affSColin Finck { 188c2c66affSColin Finck /* For each one, set the correct filename and object name */ 189c2c66affSColin Finck case 1: 190c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionUnicode"); 191c2c66affSColin Finck NlsFileName = L"unicode.nls"; 192c2c66affSColin Finck break; 193c2c66affSColin Finck case 2: 194c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionLocale"); 195c2c66affSColin Finck NlsFileName = L"locale.nls"; 196c2c66affSColin Finck break; 197c2c66affSColin Finck case 3: 198c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCType"); 199c2c66affSColin Finck NlsFileName = L"ctype.nls"; 200c2c66affSColin Finck break; 201c2c66affSColin Finck case 4: 202c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionSortkey"); 203c2c66affSColin Finck NlsFileName = L"sortkey.nls"; 204c2c66affSColin Finck break; 205c2c66affSColin Finck case 5: 206c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionSortTbls"); 207c2c66affSColin Finck NlsFileName = L"sorttbls.nls"; 208c2c66affSColin Finck break; 209c2c66affSColin Finck case 6: 210c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCP437"); 211c2c66affSColin Finck NlsFileName = L"c_437.nls"; 212c2c66affSColin Finck break; 213c2c66affSColin Finck case 7: 214c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCP1252"); 215c2c66affSColin Finck NlsFileName = L"c_1252.nls"; 216c2c66affSColin Finck break; 217c2c66affSColin Finck case 8: 218c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionLANG_EXCEPT"); 219c2c66affSColin Finck NlsFileName = L"l_except.nls"; 220c2c66affSColin Finck break; 221c2c66affSColin Finck case 9: 222c2c66affSColin Finck DPRINT1("This type not yet supported\n"); 223c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 224c2c66affSColin Finck case 10: 225c2c66affSColin Finck DPRINT1("This type not yet supported\n"); 226c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 227c2c66affSColin Finck case 11: 228c2c66affSColin Finck /* Get the filename for this locale */ 229c2c66affSColin Finck if (!pGetCPFileNameFromRegistry(NlsMsg->LocaleId, 230c2c66affSColin Finck FileNameBuffer, 231c2c66affSColin Finck RTL_NUMBER_OF(FileNameBuffer))) 232c2c66affSColin Finck { 233c2c66affSColin Finck DPRINT1("File name query failed\n"); 234c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 235c2c66affSColin Finck } 236c2c66affSColin Finck 237c2c66affSColin Finck /* Get the name of the section for this locale */ 238c2c66affSColin Finck DPRINT1("File name: %S\n", FileNameBuffer); 239c2c66affSColin Finck Status = pGetNlsSectionName(NlsMsg->LocaleId, 240c2c66affSColin Finck 10, 241c2c66affSColin Finck 0, 242c2c66affSColin Finck L"\\NLS\\NlsSectionCP", 243c2c66affSColin Finck NlsSectionNameBuffer, 244c2c66affSColin Finck RTL_NUMBER_OF(NlsSectionNameBuffer)); 245c2c66affSColin Finck if (!NT_SUCCESS(Status)) 246c2c66affSColin Finck { 247c2c66affSColin Finck DPRINT1("Section name query failed: %lx\n", Status); 248c2c66affSColin Finck return Status; 249c2c66affSColin Finck } 250c2c66affSColin Finck 251c2c66affSColin Finck /* Setup the name and go open it */ 252c2c66affSColin Finck NlsFileName = FileNameBuffer; 253c2c66affSColin Finck DPRINT1("Section name: %S\n", NlsSectionNameBuffer); 254c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, NlsSectionNameBuffer); 255c2c66affSColin Finck break; 256c2c66affSColin Finck case 12: 257c2c66affSColin Finck RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionGeo"); 258c2c66affSColin Finck NlsFileName = L"geo.nls"; 259c2c66affSColin Finck break; 260c2c66affSColin Finck default: 261c2c66affSColin Finck DPRINT1("NLS: Invalid NLS type!\n"); 262c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 263c2c66affSColin Finck } 264c2c66affSColin Finck 265c2c66affSColin Finck /* Open the specified NLS file */ 266c2c66affSColin Finck Status = pOpenDataFile(&FileHandle, NlsFileName); 267c2c66affSColin Finck if (Status != STATUS_SUCCESS) 268c2c66affSColin Finck { 269c2c66affSColin Finck DPRINT1("NLS: Failed to open file: %lx\n", Status); 270c2c66affSColin Finck return Status; 271c2c66affSColin Finck } 272c2c66affSColin Finck 273c2c66affSColin Finck /* Create an SD for the section object */ 274c2c66affSColin Finck Status = pCreateNlsSecurityDescriptor(&SecurityDescriptor, 275c2c66affSColin Finck sizeof(SecurityDescriptor), 276c2c66affSColin Finck 0x80000000); 277c2c66affSColin Finck if (!NT_SUCCESS(Status)) 278c2c66affSColin Finck { 279c2c66affSColin Finck DPRINT1("NLS: CreateNlsSecurityDescriptor FAILED!: %lx\n", Status); 280c2c66affSColin Finck NtClose(FileHandle); 281c2c66affSColin Finck return Status; 282c2c66affSColin Finck } 283c2c66affSColin Finck 284c2c66affSColin Finck /* Create the section object proper */ 285c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 286c2c66affSColin Finck &NlsSectionName, 287c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_OPENIF, 288c2c66affSColin Finck NULL, 289c2c66affSColin Finck &SecurityDescriptor); 290c2c66affSColin Finck Status = NtCreateSection(&SectionHandle, 291c2c66affSColin Finck SECTION_MAP_READ, 292c2c66affSColin Finck &ObjectAttributes, 293c2c66affSColin Finck 0, 294c2c66affSColin Finck PAGE_READONLY, 295c2c66affSColin Finck SEC_COMMIT, 296c2c66affSColin Finck FileHandle); 297c2c66affSColin Finck NtClose(FileHandle); 298c2c66affSColin Finck if (!NT_SUCCESS(Status)) 299c2c66affSColin Finck { 300c2c66affSColin Finck DPRINT1("NLS: Failed to create section! %lx\n", Status); 301c2c66affSColin Finck return Status; 302c2c66affSColin Finck } 303c2c66affSColin Finck 304c2c66affSColin Finck /* Open a handle to the calling process */ 305c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 306c2c66affSColin Finck Status = NtOpenProcess(&ProcessHandle, 307c2c66affSColin Finck PROCESS_DUP_HANDLE, 308c2c66affSColin Finck &ObjectAttributes, 309c2c66affSColin Finck &ApiMessage->Header.ClientId); 310c2c66affSColin Finck if (!NT_SUCCESS(Status)) 311c2c66affSColin Finck { 312c2c66affSColin Finck DPRINT1("NLS: Failed to open process! %lx\n", Status); 313c2c66affSColin Finck NtClose(SectionHandle); 314c2c66affSColin Finck return Status; 315c2c66affSColin Finck } 316c2c66affSColin Finck 317c2c66affSColin Finck /* Duplicate the handle to the section object into it */ 318c2c66affSColin Finck Status = NtDuplicateObject(NtCurrentProcess(), 319c2c66affSColin Finck SectionHandle, 320c2c66affSColin Finck ProcessHandle, 321c2c66affSColin Finck &NlsMsg->SectionHandle, 322c2c66affSColin Finck 0, 323c2c66affSColin Finck 0, 324c2c66affSColin Finck 3); 325c2c66affSColin Finck NtClose(ProcessHandle); 326c2c66affSColin Finck return Status; 327c2c66affSColin Finck } 328c2c66affSColin Finck 329c2c66affSColin Finck CSR_API(BaseSrvNlsUpdateCacheCount) 330c2c66affSColin Finck { 331c2c66affSColin Finck DPRINT1("%s not yet implemented\n", __FUNCTION__); 332c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 333c2c66affSColin Finck } 334c2c66affSColin Finck 335c2c66affSColin Finck CSR_API(BaseSrvNlsGetUserInfo) 336c2c66affSColin Finck { 337c2c66affSColin Finck NTSTATUS Status; 338c2c66affSColin Finck PBASE_NLS_GET_USER_INFO NlsMsg = &((PBASE_API_MESSAGE)ApiMessage)->Data.NlsGetUserInfo; 339c2c66affSColin Finck 340c2c66affSColin Finck /* Make sure the buffer is valid and of the right size */ 341*c7c0b09eSHermès Bélusca-Maïto if ((CsrValidateMessageBuffer(ApiMessage, &NlsMsg->NlsUserInfo, NlsMsg->Size, sizeof(BYTE))) && 342c2c66affSColin Finck (NlsMsg->Size == sizeof(NLS_USER_INFO))) 343c2c66affSColin Finck { 344c2c66affSColin Finck /* Acquire the lock to prevent updates while we copy */ 345c2c66affSColin Finck Status = RtlEnterCriticalSection(&NlsCacheCriticalSection); 346c2c66affSColin Finck if (NT_SUCCESS(Status)) 347c2c66affSColin Finck { 348c2c66affSColin Finck /* Do the copy now, then drop the lock */ 349c2c66affSColin Finck RtlCopyMemory(NlsMsg->NlsUserInfo, pNlsRegUserInfo, NlsMsg->Size); 350c2c66affSColin Finck DPRINT1("NLS Data copy complete\n"); 351c2c66affSColin Finck RtlLeaveCriticalSection(&NlsCacheCriticalSection); 352c2c66affSColin Finck } 353c2c66affSColin Finck } 354c2c66affSColin Finck else 355c2c66affSColin Finck { 356c2c66affSColin Finck /* The data was invalid, bail out */ 357c2c66affSColin Finck DPRINT1("NLS: Size of info is invalid: %lx vs %lx\n", NlsMsg->Size, sizeof(NLS_USER_INFO)); 358c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER; 359c2c66affSColin Finck } 360c2c66affSColin Finck 361c2c66affSColin Finck /* All done */ 362c2c66affSColin Finck return Status; 363c2c66affSColin Finck } 364c2c66affSColin Finck 365c2c66affSColin Finck /* PUBLIC APIS ****************************************************************/ 366c2c66affSColin Finck 367c2c66affSColin Finck NTSTATUS 368c2c66affSColin Finck NTAPI 369c2c66affSColin Finck BaseSrvNlsLogon(DWORD Unknown) 370c2c66affSColin Finck { 371c2c66affSColin Finck DPRINT1("%s(%lu) not yet implemented\n", __FUNCTION__, Unknown); 372c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 373c2c66affSColin Finck } 374c2c66affSColin Finck 375c2c66affSColin Finck NTSTATUS 376c2c66affSColin Finck NTAPI 377c2c66affSColin Finck BaseSrvNlsUpdateRegistryCache(DWORD Unknown1, 378c2c66affSColin Finck DWORD Unknown2) 379c2c66affSColin Finck { 380c2c66affSColin Finck DPRINT1("%s(%lu, %lu) not yet implemented\n", __FUNCTION__, Unknown1, Unknown2); 381c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 382c2c66affSColin Finck } 383c2c66affSColin Finck 384c2c66affSColin Finck /* EOF */ 385