ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rpcrt4_main.c
Go to the documentation of this file.
00001 /*
00002  *  RPCRT4
00003  *
00004  * Copyright 2000 Huw D M Davies for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  * 
00020  * WINE RPC TODO's (and a few TODONT's)
00021  *
00022  * - Statistics: we are supposed to be keeping various counters.  we aren't.
00023  *
00024  * - Async RPC: Unimplemented.
00025  *
00026  * - The NT "ports" API, aka LPC.  Greg claims this is on his radar.  Might (or
00027  *   might not) enable users to get some kind of meaningful result out of
00028  *   NT-based native rpcrt4's.  Commonly-used transport for self-to-self RPC's.
00029  */
00030 
00031 #include "config.h"
00032 
00033 #include <stdarg.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 
00038 #include "ntstatus.h"
00039 #define WIN32_NO_STATUS
00040 #include "windef.h"
00041 #include "winerror.h"
00042 #include "winbase.h"
00043 #include "winuser.h"
00044 #include "winnt.h"
00045 #include "winternl.h"
00046 #include "ntsecapi.h"
00047 #include "iptypes.h"
00048 #include "iphlpapi.h"
00049 #include "wine/unicode.h"
00050 #include "rpc.h"
00051 
00052 #include "ole2.h"
00053 #include "rpcndr.h"
00054 #include "rpcproxy.h"
00055 
00056 #include "rpc_binding.h"
00057 #include "rpc_server.h"
00058 
00059 #include "wine/debug.h"
00060 
00061 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
00062 
00063 static UUID uuid_nil;
00064 
00065 static CRITICAL_SECTION uuid_cs;
00066 static CRITICAL_SECTION_DEBUG critsect_debug =
00067 {
00068     0, 0, &uuid_cs,
00069     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
00070       0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") }
00071 };
00072 static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
00073 
00074 static CRITICAL_SECTION threaddata_cs;
00075 static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
00076 {
00077     0, 0, &threaddata_cs,
00078     { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList },
00079       0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
00080 };
00081 static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 };
00082 
00083 static struct list threaddata_list = LIST_INIT(threaddata_list);
00084 
00085 struct context_handle_list
00086 {
00087     struct context_handle_list *next;
00088     NDR_SCONTEXT context_handle;
00089 };
00090 
00091 struct threaddata
00092 {
00093     struct list entry;
00094     CRITICAL_SECTION cs;
00095     DWORD thread_id;
00096     RpcConnection *connection;
00097     RpcBinding *server_binding;
00098     struct context_handle_list *context_handle_list;
00099 };
00100 
00101 /***********************************************************************
00102  * DllMain
00103  *
00104  * PARAMS
00105  *     hinstDLL    [I] handle to the DLL's instance
00106  *     fdwReason   [I]
00107  *     lpvReserved [I] reserved, must be NULL
00108  *
00109  * RETURNS
00110  *     Success: TRUE
00111  *     Failure: FALSE
00112  */
00113 
00114 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
00115 {
00116     struct threaddata *tdata;
00117 
00118     switch (fdwReason) {
00119     case DLL_PROCESS_ATTACH:
00120         break;
00121 
00122     case DLL_THREAD_DETACH:
00123         tdata = NtCurrentTeb()->ReservedForNtRpc;
00124         if (tdata)
00125         {
00126             EnterCriticalSection(&threaddata_cs);
00127             list_remove(&tdata->entry);
00128             LeaveCriticalSection(&threaddata_cs);
00129 
00130             DeleteCriticalSection(&tdata->cs);
00131             if (tdata->connection)
00132                 ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection);
00133             if (tdata->server_binding)
00134                 ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding);
00135             HeapFree(GetProcessHeap(), 0, tdata);
00136         }
00137         break;
00138 
00139     case DLL_PROCESS_DETACH:
00140         RPCRT4_destroy_all_protseqs();
00141         RPCRT4_ServerFreeAllRegisteredAuthInfo();
00142         break;
00143     }
00144 
00145     return TRUE;
00146 }
00147 
00148 /*************************************************************************
00149  *           RpcStringFreeA   [RPCRT4.@]
00150  *
00151  * Frees a character string allocated by the RPC run-time library.
00152  *
00153  * RETURNS
00154  *
00155  *  S_OK if successful.
00156  */
00157 RPC_STATUS WINAPI RpcStringFreeA(RPC_CSTR* String)
00158 {
00159   HeapFree( GetProcessHeap(), 0, *String);
00160 
00161   return RPC_S_OK;
00162 }
00163 
00164 /*************************************************************************
00165  *           RpcStringFreeW   [RPCRT4.@]
00166  *
00167  * Frees a character string allocated by the RPC run-time library.
00168  *
00169  * RETURNS
00170  *
00171  *  S_OK if successful.
00172  */
00173 RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String)
00174 {
00175   HeapFree( GetProcessHeap(), 0, *String);
00176 
00177   return RPC_S_OK;
00178 }
00179 
00180 /*************************************************************************
00181  *           RpcRaiseException   [RPCRT4.@]
00182  *
00183  * Raises an exception.
00184  */
00185 void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception)
00186 {
00187   /* shouldn't return */
00188   RaiseException(exception, 0, 0, NULL);
00189   ERR("handler continued execution\n");
00190   ExitProcess(1);
00191 }
00192 
00193 /*************************************************************************
00194  * UuidCompare [RPCRT4.@]
00195  *
00196  * PARAMS
00197  *     UUID *Uuid1        [I] Uuid to compare
00198  *     UUID *Uuid2        [I] Uuid to compare
00199  *     RPC_STATUS *Status [O] returns RPC_S_OK
00200  * 
00201  * RETURNS
00202  *    -1  if Uuid1 is less than Uuid2
00203  *     0  if Uuid1 and Uuid2 are equal
00204  *     1  if Uuid1 is greater than Uuid2
00205  */
00206 int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)
00207 {
00208   int i;
00209 
00210   TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));
00211 
00212   *Status = RPC_S_OK;
00213 
00214   if (!Uuid1) Uuid1 = &uuid_nil;
00215   if (!Uuid2) Uuid2 = &uuid_nil;
00216 
00217   if (Uuid1 == Uuid2) return 0;
00218 
00219   if (Uuid1->Data1 != Uuid2->Data1)
00220     return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1;
00221 
00222   if (Uuid1->Data2 != Uuid2->Data2)
00223     return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1;
00224 
00225   if (Uuid1->Data3 != Uuid2->Data3)
00226     return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1;
00227 
00228   for (i = 0; i < 8; i++) {
00229     if (Uuid1->Data4[i] < Uuid2->Data4[i])
00230       return -1;
00231     if (Uuid1->Data4[i] > Uuid2->Data4[i])
00232       return 1;
00233   }
00234 
00235   return 0;
00236 }
00237 
00238 /*************************************************************************
00239  * UuidEqual [RPCRT4.@]
00240  *
00241  * PARAMS
00242  *     UUID *Uuid1        [I] Uuid to compare
00243  *     UUID *Uuid2        [I] Uuid to compare
00244  *     RPC_STATUS *Status [O] returns RPC_S_OK
00245  *
00246  * RETURNS
00247  *     TRUE/FALSE
00248  */
00249 int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)
00250 {
00251   TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));
00252   return !UuidCompare(Uuid1, Uuid2, Status);
00253 }
00254 
00255 /*************************************************************************
00256  * UuidIsNil [RPCRT4.@]
00257  *
00258  * PARAMS
00259  *     UUID *Uuid         [I] Uuid to compare
00260  *     RPC_STATUS *Status [O] returns RPC_S_OK
00261  *
00262  * RETURNS
00263  *     TRUE/FALSE
00264  */
00265 int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status)
00266 {
00267   TRACE("(%s)\n", debugstr_guid(Uuid));
00268   if (!Uuid) return TRUE;
00269   return !UuidCompare(Uuid, &uuid_nil, Status);
00270 }
00271 
00272  /*************************************************************************
00273  * UuidCreateNil [RPCRT4.@]
00274  *
00275  * PARAMS
00276  *     UUID *Uuid [O] returns a nil UUID
00277  *
00278  * RETURNS
00279  *     RPC_S_OK
00280  */
00281 RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
00282 {
00283   *Uuid = uuid_nil;
00284   return RPC_S_OK;
00285 }
00286 
00287 /*************************************************************************
00288  *           UuidCreate   [RPCRT4.@]
00289  *
00290  * Creates a 128bit UUID.
00291  *
00292  * RETURNS
00293  *
00294  *  RPC_S_OK if successful.
00295  *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
00296  *
00297  * NOTES
00298  *
00299  *  Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
00300  *  Truly Random or Pseudo-Random Numbers)
00301  */
00302 RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
00303 {
00304     RtlGenRandom(Uuid, sizeof(*Uuid));
00305     /* Clear the version bits and set the version (4) */
00306     Uuid->Data3 &= 0x0fff;
00307     Uuid->Data3 |= (4 << 12);
00308     /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
00309      * specified in RFC 4122, section 4.4.
00310      */
00311     Uuid->Data4[0] &= 0x3f;
00312     Uuid->Data4[0] |= 0x80;
00313 
00314     TRACE("%s\n", debugstr_guid(Uuid));
00315 
00316     return RPC_S_OK;
00317 }
00318 
00319 /* Number of 100ns ticks per clock tick. To be safe, assume that the clock
00320    resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
00321 #define TICKS_PER_CLOCK_TICK 1000
00322 #define SECSPERDAY  86400
00323 #define TICKSPERSEC 10000000
00324 /* UUID system time starts at October 15, 1582 */
00325 #define SECS_15_OCT_1582_TO_1601  ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
00326 #define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
00327 
00328 static void RPC_UuidGetSystemTime(ULONGLONG *time)
00329 {
00330     FILETIME ft;
00331 
00332     GetSystemTimeAsFileTime(&ft);
00333 
00334     *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
00335     *time += TICKS_15_OCT_1582_TO_1601;
00336 }
00337 
00338 /* Assume that a hardware address is at least 6 bytes long */
00339 #define ADDRESS_BYTES_NEEDED 6
00340 
00341 static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
00342 {
00343     int i;
00344     DWORD status = RPC_S_OK;
00345 
00346     ULONG buflen = sizeof(IP_ADAPTER_INFO);
00347     PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
00348 
00349     if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) {
00350         HeapFree(GetProcessHeap(), 0, adapter);
00351         adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
00352     }
00353 
00354     if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) {
00355         for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
00356             address[i] = adapter->Address[i];
00357         }
00358     }
00359     /* We can't get a hardware address, just use random numbers.
00360        Set the multicast bit to prevent conflicts with real cards. */
00361     else {
00362         RtlGenRandom(address, ADDRESS_BYTES_NEEDED);
00363         address[0] |= 0x01;
00364         status = RPC_S_UUID_LOCAL_ONLY;
00365     }
00366 
00367     HeapFree(GetProcessHeap(), 0, adapter);
00368     return status;
00369 }
00370 
00371 /*************************************************************************
00372  *           UuidCreateSequential   [RPCRT4.@]
00373  *
00374  * Creates a 128bit UUID.
00375  *
00376  * RETURNS
00377  *
00378  *  RPC_S_OK if successful.
00379  *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
00380  *
00381  *  FIXME: No compensation for changes across reloading
00382  *         this dll or across reboots (e.g. clock going
00383  *         backwards and swapped network cards). The RFC
00384  *         suggests using NVRAM for storing persistent
00385  *         values.
00386  */
00387 RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
00388 {
00389     static int initialised, count;
00390 
00391     ULONGLONG time;
00392     static ULONGLONG timelast;
00393     static WORD sequence;
00394 
00395     static DWORD status;
00396     static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];
00397 
00398     EnterCriticalSection(&uuid_cs);
00399 
00400     if (!initialised) {
00401         RPC_UuidGetSystemTime(&timelast);
00402         count = TICKS_PER_CLOCK_TICK;
00403 
00404         sequence = ((rand() & 0xff) << 8) + (rand() & 0xff);
00405         sequence &= 0x1fff;
00406 
00407         status = RPC_UuidGetNodeAddress(address);
00408         initialised = 1;
00409     }
00410 
00411     /* Generate time element of the UUID. Account for going faster
00412        than our clock as well as the clock going backwards. */
00413     while (1) {
00414         RPC_UuidGetSystemTime(&time);
00415         if (time > timelast) {
00416             count = 0;
00417             break;
00418         }
00419         if (time < timelast) {
00420             sequence = (sequence + 1) & 0x1fff;
00421             count = 0;
00422             break;
00423         }
00424         if (count < TICKS_PER_CLOCK_TICK) {
00425             count++;
00426             break;
00427         }
00428     }
00429 
00430     timelast = time;
00431     time += count;
00432 
00433     /* Pack the information into the UUID structure. */
00434 
00435     Uuid->Data1  = (ULONG)(time & 0xffffffff);
00436     Uuid->Data2  = (unsigned short)((time >> 32) & 0xffff);
00437     Uuid->Data3  = (unsigned short)((time >> 48) & 0x0fff);
00438 
00439     /* This is a version 1 UUID */
00440     Uuid->Data3 |= (1 << 12);
00441 
00442     Uuid->Data4[0]  = sequence & 0xff;
00443     Uuid->Data4[1]  = (sequence & 0x3f00) >> 8;
00444     Uuid->Data4[1] |= 0x80;
00445     memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED);
00446 
00447     LeaveCriticalSection(&uuid_cs);
00448 
00449     TRACE("%s\n", debugstr_guid(Uuid));
00450 
00451     return status;
00452 }
00453 
00454 
00455 /*************************************************************************
00456  *           UuidHash   [RPCRT4.@]
00457  *
00458  * Generates a hash value for a given UUID
00459  *
00460  * Code based on FreeDCE implementation
00461  *
00462  */
00463 unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status)
00464 {
00465   BYTE *data = (BYTE*)uuid;
00466   short c0 = 0, c1 = 0, x, y;
00467   unsigned int i;
00468 
00469   if (!uuid) data = (BYTE*)(uuid = &uuid_nil);
00470 
00471   TRACE("(%s)\n", debugstr_guid(uuid));
00472 
00473   for (i=0; i<sizeof(UUID); i++) {
00474     c0 += data[i];
00475     c1 += c0;
00476   }
00477 
00478   x = -c1 % 255;
00479   if (x < 0) x += 255;
00480 
00481   y = (c1 - c0) % 255;
00482   if (y < 0) y += 255;
00483 
00484   *Status = RPC_S_OK;
00485   return y*256 + x;
00486 }
00487 
00488 /*************************************************************************
00489  *           UuidToStringA   [RPCRT4.@]
00490  *
00491  * Converts a UUID to a string.
00492  *
00493  * UUID format is 8 hex digits, followed by a hyphen then three groups of
00494  * 4 hex digits each followed by a hyphen and then 12 hex digits
00495  *
00496  * RETURNS
00497  *
00498  *  S_OK if successful.
00499  *  S_OUT_OF_MEMORY if unsuccessful.
00500  */
00501 RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, RPC_CSTR* StringUuid)
00502 {
00503   *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
00504 
00505   if(!(*StringUuid))
00506     return RPC_S_OUT_OF_MEMORY;
00507 
00508   if (!Uuid) Uuid = &uuid_nil;
00509 
00510   sprintf( (char*)*StringUuid, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00511                  Uuid->Data1, Uuid->Data2, Uuid->Data3,
00512                  Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],
00513                  Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
00514                  Uuid->Data4[6], Uuid->Data4[7] );
00515 
00516   return RPC_S_OK;
00517 }
00518 
00519 /*************************************************************************
00520  *           UuidToStringW   [RPCRT4.@]
00521  *
00522  * Converts a UUID to a string.
00523  *
00524  *  S_OK if successful.
00525  *  S_OUT_OF_MEMORY if unsuccessful.
00526  */
00527 RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, RPC_WSTR* StringUuid)
00528 {
00529   char buf[37];
00530 
00531   if (!Uuid) Uuid = &uuid_nil;
00532 
00533   sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00534                Uuid->Data1, Uuid->Data2, Uuid->Data3,
00535                Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],
00536                Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
00537                Uuid->Data4[6], Uuid->Data4[7] );
00538 
00539   *StringUuid = RPCRT4_strdupAtoW(buf);
00540 
00541   if(!(*StringUuid))
00542     return RPC_S_OUT_OF_MEMORY;
00543 
00544   return RPC_S_OK;
00545 }
00546 
00547 static const BYTE hex2bin[] =
00548 {
00549     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x00 */
00550     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x10 */
00551     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x20 */
00552     0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,        /* 0x30 */
00553     0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  /* 0x40 */
00554     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x50 */
00555     0,10,11,12,13,14,15                     /* 0x60 */
00556 };
00557 
00558 /***********************************************************************
00559  *      UuidFromStringA (RPCRT4.@)
00560  */
00561 RPC_STATUS WINAPI UuidFromStringA(RPC_CSTR s, UUID *uuid)
00562 {
00563     int i;
00564 
00565     if (!s) return UuidCreateNil( uuid );
00566 
00567     if (strlen((char*)s) != 36) return RPC_S_INVALID_STRING_UUID;
00568 
00569     if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-'))
00570         return RPC_S_INVALID_STRING_UUID;
00571 
00572     for (i=0; i<36; i++)
00573     {
00574         if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue;
00575         if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID;
00576     }
00577 
00578     /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
00579 
00580     uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 |
00581                    hex2bin[s[4]] << 12 | hex2bin[s[5]]  << 8 | hex2bin[s[6]]  << 4 | hex2bin[s[7]]);
00582     uuid->Data2 =  hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]];
00583     uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]];
00584 
00585     /* these are just sequential bytes */
00586     uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]];
00587     uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]];
00588     uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]];
00589     uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]];
00590     uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]];
00591     uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]];
00592     uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]];
00593     uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]];
00594     return RPC_S_OK;
00595 }
00596 
00597 
00598 /***********************************************************************
00599  *      UuidFromStringW (RPCRT4.@)
00600  */
00601 RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid)
00602 {
00603     int i;
00604 
00605     if (!s) return UuidCreateNil( uuid );
00606 
00607     if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID;
00608 
00609     if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-'))
00610         return RPC_S_INVALID_STRING_UUID;
00611 
00612     for (i=0; i<36; i++)
00613     {
00614         if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue;
00615         if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID;
00616     }
00617 
00618     /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
00619 
00620     uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 |
00621                    hex2bin[s[4]] << 12 | hex2bin[s[5]]  << 8 | hex2bin[s[6]]  << 4 | hex2bin[s[7]]);
00622     uuid->Data2 =  hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]];
00623     uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]];
00624 
00625     /* these are just sequential bytes */
00626     uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]];
00627     uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]];
00628     uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]];
00629     uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]];
00630     uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]];
00631     uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]];
00632     uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]];
00633     uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]];
00634     return RPC_S_OK;
00635 }
00636 
00637 /***********************************************************************
00638  *              DllRegisterServer (RPCRT4.@)
00639  */
00640 
00641 HRESULT WINAPI DllRegisterServer( void )
00642 {
00643     FIXME( "(): stub\n" );
00644     return S_OK;
00645 }
00646 
00647 #define MAX_RPC_ERROR_TEXT 256
00648 
00649 /******************************************************************************
00650  * DceErrorInqTextW   (rpcrt4.@)
00651  *
00652  * Notes
00653  * 1. On passing a NULL pointer the code does bomb out.
00654  * 2. The size of the required buffer is not defined in the documentation.
00655  *    It appears to be 256.
00656  * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know
00657  *    of any value for which it does.
00658  * 4. The MSDN documentation currently declares that the second argument is
00659  *    unsigned char *, even for the W version.  I don't believe it.
00660  */
00661 RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, RPC_WSTR buffer)
00662 {
00663     DWORD count;
00664     count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
00665                 FORMAT_MESSAGE_IGNORE_INSERTS,
00666                 NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL);
00667     if (!count)
00668     {
00669         count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
00670                 FORMAT_MESSAGE_IGNORE_INSERTS,
00671                 NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL);
00672         if (!count)
00673         {
00674             ERR ("Failed to translate error\n");
00675             return RPC_S_INVALID_ARG;
00676         }
00677     }
00678     return RPC_S_OK;
00679 }
00680 
00681 /******************************************************************************
00682  * DceErrorInqTextA   (rpcrt4.@)
00683  */
00684 RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, RPC_CSTR buffer)
00685 {
00686     RPC_STATUS status;
00687     WCHAR bufferW [MAX_RPC_ERROR_TEXT];
00688     if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK)
00689     {
00690         if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, (LPSTR)buffer, MAX_RPC_ERROR_TEXT,
00691                 NULL, NULL))
00692         {
00693             ERR ("Failed to translate error\n");
00694             status = RPC_S_INVALID_ARG;
00695         }
00696     }
00697     return status;
00698 }
00699 
00700 /******************************************************************************
00701  * I_RpcAllocate   (rpcrt4.@)
00702  */
00703 void * WINAPI I_RpcAllocate(unsigned int Size)
00704 {
00705     return HeapAlloc(GetProcessHeap(), 0, Size);
00706 }
00707 
00708 /******************************************************************************
00709  * I_RpcFree   (rpcrt4.@)
00710  */
00711 void WINAPI I_RpcFree(void *Object)
00712 {
00713     HeapFree(GetProcessHeap(), 0, Object);
00714 }
00715 
00716 /******************************************************************************
00717  * I_RpcMapWin32Status   (rpcrt4.@)
00718  *
00719  * Maps Win32 RPC error codes to NT statuses.
00720  *
00721  * PARAMS
00722  *  status [I] Win32 RPC error code.
00723  *
00724  * RETURNS
00725  *  Appropriate translation into an NT status code.
00726  */
00727 LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status)
00728 {
00729     TRACE("(%d)\n", status);
00730     switch (status)
00731     {
00732     case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
00733     case ERROR_INVALID_HANDLE: return RPC_NT_SS_CONTEXT_MISMATCH;
00734     case ERROR_OUTOFMEMORY: return STATUS_NO_MEMORY;
00735     case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
00736     case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL;
00737     case ERROR_MAX_THRDS_REACHED: return STATUS_NO_MEMORY;
00738     case ERROR_NOACCESS: return STATUS_ACCESS_VIOLATION;
00739     case ERROR_NOT_ENOUGH_SERVER_MEMORY: return STATUS_INSUFF_SERVER_RESOURCES;
00740     case ERROR_WRONG_PASSWORD: return STATUS_WRONG_PASSWORD;
00741     case ERROR_INVALID_LOGON_HOURS: return STATUS_INVALID_LOGON_HOURS;
00742     case ERROR_PASSWORD_EXPIRED: return STATUS_PASSWORD_EXPIRED;
00743     case ERROR_ACCOUNT_DISABLED: return STATUS_ACCOUNT_DISABLED;
00744     case ERROR_INVALID_SECURITY_DESCR: return STATUS_INVALID_SECURITY_DESCR;
00745     case RPC_S_INVALID_STRING_BINDING: return RPC_NT_INVALID_STRING_BINDING;
00746     case RPC_S_WRONG_KIND_OF_BINDING: return RPC_NT_WRONG_KIND_OF_BINDING;
00747     case RPC_S_INVALID_BINDING: return RPC_NT_INVALID_BINDING;
00748     case RPC_S_PROTSEQ_NOT_SUPPORTED: return RPC_NT_PROTSEQ_NOT_SUPPORTED;
00749     case RPC_S_INVALID_RPC_PROTSEQ: return RPC_NT_INVALID_RPC_PROTSEQ;
00750     case RPC_S_INVALID_STRING_UUID: return RPC_NT_INVALID_STRING_UUID;
00751     case RPC_S_INVALID_ENDPOINT_FORMAT: return RPC_NT_INVALID_ENDPOINT_FORMAT;
00752     case RPC_S_INVALID_NET_ADDR: return RPC_NT_INVALID_NET_ADDR;
00753     case RPC_S_NO_ENDPOINT_FOUND: return RPC_NT_NO_ENDPOINT_FOUND;
00754     case RPC_S_INVALID_TIMEOUT: return RPC_NT_INVALID_TIMEOUT;
00755     case RPC_S_OBJECT_NOT_FOUND: return RPC_NT_OBJECT_NOT_FOUND;
00756     case RPC_S_ALREADY_REGISTERED: return RPC_NT_ALREADY_REGISTERED;
00757     case RPC_S_TYPE_ALREADY_REGISTERED: return RPC_NT_TYPE_ALREADY_REGISTERED;
00758     case RPC_S_ALREADY_LISTENING: return RPC_NT_ALREADY_LISTENING;
00759     case RPC_S_NO_PROTSEQS_REGISTERED: return RPC_NT_NO_PROTSEQS_REGISTERED;
00760     case RPC_S_NOT_LISTENING: return RPC_NT_NOT_LISTENING;
00761     case RPC_S_UNKNOWN_MGR_TYPE: return RPC_NT_UNKNOWN_MGR_TYPE;
00762     case RPC_S_UNKNOWN_IF: return RPC_NT_UNKNOWN_IF;
00763     case RPC_S_NO_BINDINGS: return RPC_NT_NO_BINDINGS;
00764     case RPC_S_NO_PROTSEQS: return RPC_NT_NO_PROTSEQS;
00765     case RPC_S_CANT_CREATE_ENDPOINT: return RPC_NT_CANT_CREATE_ENDPOINT;
00766     case RPC_S_OUT_OF_RESOURCES: return RPC_NT_OUT_OF_RESOURCES;
00767     case RPC_S_SERVER_UNAVAILABLE: return RPC_NT_SERVER_UNAVAILABLE;
00768     case RPC_S_SERVER_TOO_BUSY: return RPC_NT_SERVER_TOO_BUSY;
00769     case RPC_S_INVALID_NETWORK_OPTIONS: return RPC_NT_INVALID_NETWORK_OPTIONS;
00770     case RPC_S_NO_CALL_ACTIVE: return RPC_NT_NO_CALL_ACTIVE;
00771     case RPC_S_CALL_FAILED: return RPC_NT_CALL_FAILED;
00772     case RPC_S_CALL_FAILED_DNE: return RPC_NT_CALL_FAILED_DNE;
00773     case RPC_S_PROTOCOL_ERROR: return RPC_NT_PROTOCOL_ERROR;
00774     case RPC_S_UNSUPPORTED_TRANS_SYN: return RPC_NT_UNSUPPORTED_TRANS_SYN;
00775     case RPC_S_UNSUPPORTED_TYPE: return RPC_NT_UNSUPPORTED_TYPE;
00776     case RPC_S_INVALID_TAG: return RPC_NT_INVALID_TAG;
00777     case RPC_S_INVALID_BOUND: return RPC_NT_INVALID_BOUND;
00778     case RPC_S_NO_ENTRY_NAME: return RPC_NT_NO_ENTRY_NAME;
00779     case RPC_S_INVALID_NAME_SYNTAX: return RPC_NT_INVALID_NAME_SYNTAX;
00780     case RPC_S_UNSUPPORTED_NAME_SYNTAX: return RPC_NT_UNSUPPORTED_NAME_SYNTAX;
00781     case RPC_S_UUID_NO_ADDRESS: return RPC_NT_UUID_NO_ADDRESS;
00782     case RPC_S_DUPLICATE_ENDPOINT: return RPC_NT_DUPLICATE_ENDPOINT;
00783     case RPC_S_UNKNOWN_AUTHN_TYPE: return RPC_NT_UNKNOWN_AUTHN_TYPE;
00784     case RPC_S_MAX_CALLS_TOO_SMALL: return RPC_NT_MAX_CALLS_TOO_SMALL;
00785     case RPC_S_STRING_TOO_LONG: return RPC_NT_STRING_TOO_LONG;
00786     case RPC_S_PROTSEQ_NOT_FOUND: return RPC_NT_PROTSEQ_NOT_FOUND;
00787     case RPC_S_PROCNUM_OUT_OF_RANGE: return RPC_NT_PROCNUM_OUT_OF_RANGE;
00788     case RPC_S_BINDING_HAS_NO_AUTH: return RPC_NT_BINDING_HAS_NO_AUTH;
00789     case RPC_S_UNKNOWN_AUTHN_SERVICE: return RPC_NT_UNKNOWN_AUTHN_SERVICE;
00790     case RPC_S_UNKNOWN_AUTHN_LEVEL: return RPC_NT_UNKNOWN_AUTHN_LEVEL;
00791     case RPC_S_INVALID_AUTH_IDENTITY: return RPC_NT_INVALID_AUTH_IDENTITY;
00792     case RPC_S_UNKNOWN_AUTHZ_SERVICE: return RPC_NT_UNKNOWN_AUTHZ_SERVICE;
00793     case EPT_S_INVALID_ENTRY: return EPT_NT_INVALID_ENTRY;
00794     case EPT_S_CANT_PERFORM_OP: return EPT_NT_CANT_PERFORM_OP;
00795     case EPT_S_NOT_REGISTERED: return EPT_NT_NOT_REGISTERED;
00796     case EPT_S_CANT_CREATE: return EPT_NT_CANT_CREATE;
00797     case RPC_S_NOTHING_TO_EXPORT: return RPC_NT_NOTHING_TO_EXPORT;
00798     case RPC_S_INCOMPLETE_NAME: return RPC_NT_INCOMPLETE_NAME;
00799     case RPC_S_INVALID_VERS_OPTION: return RPC_NT_INVALID_VERS_OPTION;
00800     case RPC_S_NO_MORE_MEMBERS: return RPC_NT_NO_MORE_MEMBERS;
00801     case RPC_S_NOT_ALL_OBJS_UNEXPORTED: return RPC_NT_NOT_ALL_OBJS_UNEXPORTED;
00802     case RPC_S_INTERFACE_NOT_FOUND: return RPC_NT_INTERFACE_NOT_FOUND;
00803     case RPC_S_ENTRY_ALREADY_EXISTS: return RPC_NT_ENTRY_ALREADY_EXISTS;
00804     case RPC_S_ENTRY_NOT_FOUND: return RPC_NT_ENTRY_NOT_FOUND;
00805     case RPC_S_NAME_SERVICE_UNAVAILABLE: return RPC_NT_NAME_SERVICE_UNAVAILABLE;
00806     case RPC_S_INVALID_NAF_ID: return RPC_NT_INVALID_NAF_ID;
00807     case RPC_S_CANNOT_SUPPORT: return RPC_NT_CANNOT_SUPPORT;
00808     case RPC_S_NO_CONTEXT_AVAILABLE: return RPC_NT_NO_CONTEXT_AVAILABLE;
00809     case RPC_S_INTERNAL_ERROR: return RPC_NT_INTERNAL_ERROR;
00810     case RPC_S_ZERO_DIVIDE: return RPC_NT_ZERO_DIVIDE;
00811     case RPC_S_ADDRESS_ERROR: return RPC_NT_ADDRESS_ERROR;
00812     case RPC_S_FP_DIV_ZERO: return RPC_NT_FP_DIV_ZERO;
00813     case RPC_S_FP_UNDERFLOW: return RPC_NT_FP_UNDERFLOW;
00814     case RPC_S_FP_OVERFLOW: return RPC_NT_FP_OVERFLOW;
00815     case RPC_S_CALL_IN_PROGRESS: return RPC_NT_CALL_IN_PROGRESS;
00816     case RPC_S_NO_MORE_BINDINGS: return RPC_NT_NO_MORE_BINDINGS;
00817     case RPC_S_CALL_CANCELLED: return RPC_NT_CALL_CANCELLED;
00818     case RPC_S_INVALID_OBJECT: return RPC_NT_INVALID_OBJECT;
00819     case RPC_S_INVALID_ASYNC_HANDLE: return RPC_NT_INVALID_ASYNC_HANDLE;
00820     case RPC_S_INVALID_ASYNC_CALL: return RPC_NT_INVALID_ASYNC_CALL;
00821     case RPC_S_GROUP_MEMBER_NOT_FOUND: return RPC_NT_GROUP_MEMBER_NOT_FOUND;
00822     case RPC_X_NO_MORE_ENTRIES: return RPC_NT_NO_MORE_ENTRIES;
00823     case RPC_X_SS_CHAR_TRANS_OPEN_FAIL: return RPC_NT_SS_CHAR_TRANS_OPEN_FAIL;
00824     case RPC_X_SS_CHAR_TRANS_SHORT_FILE: return RPC_NT_SS_CHAR_TRANS_SHORT_FILE;
00825     case RPC_X_SS_IN_NULL_CONTEXT: return RPC_NT_SS_IN_NULL_CONTEXT;
00826     case RPC_X_SS_CONTEXT_DAMAGED: return RPC_NT_SS_CONTEXT_DAMAGED;
00827     case RPC_X_SS_HANDLES_MISMATCH: return RPC_NT_SS_HANDLES_MISMATCH;
00828     case RPC_X_SS_CANNOT_GET_CALL_HANDLE: return RPC_NT_SS_CANNOT_GET_CALL_HANDLE;
00829     case RPC_X_NULL_REF_POINTER: return RPC_NT_NULL_REF_POINTER;
00830     case RPC_X_ENUM_VALUE_OUT_OF_RANGE: return RPC_NT_ENUM_VALUE_OUT_OF_RANGE;
00831     case RPC_X_BYTE_COUNT_TOO_SMALL: return RPC_NT_BYTE_COUNT_TOO_SMALL;
00832     case RPC_X_BAD_STUB_DATA: return RPC_NT_BAD_STUB_DATA;
00833     case RPC_X_PIPE_CLOSED: return RPC_NT_PIPE_CLOSED;
00834     case RPC_X_PIPE_DISCIPLINE_ERROR: return RPC_NT_PIPE_DISCIPLINE_ERROR;
00835     case RPC_X_PIPE_EMPTY: return RPC_NT_PIPE_EMPTY;
00836     case ERROR_PASSWORD_MUST_CHANGE: return STATUS_PASSWORD_MUST_CHANGE;
00837     case ERROR_ACCOUNT_LOCKED_OUT: return STATUS_ACCOUNT_LOCKED_OUT;
00838     default: return status;
00839     }
00840 }
00841 
00842 /******************************************************************************
00843  * I_RpcExceptionFilter   (rpcrt4.@)
00844  */
00845 int WINAPI I_RpcExceptionFilter(ULONG ExceptionCode)
00846 {
00847     TRACE("0x%x\n", ExceptionCode);
00848     switch (ExceptionCode)
00849     {
00850     case STATUS_DATATYPE_MISALIGNMENT:
00851     case STATUS_BREAKPOINT:
00852     case STATUS_ACCESS_VIOLATION:
00853     case STATUS_ILLEGAL_INSTRUCTION:
00854     case STATUS_PRIVILEGED_INSTRUCTION:
00855     case STATUS_INSTRUCTION_MISALIGNMENT:
00856     case STATUS_STACK_OVERFLOW:
00857     case STATUS_POSSIBLE_DEADLOCK:
00858         return EXCEPTION_CONTINUE_SEARCH;
00859     default:
00860         return EXCEPTION_EXECUTE_HANDLER;
00861     }
00862 }
00863 
00864 /******************************************************************************
00865  * RpcErrorStartEnumeration   (rpcrt4.@)
00866  */
00867 RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle)
00868 {
00869     FIXME("(%p): stub\n", EnumHandle);
00870     return RPC_S_ENTRY_NOT_FOUND;
00871 }
00872 
00873 /******************************************************************************
00874  * RpcMgmtSetCancelTimeout   (rpcrt4.@)
00875  */
00876 RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout)
00877 {
00878     FIXME("(%d): stub\n", Timeout);
00879     return RPC_S_OK;
00880 }
00881 
00882 static struct threaddata *get_or_create_threaddata(void)
00883 {
00884     struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc;
00885     if (!tdata)
00886     {
00887         tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata));
00888         if (!tdata) return NULL;
00889 
00890         InitializeCriticalSection(&tdata->cs);
00891         tdata->thread_id = GetCurrentThreadId();
00892 
00893         EnterCriticalSection(&threaddata_cs);
00894         list_add_tail(&threaddata_list, &tdata->entry);
00895         LeaveCriticalSection(&threaddata_cs);
00896 
00897         NtCurrentTeb()->ReservedForNtRpc = tdata;
00898         return tdata;
00899     }
00900     return tdata;
00901 }
00902 
00903 void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection)
00904 {
00905     struct threaddata *tdata = get_or_create_threaddata();
00906     if (!tdata) return;
00907 
00908     EnterCriticalSection(&tdata->cs);
00909     tdata->connection = Connection;
00910     LeaveCriticalSection(&tdata->cs);
00911 }
00912 
00913 void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding)
00914 {
00915     struct threaddata *tdata = get_or_create_threaddata();
00916     if (!tdata) return;
00917 
00918     tdata->server_binding = Binding;
00919 }
00920 
00921 RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void)
00922 {
00923     struct threaddata *tdata = get_or_create_threaddata();
00924     if (!tdata) return NULL;
00925 
00926     return tdata->server_binding;
00927 }
00928 
00929 void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext)
00930 {
00931     struct threaddata *tdata = get_or_create_threaddata();
00932     struct context_handle_list *context_handle_list;
00933 
00934     if (!tdata) return;
00935 
00936     context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list));
00937     if (!context_handle_list) return;
00938 
00939     context_handle_list->context_handle = SContext;
00940     context_handle_list->next = tdata->context_handle_list;
00941     tdata->context_handle_list = context_handle_list;
00942 }
00943 
00944 void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext)
00945 {
00946     struct threaddata *tdata = get_or_create_threaddata();
00947     struct context_handle_list *current, *prev;
00948 
00949     if (!tdata) return;
00950 
00951     for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next)
00952     {
00953         if (current->context_handle == SContext)
00954         {
00955             if (prev)
00956                 prev->next = current->next;
00957             else
00958                 tdata->context_handle_list = current->next;
00959             HeapFree(GetProcessHeap(), 0, current);
00960             return;
00961         }
00962     }
00963 }
00964 
00965 NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void)
00966 {
00967     struct threaddata *tdata = get_or_create_threaddata();
00968     struct context_handle_list *context_handle_list;
00969     NDR_SCONTEXT context_handle;
00970 
00971     if (!tdata) return NULL;
00972 
00973     context_handle_list = tdata->context_handle_list;
00974     if (!context_handle_list) return NULL;
00975     tdata->context_handle_list = context_handle_list->next;
00976 
00977     context_handle = context_handle_list->context_handle;
00978     HeapFree(GetProcessHeap(), 0, context_handle_list);
00979     return context_handle;
00980 }
00981 
00982 static RPC_STATUS rpc_cancel_thread(DWORD target_tid)
00983 {
00984     struct threaddata *tdata;
00985 
00986     EnterCriticalSection(&threaddata_cs);
00987     LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry)
00988         if (tdata->thread_id == target_tid)
00989         {
00990             EnterCriticalSection(&tdata->cs);
00991             if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection);
00992             LeaveCriticalSection(&tdata->cs);
00993             break;
00994         }
00995     LeaveCriticalSection(&threaddata_cs);
00996 
00997     return RPC_S_OK;
00998 }
00999 
01000 /******************************************************************************
01001  * RpcCancelThread   (rpcrt4.@)
01002  */
01003 RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle)
01004 {
01005     TRACE("(%p)\n", ThreadHandle);
01006     return RpcCancelThreadEx(ThreadHandle, 0);
01007 }
01008 
01009 /******************************************************************************
01010  * RpcCancelThreadEx   (rpcrt4.@)
01011  */
01012 RPC_STATUS RPC_ENTRY RpcCancelThreadEx(void* ThreadHandle, LONG Timeout)
01013 {
01014     DWORD target_tid;
01015 
01016     FIXME("(%p, %d)\n", ThreadHandle, Timeout);
01017 
01018     target_tid = GetThreadId(ThreadHandle);
01019     if (!target_tid)
01020         return RPC_S_INVALID_ARG;
01021 
01022     if (Timeout)
01023     {
01024         FIXME("(%p, %d)\n", ThreadHandle, Timeout);
01025         return RPC_S_OK;
01026     }
01027     else
01028         return rpc_cancel_thread(target_tid);
01029 }

Generated on Sat May 26 2012 04:24:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.