Here's hoping this doesn't break anything... :) Let me know if your favorite app stops working. Also, I wasn't too pleased with the extra function call just to create a per-new-process NULL pointer. Anyone know a better way? License: bugroff Changelog: * dlls/rpcrt4: rpc_misc.h, rpc_server.c, rpcrt4_main.c, rpcrt4.spec include: rpcdce.h Greg Turner <gmturner007@xxxxxxxxxxxxx> - Implement RpcObjectSetType -- diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/rpcrt4/rpc_misc.h ./dlls/rpcrt4/rpc_misc.h --- ../wine.test/dlls/rpcrt4/rpc_misc.h 2003-11-20 13:38:38.000000000 -0600 +++ ./dlls/rpcrt4/rpc_misc.h 2003-11-20 13:34:23.000000000 -0600 @@ -25,4 +25,6 @@ /* flags for RPC_MESSAGE.RpcFlags */ #define WINE_RPCFLAG_EXCEPTION 0x0001 +extern void InitObjTypeMapTable(); + #endif /* __WINE_RPC_MISC_H */ diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/rpcrt4/rpc_server.c ./dlls/rpcrt4/rpc_server.c --- ../wine.test/dlls/rpcrt4/rpc_server.c 2003-11-20 13:38:38.000000000 -0600 +++ ./dlls/rpcrt4/rpc_server.c 2003-11-20 13:34:23.000000000 -0600 @@ -54,6 +54,16 @@ void* buf; } RpcPacket; +typedef struct _RpcObjTypeMap +{ + /* FIXME: a hash table would be better. */ + struct _RpcObjTypeMap *next; + UUID Object; + UUID Type; +} RpcObjTypeMap; + +RpcObjTypeMap *RpcObjTypeMaps; + static RpcServerProtseq* protseqs; static RpcServerInterface* ifs; @@ -94,13 +104,37 @@ static DWORD worker_count, worker_free, worker_tls; +static UUID uuid_nil; + +inline static RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid) +{ + RpcObjTypeMap *rslt = RpcObjTypeMaps; + RPC_STATUS dummy; + + while (rslt) { + if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break; + rslt = rslt->next; + } + + return rslt; +} + +inline static UUID *LookupObjType(UUID *ObjUuid) +{ + RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid); + if (map) + return &map->Type; + else + return &uuid_nil; +} + static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id) { UUID* MgrType = NULL; RpcServerInterface* cif = NULL; RPC_STATUS status; - /* FIXME: object -> MgrType */ + MgrType = LookupObjType(object); EnterCriticalSection(&server_cs); cif = ifs; while (cif) { @@ -168,6 +202,8 @@ if (sif) { TRACE("packet received for interface %s\n", debugstr_guid(&hdr->if_id)); msg.RpcInterfaceInformation = sif->If; + /* copy the endpoint vector from sif to msg so that midl-generated code will use it */ + msg.ManagerEpv = sif->MgrEpv; /* create temporary binding for dispatch */ RPCRT4_MakeBinding(&pbind, conn); RPCRT4_SetBindingObject(pbind, &hdr->object); @@ -703,11 +739,13 @@ sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface)); sif->If = If; - if (MgrTypeUuid) + if (MgrTypeUuid) { memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID)); - else + sif->MgrEpv = MgrEpv; + } else { memset(&sif->MgrTypeUuid, 0, sizeof(UUID)); - sif->MgrEpv = MgrEpv; + sif->MgrEpv = If->DefaultManagerEpv; + } sif->Flags = Flags; sif->MaxCalls = MaxCalls; sif->MaxRpcSize = MaxRpcSize; @@ -748,6 +786,75 @@ return RPC_S_OK; } +void InitObjTypeMapTable() +{ + RpcObjTypeMaps = NULL; +} + +/*********************************************************************** + * RpcObjectSetType (RPCRT4.@) + * + * PARAMS + * ObjUuid [I] "Object" UUID + * TypeUuid [I] "Type" UUID + * + * RETURNS + * RPC_S_OK The call succeeded + * RPC_S_INVALID_OBJECT The provided object (nil) is not valid + * RPC_S_ALREADY_REGISTERED The provided object is already registered + * + * Maps "Object" UUIDs to "Type" UUID's. Passing the nil UUID as the type + * resets the mapping for the specified object UUID to nil (the default). + * The nil object is always associated with the nil type and cannot be + * reassigned. Servers can support multiple implementations on the same + * interface by registering different end-point vectors for the different + * types. There's no need to call this if a server only supports the nil + * type, as is typical. + */ +RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) +{ + RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL; + RPC_STATUS dummy; + + TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid)); + if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) { + /* nil uuid cannot be remapped */ + return RPC_S_INVALID_OBJECT; + } + + /* find the mapping for this object if there is one ... */ + while (map) { + if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break; + prev = map; + map = map->next; + } + if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) { + /* ... and drop it from the list */ + if (map) { + if (prev) + prev->next = map->next; + else + RpcObjTypeMaps = map->next; + HeapFree(GetProcessHeap(), 0, map); + } + } else { + /* ... , fail if we found it ... */ + if (map) + return RPC_S_ALREADY_REGISTERED; + /* ... otherwise create a new one and add it in. */ + map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap)); + memcpy(&map->Object, ObjUuid, sizeof(UUID)); + memcpy(&map->Type, TypeUuid, sizeof(UUID)); + map->next = NULL; + if (prev) + prev->next = map; /* prev is the last map in the linklist */ + else + RpcObjTypeMaps = map; + } + + return RPC_S_OK; +} + /*********************************************************************** * RpcServerRegisterAuthInfoA (RPCRT4.@) */ diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/rpcrt4/rpcrt4.spec ./dlls/rpcrt4/rpcrt4.spec --- ../wine.test/dlls/rpcrt4/rpcrt4.spec 2003-11-20 13:38:38.000000000 -0600 +++ ./dlls/rpcrt4/rpcrt4.spec 2003-11-20 13:34:23.000000000 -0600 @@ -106,7 +106,7 @@ @ stub RpcNsBindingInqEntryNameW @ stub RpcObjectInqType @ stub RpcObjectSetInqFn -@ stub RpcObjectSetType +@ stdcall RpcObjectSetType(ptr ptr) @ stub RpcProtseqVectorFreeA @ stub RpcProtseqVectorFreeW @ stdcall RpcRaiseException(long) diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/rpcrt4/rpcrt4_main.c ./dlls/rpcrt4/rpcrt4_main.c --- ../wine.test/dlls/rpcrt4/rpcrt4_main.c 2003-11-20 13:38:38.000000000 -0600 +++ ./dlls/rpcrt4/rpcrt4_main.c 2003-11-20 13:34:23.000000000 -0600 @@ -135,6 +135,7 @@ #include "rpc_binding.h" #include "rpcss_np_client.h" +#include "rpc_misc.h" #include "wine/debug.h" @@ -169,6 +170,7 @@ master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); if (!master_mutex) ERR("Failed to create master mutex\n"); + InitObjTypeMapTable(); break; case DLL_PROCESS_DETACH: diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/include/rpcdce.h ./include/rpcdce.h --- ../wine.test/include/rpcdce.h 2003-11-20 13:38:38.000000000 -0600 +++ ./include/rpcdce.h 2003-11-20 13:34:23.000000000 -0600 @@ -114,6 +114,8 @@ RpcBindingReset( RPC_BINDING_HANDLE Binding ); RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ); +RPCRTAPI RPC_STATUS RPC_ENTRY + RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ); RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding ); -- gmt "It is to be the assent and ratification of the several States, derived from the supreme authority in each State, the authority of the people themselves. The act, therefore, establishing the Constitution, will not be a NATIONAL, but a FEDERAL act." --James Madison, Federalist No. 39