📄 rpc_binding.c
字号:
TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
else UuidCreateNil(&Binding->ObjectUuid);
return RPC_S_OK;
}
RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
{
RpcBinding* NewBinding;
TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
RPCRT4_AllocBinding(&NewBinding, Connection->server);
NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq);
NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
NewBinding->FromConn = Connection;
TRACE("binding: %p\n", NewBinding);
*Binding = NewBinding;
return RPC_S_OK;
}
RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
{
InterlockedIncrement(&OldBinding->refs);
*Binding = OldBinding;
return RPC_S_OK;
}
RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
{
if (InterlockedDecrement(&Binding->refs))
return RPC_S_OK;
TRACE("binding: %p\n", Binding);
/* FIXME: release connections */
RPCRT4_strfree(Binding->Endpoint);
RPCRT4_strfree(Binding->NetworkAddr);
RPCRT4_strfree(Binding->Protseq);
HeapFree(GetProcessHeap(), 0, Binding);
return RPC_S_OK;
}
RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
PRPC_SYNTAX_IDENTIFIER TransferSyntax,
PRPC_SYNTAX_IDENTIFIER InterfaceId)
{
RpcConnection* NewConnection;
RPC_STATUS status;
TRACE("(Binding == ^%p)\n", Binding);
/* if we try to bind a new interface and the connection is already opened,
* close the current connection and create a new with the new binding. */
if (!Binding->server && Binding->FromConn &&
memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER))) {
TRACE("releasing pre-existing connection\n");
RPCRT4_DestroyConnection(Binding->FromConn);
Binding->FromConn = NULL;
} else {
/* we already have a connection with acceptable binding, so use it */
if (Binding->FromConn) {
*Connection = Binding->FromConn;
return RPC_S_OK;
}
}
/* create a new connection */
RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL, Binding);
*Connection = NewConnection;
status = RPCRT4_OpenConnection(NewConnection);
if (status != RPC_S_OK) {
return status;
}
/* we need to send a binding packet if we are client. */
if (!(*Connection)->server) {
RpcPktHdr *hdr;
DWORD count;
BYTE *response;
RpcPktHdr *response_hdr;
TRACE("sending bind request to server\n");
hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
InterfaceId, TransferSyntax);
status = RPCRT4_Send(*Connection, hdr, NULL, 0);
if (status != RPC_S_OK) {
RPCRT4_DestroyConnection(*Connection);
return status;
}
response = HeapAlloc(GetProcessHeap(), 0, RPC_MAX_PACKET_SIZE);
if (response == NULL) {
WARN("Can't allocate memory for binding response\n");
RPCRT4_DestroyConnection(*Connection);
return E_OUTOFMEMORY;
}
/* get a reply */
if (!ReadFile(NewConnection->conn, response, RPC_MAX_PACKET_SIZE, &count, NULL)) {
WARN("ReadFile failed with error %ld\n", GetLastError());
RPCRT4_DestroyConnection(*Connection);
return RPC_S_PROTOCOL_ERROR;
}
if (count < sizeof(response_hdr->common)) {
WARN("received invalid header\n");
RPCRT4_DestroyConnection(*Connection);
return RPC_S_PROTOCOL_ERROR;
}
response_hdr = (RpcPktHdr*)response;
if (response_hdr->common.rpc_ver != RPC_VER_MAJOR ||
response_hdr->common.rpc_ver_minor != RPC_VER_MINOR ||
response_hdr->common.ptype != PKT_BIND_ACK) {
WARN("invalid protocol version or rejection packet\n");
RPCRT4_DestroyConnection(*Connection);
return RPC_S_PROTOCOL_ERROR;
}
if (response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
WARN("server doesn't allow large enough packets\n");
RPCRT4_DestroyConnection(*Connection);
return RPC_S_PROTOCOL_ERROR;
}
/* FIXME: do more checks? */
(*Connection)->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
(*Connection)->ActiveInterface = *InterfaceId;
}
return RPC_S_OK;
}
RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
{
TRACE("(Binding == ^%p)\n", Binding);
if (!Connection) return RPC_S_OK;
if (Binding->FromConn == Connection) return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection);
}
/* utility functions for string composing and parsing */
static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
{
unsigned len = strlen(src);
memcpy(data, src, len*sizeof(CHAR));
return len;
}
static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
{
unsigned len = strlenW(src);
memcpy(data, src, len*sizeof(WCHAR));
return len;
}
static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
{
DWORD len = strlen(dst), slen = strlen(src);
LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
if (!ndst)
{
HeapFree(GetProcessHeap(), 0, dst);
return NULL;
}
ndst[len] = ',';
memcpy(ndst+len+1, src, slen+1);
return ndst;
}
static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
{
DWORD len = strlenW(dst), slen = strlenW(src);
LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
if (!ndst)
{
HeapFree(GetProcessHeap(), 0, dst);
return NULL;
}
ndst[len] = ',';
memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
return ndst;
}
/***********************************************************************
* RpcBindingCopy (RPCRT4.@)
*/
RPC_STATUS RPC_ENTRY RpcBindingCopy(
RPC_BINDING_HANDLE SourceBinding,
RPC_BINDING_HANDLE* DestinationBinding)
{
TRACE("RpcBindingCopy(%p, %p) called:\n", SourceBinding, DestinationBinding);
RpcBinding *DestBinding = 0, *SrcBinding = (RpcBinding*)SourceBinding;
if(SrcBinding->server)
{
*DestinationBinding = NULL;
return RPC_S_WRONG_KIND_OF_BINDING;
}
DestBinding = (RpcBinding*)
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
if(!DestBinding)
{
*DestinationBinding = NULL;
return ERROR_NOT_ENOUGH_MEMORY;
}
memcpy(DestBinding, SrcBinding, sizeof(RpcBinding));
DestBinding->refs = 1;
DestBinding->Next = NULL; // FIXME: ?
DestBinding->server = FALSE;
DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
*DestinationBinding = DestBinding;
return RPC_S_OK;
}
/***********************************************************************
* RpcStringBindingComposeA (RPCRT4.@)
*/
RPC_STATUS WINAPI RpcStringBindingComposeA(unsigned char *ObjUuid, unsigned char *Protseq,
unsigned char *NetworkAddr, unsigned char *Endpoint,
unsigned char *Options, unsigned char** StringBinding )
{
DWORD len = 1;
LPSTR data;
TRACE( "(%s,%s,%s,%s,%s,%p)\n",
debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
debugstr_a( (char*)Options ), StringBinding );
if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
if (Options && *Options) len += strlen((char*)Options) + 2;
data = HeapAlloc(GetProcessHeap(), 0, len);
*StringBinding = (unsigned char*)data;
if (ObjUuid && *ObjUuid) {
data += RPCRT4_strcopyA(data, (char*)ObjUuid);
*data++ = '@';
}
if (Protseq && *Protseq) {
data += RPCRT4_strcopyA(data, (char*)Protseq);
*data++ = ':';
}
if (NetworkAddr && *NetworkAddr)
data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
if ((Endpoint && *Endpoint) ||
(Options && *Options)) {
*data++ = '[';
if (Endpoint && *Endpoint) {
data += RPCRT4_strcopyA(data, (char*)Endpoint);
if (Options && *Options) *data++ = ',';
}
if (Options && *Options) {
data += RPCRT4_strcopyA(data, (char*)Options);
}
*data++ = ']';
}
*data = 0;
return RPC_S_OK;
}
/***********************************************************************
* RpcStringBindingComposeW (RPCRT4.@)
*/
RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,
LPWSTR NetworkAddr, LPWSTR Endpoint,
LPWSTR Options, LPWSTR* StringBinding )
{
DWORD len = 1;
LPWSTR data;
TRACE("(%s,%s,%s,%s,%s,%p)\n",
debugstr_w( ObjUuid ), debugstr_w( Protseq ),
debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
debugstr_w( Options ), StringBinding);
if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
if (Options && *Options) len += strlenW(Options) + 2;
data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
*StringBinding = data;
if (ObjUuid && *ObjUuid) {
data += RPCRT4_strcopyW(data, ObjUuid);
*data++ = '@';
}
if (Protseq && *Protseq) {
data += RPCRT4_strcopyW(data, Protseq);
*data++ = ':';
}
if (NetworkAddr && *NetworkAddr) {
data += RPCRT4_strcopyW(data, NetworkAddr);
}
if ((Endpoint && *Endpoint) ||
(Options && *Options)) {
*data++ = '[';
if (Endpoint && *Endpoint) {
data += RPCRT4_strcopyW(data, Endpoint);
if (Options && *Options) *data++ = ',';
}
if (Options && *Options) {
data += RPCRT4_strcopyW(data, Options);
}
*data++ = ']';
}
*data = 0;
return RPC_S_OK;
}
/***********************************************************************
* RpcStringBindingParseA (RPCRT4.@)
*/
RPC_STATUS WINAPI RpcStringBindingParseA( unsigned char *StringBinding, unsigned char **ObjUuid,
unsigned char **Protseq, unsigned char **NetworkAddr,
unsigned char **Endpoint, unsigned char **Options)
{
CHAR *data, *next;
static const char ep_opt[] = "endpoint=";
TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
if (ObjUuid) *ObjUuid = NULL;
if (Protseq) *Protseq = NULL;
if (NetworkAddr) *NetworkAddr = NULL;
if (Endpoint) *Endpoint = NULL;
if (Options) *Options = NULL;
data = (char*) StringBinding;
next = strchr(data, '@');
if (next) {
if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
data = next+1;
}
next = strchr(data, ':');
if (next) {
if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
data = next+1;
}
next = strchr(data, '[');
if (next) {
CHAR *close, *opt;
if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
data = next+1;
close = strchr(data, ']');
if (!close) goto fail;
/* tokenize options */
while (data < close) {
next = strchr(data, ',');
if (!next || next > close) next = close;
/* FIXME: this is kind of inefficient */
opt = RPCRT4_strndupA(data, next - data);
data = next+1;
/* parse option */
next = strchr(opt, '=');
if (!next) {
/* not an option, must be an endpoint */
if (*Endpoint) goto fail;
*Endpoint = (unsigned char*) opt;
} else {
if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
/* endpoint option */
if (*Endpoint) goto fail;
*Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
HeapFree(GetProcessHeap(), 0, opt);
} else {
/* network option */
if (*Options) {
/* FIXME: this is kind of inefficient */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -