rpcrt4_main.c 34.3 KB
Newer Older
Huw D M Davies's avatar
Huw D M Davies committed
1 2 3
/*
 *  RPCRT4
 *
4
 * Copyright 2000 Huw D M Davies for CodeWeavers
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 21 22 23
 * 
 * WINE RPC TODO's (and a few TODONT's)
 *
 * - Statistics: we are supposed to be keeping various counters.  we aren't.
 *
24
 * - Async RPC: Unimplemented.
25
 *
26 27 28
 * - The NT "ports" API, aka LPC.  Greg claims this is on his radar.  Might (or
 *   might not) enable users to get some kind of meaningful result out of
 *   NT-based native rpcrt4's.  Commonly-used transport for self-to-self RPC's.
Huw D M Davies's avatar
Huw D M Davies committed
29 30 31 32
 */

#include "config.h"

33
#include <stdarg.h>
34 35 36 37
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

38 39
#include "ntstatus.h"
#define WIN32_NO_STATUS
Huw D M Davies's avatar
Huw D M Davies committed
40 41 42
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
43
#include "winuser.h"
44 45
#include "winnt.h"
#include "winternl.h"
46
#include "ntsecapi.h"
47 48
#include "iptypes.h"
#include "iphlpapi.h"
49
#include "wine/unicode.h"
Huw D M Davies's avatar
Huw D M Davies committed
50 51
#include "rpc.h"

52 53 54 55
#include "ole2.h"
#include "rpcndr.h"
#include "rpcproxy.h"

56
#include "rpc_binding.h"
57
#include "rpc_server.h"
58

59
#include "wine/debug.h"
Huw D M Davies's avatar
Huw D M Davies committed
60

61
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
Huw D M Davies's avatar
Huw D M Davies committed
62

63 64
static UUID uuid_nil;

65 66 67 68 69 70 71 72 73
static CRITICAL_SECTION uuid_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &uuid_cs,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") }
};
static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 };

74 75 76
static CRITICAL_SECTION threaddata_cs;
static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
{
77
    0, 0, &threaddata_cs,
78 79 80 81 82
    { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
};
static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 };

83
static struct list threaddata_list = LIST_INIT(threaddata_list);
84

85 86 87 88 89 90
struct context_handle_list
{
    struct context_handle_list *next;
    NDR_SCONTEXT context_handle;
};

91 92 93 94 95 96
struct threaddata
{
    struct list entry;
    CRITICAL_SECTION cs;
    DWORD thread_id;
    RpcConnection *connection;
97
    RpcBinding *server_binding;
98
    struct context_handle_list *context_handle_list;
99 100
};

Huw D M Davies's avatar
Huw D M Davies committed
101
/***********************************************************************
102
 * DllMain
Huw D M Davies's avatar
Huw D M Davies committed
103 104
 *
 * PARAMS
Andreas Mohr's avatar
Andreas Mohr committed
105
 *     hinstDLL    [I] handle to the DLL's instance
Huw D M Davies's avatar
Huw D M Davies committed
106
 *     fdwReason   [I]
Andreas Mohr's avatar
Andreas Mohr committed
107
 *     lpvReserved [I] reserved, must be NULL
Huw D M Davies's avatar
Huw D M Davies committed
108 109 110 111 112 113
 *
 * RETURNS
 *     Success: TRUE
 *     Failure: FALSE
 */

114
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Huw D M Davies's avatar
Huw D M Davies committed
115
{
116 117
    struct threaddata *tdata;

Huw D M Davies's avatar
Huw D M Davies committed
118 119
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
120
        break;
Huw D M Davies's avatar
Huw D M Davies committed
121

122 123 124 125 126 127 128 129
    case DLL_THREAD_DETACH:
        tdata = NtCurrentTeb()->ReservedForNtRpc;
        if (tdata)
        {
            EnterCriticalSection(&threaddata_cs);
            list_remove(&tdata->entry);
            LeaveCriticalSection(&threaddata_cs);

130
            tdata->cs.DebugInfo->Spare[0] = 0;
131 132
            DeleteCriticalSection(&tdata->cs);
            if (tdata->connection)
133 134 135
                ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection);
            if (tdata->server_binding)
                ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding);
136 137
            HeapFree(GetProcessHeap(), 0, tdata);
        }
138
        break;
139

Huw D M Davies's avatar
Huw D M Davies committed
140
    case DLL_PROCESS_DETACH:
141
        if (lpvReserved) break; /* do nothing if process is shutting down */
142
        RPCRT4_destroy_all_protseqs();
143
        RPCRT4_ServerFreeAllRegisteredAuthInfo();
144 145
        DeleteCriticalSection(&uuid_cs);
        DeleteCriticalSection(&threaddata_cs);
146
        break;
Huw D M Davies's avatar
Huw D M Davies committed
147 148 149 150 151
    }

    return TRUE;
}

152 153 154 155 156 157 158 159 160
/*************************************************************************
 *           RpcStringFreeA   [RPCRT4.@]
 *
 * Frees a character string allocated by the RPC run-time library.
 *
 * RETURNS
 *
 *  S_OK if successful.
 */
161
RPC_STATUS WINAPI RpcStringFreeA(RPC_CSTR* String)
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
{
  HeapFree( GetProcessHeap(), 0, *String);

  return RPC_S_OK;
}

/*************************************************************************
 *           RpcStringFreeW   [RPCRT4.@]
 *
 * Frees a character string allocated by the RPC run-time library.
 *
 * RETURNS
 *
 *  S_OK if successful.
 */
177
RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String)
178 179 180 181 182 183
{
  HeapFree( GetProcessHeap(), 0, *String);

  return RPC_S_OK;
}

184 185 186 187 188
/*************************************************************************
 *           RpcRaiseException   [RPCRT4.@]
 *
 * Raises an exception.
 */
189
void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception)
190
{
191
  /* shouldn't return */
192
  RaiseException(exception, 0, 0, NULL);
193 194
  ERR("handler continued execution\n");
  ExitProcess(1);
195 196
}

197
/*************************************************************************
198 199
 * UuidCompare [RPCRT4.@]
 *
200 201 202 203
 * PARAMS
 *     UUID *Uuid1        [I] Uuid to compare
 *     UUID *Uuid2        [I] Uuid to compare
 *     RPC_STATUS *Status [O] returns RPC_S_OK
204
 * 
205
 * RETURNS
206
 *    -1  if Uuid1 is less than Uuid2
207 208
 *     0  if Uuid1 and Uuid2 are equal
 *     1  if Uuid1 is greater than Uuid2
209
 */
210
int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)
211
{
212 213
  int i;

Greg Turner's avatar
Greg Turner committed
214
  TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));
215

216
  *Status = RPC_S_OK;
217

Greg Turner's avatar
Greg Turner committed
218 219
  if (!Uuid1) Uuid1 = &uuid_nil;
  if (!Uuid2) Uuid2 = &uuid_nil;
220

221
  if (Uuid1 == Uuid2) return 0;
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

  if (Uuid1->Data1 != Uuid2->Data1)
    return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1;

  if (Uuid1->Data2 != Uuid2->Data2)
    return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1;

  if (Uuid1->Data3 != Uuid2->Data3)
    return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1;

  for (i = 0; i < 8; i++) {
    if (Uuid1->Data4[i] < Uuid2->Data4[i])
      return -1;
    if (Uuid1->Data4[i] > Uuid2->Data4[i])
      return 1;
  }

  return 0;
Greg Turner's avatar
Greg Turner committed
240 241 242
}

/*************************************************************************
243
 * UuidEqual [RPCRT4.@]
Greg Turner's avatar
Greg Turner committed
244 245 246 247 248
 *
 * PARAMS
 *     UUID *Uuid1        [I] Uuid to compare
 *     UUID *Uuid2        [I] Uuid to compare
 *     RPC_STATUS *Status [O] returns RPC_S_OK
249
 *
Greg Turner's avatar
Greg Turner committed
250
 * RETURNS
251
 *     TRUE/FALSE
Greg Turner's avatar
Greg Turner committed
252
 */
253
int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)
Greg Turner's avatar
Greg Turner committed
254 255
{
  TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));
256
  return !UuidCompare(Uuid1, Uuid2, Status);
257 258 259 260 261 262 263
}

/*************************************************************************
 * UuidIsNil [RPCRT4.@]
 *
 * PARAMS
 *     UUID *Uuid         [I] Uuid to compare
Austin English's avatar
Austin English committed
264
 *     RPC_STATUS *Status [O] returns RPC_S_OK
265 266 267 268
 *
 * RETURNS
 *     TRUE/FALSE
 */
269
int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status)
270
{
271 272 273
  TRACE("(%s)\n", debugstr_guid(Uuid));
  if (!Uuid) return TRUE;
  return !UuidCompare(Uuid, &uuid_nil, Status);
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
}

 /*************************************************************************
 * UuidCreateNil [RPCRT4.@]
 *
 * PARAMS
 *     UUID *Uuid [O] returns a nil UUID
 *
 * RETURNS
 *     RPC_S_OK
 */
RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
{
  *Uuid = uuid_nil;
  return RPC_S_OK;
}

Huw D M Davies's avatar
Huw D M Davies committed
291
/*************************************************************************
292
 *           UuidCreate   [RPCRT4.@]
Huw D M Davies's avatar
Huw D M Davies committed
293 294 295 296 297
 *
 * Creates a 128bit UUID.
 *
 * RETURNS
 *
298 299 300
 *  RPC_S_OK if successful.
 *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
 *
301 302 303 304
 * NOTES
 *
 *  Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
 *  Truly Random or Pseudo-Random Numbers)
Huw D M Davies's avatar
Huw D M Davies committed
305
 */
306
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Huw D M Davies's avatar
Huw D M Davies committed
307
{
308 309 310 311 312 313 314 315 316
    RtlGenRandom(Uuid, sizeof(*Uuid));
    /* Clear the version bits and set the version (4) */
    Uuid->Data3 &= 0x0fff;
    Uuid->Data3 |= (4 << 12);
    /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
     * specified in RFC 4122, section 4.4.
     */
    Uuid->Data4[0] &= 0x3f;
    Uuid->Data4[0] |= 0x80;
317

318 319
    TRACE("%s\n", debugstr_guid(Uuid));

320
    return RPC_S_OK;
321
}
322

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
/* Number of 100ns ticks per clock tick. To be safe, assume that the clock
   resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
#define TICKS_PER_CLOCK_TICK 1000
#define SECSPERDAY  86400
#define TICKSPERSEC 10000000
/* UUID system time starts at October 15, 1582 */
#define SECS_15_OCT_1582_TO_1601  ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)

static void RPC_UuidGetSystemTime(ULONGLONG *time)
{
    FILETIME ft;

    GetSystemTimeAsFileTime(&ft);

    *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
    *time += TICKS_15_OCT_1582_TO_1601;
}

/* Assume that a hardware address is at least 6 bytes long */
#define ADDRESS_BYTES_NEEDED 6

static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
{
    int i;
    DWORD status = RPC_S_OK;

    ULONG buflen = sizeof(IP_ADAPTER_INFO);
    PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen);

    if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) {
        HeapFree(GetProcessHeap(), 0, adapter);
        adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
    }

    if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) {
        for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
            address[i] = adapter->Address[i];
        }
    }
    /* We can't get a hardware address, just use random numbers.
       Set the multicast bit to prevent conflicts with real cards. */
    else {
        RtlGenRandom(address, ADDRESS_BYTES_NEEDED);
        address[0] |= 0x01;
        status = RPC_S_UUID_LOCAL_ONLY;
    }

    HeapFree(GetProcessHeap(), 0, adapter);
    return status;
}

375 376 377
/*************************************************************************
 *           UuidCreateSequential   [RPCRT4.@]
 *
378 379 380 381 382 383 384
 * Creates a 128bit UUID.
 *
 * RETURNS
 *
 *  RPC_S_OK if successful.
 *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
 *
385 386 387 388 389
 *  FIXME: No compensation for changes across reloading
 *         this dll or across reboots (e.g. clock going
 *         backwards and swapped network cards). The RFC
 *         suggests using NVRAM for storing persistent
 *         values.
390 391 392
 */
RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
{
393 394
    static BOOL initialised;
    static int count;
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412

    ULONGLONG time;
    static ULONGLONG timelast;
    static WORD sequence;

    static DWORD status;
    static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];

    EnterCriticalSection(&uuid_cs);

    if (!initialised) {
        RPC_UuidGetSystemTime(&timelast);
        count = TICKS_PER_CLOCK_TICK;

        sequence = ((rand() & 0xff) << 8) + (rand() & 0xff);
        sequence &= 0x1fff;

        status = RPC_UuidGetNodeAddress(address);
413
        initialised = TRUE;
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    }

    /* Generate time element of the UUID. Account for going faster
       than our clock as well as the clock going backwards. */
    while (1) {
        RPC_UuidGetSystemTime(&time);
        if (time > timelast) {
            count = 0;
            break;
        }
        if (time < timelast) {
            sequence = (sequence + 1) & 0x1fff;
            count = 0;
            break;
        }
        if (count < TICKS_PER_CLOCK_TICK) {
            count++;
            break;
        }
    }

    timelast = time;
    time += count;

    /* Pack the information into the UUID structure. */

440
    Uuid->Data1  = (ULONG)(time & 0xffffffff);
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
    Uuid->Data2  = (unsigned short)((time >> 32) & 0xffff);
    Uuid->Data3  = (unsigned short)((time >> 48) & 0x0fff);

    /* This is a version 1 UUID */
    Uuid->Data3 |= (1 << 12);

    Uuid->Data4[0]  = sequence & 0xff;
    Uuid->Data4[1]  = (sequence & 0x3f00) >> 8;
    Uuid->Data4[1] |= 0x80;
    memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED);

    LeaveCriticalSection(&uuid_cs);

    TRACE("%s\n", debugstr_guid(Uuid));

    return status;
457 458
}

459 460 461 462 463 464 465 466 467
/*************************************************************************
 *           I_UuidCreate   [RPCRT4.@]
 *
 * See UuidCreateSequential()
 */
RPC_STATUS WINAPI I_UuidCreate(UUID *Uuid)
{
    return UuidCreateSequential(Uuid);
}
468

469
/*************************************************************************
470
 *           UuidHash   [RPCRT4.@]
471
 *
472
 * Generates a hash value for a given UUID
473
 *
474
 * Code based on FreeDCE implementation
475 476
 *
 */
477
unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status)
478
{
479 480
  BYTE *data = (BYTE*)uuid;
  short c0 = 0, c1 = 0, x, y;
481
  unsigned int i;
482

483 484
  if (!uuid) data = (BYTE*)(uuid = &uuid_nil);

485
  TRACE("(%s)\n", debugstr_guid(uuid));
486

487 488 489 490 491 492 493 494 495 496
  for (i=0; i<sizeof(UUID); i++) {
    c0 += data[i];
    c1 += c0;
  }

  x = -c1 % 255;
  if (x < 0) x += 255;

  y = (c1 - c0) % 255;
  if (y < 0) y += 255;
497 498

  *Status = RPC_S_OK;
499
  return y*256 + x;
500 501
}

502
/*************************************************************************
503
 *           UuidToStringA   [RPCRT4.@]
504 505 506 507 508 509 510 511 512
 *
 * Converts a UUID to a string.
 *
 * UUID format is 8 hex digits, followed by a hyphen then three groups of
 * 4 hex digits each followed by a hyphen and then 12 hex digits
 *
 * RETURNS
 *
 *  S_OK if successful.
513
 *  S_OUT_OF_MEMORY if unsuccessful.
514
 */
515
RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, RPC_CSTR* StringUuid)
516 517 518 519
{
  *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);

  if(!(*StringUuid))
520
    return RPC_S_OUT_OF_MEMORY;
521

522 523
  if (!Uuid) Uuid = &uuid_nil;

524
  sprintf( (char*)*StringUuid, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
525 526 527 528 529
                 Uuid->Data1, Uuid->Data2, Uuid->Data3,
                 Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],
                 Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
                 Uuid->Data4[6], Uuid->Data4[7] );

530
  return RPC_S_OK;
531
}
532

533 534 535 536 537 538
/*************************************************************************
 *           UuidToStringW   [RPCRT4.@]
 *
 * Converts a UUID to a string.
 *
 *  S_OK if successful.
539
 *  S_OUT_OF_MEMORY if unsuccessful.
540
 */
541
RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, RPC_WSTR* StringUuid)
542 543 544
{
  char buf[37];

545 546
  if (!Uuid) Uuid = &uuid_nil;

547
  sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
548 549 550 551 552 553 554 555 556 557 558 559
               Uuid->Data1, Uuid->Data2, Uuid->Data3,
               Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],
               Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
               Uuid->Data4[6], Uuid->Data4[7] );

  *StringUuid = RPCRT4_strdupAtoW(buf);

  if(!(*StringUuid))
    return RPC_S_OUT_OF_MEMORY;

  return RPC_S_OK;
}
560 561 562 563 564 565 566 567 568 569 570 571

static const BYTE hex2bin[] =
{
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x00 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x10 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x20 */
    0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,        /* 0x30 */
    0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  /* 0x40 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x50 */
    0,10,11,12,13,14,15                     /* 0x60 */
};

572 573 574
/***********************************************************************
 *		UuidFromStringA (RPCRT4.@)
 */
575
RPC_STATUS WINAPI UuidFromStringA(RPC_CSTR s, UUID *uuid)
576
{
577 578 579 580
    int i;

    if (!s) return UuidCreateNil( uuid );

581
    if (strlen((char*)s) != 36) return RPC_S_INVALID_STRING_UUID;
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608

    if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-'))
        return RPC_S_INVALID_STRING_UUID;

    for (i=0; i<36; i++)
    {
        if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue;
        if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID;
    }

    /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */

    uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 |
                   hex2bin[s[4]] << 12 | hex2bin[s[5]]  << 8 | hex2bin[s[6]]  << 4 | hex2bin[s[7]]);
    uuid->Data2 =  hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]];
    uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]];

    /* these are just sequential bytes */
    uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]];
    uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]];
    uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]];
    uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]];
    uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]];
    uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]];
    uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]];
    uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]];
    return RPC_S_OK;
609 610
}

611

612 613 614
/***********************************************************************
 *		UuidFromStringW (RPCRT4.@)
 */
615
RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid)
616
{
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
    int i;

    if (!s) return UuidCreateNil( uuid );

    if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID;

    if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-'))
        return RPC_S_INVALID_STRING_UUID;

    for (i=0; i<36; i++)
    {
        if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue;
        if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID;
    }

    /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */

    uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 |
                   hex2bin[s[4]] << 12 | hex2bin[s[5]]  << 8 | hex2bin[s[6]]  << 4 | hex2bin[s[7]]);
    uuid->Data2 =  hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]];
    uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]];

    /* these are just sequential bytes */
    uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]];
    uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]];
    uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]];
    uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]];
    uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]];
    uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]];
    uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]];
    uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]];
    return RPC_S_OK;
649 650
}

651 652 653 654
/***********************************************************************
 *              DllRegisterServer (RPCRT4.@)
 */

655
HRESULT WINAPI DllRegisterServer( void )
656
{
657 658 659 660
    FIXME( "(): stub\n" );
    return S_OK;
}

661 662 663 664
#define MAX_RPC_ERROR_TEXT 256

/******************************************************************************
 * DceErrorInqTextW   (rpcrt4.@)
665 666 667 668 669 670 671 672 673 674
 *
 * Notes
 * 1. On passing a NULL pointer the code does bomb out.
 * 2. The size of the required buffer is not defined in the documentation.
 *    It appears to be 256.
 * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know
 *    of any value for which it does.
 * 4. The MSDN documentation currently declares that the second argument is
 *    unsigned char *, even for the W version.  I don't believe it.
 */
675
RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, RPC_WSTR buffer)
676 677 678 679 680 681 682 683 684 685 686 687
{
    DWORD count;
    count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL);
    if (!count)
    {
        count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL);
        if (!count)
        {
688
            ERR ("Failed to translate error\n");
689 690 691 692 693 694
            return RPC_S_INVALID_ARG;
        }
    }
    return RPC_S_OK;
}

695 696 697
/******************************************************************************
 * DceErrorInqTextA   (rpcrt4.@)
 */
698
RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, RPC_CSTR buffer)
699 700 701 702 703
{
    RPC_STATUS status;
    WCHAR bufferW [MAX_RPC_ERROR_TEXT];
    if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK)
    {
704
        if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, (LPSTR)buffer, MAX_RPC_ERROR_TEXT,
705 706
                NULL, NULL))
        {
707
            ERR ("Failed to translate error\n");
708 709 710 711 712
            status = RPC_S_INVALID_ARG;
        }
    }
    return status;
}
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

/******************************************************************************
 * I_RpcAllocate   (rpcrt4.@)
 */
void * WINAPI I_RpcAllocate(unsigned int Size)
{
    return HeapAlloc(GetProcessHeap(), 0, Size);
}

/******************************************************************************
 * I_RpcFree   (rpcrt4.@)
 */
void WINAPI I_RpcFree(void *Object)
{
    HeapFree(GetProcessHeap(), 0, Object);
}
729 730 731

/******************************************************************************
 * I_RpcMapWin32Status   (rpcrt4.@)
732 733 734 735 736 737 738 739
 *
 * Maps Win32 RPC error codes to NT statuses.
 *
 * PARAMS
 *  status [I] Win32 RPC error code.
 *
 * RETURNS
 *  Appropriate translation into an NT status code.
740
 */
741
LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status)
742
{
743
    TRACE("(%d)\n", status);
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
    switch (status)
    {
    case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
    case ERROR_INVALID_HANDLE: return RPC_NT_SS_CONTEXT_MISMATCH;
    case ERROR_OUTOFMEMORY: return STATUS_NO_MEMORY;
    case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
    case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL;
    case ERROR_MAX_THRDS_REACHED: return STATUS_NO_MEMORY;
    case ERROR_NOACCESS: return STATUS_ACCESS_VIOLATION;
    case ERROR_NOT_ENOUGH_SERVER_MEMORY: return STATUS_INSUFF_SERVER_RESOURCES;
    case ERROR_WRONG_PASSWORD: return STATUS_WRONG_PASSWORD;
    case ERROR_INVALID_LOGON_HOURS: return STATUS_INVALID_LOGON_HOURS;
    case ERROR_PASSWORD_EXPIRED: return STATUS_PASSWORD_EXPIRED;
    case ERROR_ACCOUNT_DISABLED: return STATUS_ACCOUNT_DISABLED;
    case ERROR_INVALID_SECURITY_DESCR: return STATUS_INVALID_SECURITY_DESCR;
    case RPC_S_INVALID_STRING_BINDING: return RPC_NT_INVALID_STRING_BINDING;
    case RPC_S_WRONG_KIND_OF_BINDING: return RPC_NT_WRONG_KIND_OF_BINDING;
    case RPC_S_INVALID_BINDING: return RPC_NT_INVALID_BINDING;
    case RPC_S_PROTSEQ_NOT_SUPPORTED: return RPC_NT_PROTSEQ_NOT_SUPPORTED;
    case RPC_S_INVALID_RPC_PROTSEQ: return RPC_NT_INVALID_RPC_PROTSEQ;
    case RPC_S_INVALID_STRING_UUID: return RPC_NT_INVALID_STRING_UUID;
    case RPC_S_INVALID_ENDPOINT_FORMAT: return RPC_NT_INVALID_ENDPOINT_FORMAT;
    case RPC_S_INVALID_NET_ADDR: return RPC_NT_INVALID_NET_ADDR;
    case RPC_S_NO_ENDPOINT_FOUND: return RPC_NT_NO_ENDPOINT_FOUND;
    case RPC_S_INVALID_TIMEOUT: return RPC_NT_INVALID_TIMEOUT;
    case RPC_S_OBJECT_NOT_FOUND: return RPC_NT_OBJECT_NOT_FOUND;
    case RPC_S_ALREADY_REGISTERED: return RPC_NT_ALREADY_REGISTERED;
    case RPC_S_TYPE_ALREADY_REGISTERED: return RPC_NT_TYPE_ALREADY_REGISTERED;
    case RPC_S_ALREADY_LISTENING: return RPC_NT_ALREADY_LISTENING;
    case RPC_S_NO_PROTSEQS_REGISTERED: return RPC_NT_NO_PROTSEQS_REGISTERED;
    case RPC_S_NOT_LISTENING: return RPC_NT_NOT_LISTENING;
    case RPC_S_UNKNOWN_MGR_TYPE: return RPC_NT_UNKNOWN_MGR_TYPE;
    case RPC_S_UNKNOWN_IF: return RPC_NT_UNKNOWN_IF;
    case RPC_S_NO_BINDINGS: return RPC_NT_NO_BINDINGS;
    case RPC_S_NO_PROTSEQS: return RPC_NT_NO_PROTSEQS;
    case RPC_S_CANT_CREATE_ENDPOINT: return RPC_NT_CANT_CREATE_ENDPOINT;
    case RPC_S_OUT_OF_RESOURCES: return RPC_NT_OUT_OF_RESOURCES;
    case RPC_S_SERVER_UNAVAILABLE: return RPC_NT_SERVER_UNAVAILABLE;
    case RPC_S_SERVER_TOO_BUSY: return RPC_NT_SERVER_TOO_BUSY;
    case RPC_S_INVALID_NETWORK_OPTIONS: return RPC_NT_INVALID_NETWORK_OPTIONS;
    case RPC_S_NO_CALL_ACTIVE: return RPC_NT_NO_CALL_ACTIVE;
    case RPC_S_CALL_FAILED: return RPC_NT_CALL_FAILED;
    case RPC_S_CALL_FAILED_DNE: return RPC_NT_CALL_FAILED_DNE;
    case RPC_S_PROTOCOL_ERROR: return RPC_NT_PROTOCOL_ERROR;
    case RPC_S_UNSUPPORTED_TRANS_SYN: return RPC_NT_UNSUPPORTED_TRANS_SYN;
    case RPC_S_UNSUPPORTED_TYPE: return RPC_NT_UNSUPPORTED_TYPE;
    case RPC_S_INVALID_TAG: return RPC_NT_INVALID_TAG;
    case RPC_S_INVALID_BOUND: return RPC_NT_INVALID_BOUND;
    case RPC_S_NO_ENTRY_NAME: return RPC_NT_NO_ENTRY_NAME;
    case RPC_S_INVALID_NAME_SYNTAX: return RPC_NT_INVALID_NAME_SYNTAX;
    case RPC_S_UNSUPPORTED_NAME_SYNTAX: return RPC_NT_UNSUPPORTED_NAME_SYNTAX;
    case RPC_S_UUID_NO_ADDRESS: return RPC_NT_UUID_NO_ADDRESS;
    case RPC_S_DUPLICATE_ENDPOINT: return RPC_NT_DUPLICATE_ENDPOINT;
    case RPC_S_UNKNOWN_AUTHN_TYPE: return RPC_NT_UNKNOWN_AUTHN_TYPE;
    case RPC_S_MAX_CALLS_TOO_SMALL: return RPC_NT_MAX_CALLS_TOO_SMALL;
    case RPC_S_STRING_TOO_LONG: return RPC_NT_STRING_TOO_LONG;
    case RPC_S_PROTSEQ_NOT_FOUND: return RPC_NT_PROTSEQ_NOT_FOUND;
    case RPC_S_PROCNUM_OUT_OF_RANGE: return RPC_NT_PROCNUM_OUT_OF_RANGE;
    case RPC_S_BINDING_HAS_NO_AUTH: return RPC_NT_BINDING_HAS_NO_AUTH;
    case RPC_S_UNKNOWN_AUTHN_SERVICE: return RPC_NT_UNKNOWN_AUTHN_SERVICE;
    case RPC_S_UNKNOWN_AUTHN_LEVEL: return RPC_NT_UNKNOWN_AUTHN_LEVEL;
    case RPC_S_INVALID_AUTH_IDENTITY: return RPC_NT_INVALID_AUTH_IDENTITY;
    case RPC_S_UNKNOWN_AUTHZ_SERVICE: return RPC_NT_UNKNOWN_AUTHZ_SERVICE;
    case EPT_S_INVALID_ENTRY: return EPT_NT_INVALID_ENTRY;
    case EPT_S_CANT_PERFORM_OP: return EPT_NT_CANT_PERFORM_OP;
    case EPT_S_NOT_REGISTERED: return EPT_NT_NOT_REGISTERED;
    case EPT_S_CANT_CREATE: return EPT_NT_CANT_CREATE;
    case RPC_S_NOTHING_TO_EXPORT: return RPC_NT_NOTHING_TO_EXPORT;
    case RPC_S_INCOMPLETE_NAME: return RPC_NT_INCOMPLETE_NAME;
    case RPC_S_INVALID_VERS_OPTION: return RPC_NT_INVALID_VERS_OPTION;
    case RPC_S_NO_MORE_MEMBERS: return RPC_NT_NO_MORE_MEMBERS;
    case RPC_S_NOT_ALL_OBJS_UNEXPORTED: return RPC_NT_NOT_ALL_OBJS_UNEXPORTED;
    case RPC_S_INTERFACE_NOT_FOUND: return RPC_NT_INTERFACE_NOT_FOUND;
    case RPC_S_ENTRY_ALREADY_EXISTS: return RPC_NT_ENTRY_ALREADY_EXISTS;
    case RPC_S_ENTRY_NOT_FOUND: return RPC_NT_ENTRY_NOT_FOUND;
    case RPC_S_NAME_SERVICE_UNAVAILABLE: return RPC_NT_NAME_SERVICE_UNAVAILABLE;
    case RPC_S_INVALID_NAF_ID: return RPC_NT_INVALID_NAF_ID;
    case RPC_S_CANNOT_SUPPORT: return RPC_NT_CANNOT_SUPPORT;
    case RPC_S_NO_CONTEXT_AVAILABLE: return RPC_NT_NO_CONTEXT_AVAILABLE;
    case RPC_S_INTERNAL_ERROR: return RPC_NT_INTERNAL_ERROR;
    case RPC_S_ZERO_DIVIDE: return RPC_NT_ZERO_DIVIDE;
    case RPC_S_ADDRESS_ERROR: return RPC_NT_ADDRESS_ERROR;
    case RPC_S_FP_DIV_ZERO: return RPC_NT_FP_DIV_ZERO;
    case RPC_S_FP_UNDERFLOW: return RPC_NT_FP_UNDERFLOW;
    case RPC_S_FP_OVERFLOW: return RPC_NT_FP_OVERFLOW;
    case RPC_S_CALL_IN_PROGRESS: return RPC_NT_CALL_IN_PROGRESS;
    case RPC_S_NO_MORE_BINDINGS: return RPC_NT_NO_MORE_BINDINGS;
    case RPC_S_CALL_CANCELLED: return RPC_NT_CALL_CANCELLED;
    case RPC_S_INVALID_OBJECT: return RPC_NT_INVALID_OBJECT;
    case RPC_S_INVALID_ASYNC_HANDLE: return RPC_NT_INVALID_ASYNC_HANDLE;
    case RPC_S_INVALID_ASYNC_CALL: return RPC_NT_INVALID_ASYNC_CALL;
    case RPC_S_GROUP_MEMBER_NOT_FOUND: return RPC_NT_GROUP_MEMBER_NOT_FOUND;
    case RPC_X_NO_MORE_ENTRIES: return RPC_NT_NO_MORE_ENTRIES;
    case RPC_X_SS_CHAR_TRANS_OPEN_FAIL: return RPC_NT_SS_CHAR_TRANS_OPEN_FAIL;
    case RPC_X_SS_CHAR_TRANS_SHORT_FILE: return RPC_NT_SS_CHAR_TRANS_SHORT_FILE;
    case RPC_X_SS_IN_NULL_CONTEXT: return RPC_NT_SS_IN_NULL_CONTEXT;
    case RPC_X_SS_CONTEXT_DAMAGED: return RPC_NT_SS_CONTEXT_DAMAGED;
    case RPC_X_SS_HANDLES_MISMATCH: return RPC_NT_SS_HANDLES_MISMATCH;
    case RPC_X_SS_CANNOT_GET_CALL_HANDLE: return RPC_NT_SS_CANNOT_GET_CALL_HANDLE;
    case RPC_X_NULL_REF_POINTER: return RPC_NT_NULL_REF_POINTER;
    case RPC_X_ENUM_VALUE_OUT_OF_RANGE: return RPC_NT_ENUM_VALUE_OUT_OF_RANGE;
    case RPC_X_BYTE_COUNT_TOO_SMALL: return RPC_NT_BYTE_COUNT_TOO_SMALL;
    case RPC_X_BAD_STUB_DATA: return RPC_NT_BAD_STUB_DATA;
    case RPC_X_PIPE_CLOSED: return RPC_NT_PIPE_CLOSED;
    case RPC_X_PIPE_DISCIPLINE_ERROR: return RPC_NT_PIPE_DISCIPLINE_ERROR;
    case RPC_X_PIPE_EMPTY: return RPC_NT_PIPE_EMPTY;
    case ERROR_PASSWORD_MUST_CHANGE: return STATUS_PASSWORD_MUST_CHANGE;
    case ERROR_ACCOUNT_LOCKED_OUT: return STATUS_ACCOUNT_LOCKED_OUT;
    default: return status;
    }
854
}
855

856 857 858 859 860 861 862 863
/******************************************************************************
 * I_RpcExceptionFilter   (rpcrt4.@)
 */
int WINAPI I_RpcExceptionFilter(ULONG ExceptionCode)
{
    TRACE("0x%x\n", ExceptionCode);
    switch (ExceptionCode)
    {
864 865 866 867 868 869 870 871
    case STATUS_DATATYPE_MISALIGNMENT:
    case STATUS_BREAKPOINT:
    case STATUS_ACCESS_VIOLATION:
    case STATUS_ILLEGAL_INSTRUCTION:
    case STATUS_PRIVILEGED_INSTRUCTION:
    case STATUS_INSTRUCTION_MISALIGNMENT:
    case STATUS_STACK_OVERFLOW:
    case STATUS_POSSIBLE_DEADLOCK:
872 873 874 875 876 877
        return EXCEPTION_CONTINUE_SEARCH;
    default:
        return EXCEPTION_EXECUTE_HANDLER;
    }
}

878 879 880
/******************************************************************************
 * RpcErrorStartEnumeration   (rpcrt4.@)
 */
881
RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle)
882 883 884 885
{
    FIXME("(%p): stub\n", EnumHandle);
    return RPC_S_ENTRY_NOT_FOUND;
}
886

887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
/******************************************************************************
 * RpcErrorEndEnumeration   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcErrorEndEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle)
{
    FIXME("(%p): stub\n", EnumHandle);
    return RPC_S_OK;
}

/******************************************************************************
 * RpcErrorSaveErrorInfo   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcErrorSaveErrorInfo(RPC_ERROR_ENUM_HANDLE *EnumHandle, void **ErrorBlob, SIZE_T *BlobSize)
{
    FIXME("(%p %p %p): stub\n", EnumHandle, ErrorBlob, BlobSize);
    return ERROR_CALL_NOT_IMPLEMENTED;
}

/******************************************************************************
 * RpcErrorLoadErrorInfo   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcErrorLoadErrorInfo(void *ErrorBlob, SIZE_T BlobSize, RPC_ERROR_ENUM_HANDLE *EnumHandle)
{
    FIXME("(%p %lu %p): stub\n", ErrorBlob, BlobSize, EnumHandle);
    return ERROR_CALL_NOT_IMPLEMENTED;
}

/******************************************************************************
 * RpcErrorGetNextRecord   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcErrorGetNextRecord(RPC_ERROR_ENUM_HANDLE *EnumHandle, BOOL CopyStrings, RPC_EXTENDED_ERROR_INFO *ErrorInfo)
{
    FIXME("(%p %x %p): stub\n", EnumHandle, CopyStrings, ErrorInfo);
    return RPC_S_ENTRY_NOT_FOUND;
}

923 924 925 926 927 928 929 930 931
/******************************************************************************
 * RpcMgmtSetCancelTimeout   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout)
{
    FIXME("(%d): stub\n", Timeout);
    return RPC_S_OK;
}

932
static struct threaddata *get_or_create_threaddata(void)
933 934 935 936
{
    struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc;
    if (!tdata)
    {
937 938
        tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata));
        if (!tdata) return NULL;
939 940

        InitializeCriticalSection(&tdata->cs);
941
        tdata->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threaddata.cs");
942 943 944 945 946 947 948
        tdata->thread_id = GetCurrentThreadId();

        EnterCriticalSection(&threaddata_cs);
        list_add_tail(&threaddata_list, &tdata->entry);
        LeaveCriticalSection(&threaddata_cs);

        NtCurrentTeb()->ReservedForNtRpc = tdata;
949
        return tdata;
950
    }
951 952 953 954 955 956 957
    return tdata;
}

void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection)
{
    struct threaddata *tdata = get_or_create_threaddata();
    if (!tdata) return;
958 959 960 961 962 963

    EnterCriticalSection(&tdata->cs);
    tdata->connection = Connection;
    LeaveCriticalSection(&tdata->cs);
}

964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding)
{
    struct threaddata *tdata = get_or_create_threaddata();
    if (!tdata) return;

    tdata->server_binding = Binding;
}

RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void)
{
    struct threaddata *tdata = get_or_create_threaddata();
    if (!tdata) return NULL;

    return tdata->server_binding;
}

980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext)
{
    struct threaddata *tdata = get_or_create_threaddata();
    struct context_handle_list *context_handle_list;

    if (!tdata) return;

    context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list));
    if (!context_handle_list) return;

    context_handle_list->context_handle = SContext;
    context_handle_list->next = tdata->context_handle_list;
    tdata->context_handle_list = context_handle_list;
}

void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext)
{
    struct threaddata *tdata = get_or_create_threaddata();
    struct context_handle_list *current, *prev;

    if (!tdata) return;

    for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next)
    {
        if (current->context_handle == SContext)
        {
            if (prev)
                prev->next = current->next;
            else
                tdata->context_handle_list = current->next;
            HeapFree(GetProcessHeap(), 0, current);
            return;
        }
    }
}

NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void)
{
    struct threaddata *tdata = get_or_create_threaddata();
    struct context_handle_list *context_handle_list;
    NDR_SCONTEXT context_handle;

    if (!tdata) return NULL;

    context_handle_list = tdata->context_handle_list;
    if (!context_handle_list) return NULL;
    tdata->context_handle_list = context_handle_list->next;

    context_handle = context_handle_list->context_handle;
    HeapFree(GetProcessHeap(), 0, context_handle_list);
    return context_handle;
}

1033
static RPC_STATUS rpc_cancel_thread(DWORD target_tid)
1034
{
1035 1036 1037 1038 1039 1040
    struct threaddata *tdata;

    EnterCriticalSection(&threaddata_cs);
    LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry)
        if (tdata->thread_id == target_tid)
        {
1041 1042 1043
            EnterCriticalSection(&tdata->cs);
            if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection);
            LeaveCriticalSection(&tdata->cs);
1044 1045 1046 1047
            break;
        }
    LeaveCriticalSection(&threaddata_cs);

1048 1049
    return RPC_S_OK;
}
1050

1051 1052 1053 1054 1055 1056 1057 1058 1059
/******************************************************************************
 * RpcCancelThread   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle)
{
    TRACE("(%p)\n", ThreadHandle);
    return RpcCancelThreadEx(ThreadHandle, 0);
}

1060 1061 1062 1063 1064
/******************************************************************************
 * RpcCancelThreadEx   (rpcrt4.@)
 */
RPC_STATUS RPC_ENTRY RpcCancelThreadEx(void* ThreadHandle, LONG Timeout)
{
1065 1066
    DWORD target_tid;

1067
    FIXME("(%p, %d)\n", ThreadHandle, Timeout);
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079

    target_tid = GetThreadId(ThreadHandle);
    if (!target_tid)
        return RPC_S_INVALID_ARG;

    if (Timeout)
    {
        FIXME("(%p, %d)\n", ThreadHandle, Timeout);
        return RPC_S_OK;
    }
    else
        return rpc_cancel_thread(target_tid);
1080
}