4 * Copyright 2000 Huw D M Davies for Codeweavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #ifdef HAVE_SYS_TIME_H
28 # include <sys/time.h>
37 #include "wine/unicode.h"
44 #ifdef HAVE_SYS_FILE_H
45 # include <sys/file.h>
47 #ifdef HAVE_SYS_IOCTL_H
48 # include <sys/ioctl.h>
50 #ifdef HAVE_SYS_SOCKET_H
51 # include <sys/socket.h>
53 #ifdef HAVE_SYS_SOCKIO_H
54 # include <sys/sockio.h>
59 #ifdef HAVE_NETINET_IN_H
60 # include <netinet/in.h>
63 #include "rpc_binding.h"
65 #include "wine/debug.h"
67 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
71 /***********************************************************************
75 * hinstDLL [I] handle to the DLL's instance
77 * lpvReserved [I] reserved, must be NULL
85 RPCRT4_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
88 case DLL_PROCESS_ATTACH
:
91 case DLL_PROCESS_DETACH
:
98 /*************************************************************************
99 * RpcStringFreeA [RPCRT4.@]
101 * Frees a character string allocated by the RPC run-time library.
105 * S_OK if successful.
107 RPC_STATUS WINAPI
RpcStringFreeA(LPSTR
* String
)
109 HeapFree( GetProcessHeap(), 0, *String
);
114 /*************************************************************************
115 * RpcStringFreeW [RPCRT4.@]
117 * Frees a character string allocated by the RPC run-time library.
121 * S_OK if successful.
123 RPC_STATUS WINAPI
RpcStringFreeW(LPWSTR
* String
)
125 HeapFree( GetProcessHeap(), 0, *String
);
130 /*************************************************************************
131 * UuidCompare [RPCRT4.@]
133 * (an educated-guess implementation)
136 * UUID *Uuid1 [I] Uuid to compare
137 * UUID *Uuid2 [I] Uuid to compare
138 * RPC_STATUS *Status [O] returns RPC_S_OK
141 * -1 if Uuid1 is less than Uuid2
142 * 0 if Uuid1 and Uuid2 are equal
143 * 1 if Uuid1 is greater than Uuid2
145 int WINAPI
UuidCompare(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
147 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
149 if (!Uuid1
) Uuid1
= &uuid_nil
;
150 if (!Uuid2
) Uuid2
= &uuid_nil
;
151 if (Uuid1
== Uuid2
) return 0;
152 return memcmp(Uuid1
, Uuid2
, sizeof(UUID
));
155 /*************************************************************************
156 * UuidEqual [RPCRT4.@]
159 * UUID *Uuid1 [I] Uuid to compare
160 * UUID *Uuid2 [I] Uuid to compare
161 * RPC_STATUS *Status [O] returns RPC_S_OK
166 int WINAPI
UuidEqual(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
168 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
169 return !UuidCompare(Uuid1
, Uuid2
, Status
);
172 /*************************************************************************
173 * UuidIsNil [RPCRT4.@]
176 * UUID *Uuid [I] Uuid to compare
177 * RPC_STATUS *Status [O] retuns RPC_S_OK
182 int WINAPI
UuidIsNil(UUID
*uuid
, RPC_STATUS
*Status
)
184 TRACE("(%s)\n", debugstr_guid(uuid
));
186 if (!uuid
) return TRUE
;
187 return !memcmp(uuid
, &uuid_nil
, sizeof(UUID
));
190 /*************************************************************************
191 * UuidCreateNil [RPCRT4.@]
194 * UUID *Uuid [O] returns a nil UUID
199 RPC_STATUS WINAPI
UuidCreateNil(UUID
*Uuid
)
205 /*************************************************************************
206 * UuidCreate [RPCRT4.@]
208 * Creates a 128bit UUID.
209 * Implemented according the DCE specification for UUID generation.
210 * Code is based upon uuid library in e2fsprogs by Theodore Ts'o.
211 * Copyright (C) 1996, 1997 Theodore Ts'o.
215 * S_OK if successful.
217 RPC_STATUS WINAPI
UuidCreate(UUID
*Uuid
)
219 static char has_init
= 0;
220 static unsigned char a
[6];
221 static int adjustment
= 0;
222 static struct timeval last
= {0, 0};
223 static WORD clock_seq
;
225 unsigned long long clock_reg
;
226 DWORD clock_high
, clock_low
;
227 WORD temp_clock_seq
, temp_clock_mid
, temp_clock_hi_and_version
;
230 struct ifreq ifr
, *ifrp
;
236 /* Have we already tried to get the MAC address? */
239 /* BSD 4.4 defines the size of an ifreq to be
240 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
241 * However, under earlier systems, sa_len isn't present, so
242 * the size is just sizeof(struct ifreq)
244 #ifdef HAVE_SOCKADDR_SA_LEN
246 # define max(a,b) ((a) > (b) ? (a) : (b))
248 # define ifreq_size(i) max(sizeof(struct ifreq),\
249 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
251 # define ifreq_size(i) sizeof(struct ifreq)
252 # endif /* defined(HAVE_SOCKADDR_SA_LEN) */
254 sd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
256 /* if we can't open a socket, just use random numbers */
257 /* set the multicast bit to prevent conflicts with real cards */
258 a
[0] = (rand() & 0xff) | 0x80;
259 a
[1] = rand() & 0xff;
260 a
[2] = rand() & 0xff;
261 a
[3] = rand() & 0xff;
262 a
[4] = rand() & 0xff;
263 a
[5] = rand() & 0xff;
265 memset(buf
, 0, sizeof(buf
));
266 ifc
.ifc_len
= sizeof(buf
);
268 /* get the ifconf interface */
269 if (ioctl (sd
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
271 /* no ifconf, so just use random numbers */
272 /* set the multicast bit to prevent conflicts with real cards */
273 a
[0] = (rand() & 0xff) | 0x80;
274 a
[1] = rand() & 0xff;
275 a
[2] = rand() & 0xff;
276 a
[3] = rand() & 0xff;
277 a
[4] = rand() & 0xff;
278 a
[5] = rand() & 0xff;
280 /* loop through the interfaces, looking for a valid one */
282 for (i
= 0; i
< n
; i
+= ifreq_size(ifr
) ) {
283 ifrp
= (struct ifreq
*)((char *) ifc
.ifc_buf
+i
);
284 strncpy(ifr
.ifr_name
, ifrp
->ifr_name
, IFNAMSIZ
);
285 /* try to get the address for this interface */
286 # ifdef SIOCGIFHWADDR
287 if (ioctl(sd
, SIOCGIFHWADDR
, &ifr
) < 0)
289 memcpy(a
, (unsigned char *)&ifr
.ifr_hwaddr
.sa_data
, 6);
292 if (ioctl(sd
, SIOCGENADDR
, &ifr
) < 0)
294 memcpy(a
, (unsigned char *) ifr
.ifr_enaddr
, 6);
296 /* XXX we don't have a way of getting the hardware address */
300 # endif /* SIOCGENADDR */
301 # endif /* SIOCGIFHWADDR */
302 /* make sure it's not blank */
303 if (!a
[0] && !a
[1] && !a
[2] && !a
[3] && !a
[4] && !a
[5])
308 /* if we didn't find a valid address, make a random one */
309 /* once again, set multicast bit to avoid conflicts */
310 a
[0] = (rand() & 0xff) | 0x80;
311 a
[1] = rand() & 0xff;
312 a
[2] = rand() & 0xff;
313 a
[3] = rand() & 0xff;
314 a
[4] = rand() & 0xff;
315 a
[5] = rand() & 0xff;
322 /* no networking info, so generate a random address */
323 a
[0] = (rand() & 0xff) | 0x80;
324 a
[1] = rand() & 0xff;
325 a
[2] = rand() & 0xff;
326 a
[3] = rand() & 0xff;
327 a
[4] = rand() & 0xff;
328 a
[5] = rand() & 0xff;
329 #endif /* HAVE_NET_IF_H */
333 /* generate time element of GUID */
335 /* Assume that the gettimeofday() has microsecond granularity */
336 #define MAX_ADJUSTMENT 10
339 gettimeofday(&tv
, 0);
340 if ((last
.tv_sec
== 0) && (last
.tv_usec
== 0)) {
341 clock_seq
= ((rand() & 0xff) << 8) + (rand() & 0xff);
346 if ((tv
.tv_sec
< last
.tv_sec
) ||
347 ((tv
.tv_sec
== last
.tv_sec
) &&
348 (tv
.tv_usec
< last
.tv_usec
))) {
349 clock_seq
= (clock_seq
+1) & 0x1FFF;
351 } else if ((tv
.tv_sec
== last
.tv_sec
) &&
352 (tv
.tv_usec
== last
.tv_usec
)) {
353 if (adjustment
>= MAX_ADJUSTMENT
)
359 clock_reg
= tv
.tv_usec
*10 + adjustment
;
360 clock_reg
+= ((unsigned long long) tv
.tv_sec
)*10000000;
361 clock_reg
+= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
363 clock_high
= clock_reg
>> 32;
364 clock_low
= clock_reg
;
365 temp_clock_seq
= clock_seq
| 0x8000;
366 temp_clock_mid
= (WORD
)clock_high
;
367 temp_clock_hi_and_version
= (clock_high
>> 16) | 0x1000;
369 /* pack the information into the GUID structure */
371 ((unsigned char*)&Uuid
->Data1
)[3] = (unsigned char)clock_low
;
373 ((unsigned char*)&Uuid
->Data1
)[2] = (unsigned char)clock_low
;
375 ((unsigned char*)&Uuid
->Data1
)[1] = (unsigned char)clock_low
;
377 ((unsigned char*)&Uuid
->Data1
)[0] = (unsigned char)clock_low
;
379 ((unsigned char*)&Uuid
->Data2
)[1] = (unsigned char)temp_clock_mid
;
380 temp_clock_mid
>>= 8;
381 ((unsigned char*)&Uuid
->Data2
)[0] = (unsigned char)temp_clock_mid
;
383 ((unsigned char*)&Uuid
->Data3
)[1] = (unsigned char)temp_clock_hi_and_version
;
384 temp_clock_hi_and_version
>>= 8;
385 ((unsigned char*)&Uuid
->Data3
)[0] = (unsigned char)temp_clock_hi_and_version
;
387 ((unsigned char*)Uuid
->Data4
)[1] = (unsigned char)temp_clock_seq
;
388 temp_clock_seq
>>= 8;
389 ((unsigned char*)Uuid
->Data4
)[0] = (unsigned char)temp_clock_seq
;
391 ((unsigned char*)Uuid
->Data4
)[2] = a
[0];
392 ((unsigned char*)Uuid
->Data4
)[3] = a
[1];
393 ((unsigned char*)Uuid
->Data4
)[4] = a
[2];
394 ((unsigned char*)Uuid
->Data4
)[5] = a
[3];
395 ((unsigned char*)Uuid
->Data4
)[6] = a
[4];
396 ((unsigned char*)Uuid
->Data4
)[7] = a
[5];
398 TRACE("%s\n", debugstr_guid(Uuid
));
404 /*************************************************************************
405 * UuidCreateSequential [RPCRT4.@]
407 * Creates a 128bit UUID by calling UuidCreate.
408 * New API in Win 2000
410 RPC_STATUS WINAPI
UuidCreateSequential(UUID
*Uuid
)
412 return UuidCreate (Uuid
);
416 /*************************************************************************
417 * UuidHash [RPCRT4.@]
419 * Generates a hash value for a given UUID
421 * Code based on FreeDCE implementation
424 unsigned short WINAPI
UuidHash(UUID
*uuid
, RPC_STATUS
*Status
)
426 BYTE
*data
= (BYTE
*)uuid
;
427 short c0
= 0, c1
= 0, x
, y
;
430 TRACE("(%s)\n", debugstr_guid(uuid
));
432 for (i
=0; i
<sizeof(UUID
); i
++) {
447 /*************************************************************************
448 * UuidToStringA [RPCRT4.@]
450 * Converts a UUID to a string.
452 * UUID format is 8 hex digits, followed by a hyphen then three groups of
453 * 4 hex digits each followed by a hyphen and then 12 hex digits
457 * S_OK if successful.
458 * S_OUT_OF_MEMORY if unsucessful.
460 RPC_STATUS WINAPI
UuidToStringA(UUID
*Uuid
, LPSTR
* StringUuid
)
462 *StringUuid
= HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
465 return RPC_S_OUT_OF_MEMORY
;
467 sprintf(*StringUuid
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
468 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
469 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
470 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
471 Uuid
->Data4
[6], Uuid
->Data4
[7] );
476 /*************************************************************************
477 * UuidToStringW [RPCRT4.@]
479 * Converts a UUID to a string.
481 * S_OK if successful.
482 * S_OUT_OF_MEMORY if unsucessful.
484 RPC_STATUS WINAPI
UuidToStringW(UUID
*Uuid
, LPWSTR
* StringUuid
)
488 sprintf(buf
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
489 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
490 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
491 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
492 Uuid
->Data4
[6], Uuid
->Data4
[7] );
494 *StringUuid
= RPCRT4_strdupAtoW(buf
);
497 return RPC_S_OUT_OF_MEMORY
;
502 static const BYTE hex2bin
[] =
504 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
505 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
506 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
507 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
508 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
509 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
510 0,10,11,12,13,14,15 /* 0x60 */
513 /***********************************************************************
514 * UuidFromStringA (RPCRT4.@)
516 RPC_STATUS WINAPI
UuidFromStringA(LPSTR str
, UUID
*uuid
)
518 BYTE
*s
= (BYTE
*)str
;
521 if (!s
) return UuidCreateNil( uuid
);
523 if (strlen(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
525 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
526 return RPC_S_INVALID_STRING_UUID
;
530 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
531 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
534 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
536 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
537 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
538 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
539 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
541 /* these are just sequential bytes */
542 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
543 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
544 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
545 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
546 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
547 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
548 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
549 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
554 /***********************************************************************
555 * UuidFromStringW (RPCRT4.@)
557 RPC_STATUS WINAPI
UuidFromStringW(LPWSTR s
, UUID
*uuid
)
561 if (!s
) return UuidCreateNil( uuid
);
563 if (strlenW(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
565 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
566 return RPC_S_INVALID_STRING_UUID
;
570 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
571 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
574 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
576 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
577 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
578 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
579 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
581 /* these are just sequential bytes */
582 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
583 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
584 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
585 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
586 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
587 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
588 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
589 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
593 /***********************************************************************
594 * DllRegisterServer (RPCRT4.@)
597 HRESULT WINAPI
RPCRT4_DllRegisterServer( void )
599 FIXME( "(): stub\n" );