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
20 * WINE RPC TODO's (and a few TODONT's)
22 * - widl is like MIDL for wine. For wine to be a useful RPC platform, quite
23 * a bit of work needs to be done here. widl currently doesn't generate stubs
24 * for RPC invocation -- it will need to; this is tricky because the MIDL compiler
25 * does some really weird stuff. Then again, we don't necessarily have to
26 * make widl work like MIDL, so it could be worse. Lately Ove has been working on
27 * some widl enhancements.
29 * - RPC has a quite featureful error handling mechanism; basically none of this is
30 * implemented right now.
32 * - There are several different memory allocation schemes for MSRPC.
33 * I don't even understand what they all are yet, much less have them
34 * properly implemented. Surely we are supposed to be doing something with
35 * the user-provided allocation/deallocation functions, but so far,
36 * I don't think we are doing this...
38 * - MSRPC provides impersonation capabilities which currently are not possible
39 * to implement in wine. At the very least we should implement the authorization
40 * API's & gracefully ignore the irrelevant stuff (to a small extent we already do).
42 * - Some transports are not yet implemented. The existing transport implementations
43 * are incomplete and many seem to be buggy
45 * - The various transports that we do support ought to be supported in a more
46 * object-oriented manner, like in DCE's RPC implementation, instead of cluttering
47 * up the code with conditionals like we do now.
49 * - Data marshalling: So far, only the very beginnings of an implementation
50 * exist in wine. NDR protocol itself is documented, but the MS API's to
51 * convert data-types in memory into NDR are not. This is a bit of a challenge,
52 * but it is at the top of Greg's queue and should be improving soon.
54 * - ORPC is RPC for OLE; once we have a working RPC framework, we can
55 * use it to implement out-of-process OLE client/server communications.
56 * ATM there is a 100% disconnect between the marshalling in the OLE DLL's
57 * and the marshalling going on here. This is a good thing, since marshalling
58 * doesn't work yet. But once it does, obviously there will be the opportunity
59 * to implement out-of-process OLE using wine's rpcrt4 or some derivative.
60 * This may require some collaboration between the RPC workers and the OLE
63 * - In-source API Documentation, at least for those functions which we have
64 * implemented, but preferably for everything we can document, would be nice.
65 * Some stuff is undocumented by Microsoft and we are guessing how to implement
66 * (in these cases we should document the behavior we implemented, or, if there
67 * is no implementation, at least hazard some kind of guess, and put a few
68 * question marks after it ;) ).
70 * - Stubs. Lots of stuff is defined in Microsoft's headers, including undocumented
71 * stuff. So let's make a stub-farm and populate it with as many rpcrt4 api's as
72 * we can stand, so people don't get unimplemented function exceptions.
74 * - Name services: this part hasn't even been started.
76 * - Concurrency: right now I have not tested more than one request at a time;
77 * we are supposed to be able to do this, and to queue requests which exceed the
80 * - Protocol Towers: Totally unimplemented.... I think.
82 * - Context Handle Rundown: whatever that is.
84 * - Nested RPC's: Totally unimplemented.
86 * - Statistics: we are supposed to be keeping various counters. we aren't.
88 * - Connectionless RPC: unimplemented (DNE in win9x so not a top priority)
90 * - XML RPC: Dunno if microsoft does it... but we'd might as well just for kicks.
92 * - ...? More stuff I haven't thought of. If you think of more RPC todo's drop me
93 * an e-mail <gmturner007@ameritech.net> or send a patch to wine-patches.
102 #ifdef HAVE_SYS_TIME_H
103 # include <sys/time.h>
110 #include "winerror.h"
112 #include "wine/unicode.h"
117 #include "rpcproxy.h"
119 #ifdef HAVE_SYS_FILE_H
120 # include <sys/file.h>
122 #ifdef HAVE_SYS_IOCTL_H
123 # include <sys/ioctl.h>
125 #ifdef HAVE_SYS_SOCKET_H
126 # include <sys/socket.h>
128 #ifdef HAVE_SYS_SOCKIO_H
129 # include <sys/sockio.h>
134 #ifdef HAVE_NETINET_IN_H
135 # include <netinet/in.h>
138 #include "rpc_binding.h"
139 #include "rpcss_np_client.h"
141 #include "wine/debug.h"
143 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
145 static UUID uuid_nil
;
146 static HANDLE master_mutex
;
148 HANDLE
RPCRT4_GetMasterMutex(void)
153 /***********************************************************************
157 * hinstDLL [I] handle to the DLL's instance
159 * lpvReserved [I] reserved, must be NULL
166 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
169 case DLL_PROCESS_ATTACH
:
170 master_mutex
= CreateMutexA( NULL
, FALSE
, RPCSS_MASTER_MUTEX_NAME
);
172 ERR("Failed to create master mutex\n");
175 case DLL_PROCESS_DETACH
:
176 CloseHandle(master_mutex
);
184 /*************************************************************************
185 * RpcStringFreeA [RPCRT4.@]
187 * Frees a character string allocated by the RPC run-time library.
191 * S_OK if successful.
193 RPC_STATUS WINAPI
RpcStringFreeA(unsigned char** String
)
195 HeapFree( GetProcessHeap(), 0, *String
);
200 /*************************************************************************
201 * RpcStringFreeW [RPCRT4.@]
203 * Frees a character string allocated by the RPC run-time library.
207 * S_OK if successful.
209 RPC_STATUS WINAPI
RpcStringFreeW(unsigned short** String
)
211 HeapFree( GetProcessHeap(), 0, *String
);
216 /*************************************************************************
217 * RpcRaiseException [RPCRT4.@]
219 * Raises an exception.
221 void WINAPI
RpcRaiseException(RPC_STATUS exception
)
223 /* FIXME: translate exception? */
224 RaiseException(exception
, 0, 0, NULL
);
227 /*************************************************************************
228 * UuidCompare [RPCRT4.@]
230 * (an educated-guess implementation)
233 * UUID *Uuid1 [I] Uuid to compare
234 * UUID *Uuid2 [I] Uuid to compare
235 * RPC_STATUS *Status [O] returns RPC_S_OK
238 * -1 if Uuid1 is less than Uuid2
239 * 0 if Uuid1 and Uuid2 are equal
240 * 1 if Uuid1 is greater than Uuid2
242 int WINAPI
UuidCompare(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
244 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
246 if (!Uuid1
) Uuid1
= &uuid_nil
;
247 if (!Uuid2
) Uuid2
= &uuid_nil
;
248 if (Uuid1
== Uuid2
) return 0;
249 return memcmp(Uuid1
, Uuid2
, sizeof(UUID
));
252 /*************************************************************************
253 * UuidEqual [RPCRT4.@]
256 * UUID *Uuid1 [I] Uuid to compare
257 * UUID *Uuid2 [I] Uuid to compare
258 * RPC_STATUS *Status [O] returns RPC_S_OK
263 int WINAPI
UuidEqual(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
265 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
266 return !UuidCompare(Uuid1
, Uuid2
, Status
);
269 /*************************************************************************
270 * UuidIsNil [RPCRT4.@]
273 * UUID *Uuid [I] Uuid to compare
274 * RPC_STATUS *Status [O] retuns RPC_S_OK
279 int WINAPI
UuidIsNil(UUID
*uuid
, RPC_STATUS
*Status
)
281 TRACE("(%s)\n", debugstr_guid(uuid
));
283 if (!uuid
) return TRUE
;
284 return !memcmp(uuid
, &uuid_nil
, sizeof(UUID
));
287 /*************************************************************************
288 * UuidCreateNil [RPCRT4.@]
291 * UUID *Uuid [O] returns a nil UUID
296 RPC_STATUS WINAPI
UuidCreateNil(UUID
*Uuid
)
302 /*************************************************************************
303 * UuidCreate [RPCRT4.@]
305 * Creates a 128bit UUID.
306 * Implemented according the DCE specification for UUID generation.
307 * Code is based upon uuid library in e2fsprogs by Theodore Ts'o.
308 * Copyright (C) 1996, 1997 Theodore Ts'o.
312 * S_OK if successful.
314 RPC_STATUS WINAPI
UuidCreate(UUID
*Uuid
)
316 static char has_init
= 0;
317 static unsigned char a
[6];
318 static int adjustment
= 0;
319 static struct timeval last
= {0, 0};
320 static WORD clock_seq
;
322 unsigned long long clock_reg
;
323 DWORD clock_high
, clock_low
;
324 WORD temp_clock_seq
, temp_clock_mid
, temp_clock_hi_and_version
;
327 struct ifreq ifr
, *ifrp
;
333 /* Have we already tried to get the MAC address? */
336 /* BSD 4.4 defines the size of an ifreq to be
337 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
338 * However, under earlier systems, sa_len isn't present, so
339 * the size is just sizeof(struct ifreq)
341 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
343 # define max(a,b) ((a) > (b) ? (a) : (b))
345 # define ifreq_size(i) max(sizeof(struct ifreq),\
346 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
348 # define ifreq_size(i) sizeof(struct ifreq)
349 # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
351 sd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
353 /* if we can't open a socket, just use random numbers */
354 /* set the multicast bit to prevent conflicts with real cards */
355 a
[0] = (rand() & 0xff) | 0x80;
356 a
[1] = rand() & 0xff;
357 a
[2] = rand() & 0xff;
358 a
[3] = rand() & 0xff;
359 a
[4] = rand() & 0xff;
360 a
[5] = rand() & 0xff;
362 memset(buf
, 0, sizeof(buf
));
363 ifc
.ifc_len
= sizeof(buf
);
365 /* get the ifconf interface */
366 if (ioctl (sd
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
368 /* no ifconf, so just use random numbers */
369 /* set the multicast bit to prevent conflicts with real cards */
370 a
[0] = (rand() & 0xff) | 0x80;
371 a
[1] = rand() & 0xff;
372 a
[2] = rand() & 0xff;
373 a
[3] = rand() & 0xff;
374 a
[4] = rand() & 0xff;
375 a
[5] = rand() & 0xff;
377 /* loop through the interfaces, looking for a valid one */
379 for (i
= 0; i
< n
; i
+= ifreq_size(ifr
) ) {
380 ifrp
= (struct ifreq
*)((char *) ifc
.ifc_buf
+i
);
381 strncpy(ifr
.ifr_name
, ifrp
->ifr_name
, IFNAMSIZ
);
382 /* try to get the address for this interface */
383 # ifdef SIOCGIFHWADDR
384 if (ioctl(sd
, SIOCGIFHWADDR
, &ifr
) < 0)
386 memcpy(a
, (unsigned char *)&ifr
.ifr_hwaddr
.sa_data
, 6);
389 if (ioctl(sd
, SIOCGENADDR
, &ifr
) < 0)
391 memcpy(a
, (unsigned char *) ifr
.ifr_enaddr
, 6);
393 /* XXX we don't have a way of getting the hardware address */
397 # endif /* SIOCGENADDR */
398 # endif /* SIOCGIFHWADDR */
399 /* make sure it's not blank */
400 if (!a
[0] && !a
[1] && !a
[2] && !a
[3] && !a
[4] && !a
[5])
405 /* if we didn't find a valid address, make a random one */
406 /* once again, set multicast bit to avoid conflicts */
407 a
[0] = (rand() & 0xff) | 0x80;
408 a
[1] = rand() & 0xff;
409 a
[2] = rand() & 0xff;
410 a
[3] = rand() & 0xff;
411 a
[4] = rand() & 0xff;
412 a
[5] = rand() & 0xff;
419 /* no networking info, so generate a random address */
420 a
[0] = (rand() & 0xff) | 0x80;
421 a
[1] = rand() & 0xff;
422 a
[2] = rand() & 0xff;
423 a
[3] = rand() & 0xff;
424 a
[4] = rand() & 0xff;
425 a
[5] = rand() & 0xff;
426 #endif /* HAVE_NET_IF_H */
430 /* generate time element of GUID */
432 /* Assume that the gettimeofday() has microsecond granularity */
433 #define MAX_ADJUSTMENT 10
436 gettimeofday(&tv
, 0);
437 if ((last
.tv_sec
== 0) && (last
.tv_usec
== 0)) {
438 clock_seq
= ((rand() & 0xff) << 8) + (rand() & 0xff);
443 if ((tv
.tv_sec
< last
.tv_sec
) ||
444 ((tv
.tv_sec
== last
.tv_sec
) &&
445 (tv
.tv_usec
< last
.tv_usec
))) {
446 clock_seq
= (clock_seq
+1) & 0x1FFF;
448 } else if ((tv
.tv_sec
== last
.tv_sec
) &&
449 (tv
.tv_usec
== last
.tv_usec
)) {
450 if (adjustment
>= MAX_ADJUSTMENT
)
456 clock_reg
= tv
.tv_usec
*10 + adjustment
;
457 clock_reg
+= ((unsigned long long) tv
.tv_sec
)*10000000;
458 clock_reg
+= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
460 clock_high
= clock_reg
>> 32;
461 clock_low
= clock_reg
;
462 temp_clock_seq
= clock_seq
| 0x8000;
463 temp_clock_mid
= (WORD
)clock_high
;
464 temp_clock_hi_and_version
= (clock_high
>> 16) | 0x1000;
466 /* pack the information into the GUID structure */
468 ((unsigned char*)&Uuid
->Data1
)[3] = (unsigned char)clock_low
;
470 ((unsigned char*)&Uuid
->Data1
)[2] = (unsigned char)clock_low
;
472 ((unsigned char*)&Uuid
->Data1
)[1] = (unsigned char)clock_low
;
474 ((unsigned char*)&Uuid
->Data1
)[0] = (unsigned char)clock_low
;
476 ((unsigned char*)&Uuid
->Data2
)[1] = (unsigned char)temp_clock_mid
;
477 temp_clock_mid
>>= 8;
478 ((unsigned char*)&Uuid
->Data2
)[0] = (unsigned char)temp_clock_mid
;
480 ((unsigned char*)&Uuid
->Data3
)[1] = (unsigned char)temp_clock_hi_and_version
;
481 temp_clock_hi_and_version
>>= 8;
482 ((unsigned char*)&Uuid
->Data3
)[0] = (unsigned char)temp_clock_hi_and_version
;
484 ((unsigned char*)Uuid
->Data4
)[1] = (unsigned char)temp_clock_seq
;
485 temp_clock_seq
>>= 8;
486 ((unsigned char*)Uuid
->Data4
)[0] = (unsigned char)temp_clock_seq
;
488 ((unsigned char*)Uuid
->Data4
)[2] = a
[0];
489 ((unsigned char*)Uuid
->Data4
)[3] = a
[1];
490 ((unsigned char*)Uuid
->Data4
)[4] = a
[2];
491 ((unsigned char*)Uuid
->Data4
)[5] = a
[3];
492 ((unsigned char*)Uuid
->Data4
)[6] = a
[4];
493 ((unsigned char*)Uuid
->Data4
)[7] = a
[5];
495 TRACE("%s\n", debugstr_guid(Uuid
));
501 /*************************************************************************
502 * UuidCreateSequential [RPCRT4.@]
504 * Creates a 128bit UUID by calling UuidCreate.
505 * New API in Win 2000
507 RPC_STATUS WINAPI
UuidCreateSequential(UUID
*Uuid
)
509 return UuidCreate (Uuid
);
513 /*************************************************************************
514 * UuidHash [RPCRT4.@]
516 * Generates a hash value for a given UUID
518 * Code based on FreeDCE implementation
521 unsigned short WINAPI
UuidHash(UUID
*uuid
, RPC_STATUS
*Status
)
523 BYTE
*data
= (BYTE
*)uuid
;
524 short c0
= 0, c1
= 0, x
, y
;
527 if (!uuid
) data
= (BYTE
*)(uuid
= &uuid_nil
);
529 TRACE("(%s)\n", debugstr_guid(uuid
));
531 for (i
=0; i
<sizeof(UUID
); i
++) {
546 /*************************************************************************
547 * UuidToStringA [RPCRT4.@]
549 * Converts a UUID to a string.
551 * UUID format is 8 hex digits, followed by a hyphen then three groups of
552 * 4 hex digits each followed by a hyphen and then 12 hex digits
556 * S_OK if successful.
557 * S_OUT_OF_MEMORY if unsucessful.
559 RPC_STATUS WINAPI
UuidToStringA(UUID
*Uuid
, unsigned char** StringUuid
)
561 *StringUuid
= HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
564 return RPC_S_OUT_OF_MEMORY
;
566 if (!Uuid
) Uuid
= &uuid_nil
;
568 sprintf(*StringUuid
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
569 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
570 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
571 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
572 Uuid
->Data4
[6], Uuid
->Data4
[7] );
577 /*************************************************************************
578 * UuidToStringW [RPCRT4.@]
580 * Converts a UUID to a string.
582 * S_OK if successful.
583 * S_OUT_OF_MEMORY if unsucessful.
585 RPC_STATUS WINAPI
UuidToStringW(UUID
*Uuid
, unsigned short** StringUuid
)
589 if (!Uuid
) Uuid
= &uuid_nil
;
591 sprintf(buf
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
592 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
593 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
594 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
595 Uuid
->Data4
[6], Uuid
->Data4
[7] );
597 *StringUuid
= RPCRT4_strdupAtoW(buf
);
600 return RPC_S_OUT_OF_MEMORY
;
605 static const BYTE hex2bin
[] =
607 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
608 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
609 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
610 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
611 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
612 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
613 0,10,11,12,13,14,15 /* 0x60 */
616 /***********************************************************************
617 * UuidFromStringA (RPCRT4.@)
619 RPC_STATUS WINAPI
UuidFromStringA(unsigned char* str
, UUID
*uuid
)
621 BYTE
*s
= (BYTE
*)str
;
624 if (!s
) return UuidCreateNil( uuid
);
626 if (strlen(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
628 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
629 return RPC_S_INVALID_STRING_UUID
;
633 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
634 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
637 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
639 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
640 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
641 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
642 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
644 /* these are just sequential bytes */
645 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
646 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
647 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
648 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
649 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
650 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
651 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
652 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
657 /***********************************************************************
658 * UuidFromStringW (RPCRT4.@)
660 RPC_STATUS WINAPI
UuidFromStringW(unsigned short* s
, UUID
*uuid
)
664 if (!s
) return UuidCreateNil( uuid
);
666 if (strlenW(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
668 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
669 return RPC_S_INVALID_STRING_UUID
;
673 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
674 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
677 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
679 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
680 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
681 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
682 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
684 /* these are just sequential bytes */
685 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
686 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
687 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
688 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
689 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
690 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
691 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
692 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
696 /***********************************************************************
697 * DllRegisterServer (RPCRT4.@)
700 HRESULT WINAPI
RPCRT4_DllRegisterServer( void )
702 FIXME( "(): stub\n" );
706 BOOL
RPCRT4_StartRPCSS(void)
708 PROCESS_INFORMATION pi
;
713 ZeroMemory(&pi
, sizeof(PROCESS_INFORMATION
));
714 ZeroMemory(&si
, sizeof(STARTUPINFOA
));
715 si
.cb
= sizeof(STARTUPINFOA
);
717 /* apparently it's not OK to use a constant string below */
718 CopyMemory(cmd
, "rpcss", 6);
720 /* FIXME: will this do the right thing when run as a test? */
721 rslt
= CreateProcessA(
722 NULL
, /* executable */
723 cmd
, /* command line */
724 NULL
, /* process security attributes */
725 NULL
, /* primary thread security attributes */
726 FALSE
, /* inherit handles */
727 0, /* creation flags */
728 NULL
, /* use parent's environment */
729 NULL
, /* use parent's current directory */
730 &si
, /* STARTUPINFO pointer */
731 &pi
/* PROCESS_INFORMATION */
735 CloseHandle(pi
.hProcess
);
736 CloseHandle(pi
.hThread
);
742 /***********************************************************************
743 * RPCRT4_RPCSSOnDemandCall (internal)
745 * Attempts to send a message to the RPCSS process
746 * on the local machine, invoking it if necessary.
747 * For remote RPCSS calls, use.... your imagination.
750 * msg [I] pointer to the RPCSS message
751 * vardata_payload [I] pointer vardata portion of the RPCSS message
752 * reply [O] pointer to reply structure
758 BOOL
RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg
, char *vardata_payload
, PRPCSS_NP_REPLY reply
)
760 HANDLE client_handle
;
763 TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg
, vardata_payload
, reply
);
765 client_handle
= RPCRT4_RpcssNPConnect();
767 while (!client_handle
) {
768 /* start the RPCSS process */
769 if (!RPCRT4_StartRPCSS()) {
770 ERR("Unable to start RPCSS process.\n");
773 /* wait for a connection (w/ periodic polling) */
774 for (i
= 0; i
< 60; i
++) {
776 client_handle
= RPCRT4_RpcssNPConnect();
777 if (client_handle
) break;
779 /* we are only willing to try twice */
783 if (!client_handle
) {
785 ERR("Unable to connect to RPCSS process!\n");
786 SetLastError(RPC_E_SERVER_DIED_DNE
);
790 /* great, we're connected. now send the message */
791 if (!RPCRT4_SendReceiveNPMsg(client_handle
, msg
, vardata_payload
, reply
)) {
792 ERR("Something is amiss: RPC_SendReceive failed.\n");