wine/programs/rpcss/epmp.c
2008-08-18 14:35:34 +02:00

285 lines
9.1 KiB
C

/*
* Endpoint Mapper
*
* Copyright (C) 2007 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "epm.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
struct registered_ept_entry
{
struct list entry;
GUID object;
RPC_SYNTAX_IDENTIFIER iface;
RPC_SYNTAX_IDENTIFIER syntax;
char *protseq;
char *endpoint;
char *address;
char annotation[ept_max_annotation_size];
};
static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list);
static CRITICAL_SECTION csEpm;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &csEpm,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") }
};
static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 };
static const UUID nil_object;
/* must be called inside csEpm */
static void delete_registered_ept_entry(struct registered_ept_entry *entry)
{
I_RpcFree(entry->protseq);
I_RpcFree(entry->endpoint);
I_RpcFree(entry->address);
list_remove(&entry->entry);
HeapFree(GetProcessHeap(), 0, entry);
}
static struct registered_ept_entry *find_ept_entry(
const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax,
const char *protseq, const char *endpoint, const char *address,
const UUID *object)
{
struct registered_ept_entry *entry;
LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
{
if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
if (strcmp(entry->protseq, protseq)) continue;
if (memcmp(&entry->object, object, sizeof(UUID))) continue;
WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n",
entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion,
wine_dbgstr_guid(&entry->iface.SyntaxGUID),
entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion,
wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq,
wine_dbgstr_guid(&entry->object));
return entry;
}
WINE_TRACE("not found\n");
return NULL;
}
void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle)
{
WINE_FIXME("%p\n", entry_handle);
}
void ept_insert(handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
boolean32 replace,
error_status_t *status)
{
unsigned32 i;
RPC_STATUS rpc_status;
WINE_TRACE("(%p, %lu, %p, %lu, %p)\n", h, num_ents, entries, replace, status);
*status = RPC_S_OK;
EnterCriticalSection(&csEpm);
for (i = 0; i < num_ents; i++)
{
struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
if (!entry)
{
/* FIXME: cleanup code to delete added entries */
*status = EPT_S_CANT_PERFORM_OP;
break;
}
list_init(&entry->entry);
memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation));
rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax,
&entry->protseq, &entry->endpoint,
&entry->address);
if (rpc_status != RPC_S_OK)
{
WINE_WARN("TowerExplode failed %lu\n", rpc_status);
*status = rpc_status;
break; /* FIXME: more cleanup? */
}
entry->object = entries[i].object;
if (replace)
{
/* FIXME: correct find algorithm */
struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object);
if (old_entry) delete_registered_ept_entry(old_entry);
}
list_add_tail(&registered_ept_entry_list, &entry->entry);
}
LeaveCriticalSection(&csEpm);
}
void ept_delete(handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
error_status_t *status)
{
unsigned32 i;
RPC_STATUS rpc_status;
*status = RPC_S_OK;
WINE_TRACE("(%p, %lu, %p, %p)\n", h, num_ents, entries, status);
EnterCriticalSection(&csEpm);
for (i = 0; i < num_ents; i++)
{
struct registered_ept_entry *entry;
RPC_SYNTAX_IDENTIFIER iface, syntax;
char *protseq;
char *endpoint;
char *address;
rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq,
&endpoint, &address);
if (rpc_status != RPC_S_OK)
break;
entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object);
if (entry)
delete_registered_ept_entry(entry);
else
{
*status = EPT_S_NOT_REGISTERED;
break;
}
I_RpcFree(protseq);
I_RpcFree(endpoint);
I_RpcFree(address);
}
LeaveCriticalSection(&csEpm);
}
void ept_lookup(handle_t h,
unsigned32 inquiry_type,
uuid_p_t object,
rpc_if_id_p_t interface_id,
unsigned32 vers_option,
ept_lookup_handle_t *entry_handle,
unsigned32 max_ents,
unsigned32 *num_ents,
ept_entry_t entries[],
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_map(handle_t h,
uuid_p_t object,
twr_p_t map_tower,
ept_lookup_handle_t *entry_handle,
unsigned32 max_towers,
unsigned32 *num_towers,
twr_p_t *towers,
error_status_t *status)
{
RPC_STATUS rpc_status;
RPC_SYNTAX_IDENTIFIER iface, syntax;
char *protseq;
struct registered_ept_entry *entry;
*status = RPC_S_OK;
*num_towers = 0;
WINE_TRACE("(%p, %p, %p, %p, %lu, %p, %p, %p)\n", h, object, map_tower,
entry_handle, max_towers, num_towers, towers, status);
rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq,
NULL, NULL);
if (rpc_status != RPC_S_OK)
{
*status = rpc_status;
return;
}
EnterCriticalSection(&csEpm);
LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
{
if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) &&
(entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) &&
(entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) &&
!memcmp(&entry->syntax, &syntax, sizeof(syntax)) &&
!strcmp(entry->protseq, protseq) &&
((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object)))
{
if (*num_towers < max_towers)
{
rpc_status = TowerConstruct(&entry->iface, &entry->syntax,
entry->protseq, entry->endpoint,
entry->address,
&towers[*num_towers]);
if (rpc_status != RPC_S_OK)
{
*status = rpc_status;
break; /* FIXME: more cleanup? */
}
}
(*num_towers)++;
}
}
LeaveCriticalSection(&csEpm);
}
void ept_lookup_handle_free(handle_t h,
ept_lookup_handle_t *entry_handle,
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_inq_object(handle_t h,
GUID *ept_object,
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_mgmt_delete(handle_t h,
boolean32 object_speced,
uuid_p_t object,
twr_p_t tower,
error_status_t *status)
{
WINE_FIXME("(%p, %ld, %p, %p, %p): stub\n", h, object_speced, object, tower, status);
*status = EPT_S_CANT_PERFORM_OP;
}