summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
authortumagonx2017-08-08 10:54:53 +0700
committertumagonx2017-08-08 10:54:53 +0700
commit2acec63b2ed75bf4b71ad257db573c4b8f9639e7 (patch)
treea8bea139ddd26116d44ea182b0b8436f2162e6e3 /misc.c
initial commit
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c943
1 files changed, 943 insertions, 0 deletions
diff --git a/misc.c b/misc.c
new file mode 100644
index 0000000..1381272
--- /dev/null
+++ b/misc.c
@@ -0,0 +1,943 @@
1/*
2 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
3 *
4 * Module Name:
5 *
6 * misc.c
7 *
8 * Abstract:
9 *
10 * This module implements various miscellaneous routines.
11 *
12 * Author:
13 *
14 * Eugene Tsyrklevich 24-Feb-2004
15 *
16 * Revision History:
17 *
18 * None.
19 */
20
21
22#include "misc.h"
23#include "process.h"
24#include "userland.h"
25#include "policy.h"
26#include "token.h"
27
28
29BOOLEAN BootingUp = FALSE;
30
31
32/*
33 * atoi()
34 *
35 * Description:
36 * Convert a given string to an integer.
37 *
38 * Parameters:
39 * buf - Pointer to a source character string.
40 *
41 * Returns:
42 * String's integer value (0 in case of an error).
43 */
44
45INT32
46atoi(IN PCHAR buf)
47{
48 int ret = 0;
49
50
51 while (*buf >= '0' && *buf <= '9')
52 {
53 ret *= 10;
54 ret += *buf - '0';
55 buf++;
56 }
57
58
59 return ret;
60}
61
62
63
64/*
65 * itoa()
66 *
67 * Description:
68 * Convert an integer to a string.
69 *
70 * Parameters:
71 * value - Number to be converted.
72 * string - String result.
73 * radix - Base of value; must be in the range 2 – 36.
74 *
75 * Returns:
76 * Pointer to a string.
77 */
78
79PCHAR
80itoa(int value, char *string, unsigned int radix)
81{
82 static const char base36[] = "0123456789abcdefghijklmnopqrstuvwxyz";
83 PCHAR s;
84 int tmp = value;
85 int digits = 1;
86
87
88 ASSERT(radix > 1 && radix < (int) sizeof base36);
89 ASSERT(string);
90 ASSERT(value >= 0);
91
92 while ((tmp /= (int)radix) != 0)
93 ++digits;
94
95 s = string;
96
97 string += digits;
98 *string = '\0';
99
100 do {
101
102 *--string = base36[value % radix];
103
104 } while ((value /= radix) != 0);
105
106
107 return string;
108}
109
110
111
112/*
113 * ntohl()
114 *
115 * Description:
116 * Convert a ULONG from TCP/IP network order to host byte order (which is little-endian on Intel processors).
117 *
118 * Parameters:
119 * netlong - 32-bit number in TCP/IP network byte order.
120 *
121 * Returns:
122 * The value in host byte order.
123 * If the netlong parameter was already in host byte order, then no operation is performed.
124 */
125
126ULONG
127ntohl(IN ULONG netlong)
128{
129 ULONG result = 0;
130
131 ((char *)&result)[0] = ((char *)&netlong)[3];
132 ((char *)&result)[1] = ((char *)&netlong)[2];
133 ((char *)&result)[2] = ((char *)&netlong)[1];
134 ((char *)&result)[3] = ((char *)&netlong)[0];
135
136 return result;
137}
138
139
140
141/*
142 * ntohs()
143 *
144 * Description:
145 * Convert a USHORT from TCP/IP network byte order to host byte order (which is little-endian on Intel processors).
146 *
147 * Parameters:
148 * netshort - 16-bit number in TCP/IP network byte order.
149 *
150 * Returns:
151 * The value in host byte order.
152 * If the netshort parameter was already in host byte order, then no operation is performed.
153 */
154
155USHORT
156ntohs(IN USHORT netshort)
157{
158 USHORT result = 0;
159
160 ((char *)&result)[0] = ((char *)&netshort)[1];
161 ((char *)&result)[1] = ((char *)&netshort)[0];
162
163 return result;
164}
165
166
167/*
168 * htonl()
169 *
170 * Description:
171 * Converts a ULONG from host to TCP/IP network byte order (which is big-endian).
172 *
173 * Parameters:
174 * hostlong - 32-bit number in host byte order.
175 *
176 * Returns:
177 * The value in TCP/IP's network byte order.
178 */
179
180ULONG
181htonl(ULONG hostlong)
182{
183 ULONG r1, r2, r3, r4;
184
185 r1 = (hostlong >> 24);
186 r2 = (hostlong << 24);
187 r3 = (hostlong & 0xff00) << 8;
188 r4 = (hostlong >> 8) & 0xff00;
189
190 return (r1 | r2 | r3 | r4);
191}
192
193
194
195/*
196 * inet_aton()
197 *
198 * Description:
199 * Convert a ULONG from host to TCP/IP network byte order (which is big-endian).
200 *
201 * Parameters:
202 * hostlong - 32-bit number in host byte order.
203 *
204 * Returns:
205 * returns the value in TCP/IP's network byte order.
206 */
207
208#define _islower(c) ( ((c) >= 'a' && (c) <= 'f') )
209#define _isxdigit(c) ( ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F') )
210#define _isascii(c) ( (c) <= 0177 )
211#define _isdigit(c) ( ((c) >= '0' && (c) <= '9') )
212#define _isspace(c) ( ((c) == ' ' ) )
213
214//XXX verify... can invalid IPs be accepted as valid ones?
215
216
217/*
218 * inet_addr() XXX rewrite
219 *
220 * Description:
221 * Convert a string containing an (IPv4) Internet Protocol dotted address into a ULONG (network order).
222 *
223 * Parameters:
224 * cp - Null-terminated character string representing a number expressed in the Internet
225 * standard ".'' (dotted) notation.
226 *
227 * Returns:
228 * A ULONG value containing a suitable binary representation of the Internet address given.
229 */
230
231ULONG
232inet_addr(PCCHAR cp)
233{
234 ULONG val;
235 int base, n;
236 char c;
237 unsigned int parts[4];
238 unsigned int *pp = parts;
239
240 c = *cp;
241 for (;;) {
242 /*
243 * Collect number up to ``.''.
244 * Values are specified as for C:
245 * 0x=hex, 0=octal, isdigit=decimal.
246 */
247 if (!_isdigit(c))
248 return (0);
249
250 val = 0; base = 10;
251//XXX get rid of multiple base support?
252 if (c == '0') {
253 c = *++cp;
254 if (c == 'x' || c == 'X')
255 base = 16, c = *++cp;
256 else
257 base = 8;
258 }
259
260 for (;;) {
261 if (_isascii(c) && _isdigit(c)) {
262 val = (val * base) + (c - '0');
263 c = *++cp;
264 } else if (base == 16 && _isascii(c) && _isxdigit(c)) {
265 val = (val << 4) |
266 (c + 10 - (_islower(c) ? 'a' : 'A'));
267 c = *++cp;
268 } else
269 break;
270 }
271
272 if (c == '.') {
273 /*
274 * Internet format:
275 * a.b.c.d
276 * a.b.c (with c treated as 16 bits)
277 * a.b (with b treated as 24 bits)
278 */
279 if (pp >= parts + 3)
280 return (0);
281 *pp++ = val;
282 c = *++cp;
283 } else
284 break;
285 }
286 /*
287 * Check for trailing characters.
288 */
289 if (c != '\0' && (!_isascii(c) || !_isspace(c)))
290 return (0);
291 /*
292 * Concoct the address according to
293 * the number of parts specified.
294 */
295 n = pp - parts + 1;
296 switch (n) {
297
298 case 0:
299 return (0); /* initial nondigit */
300
301 case 1: /* a -- 32 bits */
302 break;
303
304 case 2: /* a.b -- 8.24 bits */
305 if (val > 0xffffff)
306 return (0);
307 val |= parts[0] << 24;
308 break;
309
310 case 3: /* a.b.c -- 8.8.16 bits */
311 if (val > 0xffff)
312 return (0);
313 val |= (parts[0] << 24) | (parts[1] << 16);
314 break;
315
316 case 4: /* a.b.c.d -- 8.8.8.8 bits */
317 if (val > 0xff)
318 return (0);
319 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
320 break;
321 }
322
323 return htonl(val);
324}
325
326
327
328/*
329 * inet_ntoa()
330 *
331 * Description:
332 * Convert an (IPv4) Internet network address into a string in Internet standard dotted format.
333 *
334 * Parameters:
335 * ina - ULONG that represents an Internet host address.
336 *
337 * Returns:
338 * A character pointer to a static buffer containing the text address in standard ".'' notation.
339 */
340
341//XXX not SMP safe
342PCHAR
343inet_ntoa2(ULONG ina)
344{
345 static char buf[4*sizeof "123"];
346 unsigned char *ucp = (unsigned char *)&ina;
347
348 sprintf(buf, "%d.%d.%d.%d",
349 ucp[0] & 0xff,
350 ucp[1] & 0xff,
351 ucp[2] & 0xff,
352 ucp[3] & 0xff);
353
354 return buf;
355}
356
357/* XXX move to netmisc.c or network.c */
358VOID
359inet_ntoa(ULONG ina, PCHAR buf)
360{
361 unsigned char *ucp = (unsigned char *)&ina;
362
363 sprintf(buf, "%d.%d.%d.%d",
364 ucp[0] & 0xff,
365 ucp[1] & 0xff,
366 ucp[2] & 0xff,
367 ucp[3] & 0xff);
368}
369
370
371
372/*
373 * VerifyUnicodeString()
374 *
375 * Description:
376 * Make sure Unicode String buffer is readable.
377 *
378 * Parameters:
379 * InputUnicodeString - input unicode buffer.
380 * OutputUnicodeString - output buffer.
381 *
382 * Returns:
383 * TRUE to indicate success, FALSE is failed.
384 */
385
386#define FINISH_VerifyUnicodeString(msg) \
387 do { \
388 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, msg); \
389 return(FALSE); \
390 } while(0)
391
392BOOLEAN
393VerifyUnicodeString(IN PUNICODE_STRING InputUnicodeString, OUT PUNICODE_STRING OutputUnicodeString)
394{
395 if (! ARGUMENT_PRESENT(InputUnicodeString) )
396
397 FINISH_VerifyUnicodeString(("VerifyUnicodeString: Unicode string is NULL\n"));
398
399
400 /* this code is duplicated in pathproc.c!GetPathFromHandle for efficiency */
401 __try
402 {
403 if (KeGetPreviousMode() != KernelMode)
404 {
405 ProbeForRead(InputUnicodeString, sizeof(UNICODE_STRING), sizeof(ULONG));
406
407 *OutputUnicodeString = ProbeAndReadUnicodeString(InputUnicodeString);
408 }
409 else
410 {
411 *OutputUnicodeString = *InputUnicodeString;
412 }
413
414
415 if (OutputUnicodeString->Length == 0)
416
417 return FALSE;
418
419
420 if (((OutputUnicodeString->Length & (sizeof(WCHAR) - 1)) != 0) ||
421 (OutputUnicodeString->Length > bMAX_PATH - sizeof(WCHAR)) )
422
423 FINISH_VerifyUnicodeString(("VerifyUnicodeString: invalid wchar string length = %d\n", OutputUnicodeString->Length));
424
425
426 if (KeGetPreviousMode() != KernelMode)
427
428 ProbeForRead(OutputUnicodeString->Buffer, OutputUnicodeString->Length, sizeof(WCHAR));
429 }
430
431 __except(EXCEPTION_EXECUTE_HANDLER)
432 {
433 NTSTATUS status = GetExceptionCode();
434
435 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("VerifyUnicodeString: caught an exception. status = 0x%x\n", status));
436
437 return(FALSE);
438 }
439
440 return(TRUE);
441}
442
443
444
445/*
446 * VerifyPwstr()
447 *
448 * Description:
449 * Make sure PWSTR buffer is readable.
450 *
451 * Parameters:
452 * InputString - input PWSTR buffer.
453 * InputStringLength - input string length.
454 *
455 * Returns:
456 * TRUE to indicate success, FALSE is failed.
457 */
458
459#define FINISH_VerifyPwstr(msg) \
460 do { \
461 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, msg); \
462 return(FALSE); \
463 } while(0)
464
465BOOLEAN
466VerifyPwstr(IN PWSTR InputString, IN ULONG InputStringLength)
467{
468 if (! ARGUMENT_PRESENT(InputString) )
469
470 FINISH_VerifyPwstr(("VerifyPwstr: Input string is NULL\n"));
471
472
473 if ((InputStringLength == 0) ||
474 ((InputStringLength & (sizeof(WCHAR) - 1)) != 0) ||
475 (InputStringLength > bMAX_PATH - sizeof(WCHAR)) )
476
477 FINISH_VerifyPwstr(("VerifyPwstr: invalid wchar string length = %d\n", InputStringLength));
478
479
480 if (KeGetPreviousMode() != KernelMode)
481 {
482 __try
483 {
484 ProbeForRead(InputString, InputStringLength, sizeof(WCHAR));
485 }
486
487 __except(EXCEPTION_EXECUTE_HANDLER)
488 {
489 NTSTATUS status = GetExceptionCode();
490
491 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("VerifyPwstr: caught an exception. address=%x, status = 0x%x\n", InputString, status));
492
493 return(FALSE);
494 }
495 }
496
497
498 return(TRUE);
499}
500
501
502
503/*
504 * ReadStringRegistryValue()
505 *
506 * Description:
507 * .
508 *
509 * Parameters:
510 * .
511 *
512 * Returns:
513 * TRUE to indicate success, FALSE is failed.
514 */
515
516#define FINISH_ReadStringRegistryValue(msg) \
517 do { \
518 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, msg); \
519 if (vpip) ExFreePoolWithTag(vpip, _POOL_TAG); \
520 if (hKey) ZwClose(hKey); \
521 return(NULL); \
522 } while(0)
523
524PKEY_VALUE_PARTIAL_INFORMATION
525ReadStringRegistryValue(IN PWSTR RegistryPath, IN PWSTR KeyName, OUT ULONG *VPIPSize)
526{
527 OBJECT_ATTRIBUTES oa;
528 HANDLE hKey = 0;
529 UNICODE_STRING usRegistryPath, usKeyName;
530 ULONG size;
531 NTSTATUS status;
532 PKEY_VALUE_PARTIAL_INFORMATION vpip = NULL;
533 PCHAR FunctionName = "ReadStringRegistryValue";
534
535
536 if (RegistryPath == NULL || KeyName == NULL)
537
538 FINISH_ReadStringRegistryValue(("%s: Received NULL parameter. %x %x\n", RegistryPath, KeyName));
539
540
541 RtlInitUnicodeString(&usRegistryPath, RegistryPath);
542
543 InitializeObjectAttributes(&oa, &usRegistryPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
544
545 status = ZwOpenKey(&hKey, KEY_QUERY_VALUE , &oa);
546 if (! NT_SUCCESS(status))
547
548 FINISH_ReadStringRegistryValue(("%s: ZwOpenKey('%S') failed with status=%x\n", FunctionName, RegistryPath, status));
549
550
551 RtlInitUnicodeString(&usKeyName, KeyName);
552
553 status = ZwQueryValueKey(hKey, &usKeyName, KeyValuePartialInformation, NULL, 0, &size);
554 if (status == STATUS_OBJECT_NAME_NOT_FOUND || size == 0)
555
556 FINISH_ReadStringRegistryValue(("%s: ZwQueryValueKey(%S) failed with status=%x\n", FunctionName, KeyName, status));
557
558
559 vpip = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, size, _POOL_TAG);
560
561 if (!vpip)
562
563 FINISH_ReadStringRegistryValue(("%s: out of memory\n", FunctionName));
564
565
566 status = ZwQueryValueKey(hKey, &usKeyName, KeyValuePartialInformation, vpip, size, &size);
567 if (! NT_SUCCESS(status))
568
569 FINISH_ReadStringRegistryValue(("%s: ZwQueryValueKey2(%S) failed with status=%x\n", FunctionName, KeyName, status));
570
571
572 if (vpip->Type != REG_SZ)
573
574 FINISH_ReadStringRegistryValue(("%s: Wrong Type: %x\n", FunctionName, vpip->Type));
575
576
577 ZwClose(hKey);
578
579
580 *VPIPSize = size;
581
582
583 return vpip;
584}
585
586
587
588/*
589 * ReadStringRegistryValueA()
590 *
591 * Description:
592 * Read an ASCII value from the registry.
593 *
594 * Parameters:
595 * .
596 *
597 * Returns:
598 * TRUE to indicate success, FALSE is failed.
599 */
600
601BOOLEAN
602ReadStringRegistryValueA(IN PWSTR RegistryPath, IN PWSTR KeyName, OUT PCHAR Buffer, IN USHORT BufferSize)
603{
604 PKEY_VALUE_PARTIAL_INFORMATION vpip;
605 ULONG size;
606
607
608 ASSERT(Buffer);
609
610
611 if ((vpip = ReadStringRegistryValue(RegistryPath, KeyName, &size)) == NULL)
612 return FALSE;
613
614
615 if (_snprintf(Buffer, BufferSize, "%S", (PWSTR) &vpip->Data) < 0)
616 {
617 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%s: Buffer is too small %d vs %d\n", BufferSize, size));
618 ExFreePoolWithTag(vpip, _POOL_TAG);
619 return FALSE;
620 }
621 Buffer[BufferSize - 1] = 0;
622
623
624 ExFreePoolWithTag(vpip, _POOL_TAG);
625
626
627 return TRUE;
628}
629
630
631
632/*
633 * ReadStringRegistryValueW()
634 *
635 * Description:
636 * Read a UNICODE value from the registry.
637 *
638 * Parameters:
639 * .
640 *
641 * Returns:
642 * TRUE to indicate success, FALSE is failed.
643 */
644
645BOOLEAN
646ReadStringRegistryValueW(IN PWSTR RegistryPath, IN PWSTR KeyName, OUT PWSTR Buffer, IN USHORT BufferSize)
647{
648 PKEY_VALUE_PARTIAL_INFORMATION vpip;
649 ULONG size;
650
651
652 ASSERT(Buffer);
653
654
655 if ((vpip = ReadStringRegistryValue(RegistryPath, KeyName, &size)) == NULL)
656 return FALSE;
657
658
659 if ((size - sizeof(KEY_VALUE_PARTIAL_INFORMATION)) + 1 > BufferSize)
660 {
661 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%s: Buffer is too small %d vs %d\n", BufferSize, size));
662 ExFreePoolWithTag(vpip, _POOL_TAG);
663 return FALSE;
664 }
665
666 wcsncpy(Buffer, (PWSTR) vpip->Data, BufferSize);
667 Buffer[BufferSize - 1] = 0;
668
669
670 ExFreePoolWithTag(vpip, _POOL_TAG);
671
672
673 return TRUE;
674}
675
676
677
678/*
679 * ReadSymlinkValue()
680 *
681 * Description:
682 * .
683 *
684 * Parameters:
685 * .
686 *
687 * Returns:
688 * TRUE to indicate success, FALSE is failed.
689 */
690
691#define FINISH_ReadSymlinkValue(msg) \
692 do { \
693 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, msg); \
694 if (hLink) ZwClose(hLink); \
695 return(FALSE); \
696 } while(0)
697
698BOOLEAN
699ReadSymlinkValue(IN PWSTR SymlinkPath, OUT PCHAR Buffer, IN USHORT BufferSize)
700{
701 OBJECT_ATTRIBUTES oa;
702 HANDLE hLink = 0;
703 UNICODE_STRING usLink;
704 ANSI_STRING asLink;
705 WCHAR Link[MAX_PATH];
706 ULONG size;
707 NTSTATUS status;
708
709
710 RtlInitUnicodeString(&usLink, SymlinkPath);
711 InitializeObjectAttributes(&oa, &usLink, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);
712
713 status = ZwOpenSymbolicLinkObject(&hLink, GENERIC_READ, &oa);
714 if (! NT_SUCCESS(status))
715
716 FINISH_ReadSymlinkValue(("ReadSymlinkValue: Unable to open '%S' link. status=%x\n", SymlinkPath, status));
717
718
719 usLink.Buffer = Link;
720 usLink.MaximumLength = bMAX_PATH;
721 usLink.Length = 0;
722
723 status = ZwQuerySymbolicLinkObject(hLink, &usLink, NULL);
724 if (! NT_SUCCESS(status))
725
726 FINISH_ReadSymlinkValue(("ReadSymlinkValue: Unable to query SystemRoot link. status=%x\n", status));
727
728
729 asLink.Length = 0;
730 asLink.MaximumLength = BufferSize;
731 asLink.Buffer = Buffer;
732
733 RtlUnicodeStringToAnsiString(&asLink, &usLink, FALSE);
734 asLink.Buffer[asLink.Length] = '\0';
735
736
737 ZwClose(hLink);
738
739 return TRUE;
740}
741
742
743
744/*
745 * RunPostBootup()
746 *
747 * Description:
748 * Initializes any subsystems that require to be initialized after the system finished booting up.
749 *
750 * Parameters:
751 * None.
752 *
753 * Returns:
754 * Nothing.
755 */
756
757VOID
758InitPostBootup()
759{
760 ASSERT(BootingUp == FALSE);
761
762 ProcessPostBootup();
763 LogPostBootup();
764 PolicyPostBootup();
765 UserlandPostBootup();
766}
767
768
769
770/*
771 * GetCurrentUserSid()
772 *
773 * Description:
774 * Retrieves current user's SID.
775 *
776 * Parameters:
777 * Size - Extra number of bytes to allocate [IN]. Total number of bytes allocated [OUT].
778 *
779 * Returns:
780 * Pointer to an allocated memory block, the actual SID is at offset +Size.
781 * NULL is failed.
782 */
783
784typedef struct _TOKEN_GROUPS {
785 DWORD GroupCount;
786 SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
787} TOKEN_GROUPS, *PTOKEN_GROUPS;
788
789PCHAR
790GetCurrentUserSid(PUSHORT Size) // IN OUT
791{
792 HANDLE TokenHandle;
793 NTSTATUS status;
794 ULONG TokenSize, tmp;
795 PCHAR UserInfo;
796 PSID_AND_ATTRIBUTES psa;
797// PTOKEN_GROUPS ptg;
798// PSID ps;
799
800
801 status = ZwOpenThreadToken(CURRENT_THREAD, TOKEN_QUERY, FALSE, &TokenHandle);
802
803 if (! NT_SUCCESS(status))
804 {
805 if (status != STATUS_NO_TOKEN)
806 {
807 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d GetCurrentUserSid: ZwOpenThreadToken failed with status %x\n", status));
808 return NULL;
809 }
810
811 status = ZwOpenProcessToken(CURRENT_PROCESS, TOKEN_QUERY, &TokenHandle);
812
813 if (! NT_SUCCESS(status))
814 {
815 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d GetCurrentUserSid: ZwOpenProcessToken failed with status %x\n", status));
816 return NULL;
817 }
818 }
819
820
821 /* first, find out the total amount of token information to be returned */
822
823 status = ZwQueryInformationToken(TokenHandle, TokenUser, &TokenSize, 0, &TokenSize);
824// status = ZwQueryInformationToken(TokenHandle, TokenGroups, &TokenSize, 0, &TokenSize);
825// status = ZwQueryInformationToken(TokenHandle, TokenPrimaryGroup, &TokenSize, 0, &TokenSize);
826 if (status != STATUS_BUFFER_TOO_SMALL || TokenSize == 0)
827 {
828 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("GetCurrentUserSid: ZwQueryInformationToken failed. status=%x size=%d\n", status, TokenSize));
829 return NULL;
830 }
831
832
833 /* second, allocate the required amount of memory */
834
835 UserInfo = ExAllocatePoolWithTag(NonPagedPool, TokenSize + *Size, _POOL_TAG);
836 if (UserInfo == NULL)
837 {
838 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("GetCurrentUserSid: out of memory (requested %d bytes)\n", TokenSize + *Size));
839 return NULL;
840 }
841
842
843 psa = (PSID_AND_ATTRIBUTES) (UserInfo + *Size);
844// ptg = (PTOKEN_GROUPS) (UserInfo + *Size);
845// ps = (PSID) (UserInfo + *Size);
846
847
848 /* third, request the token information */
849
850 status = ZwQueryInformationToken(TokenHandle, TokenUser, psa, TokenSize, &tmp);
851// status = ZwQueryInformationToken(TokenHandle, TokenGroups, psa, TokenSize, &tmp);
852// status = ZwQueryInformationToken(TokenHandle, TokenPrimaryGroup, ps, TokenSize, &tmp);
853 if (! NT_SUCCESS(status))
854 {
855 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("GetCurrentUserSid: ZwQueryInformationToken failed with status %x\n", status));
856 ExFreePoolWithTag(UserInfo, _POOL_TAG);
857 return NULL;
858 }
859
860 ZwClose(TokenHandle);
861
862
863 /* convert absolute SID into a relative one */
864 psa->Sid = (PSID) ( (PCHAR) psa->Sid - (PCHAR) psa );
865/*
866 for (tmp = 0; tmp < ptg->GroupCount; tmp++)
867 {
868 ptg->Groups[tmp].Sid = (PSID) ( (PCHAR) ptg->Groups[tmp].Sid - (PCHAR) ptg->Groups );
869 }
870*/
871// * (PULONG) ps = 4;
872
873 /* return size value */
874 *Size += (USHORT) TokenSize;
875
876 return UserInfo;
877}
878
879
880
881/*
882 * NOTE: Adapted from "The VTrace Tool: Building a System Tracer for Windows NT and Windows 2000" -- MSDN Magazine, October 2000
883 * NOTE2: This function should only be called on Windows 2000+.
884 * It's not necessary on Windows NT, and, besides, on Windows NT 4.0 SP3 and earlier,
885 * MmMapLockedPages() does not give the result we need.
886 */
887
888PVOID
889ExchangeReadOnlyMemoryPointer(IN OUT PVOID *Target, IN PVOID Value)
890{
891 PMDL MDL;
892 PVOID MappedAddress, ReturnValue;
893
894
895 MDL = IoAllocateMdl(Target, sizeof(Value), FALSE, FALSE, NULL);
896
897 if (MDL == NULL)
898 return NULL;
899
900
901// MmBuildMdlForNonPagedPool(MDL);
902
903
904 /*
905 * Calls to MmProbeAndLockPages must be enclosed in a try/except block.
906 * If the pages do not support the specified operation, the routine raises the
907 * STATUS_ACCESS_VIOLATION exception.
908 */
909
910 __try
911 {
912 MmProbeAndLockPages(MDL, KernelMode, IoModifyAccess);
913 }
914
915 __except(EXCEPTION_EXECUTE_HANDLER)
916 {
917 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("ExchangeReadOnlyMemoryPointer(%x, %x): Caught an exception\n", Target, Value));
918 IoFreeMdl(MDL);
919 return NULL;
920 }
921
922
923// MappedAddress = MmMapLockedPages(MDL, KernelMode);
924 MappedAddress = MmMapLockedPagesSpecifyCache(MDL, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
925
926 if (MappedAddress == NULL)
927 {
928 MmUnlockPages(MDL);
929 IoFreeMdl(MDL);
930 return NULL;
931 }
932
933
934 ReturnValue = InterlockedExchangePointer(MappedAddress, Value);
935
936
937 MmUnmapLockedPages(MappedAddress, MDL);
938 MmUnlockPages(MDL);
939 IoFreeMdl(MDL);
940
941
942 return ReturnValue;
943}