1 /* 2 * RPCRT4 3 * 4 * Copyright 2000 Huw D M Davies for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 * WINE RPC TODO's (and a few TODONT's) 21 * 22 * - Statistics: we are supposed to be keeping various counters. we aren't. 23 * 24 * - Async RPC: Unimplemented. 25 * 26 * - The NT "ports" API, aka LPC. Greg claims this is on his radar. Might (or 27 * might not) enable users to get some kind of meaningful result out of 28 * NT-based native rpcrt4's. Commonly-used transport for self-to-self RPC's. 29 */ 30 31 #include "config.h" 32 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 #include "ntstatus.h" 39 #define WIN32_NO_STATUS 40 #include "windef.h" 41 #include "winerror.h" 42 #include "winbase.h" 43 #include "winuser.h" 44 #include "winnt.h" 45 #include "winternl.h" 46 #include "iptypes.h" 47 #include "iphlpapi.h" 48 #include "wine/unicode.h" 49 #include "rpc.h" 50 51 #include "ole2.h" 52 #include "rpcndr.h" 53 #include "rpcproxy.h" 54 55 #include "rpc_binding.h" 56 57 #include "wine/debug.h" 58 59 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 60 61 static UUID uuid_nil; 62 63 static CRITICAL_SECTION uuid_cs; 64 static CRITICAL_SECTION_DEBUG critsect_debug = 65 { 66 0, 0, &uuid_cs, 67 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 68 0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") } 69 }; 70 static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; 71 72 static CRITICAL_SECTION threaddata_cs; 73 static CRITICAL_SECTION_DEBUG threaddata_cs_debug = 74 { 75 0, 0, &threaddata_cs, 76 { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList }, 77 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } 78 }; 79 static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 }; 80 81 static struct list threaddata_list = LIST_INIT(threaddata_list); 82 83 struct context_handle_list 84 { 85 struct context_handle_list *next; 86 NDR_SCONTEXT context_handle; 87 }; 88 89 struct threaddata 90 { 91 struct list entry; 92 CRITICAL_SECTION cs; 93 DWORD thread_id; 94 RpcConnection *connection; 95 RpcBinding *server_binding; 96 struct context_handle_list *context_handle_list; 97 }; 98 99 /*********************************************************************** 100 * DllMain 101 * 102 * PARAMS 103 * hinstDLL [I] handle to the DLL's instance 104 * fdwReason [I] 105 * lpvReserved [I] reserved, must be NULL 106 * 107 * RETURNS 108 * Success: TRUE 109 * Failure: FALSE 110 */ 111 112 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 113 { 114 struct threaddata *tdata; 115 116 switch (fdwReason) { 117 case DLL_PROCESS_ATTACH: 118 break; 119 120 case DLL_THREAD_DETACH: 121 tdata = NtCurrentTeb()->ReservedForNtRpc; 122 if (tdata) 123 { 124 EnterCriticalSection(&threaddata_cs); 125 list_remove(&tdata->entry); 126 LeaveCriticalSection(&threaddata_cs); 127 128 DeleteCriticalSection(&tdata->cs); 129 if (tdata->connection) 130 ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection); 131 if (tdata->server_binding) 132 ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding); 133 HeapFree(GetProcessHeap(), 0, tdata); 134 } 135 break; 136 137 case DLL_PROCESS_DETACH: 138 break; 139 } 140 141 return TRUE; 142 } 143 144 /************************************************************************* 145 * RpcStringFreeA [RPCRT4.@] 146 * 147 * Frees a character string allocated by the RPC run-time library. 148 * 149 * RETURNS 150 * 151 * S_OK if successful. 152 */ 153 RPC_STATUS WINAPI RpcStringFreeA(RPC_CSTR* String) 154 { 155 HeapFree( GetProcessHeap(), 0, *String); 156 157 return RPC_S_OK; 158 } 159 160 /************************************************************************* 161 * RpcStringFreeW [RPCRT4.@] 162 * 163 * Frees a character string allocated by the RPC run-time library. 164 * 165 * RETURNS 166 * 167 * S_OK if successful. 168 */ 169 RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String) 170 { 171 HeapFree( GetProcessHeap(), 0, *String); 172 173 return RPC_S_OK; 174 } 175 176 /************************************************************************* 177 * RpcRaiseException [RPCRT4.@] 178 * 179 * Raises an exception. 180 */ 181 void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception) 182 { 183 /* shouldn't return */ 184 RaiseException(exception, 0, 0, NULL); 185 ERR("handler continued execution\n"); 186 ExitProcess(1); 187 } 188 189 /************************************************************************* 190 * UuidCompare [RPCRT4.@] 191 * 192 * PARAMS 193 * UUID *Uuid1 [I] Uuid to compare 194 * UUID *Uuid2 [I] Uuid to compare 195 * RPC_STATUS *Status [O] returns RPC_S_OK 196 * 197 * RETURNS 198 * -1 if Uuid1 is less than Uuid2 199 * 0 if Uuid1 and Uuid2 are equal 200 * 1 if Uuid1 is greater than Uuid2 201 */ 202 int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) 203 { 204 int i; 205 206 TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); 207 208 *Status = RPC_S_OK; 209 210 if (!Uuid1) Uuid1 = &uuid_nil; 211 if (!Uuid2) Uuid2 = &uuid_nil; 212 213 if (Uuid1 == Uuid2) return 0; 214 215 if (Uuid1->Data1 != Uuid2->Data1) 216 return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1; 217 218 if (Uuid1->Data2 != Uuid2->Data2) 219 return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1; 220 221 if (Uuid1->Data3 != Uuid2->Data3) 222 return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1; 223 224 for (i = 0; i < 8; i++) { 225 if (Uuid1->Data4[i] < Uuid2->Data4[i]) 226 return -1; 227 if (Uuid1->Data4[i] > Uuid2->Data4[i]) 228 return 1; 229 } 230 231 return 0; 232 } 233 234 /************************************************************************* 235 * UuidEqual [RPCRT4.@] 236 * 237 * PARAMS 238 * UUID *Uuid1 [I] Uuid to compare 239 * UUID *Uuid2 [I] Uuid to compare 240 * RPC_STATUS *Status [O] returns RPC_S_OK 241 * 242 * RETURNS 243 * TRUE/FALSE 244 */ 245 int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) 246 { 247 TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); 248 return !UuidCompare(Uuid1, Uuid2, Status); 249 } 250 251 /************************************************************************* 252 * UuidIsNil [RPCRT4.@] 253 * 254 * PARAMS 255 * UUID *Uuid [I] Uuid to compare 256 * RPC_STATUS *Status [O] returns RPC_S_OK 257 * 258 * RETURNS 259 * TRUE/FALSE 260 */ 261 int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status) 262 { 263 TRACE("(%s)\n", debugstr_guid(Uuid)); 264 if (!Uuid) return TRUE; 265 return !UuidCompare(Uuid, &uuid_nil, Status); 266 } 267 268 /************************************************************************* 269 * UuidCreateNil [RPCRT4.@] 270 * 271 * PARAMS 272 * UUID *Uuid [O] returns a nil UUID 273 * 274 * RETURNS 275 * RPC_S_OK 276 */ 277 RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) 278 { 279 *Uuid = uuid_nil; 280 return RPC_S_OK; 281 } 282 283 /* Number of 100ns ticks per clock tick. To be safe, assume that the clock 284 resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ 285 #define TICKS_PER_CLOCK_TICK 1000 286 #define SECSPERDAY 86400 287 #define TICKSPERSEC 10000000 288 /* UUID system time starts at October 15, 1582 */ 289 #define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY) 290 #define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC) 291 292 static void RPC_UuidGetSystemTime(ULONGLONG *time) 293 { 294 FILETIME ft; 295 296 GetSystemTimeAsFileTime(&ft); 297 298 *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; 299 *time += TICKS_15_OCT_1582_TO_1601; 300 } 301 302 /* Assume that a hardware address is at least 6 bytes long */ 303 #define ADDRESS_BYTES_NEEDED 6 304 305 static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) 306 { 307 int i; 308 DWORD status = RPC_S_OK; 309 310 ULONG buflen = sizeof(IP_ADAPTER_INFO); 311 PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen); 312 313 if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) { 314 HeapFree(GetProcessHeap(), 0, adapter); 315 adapter = HeapAlloc(GetProcessHeap(), 0, buflen); 316 } 317 318 if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) { 319 for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { 320 address[i] = adapter->Address[i]; 321 } 322 } 323 /* We can't get a hardware address, just use random numbers. 324 Set the multicast bit to prevent conflicts with real cards. */ 325 else { 326 for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { 327 address[i] = rand() & 0xff; 328 } 329 330 address[0] |= 0x01; 331 status = RPC_S_UUID_LOCAL_ONLY; 332 } 333 334 HeapFree(GetProcessHeap(), 0, adapter); 335 return status; 336 } 337 338 /************************************************************************* 339 * UuidCreate [RPCRT4.@] 340 * 341 * Creates a 128bit UUID. 342 * 343 * RETURNS 344 * 345 * RPC_S_OK if successful. 346 * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. 347 * 348 * FIXME: No compensation for changes across reloading 349 * this dll or across reboots (e.g. clock going 350 * backwards and swapped network cards). The RFC 351 * suggests using NVRAM for storing persistent 352 * values. 353 */ 354 RPC_STATUS WINAPI UuidCreate(UUID *Uuid) 355 { 356 static int initialised, count; 357 358 ULONGLONG time; 359 static ULONGLONG timelast; 360 static WORD sequence; 361 362 static DWORD status; 363 static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH]; 364 365 EnterCriticalSection(&uuid_cs); 366 367 if (!initialised) { 368 RPC_UuidGetSystemTime(&timelast); 369 count = TICKS_PER_CLOCK_TICK; 370 371 sequence = ((rand() & 0xff) << 8) + (rand() & 0xff); 372 sequence &= 0x1fff; 373 374 status = RPC_UuidGetNodeAddress(address); 375 initialised = 1; 376 } 377 378 /* Generate time element of the UUID. Account for going faster 379 than our clock as well as the clock going backwards. */ 380 while (1) { 381 RPC_UuidGetSystemTime(&time); 382 if (time > timelast) { 383 count = 0; 384 break; 385 } 386 if (time < timelast) { 387 sequence = (sequence + 1) & 0x1fff; 388 count = 0; 389 break; 390 } 391 if (count < TICKS_PER_CLOCK_TICK) { 392 count++; 393 break; 394 } 395 } 396 397 timelast = time; 398 time += count; 399 400 /* Pack the information into the UUID structure. */ 401 402 Uuid->Data1 = (unsigned long)(time & 0xffffffff); 403 Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); 404 Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); 405 406 /* This is a version 1 UUID */ 407 Uuid->Data3 |= (1 << 12); 408 409 Uuid->Data4[0] = sequence & 0xff; 410 Uuid->Data4[1] = (sequence & 0x3f00) >> 8; 411 Uuid->Data4[1] |= 0x80; 412 413 Uuid->Data4[2] = address[0]; 414 Uuid->Data4[3] = address[1]; 415 Uuid->Data4[4] = address[2]; 416 Uuid->Data4[5] = address[3]; 417 Uuid->Data4[6] = address[4]; 418 Uuid->Data4[7] = address[5]; 419 420 LeaveCriticalSection(&uuid_cs); 421 422 TRACE("%s\n", debugstr_guid(Uuid)); 423 424 return status; 425 } 426 427 /************************************************************************* 428 * UuidCreateSequential [RPCRT4.@] 429 * 430 * Creates a 128bit UUID. 431 * 432 * RETURNS 433 * 434 * RPC_S_OK if successful. 435 * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. 436 * 437 */ 438 RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid) 439 { 440 return UuidCreate(Uuid); 441 } 442 443 444 /************************************************************************* 445 * UuidHash [RPCRT4.@] 446 * 447 * Generates a hash value for a given UUID 448 * 449 * Code based on FreeDCE implementation 450 * 451 */ 452 unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status) 453 { 454 BYTE *data = (BYTE*)uuid; 455 short c0 = 0, c1 = 0, x, y; 456 unsigned int i; 457 458 if (!uuid) data = (BYTE*)(uuid = &uuid_nil); 459 460 TRACE("(%s)\n", debugstr_guid(uuid)); 461 462 for (i=0; i<sizeof(UUID); i++) { 463 c0 += data[i]; 464 c1 += c0; 465 } 466 467 x = -c1 % 255; 468 if (x < 0) x += 255; 469 470 y = (c1 - c0) % 255; 471 if (y < 0) y += 255; 472 473 *Status = RPC_S_OK; 474 return y*256 + x; 475 } 476 477 /************************************************************************* 478 * UuidToStringA [RPCRT4.@] 479 * 480 * Converts a UUID to a string. 481 * 482 * UUID format is 8 hex digits, followed by a hyphen then three groups of 483 * 4 hex digits each followed by a hyphen and then 12 hex digits 484 * 485 * RETURNS 486 * 487 * S_OK if successful. 488 * S_OUT_OF_MEMORY if unsuccessful. 489 */ 490 RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, RPC_CSTR* StringUuid) 491 { 492 *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37); 493 494 if(!(*StringUuid)) 495 return RPC_S_OUT_OF_MEMORY; 496 497 if (!Uuid) Uuid = &uuid_nil; 498 499 sprintf( (char*)*StringUuid, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 500 Uuid->Data1, Uuid->Data2, Uuid->Data3, 501 Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], 502 Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], 503 Uuid->Data4[6], Uuid->Data4[7] ); 504 505 return RPC_S_OK; 506 } 507 508 /************************************************************************* 509 * UuidToStringW [RPCRT4.@] 510 * 511 * Converts a UUID to a string. 512 * 513 * S_OK if successful. 514 * S_OUT_OF_MEMORY if unsuccessful. 515 */ 516 RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, RPC_WSTR* StringUuid) 517 { 518 char buf[37]; 519 520 if (!Uuid) Uuid = &uuid_nil; 521 522 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 523 Uuid->Data1, Uuid->Data2, Uuid->Data3, 524 Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], 525 Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], 526 Uuid->Data4[6], Uuid->Data4[7] ); 527 528 *StringUuid = RPCRT4_strdupAtoW(buf); 529 530 if(!(*StringUuid)) 531 return RPC_S_OUT_OF_MEMORY; 532 533 return RPC_S_OK; 534 } 535 536 static const BYTE hex2bin[] = 537 { 538 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */ 539 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */ 540 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */ 541 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */ 542 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */ 543 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */ 544 0,10,11,12,13,14,15 /* 0x60 */ 545 }; 546 547 /*********************************************************************** 548 * UuidFromStringA (RPCRT4.@) 549 */ 550 RPC_STATUS WINAPI UuidFromStringA(RPC_CSTR s, UUID *uuid) 551 { 552 int i; 553 554 if (!s) return UuidCreateNil( uuid ); 555 556 if (strlen((char*)s) != 36) return RPC_S_INVALID_STRING_UUID; 557 558 if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) 559 return RPC_S_INVALID_STRING_UUID; 560 561 for (i=0; i<36; i++) 562 { 563 if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; 564 if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; 565 } 566 567 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ 568 569 uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | 570 hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); 571 uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; 572 uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; 573 574 /* these are just sequential bytes */ 575 uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; 576 uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; 577 uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; 578 uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; 579 uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; 580 uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; 581 uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; 582 uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; 583 return RPC_S_OK; 584 } 585 586 587 /*********************************************************************** 588 * UuidFromStringW (RPCRT4.@) 589 */ 590 RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid) 591 { 592 int i; 593 594 if (!s) return UuidCreateNil( uuid ); 595 596 if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID; 597 598 if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) 599 return RPC_S_INVALID_STRING_UUID; 600 601 for (i=0; i<36; i++) 602 { 603 if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; 604 if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; 605 } 606 607 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ 608 609 uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | 610 hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); 611 uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; 612 uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; 613 614 /* these are just sequential bytes */ 615 uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; 616 uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; 617 uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; 618 uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; 619 uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; 620 uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; 621 uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; 622 uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; 623 return RPC_S_OK; 624 } 625 626 /*********************************************************************** 627 * DllRegisterServer (RPCRT4.@) 628 */ 629 630 HRESULT WINAPI DllRegisterServer( void ) 631 { 632 FIXME( "(): stub\n" ); 633 return S_OK; 634 } 635 636 #define MAX_RPC_ERROR_TEXT 256 637 638 /****************************************************************************** 639 * DceErrorInqTextW (rpcrt4.@) 640 * 641 * Notes 642 * 1. On passing a NULL pointer the code does bomb out. 643 * 2. The size of the required buffer is not defined in the documentation. 644 * It appears to be 256. 645 * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know 646 * of any value for which it does. 647 * 4. The MSDN documentation currently declares that the second argument is 648 * unsigned char *, even for the W version. I don't believe it. 649 */ 650 RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, RPC_WSTR buffer) 651 { 652 DWORD count; 653 count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | 654 FORMAT_MESSAGE_IGNORE_INSERTS, 655 NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); 656 if (!count) 657 { 658 count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | 659 FORMAT_MESSAGE_IGNORE_INSERTS, 660 NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); 661 if (!count) 662 { 663 ERR ("Failed to translate error\n"); 664 return RPC_S_INVALID_ARG; 665 } 666 } 667 return RPC_S_OK; 668 } 669 670 /****************************************************************************** 671 * DceErrorInqTextA (rpcrt4.@) 672 */ 673 RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, RPC_CSTR buffer) 674 { 675 RPC_STATUS status; 676 WCHAR bufferW [MAX_RPC_ERROR_TEXT]; 677 if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK) 678 { 679 if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, (LPSTR)buffer, MAX_RPC_ERROR_TEXT, 680 NULL, NULL)) 681 { 682 ERR ("Failed to translate error\n"); 683 status = RPC_S_INVALID_ARG; 684 } 685 } 686 return status; 687 } 688 689 /****************************************************************************** 690 * I_RpcAllocate (rpcrt4.@) 691 */ 692 void * WINAPI I_RpcAllocate(unsigned int Size) 693 { 694 return HeapAlloc(GetProcessHeap(), 0, Size); 695 } 696 697 /****************************************************************************** 698 * I_RpcFree (rpcrt4.@) 699 */ 700 void WINAPI I_RpcFree(void *Object) 701 { 702 HeapFree(GetProcessHeap(), 0, Object); 703 } 704 705 /****************************************************************************** 706 * I_RpcMapWin32Status (rpcrt4.@) 707 * 708 * Maps Win32 RPC error codes to NT statuses. 709 * 710 * PARAMS 711 * status [I] Win32 RPC error code. 712 * 713 * RETURNS 714 * Appropriate translation into an NT status code. 715 */ 716 LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status) 717 { 718 TRACE("(%d)\n", status); 719 switch (status) 720 { 721 case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED; 722 case ERROR_INVALID_HANDLE: return RPC_NT_SS_CONTEXT_MISMATCH; 723 case ERROR_OUTOFMEMORY: return STATUS_NO_MEMORY; 724 case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER; 725 case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL; 726 case ERROR_MAX_THRDS_REACHED: return STATUS_NO_MEMORY; 727 case ERROR_NOACCESS: return STATUS_ACCESS_VIOLATION; 728 case ERROR_NOT_ENOUGH_SERVER_MEMORY: return STATUS_INSUFF_SERVER_RESOURCES; 729 case ERROR_WRONG_PASSWORD: return STATUS_WRONG_PASSWORD; 730 case ERROR_INVALID_LOGON_HOURS: return STATUS_INVALID_LOGON_HOURS; 731 case ERROR_PASSWORD_EXPIRED: return STATUS_PASSWORD_EXPIRED; 732 case ERROR_ACCOUNT_DISABLED: return STATUS_ACCOUNT_DISABLED; 733 case ERROR_INVALID_SECURITY_DESCR: return STATUS_INVALID_SECURITY_DESCR; 734 case RPC_S_INVALID_STRING_BINDING: return RPC_NT_INVALID_STRING_BINDING; 735 case RPC_S_WRONG_KIND_OF_BINDING: return RPC_NT_WRONG_KIND_OF_BINDING; 736 case RPC_S_INVALID_BINDING: return RPC_NT_INVALID_BINDING; 737 case RPC_S_PROTSEQ_NOT_SUPPORTED: return RPC_NT_PROTSEQ_NOT_SUPPORTED; 738 case RPC_S_INVALID_RPC_PROTSEQ: return RPC_NT_INVALID_RPC_PROTSEQ; 739 case RPC_S_INVALID_STRING_UUID: return RPC_NT_INVALID_STRING_UUID; 740 case RPC_S_INVALID_ENDPOINT_FORMAT: return RPC_NT_INVALID_ENDPOINT_FORMAT; 741 case RPC_S_INVALID_NET_ADDR: return RPC_NT_INVALID_NET_ADDR; 742 case RPC_S_NO_ENDPOINT_FOUND: return RPC_NT_NO_ENDPOINT_FOUND; 743 case RPC_S_INVALID_TIMEOUT: return RPC_NT_INVALID_TIMEOUT; 744 case RPC_S_OBJECT_NOT_FOUND: return RPC_NT_OBJECT_NOT_FOUND; 745 case RPC_S_ALREADY_REGISTERED: return RPC_NT_ALREADY_REGISTERED; 746 case RPC_S_TYPE_ALREADY_REGISTERED: return RPC_NT_TYPE_ALREADY_REGISTERED; 747 case RPC_S_ALREADY_LISTENING: return RPC_NT_ALREADY_LISTENING; 748 case RPC_S_NO_PROTSEQS_REGISTERED: return RPC_NT_NO_PROTSEQS_REGISTERED; 749 case RPC_S_NOT_LISTENING: return RPC_NT_NOT_LISTENING; 750 case RPC_S_UNKNOWN_MGR_TYPE: return RPC_NT_UNKNOWN_MGR_TYPE; 751 case RPC_S_UNKNOWN_IF: return RPC_NT_UNKNOWN_IF; 752 case RPC_S_NO_BINDINGS: return RPC_NT_NO_BINDINGS; 753 case RPC_S_NO_PROTSEQS: return RPC_NT_NO_PROTSEQS; 754 case RPC_S_CANT_CREATE_ENDPOINT: return RPC_NT_CANT_CREATE_ENDPOINT; 755 case RPC_S_OUT_OF_RESOURCES: return RPC_NT_OUT_OF_RESOURCES; 756 case RPC_S_SERVER_UNAVAILABLE: return RPC_NT_SERVER_UNAVAILABLE; 757 case RPC_S_SERVER_TOO_BUSY: return RPC_NT_SERVER_TOO_BUSY; 758 case RPC_S_INVALID_NETWORK_OPTIONS: return RPC_NT_INVALID_NETWORK_OPTIONS; 759 case RPC_S_NO_CALL_ACTIVE: return RPC_NT_NO_CALL_ACTIVE; 760 case RPC_S_CALL_FAILED: return RPC_NT_CALL_FAILED; 761 case RPC_S_CALL_FAILED_DNE: return RPC_NT_CALL_FAILED_DNE; 762 case RPC_S_PROTOCOL_ERROR: return RPC_NT_PROTOCOL_ERROR; 763 case RPC_S_UNSUPPORTED_TRANS_SYN: return RPC_NT_UNSUPPORTED_TRANS_SYN; 764 case RPC_S_UNSUPPORTED_TYPE: return RPC_NT_UNSUPPORTED_TYPE; 765 case RPC_S_INVALID_TAG: return RPC_NT_INVALID_TAG; 766 case RPC_S_INVALID_BOUND: return RPC_NT_INVALID_BOUND; 767 case RPC_S_NO_ENTRY_NAME: return RPC_NT_NO_ENTRY_NAME; 768 case RPC_S_INVALID_NAME_SYNTAX: return RPC_NT_INVALID_NAME_SYNTAX; 769 case RPC_S_UNSUPPORTED_NAME_SYNTAX: return RPC_NT_UNSUPPORTED_NAME_SYNTAX; 770 case RPC_S_UUID_NO_ADDRESS: return RPC_NT_UUID_NO_ADDRESS; 771 case RPC_S_DUPLICATE_ENDPOINT: return RPC_NT_DUPLICATE_ENDPOINT; 772 case RPC_S_UNKNOWN_AUTHN_TYPE: return RPC_NT_UNKNOWN_AUTHN_TYPE; 773 case RPC_S_MAX_CALLS_TOO_SMALL: return RPC_NT_MAX_CALLS_TOO_SMALL; 774 case RPC_S_STRING_TOO_LONG: return RPC_NT_STRING_TOO_LONG; 775 case RPC_S_PROTSEQ_NOT_FOUND: return RPC_NT_PROTSEQ_NOT_FOUND; 776 case RPC_S_PROCNUM_OUT_OF_RANGE: return RPC_NT_PROCNUM_OUT_OF_RANGE; 777 case RPC_S_BINDING_HAS_NO_AUTH: return RPC_NT_BINDING_HAS_NO_AUTH; 778 case RPC_S_UNKNOWN_AUTHN_SERVICE: return RPC_NT_UNKNOWN_AUTHN_SERVICE; 779 case RPC_S_UNKNOWN_AUTHN_LEVEL: return RPC_NT_UNKNOWN_AUTHN_LEVEL; 780 case RPC_S_INVALID_AUTH_IDENTITY: return RPC_NT_INVALID_AUTH_IDENTITY; 781 case RPC_S_UNKNOWN_AUTHZ_SERVICE: return RPC_NT_UNKNOWN_AUTHZ_SERVICE; 782 case EPT_S_INVALID_ENTRY: return EPT_NT_INVALID_ENTRY; 783 case EPT_S_CANT_PERFORM_OP: return EPT_NT_CANT_PERFORM_OP; 784 case EPT_S_NOT_REGISTERED: return EPT_NT_NOT_REGISTERED; 785 case EPT_S_CANT_CREATE: return EPT_NT_CANT_CREATE; 786 case RPC_S_NOTHING_TO_EXPORT: return RPC_NT_NOTHING_TO_EXPORT; 787 case RPC_S_INCOMPLETE_NAME: return RPC_NT_INCOMPLETE_NAME; 788 case RPC_S_INVALID_VERS_OPTION: return RPC_NT_INVALID_VERS_OPTION; 789 case RPC_S_NO_MORE_MEMBERS: return RPC_NT_NO_MORE_MEMBERS; 790 case RPC_S_NOT_ALL_OBJS_UNEXPORTED: return RPC_NT_NOT_ALL_OBJS_UNEXPORTED; 791 case RPC_S_INTERFACE_NOT_FOUND: return RPC_NT_INTERFACE_NOT_FOUND; 792 case RPC_S_ENTRY_ALREADY_EXISTS: return RPC_NT_ENTRY_ALREADY_EXISTS; 793 case RPC_S_ENTRY_NOT_FOUND: return RPC_NT_ENTRY_NOT_FOUND; 794 case RPC_S_NAME_SERVICE_UNAVAILABLE: return RPC_NT_NAME_SERVICE_UNAVAILABLE; 795 case RPC_S_INVALID_NAF_ID: return RPC_NT_INVALID_NAF_ID; 796 case RPC_S_CANNOT_SUPPORT: return RPC_NT_CANNOT_SUPPORT; 797 case RPC_S_NO_CONTEXT_AVAILABLE: return RPC_NT_NO_CONTEXT_AVAILABLE; 798 case RPC_S_INTERNAL_ERROR: return RPC_NT_INTERNAL_ERROR; 799 case RPC_S_ZERO_DIVIDE: return RPC_NT_ZERO_DIVIDE; 800 case RPC_S_ADDRESS_ERROR: return RPC_NT_ADDRESS_ERROR; 801 case RPC_S_FP_DIV_ZERO: return RPC_NT_FP_DIV_ZERO; 802 case RPC_S_FP_UNDERFLOW: return RPC_NT_FP_UNDERFLOW; 803 case RPC_S_FP_OVERFLOW: return RPC_NT_FP_OVERFLOW; 804 case RPC_S_CALL_IN_PROGRESS: return RPC_NT_CALL_IN_PROGRESS; 805 case RPC_S_NO_MORE_BINDINGS: return RPC_NT_NO_MORE_BINDINGS; 806 case RPC_S_CALL_CANCELLED: return RPC_NT_CALL_CANCELLED; 807 case RPC_S_INVALID_OBJECT: return RPC_NT_INVALID_OBJECT; 808 case RPC_S_INVALID_ASYNC_HANDLE: return RPC_NT_INVALID_ASYNC_HANDLE; 809 case RPC_S_INVALID_ASYNC_CALL: return RPC_NT_INVALID_ASYNC_CALL; 810 case RPC_S_GROUP_MEMBER_NOT_FOUND: return RPC_NT_GROUP_MEMBER_NOT_FOUND; 811 case RPC_X_NO_MORE_ENTRIES: return RPC_NT_NO_MORE_ENTRIES; 812 case RPC_X_SS_CHAR_TRANS_OPEN_FAIL: return RPC_NT_SS_CHAR_TRANS_OPEN_FAIL; 813 case RPC_X_SS_CHAR_TRANS_SHORT_FILE: return RPC_NT_SS_CHAR_TRANS_SHORT_FILE; 814 case RPC_X_SS_IN_NULL_CONTEXT: return RPC_NT_SS_IN_NULL_CONTEXT; 815 case RPC_X_SS_CONTEXT_DAMAGED: return RPC_NT_SS_CONTEXT_DAMAGED; 816 case RPC_X_SS_HANDLES_MISMATCH: return RPC_NT_SS_HANDLES_MISMATCH; 817 case RPC_X_SS_CANNOT_GET_CALL_HANDLE: return RPC_NT_SS_CANNOT_GET_CALL_HANDLE; 818 case RPC_X_NULL_REF_POINTER: return RPC_NT_NULL_REF_POINTER; 819 case RPC_X_ENUM_VALUE_OUT_OF_RANGE: return RPC_NT_ENUM_VALUE_OUT_OF_RANGE; 820 case RPC_X_BYTE_COUNT_TOO_SMALL: return RPC_NT_BYTE_COUNT_TOO_SMALL; 821 case RPC_X_BAD_STUB_DATA: return RPC_NT_BAD_STUB_DATA; 822 case RPC_X_PIPE_CLOSED: return RPC_NT_PIPE_CLOSED; 823 case RPC_X_PIPE_DISCIPLINE_ERROR: return RPC_NT_PIPE_DISCIPLINE_ERROR; 824 case RPC_X_PIPE_EMPTY: return RPC_NT_PIPE_EMPTY; 825 case ERROR_PASSWORD_MUST_CHANGE: return STATUS_PASSWORD_MUST_CHANGE; 826 case ERROR_ACCOUNT_LOCKED_OUT: return STATUS_ACCOUNT_LOCKED_OUT; 827 default: return status; 828 } 829 } 830 831 /****************************************************************************** 832 * I_RpcExceptionFilter (rpcrt4.@) 833 */ 834 int WINAPI I_RpcExceptionFilter(ULONG ExceptionCode) 835 { 836 TRACE("0x%x\n", ExceptionCode); 837 switch (ExceptionCode) 838 { 839 case STATUS_DATATYPE_MISALIGNMENT: 840 case STATUS_BREAKPOINT: 841 case STATUS_ACCESS_VIOLATION: 842 case STATUS_ILLEGAL_INSTRUCTION: 843 case STATUS_PRIVILEGED_INSTRUCTION: 844 case STATUS_INSTRUCTION_MISALIGNMENT: 845 case STATUS_STACK_OVERFLOW: 846 case STATUS_POSSIBLE_DEADLOCK: 847 return EXCEPTION_CONTINUE_SEARCH; 848 default: 849 return EXCEPTION_EXECUTE_HANDLER; 850 } 851 } 852 853 /****************************************************************************** 854 * RpcErrorStartEnumeration (rpcrt4.@) 855 */ 856 RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle) 857 { 858 FIXME("(%p): stub\n", EnumHandle); 859 return RPC_S_ENTRY_NOT_FOUND; 860 } 861 862 /****************************************************************************** 863 * RpcMgmtSetCancelTimeout (rpcrt4.@) 864 */ 865 RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout) 866 { 867 FIXME("(%d): stub\n", Timeout); 868 return RPC_S_OK; 869 } 870 871 static struct threaddata *get_or_create_threaddata(void) 872 { 873 struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc; 874 if (!tdata) 875 { 876 tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata)); 877 if (!tdata) return NULL; 878 879 InitializeCriticalSection(&tdata->cs); 880 tdata->thread_id = GetCurrentThreadId(); 881 882 EnterCriticalSection(&threaddata_cs); 883 list_add_tail(&threaddata_list, &tdata->entry); 884 LeaveCriticalSection(&threaddata_cs); 885 886 NtCurrentTeb()->ReservedForNtRpc = tdata; 887 return tdata; 888 } 889 return tdata; 890 } 891 892 void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection) 893 { 894 struct threaddata *tdata = get_or_create_threaddata(); 895 if (!tdata) return; 896 897 EnterCriticalSection(&tdata->cs); 898 tdata->connection = Connection; 899 LeaveCriticalSection(&tdata->cs); 900 } 901 902 void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding) 903 { 904 struct threaddata *tdata = get_or_create_threaddata(); 905 if (!tdata) return; 906 907 tdata->server_binding = Binding; 908 } 909 910 RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void) 911 { 912 struct threaddata *tdata = get_or_create_threaddata(); 913 if (!tdata) return NULL; 914 915 return tdata->server_binding; 916 } 917 918 void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext) 919 { 920 struct threaddata *tdata = get_or_create_threaddata(); 921 struct context_handle_list *context_handle_list; 922 923 if (!tdata) return; 924 925 context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list)); 926 if (!context_handle_list) return; 927 928 context_handle_list->context_handle = SContext; 929 context_handle_list->next = tdata->context_handle_list; 930 tdata->context_handle_list = context_handle_list; 931 } 932 933 void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext) 934 { 935 struct threaddata *tdata = get_or_create_threaddata(); 936 struct context_handle_list *current, *prev; 937 938 if (!tdata) return; 939 940 for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next) 941 { 942 if (current->context_handle == SContext) 943 { 944 if (prev) 945 prev->next = current->next; 946 else 947 tdata->context_handle_list = current->next; 948 HeapFree(GetProcessHeap(), 0, current); 949 return; 950 } 951 } 952 } 953 954 NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void) 955 { 956 struct threaddata *tdata = get_or_create_threaddata(); 957 struct context_handle_list *context_handle_list; 958 NDR_SCONTEXT context_handle; 959 960 if (!tdata) return NULL; 961 962 context_handle_list = tdata->context_handle_list; 963 if (!context_handle_list) return NULL; 964 tdata->context_handle_list = context_handle_list->next; 965 966 context_handle = context_handle_list->context_handle; 967 HeapFree(GetProcessHeap(), 0, context_handle_list); 968 return context_handle; 969 } 970 971 static RPC_STATUS rpc_cancel_thread(DWORD target_tid) 972 { 973 struct threaddata *tdata; 974 975 EnterCriticalSection(&threaddata_cs); 976 LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry) 977 if (tdata->thread_id == target_tid) 978 { 979 EnterCriticalSection(&tdata->cs); 980 if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection); 981 LeaveCriticalSection(&tdata->cs); 982 break; 983 } 984 LeaveCriticalSection(&threaddata_cs); 985 986 return RPC_S_OK; 987 } 988 989 /****************************************************************************** 990 * RpcCancelThread (rpcrt4.@) 991 */ 992 RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle) 993 { 994 TRACE("(%p)\n", ThreadHandle); 995 return RpcCancelThreadEx(ThreadHandle, 0); 996 } 997 998 /****************************************************************************** 999 * RpcCancelThreadEx (rpcrt4.@) 1000 */ 1001 RPC_STATUS RPC_ENTRY RpcCancelThreadEx(void* ThreadHandle, LONG Timeout) 1002 { 1003 DWORD target_tid; 1004 1005 FIXME("(%p, %d)\n", ThreadHandle, Timeout); 1006 1007 target_tid = GetThreadId(ThreadHandle); 1008 if (!target_tid) 1009 return RPC_S_INVALID_ARG; 1010 1011 if (Timeout) 1012 { 1013 FIXME("(%p, %d)\n", ThreadHandle, Timeout); 1014 return RPC_S_OK; 1015 } 1016 else 1017 return rpc_cancel_thread(target_tid); 1018 } 1019