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 wierd stuff. Then again, we don't neccesarily 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
);
177 master_mutex
= (HANDLE
) NULL
;
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 * UuidCompare [RPCRT4.@]
219 * (an educated-guess implementation)
222 * UUID *Uuid1 [I] Uuid to compare
223 * UUID *Uuid2 [I] Uuid to compare
224 * RPC_STATUS *Status [O] returns RPC_S_OK
227 * -1 if Uuid1 is less than Uuid2
228 * 0 if Uuid1 and Uuid2 are equal
229 * 1 if Uuid1 is greater than Uuid2
231 int WINAPI
UuidCompare(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
233 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
235 if (!Uuid1
) Uuid1
= &uuid_nil
;
236 if (!Uuid2
) Uuid2
= &uuid_nil
;
237 if (Uuid1
== Uuid2
) return 0;
238 return memcmp(Uuid1
, Uuid2
, sizeof(UUID
));
241 /*************************************************************************
242 * UuidEqual [RPCRT4.@]
245 * UUID *Uuid1 [I] Uuid to compare
246 * UUID *Uuid2 [I] Uuid to compare
247 * RPC_STATUS *Status [O] returns RPC_S_OK
252 int WINAPI
UuidEqual(UUID
*Uuid1
, UUID
*Uuid2
, RPC_STATUS
*Status
)
254 TRACE("(%s,%s)\n", debugstr_guid(Uuid1
), debugstr_guid(Uuid2
));
255 return !UuidCompare(Uuid1
, Uuid2
, Status
);
258 /*************************************************************************
259 * UuidIsNil [RPCRT4.@]
262 * UUID *Uuid [I] Uuid to compare
263 * RPC_STATUS *Status [O] retuns RPC_S_OK
268 int WINAPI
UuidIsNil(UUID
*uuid
, RPC_STATUS
*Status
)
270 TRACE("(%s)\n", debugstr_guid(uuid
));
272 if (!uuid
) return TRUE
;
273 return !memcmp(uuid
, &uuid_nil
, sizeof(UUID
));
276 /*************************************************************************
277 * UuidCreateNil [RPCRT4.@]
280 * UUID *Uuid [O] returns a nil UUID
285 RPC_STATUS WINAPI
UuidCreateNil(UUID
*Uuid
)
291 /*************************************************************************
292 * UuidCreate [RPCRT4.@]
294 * Creates a 128bit UUID.
295 * Implemented according the DCE specification for UUID generation.
296 * Code is based upon uuid library in e2fsprogs by Theodore Ts'o.
297 * Copyright (C) 1996, 1997 Theodore Ts'o.
301 * S_OK if successful.
303 RPC_STATUS WINAPI
UuidCreate(UUID
*Uuid
)
305 static char has_init
= 0;
306 static unsigned char a
[6];
307 static int adjustment
= 0;
308 static struct timeval last
= {0, 0};
309 static WORD clock_seq
;
311 unsigned long long clock_reg
;
312 DWORD clock_high
, clock_low
;
313 WORD temp_clock_seq
, temp_clock_mid
, temp_clock_hi_and_version
;
316 struct ifreq ifr
, *ifrp
;
322 /* Have we already tried to get the MAC address? */
325 /* BSD 4.4 defines the size of an ifreq to be
326 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
327 * However, under earlier systems, sa_len isn't present, so
328 * the size is just sizeof(struct ifreq)
330 #ifdef HAVE_SOCKADDR_SA_LEN
332 # define max(a,b) ((a) > (b) ? (a) : (b))
334 # define ifreq_size(i) max(sizeof(struct ifreq),\
335 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
337 # define ifreq_size(i) sizeof(struct ifreq)
338 # endif /* defined(HAVE_SOCKADDR_SA_LEN) */
340 sd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
342 /* if we can't open a socket, just use random numbers */
343 /* set the multicast bit to prevent conflicts with real cards */
344 a
[0] = (rand() & 0xff) | 0x80;
345 a
[1] = rand() & 0xff;
346 a
[2] = rand() & 0xff;
347 a
[3] = rand() & 0xff;
348 a
[4] = rand() & 0xff;
349 a
[5] = rand() & 0xff;
351 memset(buf
, 0, sizeof(buf
));
352 ifc
.ifc_len
= sizeof(buf
);
354 /* get the ifconf interface */
355 if (ioctl (sd
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
357 /* no ifconf, so just use random numbers */
358 /* set the multicast bit to prevent conflicts with real cards */
359 a
[0] = (rand() & 0xff) | 0x80;
360 a
[1] = rand() & 0xff;
361 a
[2] = rand() & 0xff;
362 a
[3] = rand() & 0xff;
363 a
[4] = rand() & 0xff;
364 a
[5] = rand() & 0xff;
366 /* loop through the interfaces, looking for a valid one */
368 for (i
= 0; i
< n
; i
+= ifreq_size(ifr
) ) {
369 ifrp
= (struct ifreq
*)((char *) ifc
.ifc_buf
+i
);
370 strncpy(ifr
.ifr_name
, ifrp
->ifr_name
, IFNAMSIZ
);
371 /* try to get the address for this interface */
372 # ifdef SIOCGIFHWADDR
373 if (ioctl(sd
, SIOCGIFHWADDR
, &ifr
) < 0)
375 memcpy(a
, (unsigned char *)&ifr
.ifr_hwaddr
.sa_data
, 6);
378 if (ioctl(sd
, SIOCGENADDR
, &ifr
) < 0)
380 memcpy(a
, (unsigned char *) ifr
.ifr_enaddr
, 6);
382 /* XXX we don't have a way of getting the hardware address */
386 # endif /* SIOCGENADDR */
387 # endif /* SIOCGIFHWADDR */
388 /* make sure it's not blank */
389 if (!a
[0] && !a
[1] && !a
[2] && !a
[3] && !a
[4] && !a
[5])
394 /* if we didn't find a valid address, make a random one */
395 /* once again, set multicast bit to avoid conflicts */
396 a
[0] = (rand() & 0xff) | 0x80;
397 a
[1] = rand() & 0xff;
398 a
[2] = rand() & 0xff;
399 a
[3] = rand() & 0xff;
400 a
[4] = rand() & 0xff;
401 a
[5] = rand() & 0xff;
408 /* no networking info, so generate a random address */
409 a
[0] = (rand() & 0xff) | 0x80;
410 a
[1] = rand() & 0xff;
411 a
[2] = rand() & 0xff;
412 a
[3] = rand() & 0xff;
413 a
[4] = rand() & 0xff;
414 a
[5] = rand() & 0xff;
415 #endif /* HAVE_NET_IF_H */
419 /* generate time element of GUID */
421 /* Assume that the gettimeofday() has microsecond granularity */
422 #define MAX_ADJUSTMENT 10
425 gettimeofday(&tv
, 0);
426 if ((last
.tv_sec
== 0) && (last
.tv_usec
== 0)) {
427 clock_seq
= ((rand() & 0xff) << 8) + (rand() & 0xff);
432 if ((tv
.tv_sec
< last
.tv_sec
) ||
433 ((tv
.tv_sec
== last
.tv_sec
) &&
434 (tv
.tv_usec
< last
.tv_usec
))) {
435 clock_seq
= (clock_seq
+1) & 0x1FFF;
437 } else if ((tv
.tv_sec
== last
.tv_sec
) &&
438 (tv
.tv_usec
== last
.tv_usec
)) {
439 if (adjustment
>= MAX_ADJUSTMENT
)
445 clock_reg
= tv
.tv_usec
*10 + adjustment
;
446 clock_reg
+= ((unsigned long long) tv
.tv_sec
)*10000000;
447 clock_reg
+= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
449 clock_high
= clock_reg
>> 32;
450 clock_low
= clock_reg
;
451 temp_clock_seq
= clock_seq
| 0x8000;
452 temp_clock_mid
= (WORD
)clock_high
;
453 temp_clock_hi_and_version
= (clock_high
>> 16) | 0x1000;
455 /* pack the information into the GUID structure */
457 ((unsigned char*)&Uuid
->Data1
)[3] = (unsigned char)clock_low
;
459 ((unsigned char*)&Uuid
->Data1
)[2] = (unsigned char)clock_low
;
461 ((unsigned char*)&Uuid
->Data1
)[1] = (unsigned char)clock_low
;
463 ((unsigned char*)&Uuid
->Data1
)[0] = (unsigned char)clock_low
;
465 ((unsigned char*)&Uuid
->Data2
)[1] = (unsigned char)temp_clock_mid
;
466 temp_clock_mid
>>= 8;
467 ((unsigned char*)&Uuid
->Data2
)[0] = (unsigned char)temp_clock_mid
;
469 ((unsigned char*)&Uuid
->Data3
)[1] = (unsigned char)temp_clock_hi_and_version
;
470 temp_clock_hi_and_version
>>= 8;
471 ((unsigned char*)&Uuid
->Data3
)[0] = (unsigned char)temp_clock_hi_and_version
;
473 ((unsigned char*)Uuid
->Data4
)[1] = (unsigned char)temp_clock_seq
;
474 temp_clock_seq
>>= 8;
475 ((unsigned char*)Uuid
->Data4
)[0] = (unsigned char)temp_clock_seq
;
477 ((unsigned char*)Uuid
->Data4
)[2] = a
[0];
478 ((unsigned char*)Uuid
->Data4
)[3] = a
[1];
479 ((unsigned char*)Uuid
->Data4
)[4] = a
[2];
480 ((unsigned char*)Uuid
->Data4
)[5] = a
[3];
481 ((unsigned char*)Uuid
->Data4
)[6] = a
[4];
482 ((unsigned char*)Uuid
->Data4
)[7] = a
[5];
484 TRACE("%s\n", debugstr_guid(Uuid
));
490 /*************************************************************************
491 * UuidCreateSequential [RPCRT4.@]
493 * Creates a 128bit UUID by calling UuidCreate.
494 * New API in Win 2000
496 RPC_STATUS WINAPI
UuidCreateSequential(UUID
*Uuid
)
498 return UuidCreate (Uuid
);
502 /*************************************************************************
503 * UuidHash [RPCRT4.@]
505 * Generates a hash value for a given UUID
507 * Code based on FreeDCE implementation
510 unsigned short WINAPI
UuidHash(UUID
*uuid
, RPC_STATUS
*Status
)
512 BYTE
*data
= (BYTE
*)uuid
;
513 short c0
= 0, c1
= 0, x
, y
;
516 if (!uuid
) data
= (BYTE
*)(uuid
= &uuid_nil
);
518 TRACE("(%s)\n", debugstr_guid(uuid
));
520 for (i
=0; i
<sizeof(UUID
); i
++) {
535 /*************************************************************************
536 * UuidToStringA [RPCRT4.@]
538 * Converts a UUID to a string.
540 * UUID format is 8 hex digits, followed by a hyphen then three groups of
541 * 4 hex digits each followed by a hyphen and then 12 hex digits
545 * S_OK if successful.
546 * S_OUT_OF_MEMORY if unsucessful.
548 RPC_STATUS WINAPI
UuidToStringA(UUID
*Uuid
, unsigned char** StringUuid
)
550 *StringUuid
= HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
553 return RPC_S_OUT_OF_MEMORY
;
555 if (!Uuid
) Uuid
= &uuid_nil
;
557 sprintf(*StringUuid
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
558 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
559 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
560 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
561 Uuid
->Data4
[6], Uuid
->Data4
[7] );
566 /*************************************************************************
567 * UuidToStringW [RPCRT4.@]
569 * Converts a UUID to a string.
571 * S_OK if successful.
572 * S_OUT_OF_MEMORY if unsucessful.
574 RPC_STATUS WINAPI
UuidToStringW(UUID
*Uuid
, unsigned short** StringUuid
)
578 if (!Uuid
) Uuid
= &uuid_nil
;
580 sprintf(buf
, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
581 Uuid
->Data1
, Uuid
->Data2
, Uuid
->Data3
,
582 Uuid
->Data4
[0], Uuid
->Data4
[1], Uuid
->Data4
[2],
583 Uuid
->Data4
[3], Uuid
->Data4
[4], Uuid
->Data4
[5],
584 Uuid
->Data4
[6], Uuid
->Data4
[7] );
586 *StringUuid
= RPCRT4_strdupAtoW(buf
);
589 return RPC_S_OUT_OF_MEMORY
;
594 static const BYTE hex2bin
[] =
596 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
597 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
598 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
599 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
600 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
601 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
602 0,10,11,12,13,14,15 /* 0x60 */
605 /***********************************************************************
606 * UuidFromStringA (RPCRT4.@)
608 RPC_STATUS WINAPI
UuidFromStringA(unsigned char* str
, UUID
*uuid
)
610 BYTE
*s
= (BYTE
*)str
;
613 if (!s
) return UuidCreateNil( uuid
);
615 if (strlen(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
617 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
618 return RPC_S_INVALID_STRING_UUID
;
622 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
623 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
626 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
628 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
629 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
630 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
631 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
633 /* these are just sequential bytes */
634 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
635 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
636 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
637 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
638 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
639 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
640 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
641 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
646 /***********************************************************************
647 * UuidFromStringW (RPCRT4.@)
649 RPC_STATUS WINAPI
UuidFromStringW(unsigned short* s
, UUID
*uuid
)
653 if (!s
) return UuidCreateNil( uuid
);
655 if (strlenW(s
) != 36) return RPC_S_INVALID_STRING_UUID
;
657 if ((s
[8]!='-') || (s
[13]!='-') || (s
[18]!='-') || (s
[23]!='-'))
658 return RPC_S_INVALID_STRING_UUID
;
662 if ((i
== 8)||(i
== 13)||(i
== 18)||(i
== 23)) continue;
663 if (s
[i
] > 'f' || (!hex2bin
[s
[i
]] && s
[i
] != '0')) return RPC_S_INVALID_STRING_UUID
;
666 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
668 uuid
->Data1
= (hex2bin
[s
[0]] << 28 | hex2bin
[s
[1]] << 24 | hex2bin
[s
[2]] << 20 | hex2bin
[s
[3]] << 16 |
669 hex2bin
[s
[4]] << 12 | hex2bin
[s
[5]] << 8 | hex2bin
[s
[6]] << 4 | hex2bin
[s
[7]]);
670 uuid
->Data2
= hex2bin
[s
[9]] << 12 | hex2bin
[s
[10]] << 8 | hex2bin
[s
[11]] << 4 | hex2bin
[s
[12]];
671 uuid
->Data3
= hex2bin
[s
[14]] << 12 | hex2bin
[s
[15]] << 8 | hex2bin
[s
[16]] << 4 | hex2bin
[s
[17]];
673 /* these are just sequential bytes */
674 uuid
->Data4
[0] = hex2bin
[s
[19]] << 4 | hex2bin
[s
[20]];
675 uuid
->Data4
[1] = hex2bin
[s
[21]] << 4 | hex2bin
[s
[22]];
676 uuid
->Data4
[2] = hex2bin
[s
[24]] << 4 | hex2bin
[s
[25]];
677 uuid
->Data4
[3] = hex2bin
[s
[26]] << 4 | hex2bin
[s
[27]];
678 uuid
->Data4
[4] = hex2bin
[s
[28]] << 4 | hex2bin
[s
[29]];
679 uuid
->Data4
[5] = hex2bin
[s
[30]] << 4 | hex2bin
[s
[31]];
680 uuid
->Data4
[6] = hex2bin
[s
[32]] << 4 | hex2bin
[s
[33]];
681 uuid
->Data4
[7] = hex2bin
[s
[34]] << 4 | hex2bin
[s
[35]];
685 /***********************************************************************
686 * DllRegisterServer (RPCRT4.@)
689 HRESULT WINAPI
RPCRT4_DllRegisterServer( void )
691 FIXME( "(): stub\n" );
695 BOOL
RPCRT4_StartRPCSS(void)
697 PROCESS_INFORMATION pi
;
702 ZeroMemory(&pi
, sizeof(PROCESS_INFORMATION
));
703 ZeroMemory(&si
, sizeof(STARTUPINFOA
));
704 si
.cb
= sizeof(STARTUPINFOA
);
706 /* apparently it's not OK to use a constant string below */
707 CopyMemory(cmd
, "rpcss", 6);
709 /* FIXME: will this do the right thing when run as a test? */
710 rslt
= CreateProcessA(
711 NULL
, /* executable */
712 cmd
, /* command line */
713 NULL
, /* process security attributes */
714 NULL
, /* primary thread security attributes */
715 FALSE
, /* inherit handles */
716 0, /* creation flags */
717 NULL
, /* use parent's environment */
718 NULL
, /* use parent's current directory */
719 &si
, /* STARTUPINFO pointer */
720 &pi
/* PROCESS_INFORMATION */
724 CloseHandle(pi
.hProcess
);
725 CloseHandle(pi
.hThread
);
731 /***********************************************************************
732 * RPCRT4_RPCSSOnDemandCall (internal)
734 * Attempts to send a message to the RPCSS process
735 * on the local machine, invoking it if necessary.
736 * For remote RPCSS calls, use.... your imagination.
739 * msg [I] pointer to the RPCSS message
740 * vardata_payload [I] pointer vardata portion of the RPCSS message
741 * reply [O] pointer to reply structure
747 BOOL
RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg
, char *vardata_payload
, PRPCSS_NP_REPLY reply
)
749 HANDLE client_handle
;
752 TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg
, vardata_payload
, reply
);
754 client_handle
= RPCRT4_RpcssNPConnect();
756 while (!client_handle
) {
757 /* start the RPCSS process */
758 if (!RPCRT4_StartRPCSS()) {
759 ERR("Unable to start RPCSS process.\n");
762 /* wait for a connection (w/ periodic polling) */
763 for (i
= 0; i
< 60; i
++) {
765 client_handle
= RPCRT4_RpcssNPConnect();
766 if (client_handle
) break;
768 /* we are only willing to try twice */
772 if (!client_handle
) {
774 ERR("Unable to connect to RPCSS process!\n");
775 SetLastError(RPC_E_SERVER_DIED_DNE
);
779 /* great, we're connected. now send the message */
780 if (!RPCRT4_SendReceiveNPMsg(client_handle
, msg
, vardata_payload
, reply
)) {
781 ERR("Something is amiss: RPC_SendReceive failed.\n");