diff --git a/reactos/include/reactos/subsys/win/basemsg.h b/reactos/include/reactos/subsys/win/basemsg.h index 45d219c264a..fc82445141c 100644 --- a/reactos/include/reactos/subsys/win/basemsg.h +++ b/reactos/include/reactos/subsys/win/basemsg.h @@ -46,6 +46,7 @@ typedef enum _BASESRV_API_NUMBER BasepNlsUpdateCacheCount, BasepSetTermsrvClientTimeZone, BasepSxsCreateActivationContext, + BasepUnknown, BasepRegisterThread, BasepNlsGetUserInfo, BasepMaxApiNumber @@ -260,6 +261,13 @@ typedef struct UNICODE_STRING TargetPath; } BASE_DEFINE_DOS_DEVICE, *PBASE_DEFINE_DOS_DEVICE; +typedef struct +{ + HANDLE SectionHandle; + ULONG Type; + ULONG LocaleId; +} BASE_NLS_CREATE_SECTION, *PBASE_NLS_CREATE_SECTION; + typedef struct _BASE_API_MESSAGE { PORT_MESSAGE Header; @@ -288,6 +296,7 @@ typedef struct _BASE_API_MESSAGE BASE_SOUND_SENTRY SoundSentryRequest; BASE_REFRESH_INIFILE_MAPPING RefreshIniFileMappingRequest; BASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest; + BASE_NLS_CREATE_SECTION NlsCreateSection; } Data; } BASE_API_MESSAGE, *PBASE_API_MESSAGE; diff --git a/reactos/subsystems/win/basesrv/basesrv.h b/reactos/subsystems/win/basesrv/basesrv.h index c44b9aeb5e9..9b634a4007c 100644 --- a/reactos/subsystems/win/basesrv/basesrv.h +++ b/reactos/subsystems/win/basesrv/basesrv.h @@ -24,6 +24,32 @@ #include #include +typedef struct _BASESRV_KERNEL_IMPORTS +{ + PCHAR FunctionName; + PVOID* FunctionPointer; +} BASESRV_KERNEL_IMPORTS, *PBASESRV_KERNEL_IMPORTS; + +/* FIXME: BASENLS.H */ +typedef NTSTATUS(*WINAPI POPEN_DATA_FILE) (HANDLE hFile, + PWCHAR FileName + ); + +typedef BOOL(*WINAPI PGET_CP_FILE_NAME_FROM_REGISTRY)(UINT CodePage, + LPWSTR FileName, + ULONG FileNameSize + ); + +typedef BOOL(*WINAPI PGET_NLS_SECTION_NAME)(UINT CodePage, + UINT Base, + ULONG Unknown, + LPSTR BaseName, + LPSTR Result, + ULONG ResultSize + ); + +typedef BOOL(*WINAPI PVALIDATE_LOCALE)(IN ULONG LocaleId); +typedef NTSTATUS(*WINAPI PCREATE_NLS_SECURTY_DESCRIPTOR)(IN PVOID Buffer, IN ULONG BufferSize, IN ULONG AceType); /* Globals */ extern HANDLE BaseSrvHeap; diff --git a/reactos/subsystems/win/basesrv/init.c b/reactos/subsystems/win/basesrv/init.c index 3030744601f..7c6754a5035 100644 --- a/reactos/subsystems/win/basesrv/init.c +++ b/reactos/subsystems/win/basesrv/init.c @@ -17,6 +17,7 @@ /* GLOBALS ********************************************************************/ HANDLE BaseSrvDllInstance = NULL; +extern UNICODE_STRING BaseSrvKernel32DllPath; /* Memory */ HANDLE BaseSrvHeap = NULL; // Our own heap. @@ -54,6 +55,7 @@ PCSR_API_ROUTINE BaseServerApiDispatchTable[BasepMaxApiNumber - BASESRV_FIRST_AP BaseSrvNlsUpdateCacheCount, BaseSrvSetTermsrvClientTimeZone, BaseSrvSxsCreateActivationContext, + BaseSrvDebugProcess, BaseSrvRegisterThread, BaseSrvNlsGetUserInfo, }; @@ -84,12 +86,13 @@ BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMB TRUE, // BaseSrvSoundSentryNotification TRUE, // BaseSrvRefreshIniFileMapping TRUE, // BaseSrvDefineDosDevice - FALSE, // BaseSrvSetTermsrvAppInstallMode - FALSE, // BaseSrvNlsUpdateCacheCount - FALSE, // BaseSrvSetTermsrvClientTimeZone - FALSE, // BaseSrvSxsCreateActivationContext - FALSE, // BaseSrvRegisterThread - FALSE, // BaseSrvNlsGetUserInfo + TRUE, // BaseSrvSetTermsrvAppInstallMode + TRUE, // BaseSrvNlsUpdateCacheCount + TRUE, // BaseSrvSetTermsrvClientTimeZone + TRUE, // BaseSrvSxsCreateActivationContext + TRUE, // BasepDebugProcess + TRUE, // BaseSrvRegisterThread + TRUE, // BaseSrvNlsGetUserInfo }; PCHAR BaseServerApiNameTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] = @@ -311,6 +314,12 @@ BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll) SystemRootString.Buffer); ASSERT(NT_SUCCESS(Status)); + /* Create the kernel32 path */ + wcscat(SystemRootString.Buffer, L"\\kernel32.dll"); + Status = RtlCreateUnicodeString(&BaseSrvKernel32DllPath, + SystemRootString.Buffer); + ASSERT(NT_SUCCESS(Status)); + /* FIXME: Check Session ID */ wcscpy(Buffer, L"\\BaseNamedObjects"); RtlInitUnicodeString(&BnoString, Buffer); diff --git a/reactos/subsystems/win/basesrv/nls.c b/reactos/subsystems/win/basesrv/nls.c index f047fbe31fe..9db5886ef1d 100644 --- a/reactos/subsystems/win/basesrv/nls.c +++ b/reactos/subsystems/win/basesrv/nls.c @@ -13,6 +13,95 @@ #define NDEBUG #include +/* GLOBALS ********************************************************************/ + +BOOLEAN BaseSrvKernel32DelayLoadComplete; +HANDLE BaseSrvKernel32DllHandle; +UNICODE_STRING BaseSrvKernel32DllPath; + +POPEN_DATA_FILE pOpenDataFile; +PVOID /*PGET_DEFAULT_SORTKEY_SIZE */ pGetDefaultSortkeySize; +PVOID /*PGET_LINGUIST_LANG_SIZE*/ pGetLinguistLangSize; +PVOID /*PNLS_CONVERT_INTEGER_TO_STRING*/ pNlsConvertIntegerToString; +PVOID /*PVALIDATE_LCTYPE*/ pValidateLCType; +PVALIDATE_LOCALE pValidateLocale; +PGET_NLS_SECTION_NAME pGetNlsSectionName; +PVOID /*PGET_USER_DEFAULT_LANGID*/ pGetUserDefaultLangID; +PGET_CP_FILE_NAME_FROM_REGISTRY pGetCPFileNameFromRegistry; +PCREATE_NLS_SECURTY_DESCRIPTOR pCreateNlsSecurityDescriptor; + +BASESRV_KERNEL_IMPORTS BaseSrvKernel32Imports[10] = +{ + { "OpenDataFile", (PVOID*) &pOpenDataFile }, + { "GetDefaultSortkeySize", (PVOID*) &pGetDefaultSortkeySize }, + { "GetLinguistLangSize", (PVOID*) &pGetLinguistLangSize }, + { "NlsConvertIntegerToString", (PVOID*) &pNlsConvertIntegerToString }, + { "ValidateLCType", (PVOID*) &pValidateLCType }, + { "ValidateLocale", (PVOID*) &pValidateLocale }, + { "GetNlsSectionName", (PVOID*) &pGetNlsSectionName }, + { "GetUserDefaultLangID", (PVOID*) &pGetUserDefaultLangID }, + { "GetCPFileNameFromRegistry", (PVOID*) &pGetCPFileNameFromRegistry }, + { "CreateNlsSecurityDescriptor", (PVOID*) &pCreateNlsSecurityDescriptor }, +}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +BaseSrvDelayLoadKernel32(VOID) +{ + NTSTATUS Status; + ULONG i; + ANSI_STRING ProcedureName; + + /* Only do this once */ + if (BaseSrvKernel32DelayLoadComplete) return STATUS_SUCCESS; + + /* Loop all imports */ + for (i = 0; i < RTL_NUMBER_OF(BaseSrvKernel32Imports); i++) + { + /* Only look them up once */ + if (!*BaseSrvKernel32Imports[i].FunctionPointer) + { + /* If we haven't loaded the DLL yet, do it now */ + if (!BaseSrvKernel32DllHandle) + { + Status = LdrLoadDll(0, + 0, + &BaseSrvKernel32DllPath, + &BaseSrvKernel32DllHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to load %wZ\n", &BaseSrvKernel32DllPath); + return Status; + } + } + + /* Get the address of the routine being looked up*/ + RtlInitAnsiString(&ProcedureName, BaseSrvKernel32Imports[i].FunctionName); + Status = LdrGetProcedureAddress(BaseSrvKernel32DllHandle, + &ProcedureName, + 0, + BaseSrvKernel32Imports[i].FunctionPointer); + DPRINT1("NLS: Found %Z at 0x%p\n", + &ProcedureName, + BaseSrvKernel32Imports[i].FunctionPointer); + if (!NT_SUCCESS(Status)) break; + } + } + + /* Did we find them all? */ + if (i == RTL_NUMBER_OF(BaseSrvKernel32Imports)) + { + /* Excellent */ + BaseSrvKernel32DelayLoadComplete = TRUE; + return STATUS_SUCCESS; + } + + /* Nope, fail */ + return Status; +} + /* PUBLIC SERVER APIS *********************************************************/ CSR_API(BaseSrvNlsSetUserInfo) @@ -28,10 +117,147 @@ CSR_API(BaseSrvNlsSetMultipleUserInfo) } CSR_API(BaseSrvNlsCreateSection) - { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + HANDLE SectionHandle, ProcessHandle, FileHandle; + ULONG LocaleId; + UNICODE_STRING NlsSectionName; + PWCHAR NlsFileName; + UCHAR SecurityDescriptor[52]; + OBJECT_ATTRIBUTES ObjectAttributes; + PBASE_NLS_CREATE_SECTION NlsMsg = &((PBASE_API_MESSAGE)ApiMessage)->Data.NlsCreateSection; + + /* Load kernel32 first and import the NLS routines */ + Status = BaseSrvDelayLoadKernel32(); + if (!NT_SUCCESS(Status)) return Status; + + /* Assume failure */ + NlsMsg->SectionHandle = NULL; + + /* Check and validate the locale ID, if one is present */ + LocaleId = NlsMsg->LocaleId; + DPRINT1("NLS: Create Section with LCID: %lx for Type: %d\n", LocaleId, NlsMsg->Type); + if (LocaleId) + { + if (!pValidateLocale(LocaleId)) return STATUS_INVALID_PARAMETER; + } + + /* Check which NLS section is being created */ + switch (NlsMsg->Type) + { + /* For each one, set the correct filename and object name */ + case 1: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionUnicode"); + NlsFileName = L"unicode.nls"; + break; + case 2: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionLocale"); + NlsFileName = L"locale.nls"; + break; + case 3: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCType"); + NlsFileName = L"ctype.nls"; + break; + case 4: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionSortkey"); + NlsFileName = L"sortkey.nls"; + break; + case 5: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionSortTbls"); + NlsFileName = L"sorttbls.nls"; + break; + case 6: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCP437"); + NlsFileName = L"c_437.nls"; + break; + case 7: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionCP1252"); + NlsFileName = L"c_1252.nls"; + break; + case 8: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionLANG_EXCEPT"); + NlsFileName = L"l_except.nls"; + break; + case 9: + DPRINT1("This type not yet supported\n"); + return STATUS_NOT_IMPLEMENTED; + case 10: + DPRINT1("This type not yet supported\n"); + return STATUS_NOT_IMPLEMENTED; + case 11: + DPRINT1("This type not yet supported\n"); + return STATUS_NOT_IMPLEMENTED; + case 12: + RtlInitUnicodeString(&NlsSectionName, L"\\NLS\\NlsSectionGeo"); + NlsFileName = L"geo.nls"; + break; + default: + DPRINT1("NLS: Invalid NLS type!\n"); + return STATUS_INVALID_PARAMETER; + } + + /* Open the specified NLS file */ + Status = pOpenDataFile(&FileHandle, NlsFileName); + if (Status != STATUS_SUCCESS) + { + DPRINT1("NLS: Failed to open file: %lx\n", Status); + return Status; + } + + /* Create an SD for the section object */ + Status = pCreateNlsSecurityDescriptor(&SecurityDescriptor, + sizeof(SecurityDescriptor), + 0x80000000); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NLS: CreateNlsSecurityDescriptor FAILED!: %lx\n", Status); + NtClose(FileHandle); + return Status; + } + + /* Create the section object proper */ + InitializeObjectAttributes(&ObjectAttributes, + &NlsSectionName, + OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_OPENIF, + NULL, + &SecurityDescriptor); + Status = NtCreateSection(&SectionHandle, + SECTION_MAP_READ, + &ObjectAttributes, + 0, + PAGE_READONLY, + SEC_COMMIT, + FileHandle); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NLS: Failed to create section! %lx\n", Status); + return Status; + } + + /* Open a handle to the calling process */ + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + Status = NtOpenProcess(&ProcessHandle, + PROCESS_DUP_HANDLE, + &ObjectAttributes, + &ApiMessage->Header.ClientId); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NLS: Failed to open process! %lx\n", Status); + NtClose(SectionHandle); + return Status; + } + + /* Duplicate the handle to the section object into it */ + Status = NtDuplicateObject(NtCurrentProcess(), + SectionHandle, + ProcessHandle, + &NlsMsg->SectionHandle, + 0, + 0, + 3); + NtClose(ProcessHandle); + return Status; } CSR_API(BaseSrvNlsUpdateCacheCount) diff --git a/reactos/subsystems/win32/csrsrv/api.c b/reactos/subsystems/win32/csrsrv/api.c index 0d7e3850317..44b92be1a43 100644 --- a/reactos/subsystems/win32/csrsrv/api.c +++ b/reactos/subsystems/win32/csrsrv/api.c @@ -76,11 +76,13 @@ CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg, ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId]))) { /* We are beyond the Maximum API ID, or it doesn't exist */ + DPRINT1("API: %d\n", ApiId); DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an " "invalid API to call from the server.\n", - ServerDll->ValidTable[ApiId], + ApiId, ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ? - ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name); + ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", + &ServerDll->Name); // DbgBreakPoint(); ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION; return STATUS_ILLEGAL_FUNCTION;