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 *******************************************************************/
17 /* TYPES **********************************************************************/
19 typedef struct _ALIAS_ENTRY
23 struct _ALIAS_ENTRY
* Next
;
24 } ALIAS_ENTRY
, *PALIAS_ENTRY
;
26 typedef struct _ALIAS_HEADER
30 struct _ALIAS_HEADER
* Next
;
31 } ALIAS_HEADER
, *PALIAS_HEADER
;
34 /* PRIVATE FUNCTIONS **********************************************************/
38 IntFindAliasHeader(PALIAS_HEADER RootHeader
, LPCWSTR lpExeName
)
42 INT diff
= _wcsicmp(RootHeader
->lpExeName
, lpExeName
);
43 if (!diff
) return RootHeader
;
46 RootHeader
= RootHeader
->Next
;
52 IntCreateAliasHeader(LPCWSTR lpExeName
)
55 UINT dwLength
= wcslen(lpExeName
) + 1;
57 Entry
= ConsoleAllocHeap(0, sizeof(ALIAS_HEADER
) + sizeof(WCHAR
) * dwLength
);
58 if (!Entry
) return Entry
;
60 Entry
->lpExeName
= (LPCWSTR
)(Entry
+ 1);
61 wcscpy((PWCHAR
)Entry
->lpExeName
, lpExeName
);
68 IntInsertAliasHeader(PALIAS_HEADER
* RootHeader
, PALIAS_HEADER NewHeader
)
70 PALIAS_HEADER CurrentHeader
;
71 PALIAS_HEADER
*LastLink
= RootHeader
;
73 while ((CurrentHeader
= *LastLink
) != NULL
)
75 INT Diff
= _wcsicmp(NewHeader
->lpExeName
, CurrentHeader
->lpExeName
);
78 LastLink
= &CurrentHeader
->Next
;
81 *LastLink
= NewHeader
;
82 NewHeader
->Next
= CurrentHeader
;
86 IntGetAliasEntry(PALIAS_HEADER Header
, LPCWSTR lpSrcName
)
88 PALIAS_ENTRY RootHeader
;
90 if (Header
== NULL
) return NULL
;
92 RootHeader
= Header
->Data
;
96 DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader
->lpSource
);
97 diff
= _wcsicmp(RootHeader
->lpSource
, lpSrcName
);
98 if (!diff
) return RootHeader
;
101 RootHeader
= RootHeader
->Next
;
107 IntInsertAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY NewEntry
)
109 PALIAS_ENTRY CurrentEntry
;
110 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
112 while ((CurrentEntry
= *LastLink
) != NULL
)
114 INT Diff
= _wcsicmp(NewEntry
->lpSource
, CurrentEntry
->lpSource
);
117 LastLink
= &CurrentEntry
->Next
;
120 *LastLink
= NewEntry
;
121 NewEntry
->Next
= CurrentEntry
;
125 IntCreateAliasEntry(LPCWSTR lpSource
, LPCWSTR lpTarget
)
131 dwSource
= wcslen(lpSource
) + 1;
132 dwTarget
= wcslen(lpTarget
) + 1;
134 Entry
= ConsoleAllocHeap(0, sizeof(ALIAS_ENTRY
) + sizeof(WCHAR
) * (dwSource
+ dwTarget
));
135 if (!Entry
) return Entry
;
137 Entry
->lpSource
= (LPCWSTR
)(Entry
+ 1);
138 wcscpy((LPWSTR
)Entry
->lpSource
, lpSource
);
139 Entry
->lpTarget
= Entry
->lpSource
+ dwSource
;
140 wcscpy((LPWSTR
)Entry
->lpTarget
, lpTarget
);
147 IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader
)
153 length
+= (wcslen(RootHeader
->lpExeName
) + 1) * sizeof(WCHAR
);
154 RootHeader
= RootHeader
->Next
;
157 length
+= sizeof(WCHAR
); // last entry entry is terminated with 2 zero bytes
163 IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader
, LPWSTR TargetBuffer
, UINT TargetBufferSize
)
168 TargetBufferSize
/= sizeof(WCHAR
);
171 Length
= wcslen(RootHeader
->lpExeName
) + 1;
172 if (TargetBufferSize
> Offset
+ Length
)
174 wcscpy(&TargetBuffer
[Offset
], RootHeader
->lpExeName
);
181 RootHeader
= RootHeader
->Next
;
183 Length
= min(Offset
+1, TargetBufferSize
);
184 TargetBuffer
[Length
] = L
'\0';
185 return Length
* sizeof(WCHAR
);
189 IntGetAllConsoleAliasesLength(PALIAS_HEADER Header
)
192 PALIAS_ENTRY CurEntry
= Header
->Data
;
196 Length
+= wcslen(CurEntry
->lpSource
);
197 Length
+= wcslen(CurEntry
->lpTarget
);
198 Length
+= 2; // zero byte and '='
199 CurEntry
= CurEntry
->Next
;
204 return (Length
+1) * sizeof(WCHAR
);
210 IntGetAllConsoleAliases(PALIAS_HEADER Header
, LPWSTR TargetBuffer
, UINT TargetBufferLength
)
212 PALIAS_ENTRY CurEntry
= Header
->Data
;
214 UINT SrcLength
, TargetLength
;
216 TargetBufferLength
/= sizeof(WCHAR
);
219 SrcLength
= wcslen(CurEntry
->lpSource
) + 1;
220 TargetLength
= wcslen(CurEntry
->lpTarget
) + 1;
221 if (Offset
+ TargetLength
+ SrcLength
>= TargetBufferLength
)
224 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpSource
);
226 TargetBuffer
[Offset
] = L
'=';
227 wcscpy(&TargetBuffer
[Offset
], CurEntry
->lpTarget
);
228 Offset
+= TargetLength
;
230 CurEntry
= CurEntry
->Next
;
232 TargetBuffer
[Offset
] = L
'\0';
233 return Offset
* sizeof(WCHAR
);
237 IntDeleteAliasEntry(PALIAS_HEADER Header
, PALIAS_ENTRY Entry
)
239 PALIAS_ENTRY
*LastLink
= &Header
->Data
;
240 PALIAS_ENTRY CurEntry
;
242 while ((CurEntry
= *LastLink
) != NULL
)
244 if (CurEntry
== Entry
)
246 *LastLink
= Entry
->Next
;
247 ConsoleFreeHeap(Entry
);
250 LastLink
= &CurEntry
->Next
;
255 IntDeleteAllAliases(PCONSOLE Console
)
257 PALIAS_HEADER Header
, NextHeader
;
258 PALIAS_ENTRY Entry
, NextEntry
;
260 for (Header
= Console
->Aliases
; Header
; Header
= NextHeader
)
262 NextHeader
= Header
->Next
;
263 for (Entry
= Header
->Data
; Entry
; Entry
= NextEntry
)
265 NextEntry
= Entry
->Next
;
266 ConsoleFreeHeap(Entry
);
268 ConsoleFreeHeap(Header
);
273 /* PUBLIC SERVER APIS *********************************************************/
275 CSR_API(SrvAddConsoleAlias
)
277 PCONSOLE_ADDGETALIAS ConsoleAliasRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAliasRequest
;
279 PALIAS_HEADER Header
;
281 LPWSTR lpSource
, lpTarget
, lpExeName
;
283 DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage
);
285 if ( !CsrValidateMessageBuffer(ApiMessage
,
286 (PVOID
*)&ConsoleAliasRequest
->Source
,
287 ConsoleAliasRequest
->SourceLength
,
289 !CsrValidateMessageBuffer(ApiMessage
,
290 (PVOID
*)&ConsoleAliasRequest
->Target
,
291 ConsoleAliasRequest
->TargetLength
,
293 !CsrValidateMessageBuffer(ApiMessage
,
294 (PVOID
*)&ConsoleAliasRequest
->Exe
,
295 ConsoleAliasRequest
->ExeLength
,
298 return STATUS_INVALID_PARAMETER
;
301 lpSource
= ConsoleAliasRequest
->Source
;
302 lpTarget
= (ConsoleAliasRequest
->TargetLength
!= 0 ? ConsoleAliasRequest
->Target
: NULL
);
303 lpExeName
= ConsoleAliasRequest
->Exe
;
305 DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource
, lpExeName
, lpTarget
);
307 if (lpExeName
== NULL
|| lpSource
== NULL
)
309 return STATUS_INVALID_PARAMETER
;
312 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
313 if (!NT_SUCCESS(ApiMessage
->Status
))
315 return ApiMessage
->Status
;
318 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
319 if (!Header
&& lpTarget
!= NULL
)
321 Header
= IntCreateAliasHeader(lpExeName
);
324 ConSrvReleaseConsole(Console
, TRUE
);
325 return STATUS_INSUFFICIENT_RESOURCES
;
327 IntInsertAliasHeader(&Console
->Aliases
, Header
);
330 if (lpTarget
== NULL
) // Delete the entry
332 Entry
= IntGetAliasEntry(Header
, lpSource
);
335 IntDeleteAliasEntry(Header
, Entry
);
336 ApiMessage
->Status
= STATUS_SUCCESS
;
340 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
342 ConSrvReleaseConsole(Console
, TRUE
);
343 return ApiMessage
->Status
;
346 Entry
= IntCreateAliasEntry(lpSource
, lpTarget
);
350 ConSrvReleaseConsole(Console
, TRUE
);
351 return STATUS_INSUFFICIENT_RESOURCES
;
354 IntInsertAliasEntry(Header
, Entry
);
355 ConSrvReleaseConsole(Console
, TRUE
);
356 return STATUS_SUCCESS
;
359 CSR_API(SrvGetConsoleAlias
)
361 PCONSOLE_ADDGETALIAS ConsoleAliasRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleAliasRequest
;
363 PALIAS_HEADER Header
;
366 LPWSTR lpSource
, lpTarget
, lpExeName
;
368 DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage
);
370 if ( !CsrValidateMessageBuffer(ApiMessage
,
371 (PVOID
*)&ConsoleAliasRequest
->Source
,
372 ConsoleAliasRequest
->SourceLength
,
374 !CsrValidateMessageBuffer(ApiMessage
,
375 (PVOID
*)&ConsoleAliasRequest
->Target
,
376 ConsoleAliasRequest
->TargetLength
,
378 !CsrValidateMessageBuffer(ApiMessage
,
379 (PVOID
*)&ConsoleAliasRequest
->Exe
,
380 ConsoleAliasRequest
->ExeLength
,
383 return STATUS_INVALID_PARAMETER
;
386 lpSource
= ConsoleAliasRequest
->Source
;
387 lpTarget
= ConsoleAliasRequest
->Target
;
388 lpExeName
= ConsoleAliasRequest
->Exe
;
390 DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
391 lpExeName
, lpSource
, lpTarget
, ConsoleAliasRequest
->TargetLength
);
393 if (ConsoleAliasRequest
->ExeLength
== 0 || lpTarget
== NULL
||
394 ConsoleAliasRequest
->TargetLength
== 0 || ConsoleAliasRequest
->SourceLength
== 0)
396 return STATUS_INVALID_PARAMETER
;
399 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
400 if (!NT_SUCCESS(ApiMessage
->Status
))
402 return ApiMessage
->Status
;
405 Header
= IntFindAliasHeader(Console
->Aliases
, lpExeName
);
408 ConSrvReleaseConsole(Console
, TRUE
);
409 return STATUS_INVALID_PARAMETER
;
412 Entry
= IntGetAliasEntry(Header
, lpSource
);
415 ConSrvReleaseConsole(Console
, TRUE
);
416 return STATUS_INVALID_PARAMETER
;
419 Length
= (wcslen(Entry
->lpTarget
) + 1) * sizeof(WCHAR
);
420 if (Length
> ConsoleAliasRequest
->TargetLength
)
422 ConSrvReleaseConsole(Console
, TRUE
);
423 return STATUS_BUFFER_TOO_SMALL
;
426 wcscpy(lpTarget
, Entry
->lpTarget
);
427 ConsoleAliasRequest
->TargetLength
= Length
;
428 ConSrvReleaseConsole(Console
, TRUE
);
429 return STATUS_SUCCESS
;
432 CSR_API(SrvGetConsoleAliases
)
434 PCONSOLE_GETALLALIASES GetAllAliasesRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllAliasesRequest
;
437 PALIAS_HEADER Header
;
439 if ( !CsrValidateMessageBuffer(ApiMessage
,
440 (PVOID
)&GetAllAliasesRequest
->ExeName
,
441 GetAllAliasesRequest
->ExeLength
,
443 !CsrValidateMessageBuffer(ApiMessage
,
444 (PVOID
)&GetAllAliasesRequest
->AliasesBuffer
,
445 GetAllAliasesRequest
->AliasesBufferLength
,
448 return STATUS_INVALID_PARAMETER
;
451 if (GetAllAliasesRequest
->ExeName
== NULL
)
453 return STATUS_INVALID_PARAMETER
;
456 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
457 if (!NT_SUCCESS(ApiMessage
->Status
))
459 return ApiMessage
->Status
;
462 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllAliasesRequest
->ExeName
);
465 ConSrvReleaseConsole(Console
, TRUE
);
466 return STATUS_INVALID_PARAMETER
;
469 if (IntGetAllConsoleAliasesLength(Header
) > GetAllAliasesRequest
->AliasesBufferLength
)
471 ConSrvReleaseConsole(Console
, TRUE
);
472 return STATUS_BUFFER_OVERFLOW
;
475 BytesWritten
= IntGetAllConsoleAliases(Header
,
476 GetAllAliasesRequest
->AliasesBuffer
,
477 GetAllAliasesRequest
->AliasesBufferLength
);
479 GetAllAliasesRequest
->AliasesBufferLength
= BytesWritten
;
480 ConSrvReleaseConsole(Console
, TRUE
);
481 return STATUS_SUCCESS
;
484 CSR_API(SrvGetConsoleAliasesLength
)
486 PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAllAliasesLengthRequest
;
488 PALIAS_HEADER Header
;
491 if (!CsrValidateMessageBuffer(ApiMessage
,
492 (PVOID
)&GetAllAliasesLengthRequest
->ExeName
,
493 GetAllAliasesLengthRequest
->ExeLength
,
496 return STATUS_INVALID_PARAMETER
;
499 if (GetAllAliasesLengthRequest
->ExeName
== NULL
)
501 return STATUS_INVALID_PARAMETER
;
504 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
505 if (!NT_SUCCESS(ApiMessage
->Status
))
507 return ApiMessage
->Status
;
510 Header
= IntFindAliasHeader(Console
->Aliases
, GetAllAliasesLengthRequest
->ExeName
);
513 ConSrvReleaseConsole(Console
, TRUE
);
514 return STATUS_INVALID_PARAMETER
;
517 Length
= IntGetAllConsoleAliasesLength(Header
);
518 GetAllAliasesLengthRequest
->Length
= Length
;
519 ConSrvReleaseConsole(Console
, TRUE
);
520 return STATUS_SUCCESS
;
523 CSR_API(SrvGetConsoleAliasExes
)
525 PCONSOLE_GETALIASESEXES GetAliasesExesRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAliasesExesRequest
;
530 DPRINT("SrvGetConsoleAliasExes entered\n");
532 if (!CsrValidateMessageBuffer(ApiMessage
,
533 (PVOID
)&GetAliasesExesRequest
->ExeNames
,
534 GetAliasesExesRequest
->Length
,
537 return STATUS_INVALID_PARAMETER
;
540 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
541 if (!NT_SUCCESS(ApiMessage
->Status
))
543 return ApiMessage
->Status
;
546 ExesLength
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
548 if (ExesLength
> GetAliasesExesRequest
->Length
)
550 ConSrvReleaseConsole(Console
, TRUE
);
551 return STATUS_BUFFER_OVERFLOW
;
554 if (GetAliasesExesRequest
->ExeNames
== NULL
)
556 ConSrvReleaseConsole(Console
, TRUE
);
557 return STATUS_INVALID_PARAMETER
;
560 BytesWritten
= IntGetConsoleAliasesExes(Console
->Aliases
,
561 GetAliasesExesRequest
->ExeNames
,
562 GetAliasesExesRequest
->Length
);
564 GetAliasesExesRequest
->Length
= BytesWritten
;
565 ConSrvReleaseConsole(Console
, TRUE
);
566 return STATUS_SUCCESS
;
569 CSR_API(SrvGetConsoleAliasExesLength
)
571 PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetAliasesExesLengthRequest
;
573 DPRINT("SrvGetConsoleAliasExesLength entered\n");
575 ApiMessage
->Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
576 if (NT_SUCCESS(ApiMessage
->Status
))
578 GetAliasesExesLengthRequest
->Length
= IntGetConsoleAliasesExesLength(Console
->Aliases
);
579 ConSrvReleaseConsole(Console
, TRUE
);
581 return ApiMessage
->Status
;