2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Base API Server DLL
4 * FILE: subsystems/win/basesrv/vdm.c
5 * PURPOSE: Virtual DOS Machines (VDM) Support
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 RTL_CRITICAL_SECTION NlsCacheCriticalSection
;
19 PNLS_USER_INFO pNlsRegUserInfo
;
21 BOOLEAN BaseSrvKernel32DelayLoadComplete
;
22 HANDLE BaseSrvKernel32DllHandle
;
23 UNICODE_STRING BaseSrvKernel32DllPath
;
25 POPEN_DATA_FILE pOpenDataFile
;
26 PVOID
/*PGET_DEFAULT_SORTKEY_SIZE */ pGetDefaultSortkeySize
;
27 PVOID
/*PGET_LINGUIST_LANG_SIZE*/ pGetLinguistLangSize
;
28 PVOID
/*PNLS_CONVERT_INTEGER_TO_STRING*/ pNlsConvertIntegerToString
;
29 PVOID
/*PVALIDATE_LCTYPE*/ pValidateLCType
;
30 PVALIDATE_LOCALE pValidateLocale
;
31 PGET_NLS_SECTION_NAME pGetNlsSectionName
;
32 PVOID
/*PGET_USER_DEFAULT_LANGID*/ pGetUserDefaultLangID
;
33 PGET_CP_FILE_NAME_FROM_REGISTRY pGetCPFileNameFromRegistry
;
34 PCREATE_NLS_SECURTY_DESCRIPTOR pCreateNlsSecurityDescriptor
;
36 BASESRV_KERNEL_IMPORTS BaseSrvKernel32Imports
[10] =
38 { "OpenDataFile", (PVOID
*) &pOpenDataFile
},
39 { "GetDefaultSortkeySize", (PVOID
*) &pGetDefaultSortkeySize
},
40 { "GetLinguistLangSize", (PVOID
*) &pGetLinguistLangSize
},
41 { "NlsConvertIntegerToString", (PVOID
*) &pNlsConvertIntegerToString
},
42 { "ValidateLCType", (PVOID
*) &pValidateLCType
},
43 { "ValidateLocale", (PVOID
*) &pValidateLocale
},
44 { "GetNlsSectionName", (PVOID
*) &pGetNlsSectionName
},
45 { "GetUserDefaultLangID", (PVOID
*) &pGetUserDefaultLangID
},
46 { "GetCPFileNameFromRegistry", (PVOID
*) &pGetCPFileNameFromRegistry
},
47 { "CreateNlsSecurityDescriptor", (PVOID
*) &pCreateNlsSecurityDescriptor
},
50 /* FUNCTIONS *****************************************************************/
54 BaseSrvDelayLoadKernel32(VOID
)
58 ANSI_STRING ProcedureName
;
60 /* Only do this once */
61 if (BaseSrvKernel32DelayLoadComplete
) return STATUS_SUCCESS
;
63 /* Loop all imports */
64 for (i
= 0; i
< RTL_NUMBER_OF(BaseSrvKernel32Imports
); i
++)
66 /* Only look them up once */
67 if (!*BaseSrvKernel32Imports
[i
].FunctionPointer
)
69 /* If we haven't loaded the DLL yet, do it now */
70 if (!BaseSrvKernel32DllHandle
)
72 Status
= LdrLoadDll(0,
74 &BaseSrvKernel32DllPath
,
75 &BaseSrvKernel32DllHandle
);
76 if (!NT_SUCCESS(Status
))
78 DPRINT1("Failed to load %wZ\n", &BaseSrvKernel32DllPath
);
83 /* Get the address of the routine being looked up*/
84 RtlInitAnsiString(&ProcedureName
, BaseSrvKernel32Imports
[i
].FunctionName
);
85 Status
= LdrGetProcedureAddress(BaseSrvKernel32DllHandle
,
88 BaseSrvKernel32Imports
[i
].FunctionPointer
);
89 DPRINT1("NLS: Found %Z at 0x%p\n",
91 BaseSrvKernel32Imports
[i
].FunctionPointer
);
92 if (!NT_SUCCESS(Status
)) break;
96 /* Did we find them all? */
97 if (i
== RTL_NUMBER_OF(BaseSrvKernel32Imports
))
100 BaseSrvKernel32DelayLoadComplete
= TRUE
;
101 return STATUS_SUCCESS
;
110 BaseSrvNLSInit(IN PBASE_STATIC_SERVER_DATA StaticData
)
112 /* Initialize the lock */
113 RtlInitializeCriticalSection(&NlsCacheCriticalSection
);
115 /* Initialize the data with all F's */
116 pNlsRegUserInfo
= &StaticData
->NlsUserInfo
;
117 RtlFillMemory(&StaticData
->NlsUserInfo
, 0xFF, sizeof(StaticData
->NlsUserInfo
));
120 pNlsRegUserInfo
->UserLocaleId
= 0;
122 /* Reset the cache update counter */
123 RtlEnterCriticalSection(&NlsCacheCriticalSection
);
124 pNlsRegUserInfo
->ulCacheUpdateCount
= 0;
125 RtlLeaveCriticalSection(&NlsCacheCriticalSection
);
128 NtQueryDefaultLocale(0, &pNlsRegUserInfo
->UserLocaleId
);
131 /* PUBLIC SERVER APIS *********************************************************/
133 CSR_API(BaseSrvNlsSetUserInfo
)
135 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
136 return STATUS_NOT_IMPLEMENTED
;
139 CSR_API(BaseSrvNlsSetMultipleUserInfo
)
141 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
142 return STATUS_NOT_IMPLEMENTED
;
145 CSR_API(BaseSrvNlsCreateSection
)
148 HANDLE SectionHandle
, ProcessHandle
, FileHandle
;
150 UNICODE_STRING NlsSectionName
;
152 UCHAR SecurityDescriptor
[52];
153 OBJECT_ATTRIBUTES ObjectAttributes
;
154 PBASE_NLS_CREATE_SECTION NlsMsg
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.NlsCreateSection
;
156 /* Load kernel32 first and import the NLS routines */
157 Status
= BaseSrvDelayLoadKernel32();
158 if (!NT_SUCCESS(Status
)) return Status
;
161 NlsMsg
->SectionHandle
= NULL
;
163 /* Check and validate the locale ID, if one is present */
164 LocaleId
= NlsMsg
->LocaleId
;
165 DPRINT1("NLS: Create Section with LCID: %lx for Type: %d\n", LocaleId
, NlsMsg
->Type
);
168 if (!pValidateLocale(LocaleId
)) return STATUS_INVALID_PARAMETER
;
171 /* Check which NLS section is being created */
172 switch (NlsMsg
->Type
)
174 /* For each one, set the correct filename and object name */
176 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionUnicode");
177 NlsFileName
= L
"unicode.nls";
180 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionLocale");
181 NlsFileName
= L
"locale.nls";
184 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionCType");
185 NlsFileName
= L
"ctype.nls";
188 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionSortkey");
189 NlsFileName
= L
"sortkey.nls";
192 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionSortTbls");
193 NlsFileName
= L
"sorttbls.nls";
196 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionCP437");
197 NlsFileName
= L
"c_437.nls";
200 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionCP1252");
201 NlsFileName
= L
"c_1252.nls";
204 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionLANG_EXCEPT");
205 NlsFileName
= L
"l_except.nls";
208 DPRINT1("This type not yet supported\n");
209 return STATUS_NOT_IMPLEMENTED
;
211 DPRINT1("This type not yet supported\n");
212 return STATUS_NOT_IMPLEMENTED
;
214 DPRINT1("This type not yet supported\n");
215 return STATUS_NOT_IMPLEMENTED
;
217 RtlInitUnicodeString(&NlsSectionName
, L
"\\NLS\\NlsSectionGeo");
218 NlsFileName
= L
"geo.nls";
221 DPRINT1("NLS: Invalid NLS type!\n");
222 return STATUS_INVALID_PARAMETER
;
225 /* Open the specified NLS file */
226 Status
= pOpenDataFile(&FileHandle
, NlsFileName
);
227 if (Status
!= STATUS_SUCCESS
)
229 DPRINT1("NLS: Failed to open file: %lx\n", Status
);
233 /* Create an SD for the section object */
234 Status
= pCreateNlsSecurityDescriptor(&SecurityDescriptor
,
235 sizeof(SecurityDescriptor
),
237 if (!NT_SUCCESS(Status
))
239 DPRINT1("NLS: CreateNlsSecurityDescriptor FAILED!: %lx\n", Status
);
244 /* Create the section object proper */
245 InitializeObjectAttributes(&ObjectAttributes
,
247 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
| OBJ_OPENIF
,
249 &SecurityDescriptor
);
250 Status
= NtCreateSection(&SectionHandle
,
258 if (!NT_SUCCESS(Status
))
260 DPRINT1("NLS: Failed to create section! %lx\n", Status
);
264 /* Open a handle to the calling process */
265 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
266 Status
= NtOpenProcess(&ProcessHandle
,
269 &ApiMessage
->Header
.ClientId
);
270 if (!NT_SUCCESS(Status
))
272 DPRINT1("NLS: Failed to open process! %lx\n", Status
);
273 NtClose(SectionHandle
);
277 /* Duplicate the handle to the section object into it */
278 Status
= NtDuplicateObject(NtCurrentProcess(),
281 &NlsMsg
->SectionHandle
,
285 NtClose(ProcessHandle
);
289 CSR_API(BaseSrvNlsUpdateCacheCount
)
291 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
292 return STATUS_NOT_IMPLEMENTED
;
295 CSR_API(BaseSrvNlsGetUserInfo
)
298 PBASE_NLS_GET_USER_INFO NlsMsg
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.NlsGetUserInfo
;
300 /* Make sure the buffer is valid and of the right size */
301 if ((CsrValidateMessageBuffer(ApiMessage
, &NlsMsg
->NlsUserInfo
, NlsMsg
->Size
, TRUE
)) &&
302 (NlsMsg
->Size
== sizeof(NLS_USER_INFO
)))
304 /* Acquire the lock to prevent updates while we copy */
305 Status
= RtlEnterCriticalSection(&NlsCacheCriticalSection
);
306 if (NT_SUCCESS(Status
))
308 /* Do the copy now, then drop the lock */
309 RtlCopyMemory(&NlsMsg
->NlsUserInfo
, pNlsRegUserInfo
, NlsMsg
->Size
);
310 DPRINT1("NLS Data copy complete\n");
311 RtlLeaveCriticalSection(&NlsCacheCriticalSection
);
316 /* The data was invalid, bail out */
317 DPRINT1("NLS: Size of info is invalid: %lx vs %lx\n", NlsMsg
->Size
, sizeof(NLS_USER_INFO
));
318 Status
= STATUS_INVALID_PARAMETER
;