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