81ec4457079928f971c5a0dc7f61a1a4525b66e3
[reactos.git] / win32ss / user / consrv / alias.c
1 /*
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
7 * Johannes Anderwald
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include "consrv.h"
13 #include "conio.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18
19 /* TYPES **********************************************************************/
20
21 typedef struct tagALIAS_ENTRY
22 {
23 LPCWSTR lpSource;
24 LPCWSTR lpTarget;
25 struct tagALIAS_ENTRY* Next;
26 } ALIAS_ENTRY, *PALIAS_ENTRY;
27
28 typedef struct tagALIAS_HEADER
29 {
30 LPCWSTR lpExeName;
31 PALIAS_ENTRY Data;
32 struct tagALIAS_HEADER* Next;
33 } ALIAS_HEADER, *PALIAS_HEADER;
34
35
36 /* PRIVATE FUNCTIONS **********************************************************/
37
38 static
39 PALIAS_HEADER
40 IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName)
41 {
42 while(RootHeader)
43 {
44 INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName);
45 if (!diff)
46 return RootHeader;
47
48 if (diff > 0)
49 break;
50
51 RootHeader = RootHeader->Next;
52 }
53 return NULL;
54 }
55
56 PALIAS_HEADER
57 IntCreateAliasHeader(LPCWSTR lpExeName)
58 {
59 PALIAS_HEADER Entry;
60 UINT dwLength = wcslen(lpExeName) + 1;
61
62 Entry = RtlAllocateHeap(ConSrvHeap, 0, sizeof(ALIAS_HEADER) + sizeof(WCHAR) * dwLength);
63 if (!Entry)
64 return Entry;
65
66 Entry->lpExeName = (LPCWSTR)(Entry + 1);
67 wcscpy((WCHAR*)Entry->lpExeName, lpExeName);
68 Entry->Data = NULL;
69 Entry->Next = NULL;
70 return Entry;
71 }
72
73 VOID
74 IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader)
75 {
76 PALIAS_HEADER CurrentHeader;
77 PALIAS_HEADER *LastLink = RootHeader;
78
79 while ((CurrentHeader = *LastLink) != NULL)
80 {
81 INT Diff = _wcsicmp(NewHeader->lpExeName, CurrentHeader->lpExeName);
82 if (Diff < 0)
83 {
84 break;
85 }
86 LastLink = &CurrentHeader->Next;
87 }
88
89 *LastLink = NewHeader;
90 NewHeader->Next = CurrentHeader;
91 }
92
93 PALIAS_ENTRY
94 IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName)
95 {
96 PALIAS_ENTRY RootHeader;
97
98 if (Header == NULL)
99 return NULL;
100
101 RootHeader = Header->Data;
102 while(RootHeader)
103 {
104 INT diff;
105 DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader->lpSource);
106 diff = _wcsicmp(RootHeader->lpSource, lpSrcName);
107 if (!diff)
108 return RootHeader;
109
110 if (diff > 0)
111 break;
112
113 RootHeader = RootHeader->Next;
114 }
115 return NULL;
116 }
117
118 VOID
119 IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry)
120 {
121 PALIAS_ENTRY CurrentEntry;
122 PALIAS_ENTRY *LastLink = &Header->Data;
123
124 while ((CurrentEntry = *LastLink) != NULL)
125 {
126 INT Diff = _wcsicmp(NewEntry->lpSource, CurrentEntry->lpSource);
127 if (Diff < 0)
128 {
129 break;
130 }
131 LastLink = &CurrentEntry->Next;
132 }
133
134 *LastLink = NewEntry;
135 NewEntry->Next = CurrentEntry;
136 }
137
138 PALIAS_ENTRY
139 IntCreateAliasEntry(LPCWSTR lpSource, LPCWSTR lpTarget)
140 {
141 UINT dwSource;
142 UINT dwTarget;
143 PALIAS_ENTRY Entry;
144
145 dwSource = wcslen(lpSource) + 1;
146 dwTarget = wcslen(lpTarget) + 1;
147
148 Entry = RtlAllocateHeap(ConSrvHeap, 0, sizeof(ALIAS_ENTRY) + sizeof(WCHAR) * (dwSource + dwTarget));
149 if (!Entry)
150 return Entry;
151
152 Entry->lpSource = (LPCWSTR)(Entry + 1);
153 wcscpy((LPWSTR)Entry->lpSource, lpSource);
154 Entry->lpTarget = Entry->lpSource + dwSource;
155 wcscpy((LPWSTR)Entry->lpTarget, lpTarget);
156 Entry->Next = NULL;
157
158 return Entry;
159 }
160
161 UINT
162 IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader)
163 {
164 UINT length = 0;
165
166 while(RootHeader)
167 {
168 length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR);
169 RootHeader = RootHeader->Next;
170 }
171 if (length)
172 length += sizeof(WCHAR); // last entry entry is terminated with 2 zero bytes
173
174 return length;
175 }
176
177 UINT
178 IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT TargetBufferSize)
179 {
180 UINT Offset = 0;
181 UINT Length;
182
183 TargetBufferSize /= sizeof(WCHAR);
184 while(RootHeader)
185 {
186 Length = wcslen(RootHeader->lpExeName) + 1;
187 if (TargetBufferSize > Offset + Length)
188 {
189 wcscpy(&TargetBuffer[Offset], RootHeader->lpExeName);
190 Offset += Length;
191 }
192 else
193 {
194 break;
195 }
196 RootHeader = RootHeader->Next;
197 }
198 Length = min(Offset+1, TargetBufferSize);
199 TargetBuffer[Length] = L'\0';
200 return Length * sizeof(WCHAR);
201 }
202
203 UINT
204 IntGetAllConsoleAliasesLength(PALIAS_HEADER Header)
205 {
206 UINT Length = 0;
207 PALIAS_ENTRY CurEntry = Header->Data;
208
209 while(CurEntry)
210 {
211 Length += wcslen(CurEntry->lpSource);
212 Length += wcslen(CurEntry->lpTarget);
213 Length += 2; // zero byte and '='
214 CurEntry = CurEntry->Next;
215 }
216
217 if (Length)
218 {
219 return (Length+1) * sizeof(WCHAR);
220 }
221 return 0;
222 }
223
224 UINT
225 IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBufferLength)
226 {
227 PALIAS_ENTRY CurEntry = Header->Data;
228 UINT Offset = 0;
229 UINT SrcLength, TargetLength;
230
231 TargetBufferLength /= sizeof(WCHAR);
232 while(CurEntry)
233 {
234 SrcLength = wcslen(CurEntry->lpSource) + 1;
235 TargetLength = wcslen(CurEntry->lpTarget) + 1;
236 if (Offset + TargetLength + SrcLength >= TargetBufferLength)
237 break;
238
239 wcscpy(&TargetBuffer[Offset], CurEntry->lpSource);
240 Offset += SrcLength;
241 TargetBuffer[Offset] = L'=';
242 wcscpy(&TargetBuffer[Offset], CurEntry->lpTarget);
243 Offset += TargetLength;
244
245 CurEntry = CurEntry->Next;
246 }
247 TargetBuffer[Offset] = L'\0';
248 return Offset * sizeof(WCHAR);
249 }
250
251 VOID
252 IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry)
253 {
254 PALIAS_ENTRY *LastLink = &Header->Data;
255 PALIAS_ENTRY CurEntry;
256
257 while ((CurEntry = *LastLink) != NULL)
258 {
259 if (CurEntry == Entry)
260 {
261 *LastLink = Entry->Next;
262 RtlFreeHeap(ConSrvHeap, 0, Entry);
263 return;
264 }
265 LastLink = &CurEntry->Next;
266 }
267 }
268
269 VOID
270 IntDeleteAllAliases(PALIAS_HEADER RootHeader)
271 {
272 PALIAS_HEADER Header, NextHeader;
273 PALIAS_ENTRY Entry, NextEntry;
274
275 for (Header = RootHeader; Header; Header = NextHeader)
276 {
277 NextHeader = Header->Next;
278 for (Entry = Header->Data; Entry; Entry = NextEntry)
279 {
280 NextEntry = Entry->Next;
281 RtlFreeHeap(ConSrvHeap, 0, Entry);
282 }
283 RtlFreeHeap(ConSrvHeap, 0, Header);
284 }
285 }
286
287
288 /* PUBLIC SERVER APIS *********************************************************/
289
290 CSR_API(SrvAddConsoleAlias)
291 {
292 PCSRSS_CONSOLE_ALIAS ConsoleAlias = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAlias;
293 PCSRSS_CONSOLE Console;
294 PALIAS_HEADER Header;
295 PALIAS_ENTRY Entry;
296 LPWSTR lpSource, lpTarget, lpExeName;
297
298 DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage);
299
300 if ( !CsrValidateMessageBuffer(ApiMessage,
301 (PVOID*)&ConsoleAlias->Source,
302 ConsoleAlias->SourceLength,
303 sizeof(BYTE)) ||
304 !CsrValidateMessageBuffer(ApiMessage,
305 (PVOID*)&ConsoleAlias->Target,
306 ConsoleAlias->TargetLength,
307 sizeof(BYTE)) ||
308 !CsrValidateMessageBuffer(ApiMessage,
309 (PVOID*)&ConsoleAlias->Exe,
310 ConsoleAlias->ExeLength,
311 sizeof(BYTE)) )
312 {
313 return STATUS_INVALID_PARAMETER;
314 }
315
316 lpSource = ConsoleAlias->Source;
317 lpTarget = (ConsoleAlias->TargetLength != 0 ? ConsoleAlias->Target : NULL);
318 lpExeName = ConsoleAlias->Exe;
319
320 DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource, lpExeName, lpTarget);
321
322 if (lpExeName == NULL || lpSource == NULL)
323 {
324 return STATUS_INVALID_PARAMETER;
325 }
326
327 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
328 if (!NT_SUCCESS(ApiMessage->Status))
329 {
330 return ApiMessage->Status;
331 }
332
333 Header = IntFindAliasHeader(Console->Aliases, lpExeName);
334 if (!Header && lpTarget != NULL)
335 {
336 Header = IntCreateAliasHeader(lpExeName);
337 if (!Header)
338 {
339 ConioUnlockConsole(Console);
340 return STATUS_INSUFFICIENT_RESOURCES;
341 }
342 IntInsertAliasHeader(&Console->Aliases, Header);
343 }
344
345 if (lpTarget == NULL) // Delete the entry
346 {
347 Entry = IntGetAliasEntry(Header, lpSource);
348 if (Entry)
349 {
350 IntDeleteAliasEntry(Header, Entry);
351 ApiMessage->Status = STATUS_SUCCESS;
352 }
353 else
354 {
355 ApiMessage->Status = STATUS_INVALID_PARAMETER;
356 }
357 ConioUnlockConsole(Console);
358 return ApiMessage->Status;
359 }
360
361 Entry = IntCreateAliasEntry(lpSource, lpTarget);
362
363 if (!Entry)
364 {
365 ConioUnlockConsole(Console);
366 return STATUS_INSUFFICIENT_RESOURCES;
367 }
368
369 IntInsertAliasEntry(Header, Entry);
370 ConioUnlockConsole(Console);
371 return STATUS_SUCCESS;
372 }
373
374 CSR_API(SrvGetConsoleAlias)
375 {
376 PCSRSS_CONSOLE_ALIAS ConsoleAlias = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAlias;
377 PCSRSS_CONSOLE Console;
378 PALIAS_HEADER Header;
379 PALIAS_ENTRY Entry;
380 UINT Length;
381 LPWSTR lpSource, lpTarget, lpExeName;
382
383 DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage);
384
385 if ( !CsrValidateMessageBuffer(ApiMessage,
386 (PVOID*)&ConsoleAlias->Source,
387 ConsoleAlias->SourceLength,
388 sizeof(BYTE)) ||
389 !CsrValidateMessageBuffer(ApiMessage,
390 (PVOID*)&ConsoleAlias->Target,
391 ConsoleAlias->TargetLength,
392 sizeof(BYTE)) ||
393 !CsrValidateMessageBuffer(ApiMessage,
394 (PVOID*)&ConsoleAlias->Exe,
395 ConsoleAlias->ExeLength,
396 sizeof(BYTE)) )
397 {
398 return STATUS_INVALID_PARAMETER;
399 }
400
401 lpSource = ConsoleAlias->Source;
402 lpTarget = ConsoleAlias->Target;
403 lpExeName = ConsoleAlias->Exe;
404
405 DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
406 lpExeName, lpSource, lpTarget, ConsoleAlias->TargetLength);
407
408 if (ConsoleAlias->ExeLength == 0 || lpTarget == NULL ||
409 ConsoleAlias->TargetLength == 0 || ConsoleAlias->SourceLength == 0)
410 {
411 return STATUS_INVALID_PARAMETER;
412 }
413
414 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
415 if (!NT_SUCCESS(ApiMessage->Status))
416 {
417 return ApiMessage->Status;
418 }
419
420 Header = IntFindAliasHeader(Console->Aliases, lpExeName);
421 if (!Header)
422 {
423 ConioUnlockConsole(Console);
424 return STATUS_INVALID_PARAMETER;
425 }
426
427 Entry = IntGetAliasEntry(Header, lpSource);
428 if (!Entry)
429 {
430 ConioUnlockConsole(Console);
431 return STATUS_INVALID_PARAMETER;
432 }
433
434 Length = (wcslen(Entry->lpTarget) + 1) * sizeof(WCHAR);
435 if (Length > ConsoleAlias->TargetLength)
436 {
437 ConioUnlockConsole(Console);
438 return STATUS_BUFFER_TOO_SMALL;
439 }
440
441 /*
442 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process, lpTarget,
443 ConsoleAlias->TargetLength, 1))
444 {
445 ConioUnlockConsole(Console);
446 return STATUS_ACCESS_VIOLATION;
447 }
448 */
449
450 wcscpy(lpTarget, Entry->lpTarget);
451 ConsoleAlias->TargetLength = Length;
452 ConioUnlockConsole(Console);
453 return STATUS_SUCCESS;
454 }
455
456 CSR_API(SrvGetConsoleAliases)
457 {
458 PCSRSS_GET_ALL_CONSOLE_ALIASES GetAllConsoleAliases = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllConsoleAliases;
459 PCSRSS_CONSOLE Console;
460 ULONG BytesWritten;
461 PALIAS_HEADER Header;
462
463 if ( !CsrValidateMessageBuffer(ApiMessage,
464 (PVOID)&GetAllConsoleAliases->ExeName,
465 GetAllConsoleAliases->ExeLength,
466 sizeof(BYTE)) ||
467 !CsrValidateMessageBuffer(ApiMessage,
468 (PVOID)&GetAllConsoleAliases->AliasesBuffer,
469 GetAllConsoleAliases->AliasesBufferLength,
470 sizeof(BYTE)) )
471 {
472 return STATUS_INVALID_PARAMETER;
473 }
474
475 if (GetAllConsoleAliases->ExeName == NULL)
476 {
477 return STATUS_INVALID_PARAMETER;
478 }
479
480 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
481 if (!NT_SUCCESS(ApiMessage->Status))
482 {
483 return ApiMessage->Status;
484 }
485
486 Header = IntFindAliasHeader(Console->Aliases, GetAllConsoleAliases->ExeName);
487 if (!Header)
488 {
489 ConioUnlockConsole(Console);
490 return STATUS_INVALID_PARAMETER;
491 }
492
493 if (IntGetAllConsoleAliasesLength(Header) > GetAllConsoleAliases->AliasesBufferLength)
494 {
495 ConioUnlockConsole(Console);
496 return STATUS_BUFFER_OVERFLOW;
497 }
498
499 /*
500 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
501 GetAllConsoleAliases->AliasesBuffer,
502 GetAllConsoleAliases->AliasesBufferLength,
503 1))
504 {
505 ConioUnlockConsole(Console);
506 return STATUS_ACCESS_VIOLATION;
507 }
508 */
509
510 BytesWritten = IntGetAllConsoleAliases(Header,
511 GetAllConsoleAliases->AliasesBuffer,
512 GetAllConsoleAliases->AliasesBufferLength);
513
514 GetAllConsoleAliases->AliasesBufferLength = BytesWritten;
515 ConioUnlockConsole(Console);
516 return STATUS_SUCCESS;
517 }
518
519 CSR_API(SrvGetConsoleAliasesLength)
520 {
521 PCSRSS_GET_ALL_CONSOLE_ALIASES_LENGTH GetAllConsoleAliasesLength = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllConsoleAliasesLength;
522 PCSRSS_CONSOLE Console;
523 PALIAS_HEADER Header;
524 UINT Length;
525
526 if (!CsrValidateMessageBuffer(ApiMessage,
527 (PVOID)&GetAllConsoleAliasesLength->ExeName,
528 GetAllConsoleAliasesLength->ExeLength,
529 sizeof(BYTE)))
530 {
531 return STATUS_INVALID_PARAMETER;
532 }
533
534 if (GetAllConsoleAliasesLength->ExeName == NULL)
535 {
536 return STATUS_INVALID_PARAMETER;
537 }
538
539 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
540 if (!NT_SUCCESS(ApiMessage->Status))
541 {
542 return ApiMessage->Status;
543 }
544
545 Header = IntFindAliasHeader(Console->Aliases, GetAllConsoleAliasesLength->ExeName);
546 if (!Header)
547 {
548 ConioUnlockConsole(Console);
549 return STATUS_INVALID_PARAMETER;
550 }
551
552 Length = IntGetAllConsoleAliasesLength(Header);
553 GetAllConsoleAliasesLength->Length = Length;
554 ConioUnlockConsole(Console);
555 return STATUS_SUCCESS;
556 }
557
558 CSR_API(SrvGetConsoleAliasExes)
559 {
560 PCSRSS_GET_CONSOLE_ALIASES_EXES GetConsoleAliasesExes = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleAliasesExes;
561 PCSRSS_CONSOLE Console;
562 UINT BytesWritten;
563 UINT ExesLength;
564
565 DPRINT("SrvGetConsoleAliasExes entered\n");
566
567 if (!CsrValidateMessageBuffer(ApiMessage,
568 (PVOID)&GetConsoleAliasesExes->ExeNames,
569 GetConsoleAliasesExes->Length,
570 sizeof(BYTE)))
571 {
572 return STATUS_INVALID_PARAMETER;
573 }
574
575 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
576 if (!NT_SUCCESS(ApiMessage->Status))
577 {
578 return ApiMessage->Status;
579 }
580
581 ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases);
582
583 if (ExesLength > GetConsoleAliasesExes->Length)
584 {
585 ConioUnlockConsole(Console);
586 return STATUS_BUFFER_OVERFLOW;
587 }
588
589 if (GetConsoleAliasesExes->ExeNames == NULL)
590 {
591 ConioUnlockConsole(Console);
592 return STATUS_INVALID_PARAMETER;
593 }
594
595 /*
596 if (!Win32CsrValidateBuffer(CsrGetClientThread()->Process,
597 GetConsoleAliasesExes->ExeNames,
598 GetConsoleAliasesExes->Length,
599 1))
600 {
601 ConioUnlockConsole(Console);
602 return STATUS_ACCESS_VIOLATION;
603 }
604 */
605
606 BytesWritten = IntGetConsoleAliasesExes(Console->Aliases,
607 GetConsoleAliasesExes->ExeNames,
608 GetConsoleAliasesExes->Length);
609
610 GetConsoleAliasesExes->Length = BytesWritten;
611 ConioUnlockConsole(Console);
612 return STATUS_SUCCESS;
613 }
614
615 CSR_API(SrvGetConsoleAliasExesLength)
616 {
617 PCSRSS_GET_CONSOLE_ALIASES_EXES_LENGTH GetConsoleAliasesExesLength = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleAliasesExesLength;
618 PCSRSS_CONSOLE Console;
619 DPRINT("SrvGetConsoleAliasExesLength entered\n");
620
621 ApiMessage->Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
622 if (NT_SUCCESS(ApiMessage->Status))
623 {
624 GetConsoleAliasesExesLength->Length = IntGetConsoleAliasesExesLength(Console->Aliases);
625 ConioUnlockConsole(Console);
626 }
627 return ApiMessage->Status;
628 }
629
630 /* EOF */