diff options
| author | tumagonx | 2017-08-08 10:54:53 +0700 |
|---|---|---|
| committer | tumagonx | 2017-08-08 10:54:53 +0700 |
| commit | 2acec63b2ed75bf4b71ad257db573c4b8f9639e7 (patch) | |
| tree | a8bea139ddd26116d44ea182b0b8436f2162e6e3 /misc.c | |
initial commit
Diffstat (limited to 'misc.c')
| -rw-r--r-- | misc.c | 943 |
1 files changed, 943 insertions, 0 deletions
| @@ -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 | |||
| 29 | BOOLEAN 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 | |||
| 45 | INT32 | ||
| 46 | atoi(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 | |||
| 79 | PCHAR | ||
| 80 | itoa(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 | |||
| 126 | ULONG | ||
| 127 | ntohl(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 | |||
| 155 | USHORT | ||
| 156 | ntohs(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 | |||
| 180 | ULONG | ||
| 181 | htonl(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 | |||
| 231 | ULONG | ||
| 232 | inet_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 | ||
| 342 | PCHAR | ||
| 343 | inet_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 */ | ||
| 358 | VOID | ||
| 359 | inet_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 | |||
| 392 | BOOLEAN | ||
| 393 | VerifyUnicodeString(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 | |||
| 465 | BOOLEAN | ||
| 466 | VerifyPwstr(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 | |||
| 524 | PKEY_VALUE_PARTIAL_INFORMATION | ||
| 525 | ReadStringRegistryValue(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 | |||
| 601 | BOOLEAN | ||
| 602 | ReadStringRegistryValueA(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 | |||
| 645 | BOOLEAN | ||
| 646 | ReadStringRegistryValueW(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 | |||
| 698 | BOOLEAN | ||
| 699 | ReadSymlinkValue(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 | |||
| 757 | VOID | ||
| 758 | InitPostBootup() | ||
| 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 | |||
| 784 | typedef struct _TOKEN_GROUPS { | ||
| 785 | DWORD GroupCount; | ||
| 786 | SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; | ||
| 787 | } TOKEN_GROUPS, *PTOKEN_GROUPS; | ||
| 788 | |||
| 789 | PCHAR | ||
| 790 | GetCurrentUserSid(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 | |||
| 888 | PVOID | ||
| 889 | ExchangeReadOnlyMemoryPointer(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 | } | ||
