Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrpcrt4_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
1.7.6.1
|