2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/alias.c
5 * PURPOSE: Alias support functions
6 * PROGRAMMERS: Christoph Wittich
10 /* INCLUDES *******************************************************************/
19 /* TYPES **********************************************************************/
21 typedef struct tagALIAS_ENTRY
25 struct tagALIAS_ENTRY
* Next
;
26 } ALIAS_ENTRY
, *PALIAS_ENTRY
;
28 typedef struct tagALIAS_HEADER
32 struct tagALIAS_HEADER
* Next
;
33 } ALIAS_HEADER
, *PALIAS_HEADER
;
36 /* PRIVATE FUNCTIONS **********************************************************/
40 IntFindAliasHeader(PALIAS_HEADER RootHeader
, LPCWSTR lpExeName
)
44 INT diff
= _wcsicmp(RootHeader
->lpExeName
, lpExeName
);
51 RootHeader
= RootHeader
->Next
;
57 IntCreateAliasHeader(LPCWSTR lpExeName
)
60 UINT dwLength
= wcslen(lpExeName
) + 1;
62 Entry
= RtlAllocateHeap(ConSrvHeap
, 0, sizeof(ALIAS_HEADER
) + sizeof(WCHAR
) * dwLength
);
66 Entry
->lpExeName
= (LPCWSTR
)(Entry
+ 1);
67 wcscpy((WCHAR
*)Entry
->lpExeName
, lpExeName
);
74 IntInsertAliasHeader(PALIAS_HEADER
* RootHeader
, PALIAS_HEADER NewHeader
)
76 PALIAS_HEADER CurrentHeader
;
77 PALIAS_HEADER
*LastLink
= RootHeader
;
79 while ((CurrentHeader
= *LastLink
) != NULL
)
81 INT Diff
= _wcsicmp(NewHeader
->lpExeName
, CurrentHeader
->lpExeName
);
86 LastLink
= &CurrentHeader
->Next
;
89 *LastLink
= NewHeader
;
90 NewHeader
->Next
= CurrentHeader
;
94 IntGetAliasEntry(PALIAS_HEADER Header
, LPCWSTR lpSrcName
)
96 PALIAS_ENTRY RootHeader
;
101 RootHeader
= Header
->Data
;
105 DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader
->lpSource
);
106 diff
= _wcsicmp(RootHeader
->lpSource
, lpSrcName
);
113 RootHeader
= RootHeader
->Next
;
119 IntInsertAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY NewEntry
)
121 PALIAS_ENTRY CurrentEntry
;
122 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
124 while ((CurrentEntry
= *LastLink
) != NULL
)
126 INT Diff
= _wcsicmp(NewEntry
->lpSource
, CurrentEntry
->lpSource
);
131 LastLink
= &CurrentEntry
->Next
;
134 *LastLink
= NewEntry
;
135 NewEntry
->Next
= CurrentEntry
;
139 IntCreateAliasEntry(LPCWSTR lpSource
, LPCWSTR lpTarget
)
145 dwSource
= wcslen(lpSource
) + 1;
146 dwTarget
= wcslen(lpTarget
) + 1;
148 Entry
= RtlAllocateHeap(ConSrvHeap
, 0, sizeof(ALIAS_ENTRY
) + sizeof(WCHAR
) * (dwSource
+ dwTarget
));
152 Entry
->lpSource
= (LPCWSTR
)(Entry
+ 1);
153 wcscpy((LPWSTR
)Entry
->lpSource
, lpSource
);
154 Entry
->lpTarget
= Entry
->lpSource
+ dwSource
;
155 wcscpy((LPWSTR
)Entry
->lpTarget
, lpTarget
);
162 IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader
)
168 length
+= (wcslen(RootHeader
->lpExeName
) + 1) * sizeof(WCHAR
);
169 RootHeader
= RootHeader
->Next
;
172 length
+= sizeof(WCHAR
); // last entry entry is terminated with 2 zero bytes
178 IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader
, LPWSTR TargetBuffer
, UINT TargetBufferSize
)
183 TargetBufferSize
/= sizeof(WCHAR
);
186 Length
= wcslen(RootHeader
->lpExeName
) + 1;
187 if (TargetBufferSize
> Offset
+ Length
)
189 wcscpy(&TargetBuffer
[Offset
], RootHeader
->lpExeName
);
196 RootHeader
= RootHeader
->Next
;
198 Length
= min(Offset
+1, TargetBufferSize
);
199 TargetBuffer
[Length
] = L
'\0';
200 return Length
* sizeof(WCHAR
);
204 IntGetAllConsoleAliasesLength(PALIAS_HEADER Header
)
207 PALIAS_ENTRY CurEntry
= Header
->Data
;
211 Length
+= wcslen(CurEntry
->lpSource
);
212 Length
+= wcslen(CurEntry
->lpTarget
);
213 Length
+= 2; // zero byte and '='
214 CurEntry
= CurEntry
->Next
;
219 return (Length
+1) * sizeof(WCHAR
);
225 IntGetAllConsoleAliases(PALIAS_HEADER Header
, LPWSTR TargetBuffer
, UINT TargetBufferLength
)
227 PALIAS_ENTRY CurEntry
= Header
->Data
;
229 UINT SrcLength
, TargetLength
;
231 TargetBufferLength
/= sizeof(WCHAR
);
234 SrcLength
= wcslen(CurEntry
->lpSource
) + 1;
235 TargetLength
= wcslen(CurEntry
->lpTarget
) + 1;
236 if (Offset
+ TargetLength
+ SrcLength
>= TargetBufferLength
)
239 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpSource
);
241 TargetBuffer
[Offset
] = L
'=';
242 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpTarget
);
243 Offset
+= TargetLength
;
245 CurEntry
= CurEntry
->Next
;
247 TargetBuffer
[Offset
] = L
'\0';
248 return Offset
* sizeof(WCHAR
);
252 IntDeleteAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY Entry
)
254 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
255 PALIAS_ENTRY CurEntry
;
257 while ((CurEntry
= *LastLink
) != NULL
)
259 if (CurEntry
== Entry
)
261 *LastLink
= Entry
->Next
;
262 RtlFreeHeap(ConSrvHeap
, 0, Entry
);
265 LastLink
= &CurEntry
->Next
;
270 IntDeleteAllAliases(PALIAS_HEADER RootHeader
)
272 PALIAS_HEADER Header
, NextHeader
;
273 PALIAS_ENTRY Entry
, NextEntry
;
275 for (Header
= RootHeader
; Header
; Header
= NextHeader
)
277 NextHeader
= Header
->Next
;
278 for (Entry
= Header
->Data
; Entry
; Entry
= NextEntry
)
280 NextEntry
= Entry
->Next
;
281 RtlFreeHeap(ConSrvHeap
, 0, Entry
);
283 RtlFreeHeap(ConSrvHeap
, 0, Header
);
288 /* PUBLIC SERVER APIS *********************************************************/
290 CSR_API(SrvAddConsoleAlias
)
292 PCSRSS_CONSOLE_ALIAS ConsoleAlias
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAlias
;
293 PCSRSS_CONSOLE Console
;
294 PALIAS_HEADER Header
;
296 LPWSTR lpSource
, lpTarget
, lpExeName
;
298 DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage
);
300 if ( !CsrValidateMessageBuffer(ApiMessage
,
301 (PVOID
*)&ConsoleAlias
->Source
,
302 ConsoleAlias
->SourceLength
,
304 !CsrValidateMessageBuffer(ApiMessage
,
305 (PVOID
*)&ConsoleAlias
->Target
,
306 ConsoleAlias
->TargetLength
,
308 !CsrValidateMessageBuffer(ApiMessage
,
309 (PVOID
*)&ConsoleAlias
->Exe
,
310 ConsoleAlias
->ExeLength
,
313 return STATUS_INVALID_PARAMETER
;
316 lpSource
= ConsoleAlias
->Source
;
317 lpTarget
= (ConsoleAlias
->TargetLength
!= 0 ? ConsoleAlias
->Target
: NULL
);
318 lpExeName
= ConsoleAlias
->Exe
;
320 DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource
, lpExeName
, lpTarget
);
322 if (lpExeName
== NULL
|| lpSource
== NULL
)
324 return STATUS_INVALID_PARAMETER
;
327 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
328 if (!NT_SUCCESS(ApiMessage
->Status
))
330 return ApiMessage
->Status
;
333 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
334 if (!Header
&& lpTarget
!= NULL
)
336 Header
= IntCreateAliasHeader(lpExeName
);
339 ConioUnlockConsole(Console
);
340 return STATUS_INSUFFICIENT_RESOURCES
;
342 IntInsertAliasHeader(&Console
->Aliases
, Header
);
345 if (lpTarget
== NULL
) // Delete the entry
347 Entry
= IntGetAliasEntry(Header
, lpSource
);
350 IntDeleteAliasEntry(Header
, Entry
);
351 ApiMessage
->Status
= STATUS_SUCCESS
;
355 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
357 ConioUnlockConsole(Console
);
358 return ApiMessage
->Status
;
361 Entry
= IntCreateAliasEntry(lpSource
, lpTarget
);
365 ConioUnlockConsole(Console
);
366 return STATUS_INSUFFICIENT_RESOURCES
;
369 IntInsertAliasEntry(Header
, Entry
);
370 ConioUnlockConsole(Console
);
371 return STATUS_SUCCESS
;
374 CSR_API(SrvGetConsoleAlias
)
376 PCSRSS_CONSOLE_ALIAS ConsoleAlias
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAlias
;
377 PCSRSS_CONSOLE Console
;
378 PALIAS_HEADER Header
;
381 LPWSTR lpSource
, lpTarget
, lpExeName
;
383 DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage
);
385 if ( !CsrValidateMessageBuffer(ApiMessage
,
386 (PVOID
*)&ConsoleAlias
->Source
,
387 ConsoleAlias
->SourceLength
,
389 !CsrValidateMessageBuffer(ApiMessage
,
390 (PVOID
*)&ConsoleAlias
->Target
,
391 ConsoleAlias
->TargetLength
,
393 !CsrValidateMessageBuffer(ApiMessage
,
394 (PVOID
*)&ConsoleAlias
->Exe
,
395 ConsoleAlias
->ExeLength
,
398 return STATUS_INVALID_PARAMETER
;
401 lpSource
= ConsoleAlias
->Source
;
402 lpTarget
= ConsoleAlias
->Target
;
403 lpExeName
= ConsoleAlias
->Exe
;
405 DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
406 lpExeName
, lpSource
, lpTarget
, ConsoleAlias
->TargetLength
);
408 if (ConsoleAlias
->ExeLength
== 0 || lpTarget
== NULL
||
409 ConsoleAlias
->TargetLength
== 0 || ConsoleAlias
->SourceLength
== 0)
411 return STATUS_INVALID_PARAMETER
;
414 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
415 if (!NT_SUCCESS(ApiMessage
->Status
))
417 return ApiMessage
->Status
;
420 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
423 ConioUnlockConsole(Console
);
424 return STATUS_INVALID_PARAMETER
;
427 Entry
= IntGetAliasEntry(Header
, lpSource
);
430 ConioUnlockConsole(Console
);
431 return STATUS_INVALID_PARAMETER
;
434 Length
= (wcslen(Entry
->lpTarget
) + 1) * sizeof(WCHAR
);
435 if (Length
> ConsoleAlias
->TargetLength
)
437 ConioUnlockConsole(Console
);
438 return STATUS_BUFFER_TOO_SMALL
;
442 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process, lpTarget,
443 ConsoleAlias->TargetLength, 1))
445 ConioUnlockConsole(Console);
446 return STATUS_ACCESS_VIOLATION;
450 wcscpy(lpTarget
, Entry
->lpTarget
);
451 ConsoleAlias
->TargetLength
= Length
;
452 ConioUnlockConsole(Console
);
453 return STATUS_SUCCESS
;
456 CSR_API(SrvGetConsoleAliases
)
458 PCSRSS_GET_ALL_CONSOLE_ALIASES GetAllConsoleAliases
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllConsoleAliases
;
459 PCSRSS_CONSOLE Console
;
461 PALIAS_HEADER Header
;
463 if ( !CsrValidateMessageBuffer(ApiMessage
,
464 (PVOID
)&GetAllConsoleAliases
->ExeName
,
465 GetAllConsoleAliases
->ExeLength
,
467 !CsrValidateMessageBuffer(ApiMessage
,
468 (PVOID
)&GetAllConsoleAliases
->AliasesBuffer
,
469 GetAllConsoleAliases
->AliasesBufferLength
,
472 return STATUS_INVALID_PARAMETER
;
475 if (GetAllConsoleAliases
->ExeName
== NULL
)
477 return STATUS_INVALID_PARAMETER
;
480 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
481 if (!NT_SUCCESS(ApiMessage
->Status
))
483 return ApiMessage
->Status
;
486 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllConsoleAliases
->ExeName
);
489 ConioUnlockConsole(Console
);
490 return STATUS_INVALID_PARAMETER
;
493 if (IntGetAllConsoleAliasesLength(Header
) > GetAllConsoleAliases
->AliasesBufferLength
)
495 ConioUnlockConsole(Console
);
496 return STATUS_BUFFER_OVERFLOW
;
500 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
501 GetAllConsoleAliases->AliasesBuffer,
502 GetAllConsoleAliases->AliasesBufferLength,
505 ConioUnlockConsole(Console);
506 return STATUS_ACCESS_VIOLATION;
510 BytesWritten
= IntGetAllConsoleAliases(Header
,
511 GetAllConsoleAliases
->AliasesBuffer
,
512 GetAllConsoleAliases
->AliasesBufferLength
);
514 GetAllConsoleAliases
->AliasesBufferLength
= BytesWritten
;
515 ConioUnlockConsole(Console
);
516 return STATUS_SUCCESS
;
519 CSR_API(SrvGetConsoleAliasesLength
)
521 PCSRSS_GET_ALL_CONSOLE_ALIASES_LENGTH GetAllConsoleAliasesLength
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllConsoleAliasesLength
;
522 PCSRSS_CONSOLE Console
;
523 PALIAS_HEADER Header
;
526 if (!CsrValidateMessageBuffer(ApiMessage
,
527 (PVOID
)&GetAllConsoleAliasesLength
->ExeName
,
528 GetAllConsoleAliasesLength
->ExeLength
,
531 return STATUS_INVALID_PARAMETER
;
534 if (GetAllConsoleAliasesLength
->ExeName
== NULL
)
536 return STATUS_INVALID_PARAMETER
;
539 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
540 if (!NT_SUCCESS(ApiMessage
->Status
))
542 return ApiMessage
->Status
;
545 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllConsoleAliasesLength
->ExeName
);
548 ConioUnlockConsole(Console
);
549 return STATUS_INVALID_PARAMETER
;
552 Length
= IntGetAllConsoleAliasesLength(Header
);
553 GetAllConsoleAliasesLength
->Length
= Length
;
554 ConioUnlockConsole(Console
);
555 return STATUS_SUCCESS
;
558 CSR_API(SrvGetConsoleAliasExes
)
560 PCSRSS_GET_CONSOLE_ALIASES_EXES GetConsoleAliasesExes
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleAliasesExes
;
561 PCSRSS_CONSOLE Console
;
565 DPRINT("SrvGetConsoleAliasExes entered\n");
567 if (!CsrValidateMessageBuffer(ApiMessage
,
568 (PVOID
)&GetConsoleAliasesExes
->ExeNames
,
569 GetConsoleAliasesExes
->Length
,
572 return STATUS_INVALID_PARAMETER
;
575 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
576 if (!NT_SUCCESS(ApiMessage
->Status
))
578 return ApiMessage
->Status
;
581 ExesLength
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
583 if (ExesLength
> GetConsoleAliasesExes
->Length
)
585 ConioUnlockConsole(Console
);
586 return STATUS_BUFFER_OVERFLOW
;
589 if (GetConsoleAliasesExes
->ExeNames
== NULL
)
591 ConioUnlockConsole(Console
);
592 return STATUS_INVALID_PARAMETER
;
596 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
597 GetConsoleAliasesExes->ExeNames,
598 GetConsoleAliasesExes->Length,
601 ConioUnlockConsole(Console);
602 return STATUS_ACCESS_VIOLATION;
606 BytesWritten
= IntGetConsoleAliasesExes(Console
->Aliases
,
607 GetConsoleAliasesExes
->ExeNames
,
608 GetConsoleAliasesExes
->Length
);
610 GetConsoleAliasesExes
->Length
= BytesWritten
;
611 ConioUnlockConsole(Console
);
612 return STATUS_SUCCESS
;
615 CSR_API(SrvGetConsoleAliasExesLength
)
617 PCSRSS_GET_CONSOLE_ALIASES_EXES_LENGTH GetConsoleAliasesExesLength
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleAliasesExesLength
;
618 PCSRSS_CONSOLE Console
;
619 DPRINT("SrvGetConsoleAliasExesLength entered\n");
621 ApiMessage
->Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
622 if (NT_SUCCESS(ApiMessage
->Status
))
624 GetConsoleAliasesExesLength
->Length
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
625 ConioUnlockConsole(Console
);
627 return ApiMessage
->Status
;