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