reactos/win32ss/user/consrv/alias.c
Hermès Bélusca-Maïto 608c1e0428 [CONSRV/WIN32CSR]
- Move all the console subsystem from win32csr to a new server dll called consrv.dll (instead of putting it directly to winsrv.dll). It's because I want to rework on this later on.
Many things must be done in order to achieve the moving (renaming functions, etc...). Tables & symbol names come from http://j00ru.vexillium.org/csrss_list/api_list.html as usual,
but here I took the Win 2k3 ones and I added few Win 7 functions which already existed in our codebase. The other table names are guessed based on what originally existed in csrsrv
and so on. Many stubs are also missing.
Cultural remark: consrv.dll originally existed in Beta releases of Windows NT 3.1 (e.g. the October 1991 one), but was soon merged with winsrv.dll and thus, in subsequent versions of
Windows, the console subsystem is also found in winsrv.dll. See http://www.logotypes.se/NT310CSRSS.txt and http://j00ru.vexillium.org/?p=349#comment-1883. One has to wait until
Windows 7 to see it moving again to conhost.exe.

[CSRSRV]
- Add an explanation comment on what the ValidTable member in the CSR_SERVER_DLL structure is for.

svn path=/branches/ros-csrss/; revision=57597
2012-10-22 23:55:51 +00:00

553 lines
15 KiB
C

/* $Id: init.c 31400 2007-12-22 17:18:32Z fireball $
* PROJECT: ReactOS CSRSS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: subsystems/win32/csrss/api/alias.c
* PURPOSE: CSRSS alias support functions
* COPYRIGHT: Christoph Wittich
* Johannes Anderwald
*
*/
/* INCLUDES ******************************************************************/
#define NDEBUG
#include "w32csr.h"
#include <debug.h>
typedef struct tagALIAS_ENTRY
{
LPCWSTR lpSource;
LPCWSTR lpTarget;
struct tagALIAS_ENTRY * Next;
} ALIAS_ENTRY, *PALIAS_ENTRY;
typedef struct tagALIAS_HEADER
{
LPCWSTR lpExeName;
PALIAS_ENTRY Data;
struct tagALIAS_HEADER * Next;
} ALIAS_HEADER, *PALIAS_HEADER;
static
PALIAS_HEADER
IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName)
{
while(RootHeader)
{
INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName);
if (!diff)
return RootHeader;
if (diff > 0)
break;
RootHeader = RootHeader->Next;
}
return NULL;
}
PALIAS_HEADER
IntCreateAliasHeader(LPCWSTR lpExeName)
{
PALIAS_HEADER Entry;
UINT dwLength = wcslen(lpExeName) + 1;
Entry = RtlAllocateHeap(ConSrvHeap, 0, sizeof(ALIAS_HEADER) + sizeof(WCHAR) * dwLength);
if (!Entry)
return Entry;
Entry->lpExeName = (LPCWSTR)(Entry + 1);
wcscpy((WCHAR*)Entry->lpExeName, lpExeName);
Entry->Data = NULL;
Entry->Next = NULL;
return Entry;
}
VOID
IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader)
{
PALIAS_HEADER CurrentHeader;
PALIAS_HEADER *LastLink = RootHeader;
while ((CurrentHeader = *LastLink) != NULL)
{
INT Diff = _wcsicmp(NewHeader->lpExeName, CurrentHeader->lpExeName);
if (Diff < 0)
{
break;
}
LastLink = &CurrentHeader->Next;
}
*LastLink = NewHeader;
NewHeader->Next = CurrentHeader;
}
PALIAS_ENTRY
IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName)
{
PALIAS_ENTRY RootHeader;
if (Header == NULL)
return NULL;
RootHeader = Header->Data;
while(RootHeader)
{
INT diff;
DPRINT("IntGetAliasEntry>lpSource %S\n", RootHeader->lpSource);
diff = _wcsicmp(RootHeader->lpSource, lpSrcName);
if (!diff)
return RootHeader;
if (diff > 0)
break;
RootHeader = RootHeader->Next;
}
return NULL;
}
VOID
IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry)
{
PALIAS_ENTRY CurrentEntry;
PALIAS_ENTRY *LastLink = &Header->Data;
while ((CurrentEntry = *LastLink) != NULL)
{
INT Diff = _wcsicmp(NewEntry->lpSource, CurrentEntry->lpSource);
if (Diff < 0)
{
break;
}
LastLink = &CurrentEntry->Next;
}
*LastLink = NewEntry;
NewEntry->Next = CurrentEntry;
}
PALIAS_ENTRY
IntCreateAliasEntry(LPCWSTR lpSource, LPCWSTR lpTarget)
{
UINT dwSource;
UINT dwTarget;
PALIAS_ENTRY Entry;
dwSource = wcslen(lpSource) + 1;
dwTarget = wcslen(lpTarget) + 1;
Entry = RtlAllocateHeap(ConSrvHeap, 0, sizeof(ALIAS_ENTRY) + sizeof(WCHAR) * (dwSource + dwTarget));
if (!Entry)
return Entry;
Entry->lpSource = (LPCWSTR)(Entry + 1);
wcscpy((LPWSTR)Entry->lpSource, lpSource);
Entry->lpTarget = Entry->lpSource + dwSource;
wcscpy((LPWSTR)Entry->lpTarget, lpTarget);
Entry->Next = NULL;
return Entry;
}
UINT
IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader)
{
UINT length = 0;
while(RootHeader)
{
length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR);
RootHeader = RootHeader->Next;
}
if (length)
length += sizeof(WCHAR); // last entry entry is terminated with 2 zero bytes
return length;
}
UINT
IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT TargetBufferSize)
{
UINT Offset = 0;
UINT Length;
TargetBufferSize /= sizeof(WCHAR);
while(RootHeader)
{
Length = wcslen(RootHeader->lpExeName) + 1;
if (TargetBufferSize > Offset + Length)
{
wcscpy(&TargetBuffer[Offset], RootHeader->lpExeName);
Offset += Length;
}
else
{
break;
}
RootHeader = RootHeader->Next;
}
Length = min(Offset+1, TargetBufferSize);
TargetBuffer[Length] = L'\0';
return Length * sizeof(WCHAR);
}
UINT
IntGetAllConsoleAliasesLength(PALIAS_HEADER Header)
{
UINT Length = 0;
PALIAS_ENTRY CurEntry = Header->Data;
while(CurEntry)
{
Length += wcslen(CurEntry->lpSource);
Length += wcslen(CurEntry->lpTarget);
Length += 2; // zero byte and '='
CurEntry = CurEntry->Next;
}
if (Length)
{
return (Length+1) * sizeof(WCHAR);
}
return 0;
}
UINT
IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBufferLength)
{
PALIAS_ENTRY CurEntry = Header->Data;
UINT Offset = 0;
UINT SrcLength, TargetLength;
TargetBufferLength /= sizeof(WCHAR);
while(CurEntry)
{
SrcLength = wcslen(CurEntry->lpSource) + 1;
TargetLength = wcslen(CurEntry->lpTarget) + 1;
if (Offset + TargetLength + SrcLength >= TargetBufferLength)
break;
wcscpy(&TargetBuffer[Offset], CurEntry->lpSource);
Offset += SrcLength;
TargetBuffer[Offset] = L'=';
wcscpy(&TargetBuffer[Offset], CurEntry->lpTarget);
Offset += TargetLength;
CurEntry = CurEntry->Next;
}
TargetBuffer[Offset] = L'\0';
return Offset * sizeof(WCHAR);
}
VOID
IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry)
{
PALIAS_ENTRY *LastLink = &Header->Data;
PALIAS_ENTRY CurEntry;
while ((CurEntry = *LastLink) != NULL)
{
if (CurEntry == Entry)
{
*LastLink = Entry->Next;
RtlFreeHeap(ConSrvHeap, 0, Entry);
return;
}
LastLink = &CurEntry->Next;
}
}
VOID
IntDeleteAllAliases(PALIAS_HEADER RootHeader)
{
PALIAS_HEADER Header, NextHeader;
PALIAS_ENTRY Entry, NextEntry;
for (Header = RootHeader; Header; Header = NextHeader)
{
NextHeader = Header->Next;
for (Entry = Header->Data; Entry; Entry = NextEntry)
{
NextEntry = Entry->Next;
RtlFreeHeap(ConSrvHeap, 0, Entry);
}
RtlFreeHeap(ConSrvHeap, 0, Header);
}
}
CSR_API(SrvAddConsoleAlias)
{
PCSRSS_CONSOLE Console;
PALIAS_HEADER Header;
PALIAS_ENTRY Entry;
WCHAR * lpExeName;
WCHAR * lpSource;
WCHAR * lpTarget;
//ULONG TotalLength;
//WCHAR * Ptr;
//TotalLength = ApiMessage->Data.AddConsoleAlias.SourceLength + ApiMessage->Data.AddConsoleAlias.ExeLength + ApiMessage->Data.AddConsoleAlias.TargetLength;
//Ptr = (WCHAR*)((ULONG_PTR)ApiMessage + sizeof(CSR_API_MESSAGE));
lpSource = (WCHAR*)((ULONG_PTR)ApiMessage + sizeof(CSR_API_MESSAGE));
lpExeName = (WCHAR*)((ULONG_PTR)ApiMessage + sizeof(CSR_API_MESSAGE) + ApiMessage->Data.AddConsoleAlias.SourceLength * sizeof(WCHAR));
lpTarget = (ApiMessage->Data.AddConsoleAlias.TargetLength != 0 ? lpExeName + ApiMessage->Data.AddConsoleAlias.ExeLength : NULL);
DPRINT("SrvAddConsoleAlias entered ApiMessage %p lpSource %p lpExeName %p lpTarget %p\n", ApiMessage, lpSource, lpExeName, lpTarget);
if (lpExeName == NULL || lpSource == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
if (!Header && lpTarget != NULL)
{
Header = IntCreateAliasHeader(lpExeName);
if (!Header)
{
ConioUnlockConsole(Console);
return STATUS_INSUFFICIENT_RESOURCES;
}
IntInsertAliasHeader(&Console->Aliases, Header);
}
if (lpTarget == NULL) // delete the entry
{
Entry = IntGetAliasEntry(Header, lpSource);
if (Entry)
{
IntDeleteAliasEntry(Header, Entry);
ApiMessage->Status = STATUS_SUCCESS;
}
else
{
ApiMessage->Status = STATUS_INVALID_PARAMETER;
}
ConioUnlockConsole(Console);
return ApiMessage->Status;
}
Entry = IntCreateAliasEntry(lpSource, lpTarget);
if (!Entry)
{
ConioUnlockConsole(Console);
return STATUS_INSUFFICIENT_RESOURCES;
}
IntInsertAliasEntry(Header, Entry);
ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAlias)
{
PCSRSS_CONSOLE Console;
PALIAS_HEADER Header;
PALIAS_ENTRY Entry;
UINT Length;
WCHAR * lpExeName;
WCHAR * lpSource;
WCHAR * lpTarget;
lpSource = (LPWSTR)((ULONG_PTR)ApiMessage + sizeof(CSR_API_MESSAGE));
lpExeName = lpSource + ApiMessage->Data.GetConsoleAlias.SourceLength;
lpTarget = ApiMessage->Data.GetConsoleAlias.TargetBuffer;
DPRINT("SrvGetConsoleAlias entered lpExeName %p lpSource %p TargetBuffer %p TargetBufferLength %u\n",
lpExeName, lpSource, lpTarget, ApiMessage->Data.GetConsoleAlias.TargetBufferLength);
if (ApiMessage->Data.GetConsoleAlias.ExeLength == 0 || lpTarget == NULL ||
ApiMessage->Data.GetConsoleAlias.TargetBufferLength == 0 || ApiMessage->Data.GetConsoleAlias.SourceLength == 0)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
if (!Header)
{
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
Entry = IntGetAliasEntry(Header, lpSource);
if (!Entry)
{
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
Length = (wcslen(Entry->lpTarget)+1) * sizeof(WCHAR);
if (Length > ApiMessage->Data.GetConsoleAlias.TargetBufferLength)
{
ConioUnlockConsole(Console);
return STATUS_BUFFER_TOO_SMALL;
}
if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process, lpTarget,
ApiMessage->Data.GetConsoleAlias.TargetBufferLength, 1))
{
ConioUnlockConsole(Console);
return STATUS_ACCESS_VIOLATION;
}
wcscpy(lpTarget, Entry->lpTarget);
ApiMessage->Data.GetConsoleAlias.BytesWritten = Length;
ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliases)
{
PCSRSS_CONSOLE Console;
ULONG BytesWritten;
PALIAS_HEADER Header;
if (ApiMessage->Data.GetAllConsoleAlias.lpExeName == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, ApiMessage->Data.GetAllConsoleAlias.lpExeName);
if (!Header)
{
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
if (IntGetAllConsoleAliasesLength(Header) > ApiMessage->Data.GetAllConsoleAlias.AliasBufferLength)
{
ConioUnlockConsole(Console);
return STATUS_BUFFER_OVERFLOW;
}
if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
ApiMessage->Data.GetAllConsoleAlias.AliasBuffer,
ApiMessage->Data.GetAllConsoleAlias.AliasBufferLength,
1))
{
ConioUnlockConsole(Console);
return STATUS_ACCESS_VIOLATION;
}
BytesWritten = IntGetAllConsoleAliases(Header,
ApiMessage->Data.GetAllConsoleAlias.AliasBuffer,
ApiMessage->Data.GetAllConsoleAlias.AliasBufferLength);
ApiMessage->Data.GetAllConsoleAlias.BytesWritten = BytesWritten;
ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasesLength)
{
PCSRSS_CONSOLE Console;
PALIAS_HEADER Header;
UINT Length;
if (ApiMessage->Data.GetAllConsoleAliasesLength.lpExeName == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, ApiMessage->Data.GetAllConsoleAliasesLength.lpExeName);
if (!Header)
{
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
Length = IntGetAllConsoleAliasesLength(Header);
ApiMessage->Data.GetAllConsoleAliasesLength.Length = Length;
ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasExes)
{
PCSRSS_CONSOLE Console;
UINT BytesWritten;
UINT ExesLength;
DPRINT("SrvGetConsoleAliasExes entered\n");
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases);
if (ExesLength > ApiMessage->Data.GetConsoleAliasesExes.Length)
{
ConioUnlockConsole(Console);
return STATUS_BUFFER_OVERFLOW;
}
if (ApiMessage->Data.GetConsoleAliasesExes.ExeNames == NULL)
{
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
ApiMessage->Data.GetConsoleAliasesExes.ExeNames,
ApiMessage->Data.GetConsoleAliasesExes.Length,
1))
{
ConioUnlockConsole(Console);
return STATUS_ACCESS_VIOLATION;
}
BytesWritten = IntGetConsoleAliasesExes(Console->Aliases,
ApiMessage->Data.GetConsoleAliasesExes.ExeNames,
ApiMessage->Data.GetConsoleAliasesExes.Length);
ApiMessage->Data.GetConsoleAliasesExes.BytesWritten = BytesWritten;
ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasExesLength)
{
PCSRSS_CONSOLE Console;
DPRINT("SrvGetConsoleAliasExesLength entered\n");
ApiMessage->Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
if (NT_SUCCESS(ApiMessage->Status))
{
ApiMessage->Data.GetConsoleAliasesExesLength.Length = IntGetConsoleAliasesExesLength(Console->Aliases);
ConioUnlockConsole(Console);
}
return ApiMessage->Status;
}