reactos/subsystems/win/basesrv/init.c

657 lines
24 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Base API Server DLL
* FILE: subsystems/win/basesrv/init.c
* PURPOSE: Initialization
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#include "basesrv.h"
#include "vdm.h"
#include <winreg.h>
#define NDEBUG
#include <debug.h>
#include "api.h"
/* GLOBALS ********************************************************************/
HANDLE BaseSrvDllInstance = NULL;
extern UNICODE_STRING BaseSrvKernel32DllPath;
/* Memory */
HANDLE BaseSrvHeap = NULL; // Our own heap.
HANDLE BaseSrvSharedHeap = NULL; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
PBASE_STATIC_SERVER_DATA BaseStaticServerData = NULL; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
PINIFILE_MAPPING BaseSrvIniFileMapping;
// Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
PCSR_API_ROUTINE BaseServerApiDispatchTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
BaseSrvCreateProcess,
BaseSrvCreateThread,
BaseSrvGetTempFile,
BaseSrvExitProcess,
BaseSrvDebugProcess,
BaseSrvCheckVDM,
BaseSrvUpdateVDMEntry,
BaseSrvGetNextVDMCommand,
BaseSrvExitVDM,
BaseSrvIsFirstVDM,
BaseSrvGetVDMExitCode,
BaseSrvSetReenterCount,
BaseSrvSetProcessShutdownParam,
BaseSrvGetProcessShutdownParam,
BaseSrvNlsSetUserInfo,
BaseSrvNlsSetMultipleUserInfo,
BaseSrvNlsCreateSection,
BaseSrvSetVDMCurDirs,
BaseSrvGetVDMCurDirs,
BaseSrvBatNotification,
BaseSrvRegisterWowExec,
BaseSrvSoundSentryNotification,
BaseSrvRefreshIniFileMapping,
BaseSrvDefineDosDevice,
BaseSrvSetTermsrvAppInstallMode,
BaseSrvNlsUpdateCacheCount,
BaseSrvSetTermsrvClientTimeZone,
BaseSrvSxsCreateActivationContext,
BaseSrvDebugProcess,
BaseSrvRegisterThread,
BaseSrvNlsGetUserInfo,
};
BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
TRUE, // BaseSrvCreateProcess
TRUE, // BaseSrvCreateThread
TRUE, // BaseSrvGetTempFile
FALSE, // BaseSrvExitProcess
FALSE, // BaseSrvDebugProcess
TRUE, // BaseSrvCheckVDM
TRUE, // BaseSrvUpdateVDMEntry
TRUE, // BaseSrvGetNextVDMCommand
TRUE, // BaseSrvExitVDM
TRUE, // BaseSrvIsFirstVDM
TRUE, // BaseSrvGetVDMExitCode
TRUE, // BaseSrvSetReenterCount
TRUE, // BaseSrvSetProcessShutdownParam
TRUE, // BaseSrvGetProcessShutdownParam
TRUE, // BaseSrvNlsSetUserInfo
TRUE, // BaseSrvNlsSetMultipleUserInfo
TRUE, // BaseSrvNlsCreateSection
TRUE, // BaseSrvSetVDMCurDirs
TRUE, // BaseSrvGetVDMCurDirs
TRUE, // BaseSrvBatNotification
TRUE, // BaseSrvRegisterWowExec
TRUE, // BaseSrvSoundSentryNotification
TRUE, // BaseSrvRefreshIniFileMapping
TRUE, // BaseSrvDefineDosDevice
TRUE, // BaseSrvSetTermsrvAppInstallMode
TRUE, // BaseSrvNlsUpdateCacheCount
TRUE, // BaseSrvSetTermsrvClientTimeZone
TRUE, // BaseSrvSxsCreateActivationContext
FALSE, // BaseSrvDebugProcess
TRUE, // BaseSrvRegisterThread
TRUE, // BaseSrvNlsGetUserInfo
};
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
/*
* On Windows Server 2003, CSR Servers contain
* the API Names Table only in Debug Builds.
*/
#ifdef CSR_DBG
PCHAR BaseServerApiNameTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
"BaseCreateProcess",
"BaseCreateThread",
"BaseGetTempFile",
"BaseExitProcess",
"BaseDebugProcess",
"BaseCheckVDM",
"BaseUpdateVDMEntry",
"BaseGetNextVDMCommand",
"BaseExitVDM",
"BaseIsFirstVDM",
"BaseGetVDMExitCode",
"BaseSetReenterCount",
"BaseSetProcessShutdownParam",
"BaseGetProcessShutdownParam",
"BaseNlsSetUserInfo",
"BaseNlsSetMultipleUserInfo",
"BaseNlsCreateSection",
"BaseSetVDMCurDirs",
"BaseGetVDMCurDirs",
"BaseBatNotification",
"BaseRegisterWowExec",
"BaseSoundSentryNotification",
"BaseRefreshIniFileMapping",
"BaseDefineDosDevice",
"BaseSetTermsrvAppInstallMode",
"BaseNlsUpdateCacheCount",
"BaseSetTermsrvClientTimeZone",
"BaseSxsCreateActivationContext",
"BaseSrvDebugProcessStop",
"BaseRegisterThread",
"BaseNlsGetUserInfo",
};
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#endif
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
BaseSrvInitializeIniFileMappings(IN PBASE_STATIC_SERVER_DATA StaticServerData)
{
/* Allocate the mapping blob */
This commit, in my opinion, marks an important milestone in ReactOS development. One is now able to boot to desktop, launch applications, download through the application manager, play solitaire, minesweeper, launch Task Manager, etc... by using an unmodified Windows 2003 kernel32.dll binary (and, until our NPFS driver is fixed, the unmodified Windows 2003 NPFS driver). Additionally, one is able to achieve the same by booting with an unmodified Windows 2003 ntdll.dll, including a combination of both. The capability to mix-and-match components such as kernel32 and ntdll, at the heart of the system, will allow to better understand apitest failures (just as Wine has long had the capability to use Windows DLLs instead). With these two building blocks, additional Windows 2003 DLLs can be dropped in/tested, etc, and where failures are seen, a likely component can now be blamed. Furthermore, debugging with public symbols for these DLLs is now possible with WinDBG (in fact, this is how many bugs were fixed in this attempt). Many issues already exist when running with this combination FYI, for example, I was not able to launch any installers (tested Firefox and MIRC). This already demonstrates either missing functionality or ReactOS-specific functionality in components which depend on kernel32. I suspect the next step is infrastructure work to get special patchbot/builders to try and report back winetest results, and for additional DLLs to be "ported"/made to work. On a final note, this mixing and matching has benefits on both ends -- it's now likely that ReactOS' ntdll can run on Server 2003, at least far enough to get to Explorer or Task Manager. Running apitests on Server 2003 with and without reactos DLLs should also easily identify if certain DLLs are directly to blame for certain regressions/failures. </end excited rant> [BASESRV]: Allocate the INI mappings from the right heap. svn path=/trunk/; revision=59985
2013-09-04 07:28:15 +00:00
BaseSrvIniFileMapping = RtlAllocateHeap(BaseSrvSharedHeap,
HEAP_ZERO_MEMORY,
sizeof(*BaseSrvIniFileMapping));
if (BaseSrvIniFileMapping == NULL)
{
DPRINT1("BASESRV: Unable to allocate memory in shared heap for IniFileMapping\n");
return STATUS_NO_MEMORY;
}
/* Set it*/
StaticServerData->IniFileMapping = BaseSrvIniFileMapping;
/* FIXME: Do the work to initialize the mappings */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CreateBaseAcls(OUT PACL* Dacl,
OUT PACL* RestrictedDacl)
{
PSID SystemSid, WorldSid, RestrictedSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
NTSTATUS Status;
#if 0 // Unused code
UCHAR KeyValueBuffer[0x40];
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
UNICODE_STRING KeyName;
ULONG ProtectionMode = 0;
#endif
ULONG AclLength;
#if 0 // Unused code
ULONG ResultLength;
HANDLE hKey;
OBJECT_ATTRIBUTES ObjectAttributes;
/* Open the Session Manager Key */
RtlInitUnicodeString(&KeyName, SM_REG_KEY);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* Read the key value */
RtlInitUnicodeString(&KeyName, L"ProtectionMode");
Status = NtQueryValueKey(hKey,
&KeyName,
KeyValuePartialInformation,
KeyValueBuffer,
sizeof(KeyValueBuffer),
&ResultLength);
/* Make sure it's what we expect it to be */
KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
(*(PULONG)KeyValuePartialInfo->Data))
{
/* Save the Protection Mode */
ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
}
/* Close the handle */
NtClose(hKey);
}
#endif
/* Allocate the System SID */
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0,
&SystemSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate the World SID */
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&WorldSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate the restricted SID */
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1, SECURITY_RESTRICTED_CODE_RID,
0, 0, 0, 0, 0, 0, 0,
&RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate one ACL with 3 ACEs each for one SID */
AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
RtlLengthSid(SystemSid) +
RtlLengthSid(WorldSid) +
RtlLengthSid(RestrictedSid);
*Dacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
ASSERT(*Dacl != NULL);
/* Set the correct header fields */
Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
ASSERT(NT_SUCCESS(Status));
/* Give the appropriate rights to each SID */
/* FIXME: Should check SessionId/ProtectionMode */
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* Now allocate the restricted DACL */
*RestrictedDacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
ASSERT(*RestrictedDacl != NULL);
/* Initialize it */
Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
ASSERT(NT_SUCCESS(Status));
/* And add the same ACEs as before */
/* FIXME: Not really fully correct */
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* The SIDs are captured, can free them now */
RtlFreeSid(RestrictedSid);
RtlFreeSid(WorldSid);
RtlFreeSid(SystemSid);
return Status;
}
VOID
NTAPI
BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll)
{
NTSTATUS Status;
BOOLEAN Success;
WCHAR Buffer[MAX_PATH];
PWCHAR HeapBuffer;
UNICODE_STRING SystemRootString;
UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
UNICODE_STRING BaseSrvCSDString;
UNICODE_STRING BaseSrvWindowsDirectory;
UNICODE_STRING BaseSrvWindowsSystemDirectory;
UNICODE_STRING BnoString;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG SessionId;
HANDLE BaseSrvNamedObjectDirectory;
HANDLE BaseSrvRestrictedObjectDirectory;
PACL BnoDacl, BnoRestrictedDacl;
PSECURITY_DESCRIPTOR BnoSd;
HANDLE SymHandle;
UNICODE_STRING DirectoryName, SymlinkName;
ULONG LuidEnabled;
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
{
{
NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"CSDVersion",
&BaseSrvCSDString,
REG_NONE, NULL, 0
},
{0}
};
/* Initialize the memory */
BaseSrvHeap = RtlGetProcessHeap(); // Initialize our own heap.
BaseSrvSharedHeap = LoadedServerDll->SharedSection; // Get the CSR shared heap.
/* Get the session ID */
SessionId = NtCurrentPeb()->SessionId;
/* Get the Windows directory */
RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
Status = RtlExpandEnvironmentStrings_U(NULL,
&UnexpandedSystemRootString,
&SystemRootString,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Create the base directory */
Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
Success = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
SystemRootString.Buffer);
ASSERT(Success);
/* Create the system directory */
wcscat(SystemRootString.Buffer, L"\\System32");
Success = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
SystemRootString.Buffer);
ASSERT(Success);
/* Create the kernel32 path */
wcscat(SystemRootString.Buffer, L"\\kernel32.dll");
Success = RtlCreateUnicodeString(&BaseSrvKernel32DllPath,
SystemRootString.Buffer);
ASSERT(Success);
/* FIXME: Check Session ID */
wcscpy(Buffer, L"\\BaseNamedObjects");
RtlInitUnicodeString(&BnoString, Buffer);
/* Allocate the server data */
BaseStaticServerData = RtlAllocateHeap(BaseSrvSharedHeap,
HEAP_ZERO_MEMORY,
sizeof(BASE_STATIC_SERVER_DATA));
ASSERT(BaseStaticServerData != NULL);
/* Process timezone information */
BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
&BaseStaticServerData->TimeOfDay,
sizeof(BaseStaticServerData->TimeOfDay),
NULL);
ASSERT(NT_SUCCESS(Status));
/* Make a shared heap copy of the Windows directory */
BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseSrvWindowsDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->WindowsDirectory.Buffer,
BaseSrvWindowsDirectory.MaximumLength);
BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
/* Make a shared heap copy of the System directory */
BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseSrvWindowsSystemDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->WindowsSystemDirectory.Buffer,
BaseSrvWindowsSystemDirectory.MaximumLength);
BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
/* This string is not used */
RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
NULL,
0);
/* Make a shared heap copy of the BNO directory */
BaseStaticServerData->NamedObjectDirectory = BnoString;
BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
sizeof(UNICODE_NULL);
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseStaticServerData->NamedObjectDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->NamedObjectDirectory.Buffer,
BaseStaticServerData->NamedObjectDirectory.MaximumLength);
BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
/*
* Confirmed that in Windows, CSDNumber and RCNumber are actually Length
* and MaximumLength of the CSD String, since the same UNICODE_STRING is
* being queried twice, the first time as a ULONG!
*
* Somehow, in Windows this doesn't cause a buffer overflow, but it might
* in ReactOS, so this code is disabled until someone figures out WTF.
*/
BaseStaticServerData->CSDNumber = 0;
BaseStaticServerData->RCNumber = 0;
/* Initialize the CSD string and query its value from the registry */
RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
L"",
BaseServerRegistryConfigurationTable,
NULL,
NULL);
if (NT_SUCCESS(Status))
{
/* Copy into the shared buffer */
wcsncpy(BaseStaticServerData->CSDVersion,
BaseSrvCSDString.Buffer,
BaseSrvCSDString.Length / sizeof(WCHAR));
}
else
{
/* Indicate nothing is there */
BaseSrvCSDString.Length = 0;
}
/* NULL-terminate */
BaseStaticServerData->CSDVersion[BaseSrvCSDString.Length / sizeof(WCHAR)] = UNICODE_NULL;
/* Cache the system information */
Status = NtQuerySystemInformation(SystemBasicInformation,
&BaseStaticServerData->SysInfo,
sizeof(BaseStaticServerData->SysInfo),
NULL);
ASSERT(NT_SUCCESS(Status));
/* Setup the ini file mappings */
Status = BaseSrvInitializeIniFileMappings(BaseStaticServerData);
ASSERT(NT_SUCCESS(Status));
/* FIXME: Should query the registry for these */
BaseStaticServerData->DefaultSeparateVDM = FALSE;
BaseStaticServerData->IsWowTaskReady = FALSE;
/* Allocate a security descriptor and create it */
BnoSd = RtlAllocateHeap(BaseSrvHeap, 0, 1024);
ASSERT(BnoSd);
Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
ASSERT(NT_SUCCESS(Status));
/* Create the BNO and \Restricted DACLs */
Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
ASSERT(NT_SUCCESS(Status));
/* Set the BNO DACL as active for now */
Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
ASSERT(NT_SUCCESS(Status));
/* Create the BNO directory */
RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
InitializeObjectAttributes(&ObjectAttributes,
&BnoString,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
NULL,
BnoSd);
Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
ASSERT(NT_SUCCESS(Status));
/* Check if we are session 0 */
if (SessionId == 0)
{
/* Mark this as a session 0 directory */
Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
ObjectSessionInformation,
NULL,
0);
ASSERT(NT_SUCCESS(Status));
}
/* Check if LUID device maps are enabled */
Status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessLUIDDeviceMapsEnabled,
&LuidEnabled,
sizeof(LuidEnabled),
NULL);
ASSERT(NT_SUCCESS(Status));
BaseStaticServerData->LUIDDeviceMapsEnabled = (BOOLEAN)LuidEnabled;
if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
{
/* Make Global point back to BNO */
RtlInitUnicodeString(&DirectoryName, L"Global");
RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Make local point back to \Sessions\x\BNO */
RtlInitUnicodeString(&DirectoryName, L"Local");
ASSERT(SessionId == 0);
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Make Session point back to BNOLINKS */
RtlInitUnicodeString(&DirectoryName, L"Session");
RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Create the BNO\Restricted directory and set the restricted DACL */
RtlInitUnicodeString(&DirectoryName, L"Restricted");
Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
ASSERT(NT_SUCCESS(Status));
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
ASSERT(NT_SUCCESS(Status));
}
/* Initialize NLS */
BaseSrvNLSInit(BaseStaticServerData);
/* Finally, set the pointer */
LoadedServerDll->SharedSection = BaseStaticServerData;
}
NTSTATUS
NTAPI
BaseClientConnectRoutine(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength)
{
PBASESRV_API_CONNECTINFO ConnectInfo = (PBASESRV_API_CONNECTINFO)ConnectionInfo;
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
*ConnectionInfoLength != sizeof(*ConnectInfo) )
{
DPRINT1("BASESRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), expected %lu\n",
ConnectionInfo,
ConnectionInfoLength,
ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1,
sizeof(*ConnectInfo));
return STATUS_INVALID_PARAMETER;
}
/* Do the NLS connection */
return BaseSrvNlsConnect(CsrProcess, ConnectionInfo, ConnectionInfoLength);
}
VOID
NTAPI
BaseClientDisconnectRoutine(IN PCSR_PROCESS CsrProcess)
{
/* Cleanup VDM resources */
BaseSrvCleanupVDMResources(CsrProcess);
}
CSR_SERVER_DLL_INIT(ServerDllInitialization)
{
/* Setup the DLL Object */
LoadedServerDll->ApiBase = BASESRV_FIRST_API_NUMBER;
LoadedServerDll->HighestApiSupported = BasepMaxApiNumber;
LoadedServerDll->DispatchTable = BaseServerApiDispatchTable;
LoadedServerDll->ValidTable = BaseServerApiServerValidTable;
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#ifdef CSR_DBG
LoadedServerDll->NameTable = BaseServerApiNameTable;
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#endif
LoadedServerDll->SizeOfProcessData = 0;
LoadedServerDll->ConnectCallback = BaseClientConnectRoutine;
LoadedServerDll->DisconnectCallback = BaseClientDisconnectRoutine;
LoadedServerDll->ShutdownProcessCallback = NULL;
BaseSrvDllInstance = LoadedServerDll->ServerHandle;
BaseInitializeStaticServerData(LoadedServerDll);
/* Initialize DOS devices management */
BaseInitDefineDosDevice();
/* Initialize VDM support */
BaseInitializeVDM();
/* All done */
return STATUS_SUCCESS;
}
BOOL
NTAPI
DllMain(IN HINSTANCE hInstanceDll,
IN DWORD dwReason,
IN LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hInstanceDll);
UNREFERENCED_PARAMETER(dwReason);
UNREFERENCED_PARAMETER(lpReserved);
if (DLL_PROCESS_DETACH == dwReason)
{
BaseCleanupDefineDosDevice();
}
return TRUE;
}
/* EOF */