reactos/reactos/win32ss/user/consrv/alias.c
Hermès Bélusca-Maïto 599a7affa3 [REACTOS]
Merge of the ros-csrss branch created with a three-fold purpose:

- Use the new Windows-compatible Client-Server Runtime Subsystem (csrss + csrsrv)
written by Alex Ionescu to replace the old hacked one. Also the CSR client part,
residing in ntdll, is updated. Some work also done on the dlls side, which
communicate with CSR, namely kernel32.

- Replace our very old win32csr.dll CSR server by the collection basesrv.dll /
winsrv.dll as it is done under Windows.

- Since the console subsystem is (for historical purposes on Windows) the
only subsystem which exploits all the possibilities of the CSR, I decided to
put it in a new CSR dll called 'consrv.dll', even if on Windows it is included
together with other APIs inside the winsrv dll (since Windows NT 3.1 release)
(I took the name 'consrv' from the dll where it was included in Windows NT 3.1
beta from October 1991). Some work was also done on its internal architecture
(the external interface is of course unchanged for compatibility reasons) and a
two-layer approach was developed, using the existing idea of console functions +
GUI or TUI we already had in win32csr:
	* the "console server" which dialogs with the console applications,
and which maintains a list of all the created consoles.
	* different "front-ends" corresponding to where you want to output
the information (~= console hardware) (Work-In-Progress).
Another idea would be to make those front-ends dynamically-loadable (instead
of being compiled inside consrv).
- I also fixed some parts of the console properties dialog box.

More information can be found in http://www.reactos.org/archives/public/ros-dev/2013-April/016121.html

CORE-122 CORE-2510 CORE-7002 #resolve #comment Committed in revision r58xxx.

svn path=/trunk/; revision=58770
2013-04-15 19:32:00 +00:00

588 lines
17 KiB
C

/*
* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/alias.c
* PURPOSE: Alias support functions
* PROGRAMMERS: Christoph Wittich
* Johannes Anderwald
*/
/* INCLUDES *******************************************************************/
#include "consrv.h"
#include "console.h"
#include "include/conio.h"
#define NDEBUG
#include <debug.h>
/* TYPES **********************************************************************/
typedef struct _ALIAS_ENTRY
{
LPCWSTR lpSource;
LPCWSTR lpTarget;
struct _ALIAS_ENTRY* Next;
} ALIAS_ENTRY, *PALIAS_ENTRY;
typedef struct _ALIAS_HEADER
{
LPCWSTR lpExeName;
PALIAS_ENTRY Data;
struct _ALIAS_HEADER* Next;
} ALIAS_HEADER, *PALIAS_HEADER;
/* PRIVATE FUNCTIONS **********************************************************/
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((PWCHAR)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(PCONSOLE Console)
{
PALIAS_HEADER Header, NextHeader;
PALIAS_ENTRY Entry, NextEntry;
for (Header = Console->Aliases; Header; Header = NextHeader)
{
NextHeader = Header->Next;
for (Entry = Header->Data; Entry; Entry = NextEntry)
{
NextEntry = Entry->Next;
RtlFreeHeap(ConSrvHeap, 0, Entry);
}
RtlFreeHeap(ConSrvHeap, 0, Header);
}
}
/* PUBLIC SERVER APIS *********************************************************/
CSR_API(SrvAddConsoleAlias)
{
PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest;
PCONSOLE Console;
PALIAS_HEADER Header;
PALIAS_ENTRY Entry;
LPWSTR lpSource, lpTarget, lpExeName;
DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage);
if ( !CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Source,
ConsoleAliasRequest->SourceLength,
sizeof(BYTE)) ||
!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Target,
ConsoleAliasRequest->TargetLength,
sizeof(BYTE)) ||
!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Exe,
ConsoleAliasRequest->ExeLength,
sizeof(BYTE)) )
{
return STATUS_INVALID_PARAMETER;
}
lpSource = ConsoleAliasRequest->Source;
lpTarget = (ConsoleAliasRequest->TargetLength != 0 ? ConsoleAliasRequest->Target : NULL);
lpExeName = ConsoleAliasRequest->Exe;
DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource, lpExeName, lpTarget);
if (lpExeName == NULL || lpSource == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
if (!Header && lpTarget != NULL)
{
Header = IntCreateAliasHeader(lpExeName);
if (!Header)
{
ConSrvReleaseConsole(Console, TRUE);
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;
}
ConSrvReleaseConsole(Console, TRUE);
return ApiMessage->Status;
}
Entry = IntCreateAliasEntry(lpSource, lpTarget);
if (!Entry)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INSUFFICIENT_RESOURCES;
}
IntInsertAliasEntry(Header, Entry);
ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAlias)
{
PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest;
PCONSOLE Console;
PALIAS_HEADER Header;
PALIAS_ENTRY Entry;
UINT Length;
LPWSTR lpSource, lpTarget, lpExeName;
DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage);
if ( !CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Source,
ConsoleAliasRequest->SourceLength,
sizeof(BYTE)) ||
!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Target,
ConsoleAliasRequest->TargetLength,
sizeof(BYTE)) ||
!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ConsoleAliasRequest->Exe,
ConsoleAliasRequest->ExeLength,
sizeof(BYTE)) )
{
return STATUS_INVALID_PARAMETER;
}
lpSource = ConsoleAliasRequest->Source;
lpTarget = ConsoleAliasRequest->Target;
lpExeName = ConsoleAliasRequest->Exe;
DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
lpExeName, lpSource, lpTarget, ConsoleAliasRequest->TargetLength);
if (ConsoleAliasRequest->ExeLength == 0 || lpTarget == NULL ||
ConsoleAliasRequest->TargetLength == 0 || ConsoleAliasRequest->SourceLength == 0)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
if (!Header)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
Entry = IntGetAliasEntry(Header, lpSource);
if (!Entry)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
Length = (wcslen(Entry->lpTarget) + 1) * sizeof(WCHAR);
if (Length > ConsoleAliasRequest->TargetLength)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_BUFFER_TOO_SMALL;
}
wcscpy(lpTarget, Entry->lpTarget);
ConsoleAliasRequest->TargetLength = Length;
ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliases)
{
PCONSOLE_GETALLALIASES GetAllAliasesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesRequest;
PCONSOLE Console;
ULONG BytesWritten;
PALIAS_HEADER Header;
if ( !CsrValidateMessageBuffer(ApiMessage,
(PVOID)&GetAllAliasesRequest->ExeName,
GetAllAliasesRequest->ExeLength,
sizeof(BYTE)) ||
!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&GetAllAliasesRequest->AliasesBuffer,
GetAllAliasesRequest->AliasesBufferLength,
sizeof(BYTE)) )
{
return STATUS_INVALID_PARAMETER;
}
if (GetAllAliasesRequest->ExeName == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesRequest->ExeName);
if (!Header)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
if (IntGetAllConsoleAliasesLength(Header) > GetAllAliasesRequest->AliasesBufferLength)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_BUFFER_OVERFLOW;
}
BytesWritten = IntGetAllConsoleAliases(Header,
GetAllAliasesRequest->AliasesBuffer,
GetAllAliasesRequest->AliasesBufferLength);
GetAllAliasesRequest->AliasesBufferLength = BytesWritten;
ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasesLength)
{
PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesLengthRequest;
PCONSOLE Console;
PALIAS_HEADER Header;
UINT Length;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&GetAllAliasesLengthRequest->ExeName,
GetAllAliasesLengthRequest->ExeLength,
sizeof(BYTE)))
{
return STATUS_INVALID_PARAMETER;
}
if (GetAllAliasesLengthRequest->ExeName == NULL)
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesLengthRequest->ExeName);
if (!Header)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
Length = IntGetAllConsoleAliasesLength(Header);
GetAllAliasesLengthRequest->Length = Length;
ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasExes)
{
PCONSOLE_GETALIASESEXES GetAliasesExesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesRequest;
PCONSOLE Console;
UINT BytesWritten;
UINT ExesLength;
DPRINT("SrvGetConsoleAliasExes entered\n");
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&GetAliasesExesRequest->ExeNames,
GetAliasesExesRequest->Length,
sizeof(BYTE)))
{
return STATUS_INVALID_PARAMETER;
}
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(ApiMessage->Status))
{
return ApiMessage->Status;
}
ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases);
if (ExesLength > GetAliasesExesRequest->Length)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_BUFFER_OVERFLOW;
}
if (GetAliasesExesRequest->ExeNames == NULL)
{
ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
BytesWritten = IntGetConsoleAliasesExes(Console->Aliases,
GetAliasesExesRequest->ExeNames,
GetAliasesExesRequest->Length);
GetAliasesExesRequest->Length = BytesWritten;
ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvGetConsoleAliasExesLength)
{
PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesLengthRequest;
PCONSOLE Console;
DPRINT("SrvGetConsoleAliasExesLength entered\n");
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (NT_SUCCESS(ApiMessage->Status))
{
GetAliasesExesLengthRequest->Length = IntGetConsoleAliasesExesLength(Console->Aliases);
ConSrvReleaseConsole(Console, TRUE);
}
return ApiMessage->Status;
}
/* EOF */