2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/alias.c
5 * PURPOSE: Alias support functions
6 * PROGRAMMERS: Christoph Wittich
10 /* INCLUDES *******************************************************************/
14 #include "include/conio.h"
20 /* TYPES **********************************************************************/
22 typedef struct _ALIAS_ENTRY
26 struct _ALIAS_ENTRY
* Next
;
27 } ALIAS_ENTRY
, *PALIAS_ENTRY
;
29 typedef struct _ALIAS_HEADER
33 struct _ALIAS_HEADER
* Next
;
34 } ALIAS_HEADER
, *PALIAS_HEADER
;
37 /* PRIVATE FUNCTIONS **********************************************************/
41 IntFindAliasHeader(PALIAS_HEADER RootHeader
, LPCWSTR lpExeName
)
45 INT diff
= _wcsicmp(RootHeader
->lpExeName
, lpExeName
);
46 if (!diff
) return RootHeader
;
49 RootHeader
= RootHeader
->Next
;
55 IntCreateAliasHeader(LPCWSTR lpExeName
)
58 UINT dwLength
= wcslen(lpExeName
) + 1;
60 Entry
= ConsoleAllocHeap(0, sizeof(ALIAS_HEADER
) + sizeof(WCHAR
) * dwLength
);
61 if (!Entry
) return Entry
;
63 Entry
->lpExeName
= (LPCWSTR
)(Entry
+ 1);
64 wcscpy((PWCHAR
)Entry
->lpExeName
, lpExeName
);
71 IntInsertAliasHeader(PALIAS_HEADER
* RootHeader
, PALIAS_HEADER NewHeader
)
73 PALIAS_HEADER CurrentHeader
;
74 PALIAS_HEADER
*LastLink
= RootHeader
;
76 while ((CurrentHeader
= *LastLink
) != NULL
)
78 INT Diff
= _wcsicmp(NewHeader
->lpExeName
, CurrentHeader
->lpExeName
);
81 LastLink
= &CurrentHeader
->Next
;
84 *LastLink
= NewHeader
;
85 NewHeader
->Next
= CurrentHeader
;
89 IntGetAliasEntry(PALIAS_HEADER Header
, LPCWSTR lpSrcName
)
91 PALIAS_ENTRY RootHeader
;
93 if (Header
== NULL
) return NULL
;
95 RootHeader
= Header
->Data
;
99 DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader
->lpSource
);
100 diff
= _wcsicmp(RootHeader
->lpSource
, lpSrcName
);
101 if (!diff
) return RootHeader
;
104 RootHeader
= RootHeader
->Next
;
110 IntInsertAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY NewEntry
)
112 PALIAS_ENTRY CurrentEntry
;
113 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
115 while ((CurrentEntry
= *LastLink
) != NULL
)
117 INT Diff
= _wcsicmp(NewEntry
->lpSource
, CurrentEntry
->lpSource
);
120 LastLink
= &CurrentEntry
->Next
;
123 *LastLink
= NewEntry
;
124 NewEntry
->Next
= CurrentEntry
;
128 IntCreateAliasEntry(LPCWSTR lpSource
, LPCWSTR lpTarget
)
134 dwSource
= wcslen(lpSource
) + 1;
135 dwTarget
= wcslen(lpTarget
) + 1;
137 Entry
= ConsoleAllocHeap(0, sizeof(ALIAS_ENTRY
) + sizeof(WCHAR
) * (dwSource
+ dwTarget
));
138 if (!Entry
) return Entry
;
140 Entry
->lpSource
= (LPCWSTR
)(Entry
+ 1);
141 wcscpy((LPWSTR
)Entry
->lpSource
, lpSource
);
142 Entry
->lpTarget
= Entry
->lpSource
+ dwSource
;
143 wcscpy((LPWSTR
)Entry
->lpTarget
, lpTarget
);
150 IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader
)
156 length
+= (wcslen(RootHeader
->lpExeName
) + 1) * sizeof(WCHAR
);
157 RootHeader
= RootHeader
->Next
;
160 length
+= sizeof(WCHAR
); // last entry entry is terminated with 2 zero bytes
166 IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader
, LPWSTR TargetBuffer
, UINT TargetBufferSize
)
171 TargetBufferSize
/= sizeof(WCHAR
);
174 Length
= wcslen(RootHeader
->lpExeName
) + 1;
175 if (TargetBufferSize
> Offset
+ Length
)
177 wcscpy(&TargetBuffer
[Offset
], RootHeader
->lpExeName
);
184 RootHeader
= RootHeader
->Next
;
186 Length
= min(Offset
+1, TargetBufferSize
);
187 TargetBuffer
[Length
] = L
'\0';
188 return Length
* sizeof(WCHAR
);
192 IntGetAllConsoleAliasesLength(PALIAS_HEADER Header
)
195 PALIAS_ENTRY CurEntry
= Header
->Data
;
199 Length
+= wcslen(CurEntry
->lpSource
);
200 Length
+= wcslen(CurEntry
->lpTarget
);
201 Length
+= 2; // zero byte and '='
202 CurEntry
= CurEntry
->Next
;
207 return (Length
+1) * sizeof(WCHAR
);
213 IntGetAllConsoleAliases(PALIAS_HEADER Header
, LPWSTR TargetBuffer
, UINT TargetBufferLength
)
215 PALIAS_ENTRY CurEntry
= Header
->Data
;
217 UINT SrcLength
, TargetLength
;
219 TargetBufferLength
/= sizeof(WCHAR
);
222 SrcLength
= wcslen(CurEntry
->lpSource
) + 1;
223 TargetLength
= wcslen(CurEntry
->lpTarget
) + 1;
224 if (Offset
+ TargetLength
+ SrcLength
>= TargetBufferLength
)
227 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpSource
);
229 TargetBuffer
[Offset
] = L
'=';
230 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpTarget
);
231 Offset
+= TargetLength
;
233 CurEntry
= CurEntry
->Next
;
235 TargetBuffer
[Offset
] = L
'\0';
236 return Offset
* sizeof(WCHAR
);
240 IntDeleteAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY Entry
)
242 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
243 PALIAS_ENTRY CurEntry
;
245 while ((CurEntry
= *LastLink
) != NULL
)
247 if (CurEntry
== Entry
)
249 *LastLink
= Entry
->Next
;
250 ConsoleFreeHeap(Entry
);
253 LastLink
= &CurEntry
->Next
;
258 IntDeleteAllAliases(PCONSOLE Console
)
260 PALIAS_HEADER Header
, NextHeader
;
261 PALIAS_ENTRY Entry
, NextEntry
;
263 for (Header
= Console
->Aliases
; Header
; Header
= NextHeader
)
265 NextHeader
= Header
->Next
;
266 for (Entry
= Header
->Data
; Entry
; Entry
= NextEntry
)
268 NextEntry
= Entry
->Next
;
269 ConsoleFreeHeap(Entry
);
271 ConsoleFreeHeap(Header
);
276 /* PUBLIC SERVER APIS *********************************************************/
278 CSR_API(SrvAddConsoleAlias
)
280 PCONSOLE_ADDGETALIAS ConsoleAliasRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAliasRequest
;
282 PALIAS_HEADER Header
;
284 LPWSTR lpSource
, lpTarget
, lpExeName
;
286 DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage
);
288 if ( !CsrValidateMessageBuffer(ApiMessage
,
289 (PVOID
*)&ConsoleAliasRequest
->Source
,
290 ConsoleAliasRequest
->SourceLength
,
292 !CsrValidateMessageBuffer(ApiMessage
,
293 (PVOID
*)&ConsoleAliasRequest
->Target
,
294 ConsoleAliasRequest
->TargetLength
,
296 !CsrValidateMessageBuffer(ApiMessage
,
297 (PVOID
*)&ConsoleAliasRequest
->Exe
,
298 ConsoleAliasRequest
->ExeLength
,
301 return STATUS_INVALID_PARAMETER
;
304 lpSource
= ConsoleAliasRequest
->Source
;
305 lpTarget
= (ConsoleAliasRequest
->TargetLength
!= 0 ? ConsoleAliasRequest
->Target
: NULL
);
306 lpExeName
= ConsoleAliasRequest
->Exe
;
308 DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource
, lpExeName
, lpTarget
);
310 if (lpExeName
== NULL
|| lpSource
== NULL
)
312 return STATUS_INVALID_PARAMETER
;
315 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
316 if (!NT_SUCCESS(ApiMessage
->Status
))
318 return ApiMessage
->Status
;
321 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
322 if (!Header
&& lpTarget
!= NULL
)
324 Header
= IntCreateAliasHeader(lpExeName
);
327 ConSrvReleaseConsole(Console
, TRUE
);
328 return STATUS_INSUFFICIENT_RESOURCES
;
330 IntInsertAliasHeader(&Console
->Aliases
, Header
);
333 if (lpTarget
== NULL
) // Delete the entry
335 Entry
= IntGetAliasEntry(Header
, lpSource
);
338 IntDeleteAliasEntry(Header
, Entry
);
339 ApiMessage
->Status
= STATUS_SUCCESS
;
343 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
345 ConSrvReleaseConsole(Console
, TRUE
);
346 return ApiMessage
->Status
;
349 Entry
= IntCreateAliasEntry(lpSource
, lpTarget
);
353 ConSrvReleaseConsole(Console
, TRUE
);
354 return STATUS_INSUFFICIENT_RESOURCES
;
357 IntInsertAliasEntry(Header
, Entry
);
358 ConSrvReleaseConsole(Console
, TRUE
);
359 return STATUS_SUCCESS
;
362 CSR_API(SrvGetConsoleAlias
)
364 PCONSOLE_ADDGETALIAS ConsoleAliasRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAliasRequest
;
366 PALIAS_HEADER Header
;
369 LPWSTR lpSource
, lpTarget
, lpExeName
;
371 DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage
);
373 if ( !CsrValidateMessageBuffer(ApiMessage
,
374 (PVOID
*)&ConsoleAliasRequest
->Source
,
375 ConsoleAliasRequest
->SourceLength
,
377 !CsrValidateMessageBuffer(ApiMessage
,
378 (PVOID
*)&ConsoleAliasRequest
->Target
,
379 ConsoleAliasRequest
->TargetLength
,
381 !CsrValidateMessageBuffer(ApiMessage
,
382 (PVOID
*)&ConsoleAliasRequest
->Exe
,
383 ConsoleAliasRequest
->ExeLength
,
386 return STATUS_INVALID_PARAMETER
;
389 lpSource
= ConsoleAliasRequest
->Source
;
390 lpTarget
= ConsoleAliasRequest
->Target
;
391 lpExeName
= ConsoleAliasRequest
->Exe
;
393 DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
394 lpExeName
, lpSource
, lpTarget
, ConsoleAliasRequest
->TargetLength
);
396 if (ConsoleAliasRequest
->ExeLength
== 0 || lpTarget
== NULL
||
397 ConsoleAliasRequest
->TargetLength
== 0 || ConsoleAliasRequest
->SourceLength
== 0)
399 return STATUS_INVALID_PARAMETER
;
402 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
403 if (!NT_SUCCESS(ApiMessage
->Status
))
405 return ApiMessage
->Status
;
408 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
411 ConSrvReleaseConsole(Console
, TRUE
);
412 return STATUS_INVALID_PARAMETER
;
415 Entry
= IntGetAliasEntry(Header
, lpSource
);
418 ConSrvReleaseConsole(Console
, TRUE
);
419 return STATUS_INVALID_PARAMETER
;
422 Length
= (wcslen(Entry
->lpTarget
) + 1) * sizeof(WCHAR
);
423 if (Length
> ConsoleAliasRequest
->TargetLength
)
425 ConSrvReleaseConsole(Console
, TRUE
);
426 return STATUS_BUFFER_TOO_SMALL
;
429 wcscpy(lpTarget
, Entry
->lpTarget
);
430 ConsoleAliasRequest
->TargetLength
= Length
;
431 ConSrvReleaseConsole(Console
, TRUE
);
432 return STATUS_SUCCESS
;
435 CSR_API(SrvGetConsoleAliases
)
437 PCONSOLE_GETALLALIASES GetAllAliasesRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllAliasesRequest
;
440 PALIAS_HEADER Header
;
442 if ( !CsrValidateMessageBuffer(ApiMessage
,
443 (PVOID
)&GetAllAliasesRequest
->ExeName
,
444 GetAllAliasesRequest
->ExeLength
,
446 !CsrValidateMessageBuffer(ApiMessage
,
447 (PVOID
)&GetAllAliasesRequest
->AliasesBuffer
,
448 GetAllAliasesRequest
->AliasesBufferLength
,
451 return STATUS_INVALID_PARAMETER
;
454 if (GetAllAliasesRequest
->ExeName
== NULL
)
456 return STATUS_INVALID_PARAMETER
;
459 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
460 if (!NT_SUCCESS(ApiMessage
->Status
))
462 return ApiMessage
->Status
;
465 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllAliasesRequest
->ExeName
);
468 ConSrvReleaseConsole(Console
, TRUE
);
469 return STATUS_INVALID_PARAMETER
;
472 if (IntGetAllConsoleAliasesLength(Header
) > GetAllAliasesRequest
->AliasesBufferLength
)
474 ConSrvReleaseConsole(Console
, TRUE
);
475 return STATUS_BUFFER_OVERFLOW
;
478 BytesWritten
= IntGetAllConsoleAliases(Header
,
479 GetAllAliasesRequest
->AliasesBuffer
,
480 GetAllAliasesRequest
->AliasesBufferLength
);
482 GetAllAliasesRequest
->AliasesBufferLength
= BytesWritten
;
483 ConSrvReleaseConsole(Console
, TRUE
);
484 return STATUS_SUCCESS
;
487 CSR_API(SrvGetConsoleAliasesLength
)
489 PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllAliasesLengthRequest
;
491 PALIAS_HEADER Header
;
494 if (!CsrValidateMessageBuffer(ApiMessage
,
495 (PVOID
)&GetAllAliasesLengthRequest
->ExeName
,
496 GetAllAliasesLengthRequest
->ExeLength
,
499 return STATUS_INVALID_PARAMETER
;
502 if (GetAllAliasesLengthRequest
->ExeName
== NULL
)
504 return STATUS_INVALID_PARAMETER
;
507 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
508 if (!NT_SUCCESS(ApiMessage
->Status
))
510 return ApiMessage
->Status
;
513 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllAliasesLengthRequest
->ExeName
);
516 ConSrvReleaseConsole(Console
, TRUE
);
517 return STATUS_INVALID_PARAMETER
;
520 Length
= IntGetAllConsoleAliasesLength(Header
);
521 GetAllAliasesLengthRequest
->Length
= Length
;
522 ConSrvReleaseConsole(Console
, TRUE
);
523 return STATUS_SUCCESS
;
526 CSR_API(SrvGetConsoleAliasExes
)
528 PCONSOLE_GETALIASESEXES GetAliasesExesRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAliasesExesRequest
;
533 DPRINT("SrvGetConsoleAliasExes entered\n");
535 if (!CsrValidateMessageBuffer(ApiMessage
,
536 (PVOID
)&GetAliasesExesRequest
->ExeNames
,
537 GetAliasesExesRequest
->Length
,
540 return STATUS_INVALID_PARAMETER
;
543 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
544 if (!NT_SUCCESS(ApiMessage
->Status
))
546 return ApiMessage
->Status
;
549 ExesLength
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
551 if (ExesLength
> GetAliasesExesRequest
->Length
)
553 ConSrvReleaseConsole(Console
, TRUE
);
554 return STATUS_BUFFER_OVERFLOW
;
557 if (GetAliasesExesRequest
->ExeNames
== NULL
)
559 ConSrvReleaseConsole(Console
, TRUE
);
560 return STATUS_INVALID_PARAMETER
;
563 BytesWritten
= IntGetConsoleAliasesExes(Console
->Aliases
,
564 GetAliasesExesRequest
->ExeNames
,
565 GetAliasesExesRequest
->Length
);
567 GetAliasesExesRequest
->Length
= BytesWritten
;
568 ConSrvReleaseConsole(Console
, TRUE
);
569 return STATUS_SUCCESS
;
572 CSR_API(SrvGetConsoleAliasExesLength
)
574 PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAliasesExesLengthRequest
;
576 DPRINT("SrvGetConsoleAliasExesLength entered\n");
578 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
579 if (NT_SUCCESS(ApiMessage
->Status
))
581 GetAliasesExesLengthRequest
->Length
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
582 ConSrvReleaseConsole(Console
, TRUE
);
584 return ApiMessage
->Status
;