xref: /reactos/subsystems/win/basesrv/nls.c (revision c7c0b09e)
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