Sync rpcrt4 to Wine 1.2rc6 (Samuel Serapion)

http transport support commented out.
Remove unix functions that are no longer needed.
Comment out check in cpsf.c that caused 2nd stage dll registrations to fail.
All rpcrt4 tests no longer crash.

svn path=/trunk/; revision=47970
This commit is contained in:
Daniel Reimer 2010-07-08 18:39:18 +00:00
parent 9919e408d5
commit ba086d41dd
22 changed files with 4517 additions and 1293 deletions

View file

@ -483,3 +483,24 @@ CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid,
} }
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT WINAPI
CreateStubFromTypeInfo(ITypeInfo *pTypeInfo, REFIID riid, IUnknown *pUnkServer,
IRpcStubBuffer **ppStub )
{
typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
HMODULE hUser32 = LoadLibraryA("user32");
MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA");
FIXME("%p %s %p %p\n", pTypeInfo, debugstr_guid(riid), pUnkServer, ppStub);
if (pMessageBoxA)
{
pMessageBoxA(NULL,
"The native implementation of OLEAUT32.DLL cannot be used "
"with Wine's RPCRT4.DLL. Remove OLEAUT32.DLL and try again.\n",
"Wine: Unimplemented CreateProxyFromTypeInfo",
0x10);
ExitProcess(1);
}
return E_NOTIMPL;
}

View file

@ -240,7 +240,16 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,
DWORD len; DWORD len;
TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
format_clsid( clsid, pclsid );
//if (!hDll) return E_HANDLE;
if (!pProxyFileList || !*pProxyFileList) return E_NOINTERFACE;
if (pclsid)
format_clsid( clsid, pclsid );
else if ((*pProxyFileList)->TableSize > 0)
format_clsid( clsid,(*pProxyFileList)->pStubVtblList[0]->header.piid);
else
return E_NOINTERFACE;
/* register interfaces to point to clsid */ /* register interfaces to point to clsid */
while (*pProxyFileList) { while (*pProxyFileList) {
@ -297,8 +306,15 @@ HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0}; static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
static const WCHAR interfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; static const WCHAR interfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
WCHAR keyname[50]; WCHAR keyname[50];
WCHAR clsid[39];
TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
if (pclsid)
format_clsid( clsid, pclsid );
else if ((*pProxyFileList)->TableSize > 0)
format_clsid( clsid,(*pProxyFileList)->pStubVtblList[0]->header.piid);
else
return E_NOINTERFACE;
/* unregister interfaces */ /* unregister interfaces */
while (*pProxyFileList) { while (*pProxyFileList) {
@ -318,7 +334,7 @@ HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
/* unregister clsid */ /* unregister clsid */
strcpyW( keyname, clsidW ); strcpyW( keyname, clsidW );
format_clsid( keyname + strlenW(keyname), pclsid ); strcatW( keyname, clsid );
RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname); RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname);
return S_OK; return S_OK;

View file

@ -137,27 +137,54 @@ static ULONG WINAPI delegating_Release(IUnknown *pUnk)
return 1; return 1;
} }
#if defined(__i386__)
/* The idea here is to replace the first param on the stack /* The idea here is to replace the first param on the stack
ie. This (which will point to cstdstubbuffer_delegating_t) ie. This (which will point to cstdstubbuffer_delegating_t)
with This->stub_buffer.pvServerObject and then jump to the with This->stub_buffer.pvServerObject and then jump to the
relevant offset in This->stub_buffer.pvServerObject's vtbl. relevant offset in This->stub_buffer.pvServerObject's vtbl.
*/ */
#ifdef __i386__
#include "pshpack1.h" #include "pshpack1.h"
typedef struct { typedef struct {
DWORD mov1; /* mov 0x4(%esp), %eax 8b 44 24 04 */ BYTE mov1[4]; /* mov 0x4(%esp),%eax 8b 44 24 04 */
WORD mov2; /* mov 0x10(%eax), %eax 8b 40 */ BYTE mov2[3]; /* mov 0x10(%eax),%eax 8b 40 10 */
BYTE sixteen; /* 10 */ BYTE mov3[4]; /* mov %eax,0x4(%esp) 89 44 24 04 */
DWORD mov3; /* mov %eax, 0x4(%esp) 89 44 24 04 */ BYTE mov4[2]; /* mov (%eax),%eax 8b 00 */
WORD mov4; /* mov (%eax), %eax 8b 00 */ BYTE mov5[2]; /* jmp *offset(%eax) ff a0 offset */
WORD mov5; /* mov offset(%eax), %eax 8b 80 */ DWORD offset;
DWORD offset; /* xx xx xx xx */ BYTE pad[1]; /* nop 90 */
WORD jmp; /* jmp *%eax ff e0 */
BYTE pad[3]; /* lea 0x0(%esi), %esi 8d 76 00 */
} vtbl_method_t; } vtbl_method_t;
#include "poppack.h" #include "poppack.h"
static const BYTE opcodes[20] = { 0x8b, 0x44, 0x24, 0x04, 0x8b, 0x40, 0x10, 0x89, 0x44, 0x24, 0x04,
0x8b, 0x00, 0xff, 0xa0, 0, 0, 0, 0, 0x90 };
#elif defined(__x86_64__)
#include "pshpack1.h"
typedef struct
{
BYTE mov1[4]; /* movq 0x20(%rcx),%rcx 48 8b 49 20 */
BYTE mov2[3]; /* movq (%rcx),%rax 48 8b 01 */
BYTE jmp[2]; /* jmp *offset(%rax) ff a0 offset */
DWORD offset;
BYTE pad[3]; /* lea 0x0(%rsi),%rsi 48 8d 36 */
} vtbl_method_t;
#include "poppack.h"
static const BYTE opcodes[16] = { 0x48, 0x8b, 0x49, 0x20, 0x48, 0x8b, 0x01,
0xff, 0xa0, 0, 0, 0, 0, 0x48, 0x8d, 0x36 };
#else
#warning You must implement delegated proxies/stubs for your CPU
typedef struct
{
DWORD offset;
} vtbl_method_t;
static const BYTE opcodes[1];
#endif
#define BLOCK_SIZE 1024 #define BLOCK_SIZE 1024
#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ #define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */
@ -174,17 +201,8 @@ static const vtbl_method_t *allocate_block( unsigned int num )
for (i = 0; i < BLOCK_SIZE; i++) for (i = 0; i < BLOCK_SIZE; i++)
{ {
block[i].mov1 = 0x0424448b; memcpy( &block[i], opcodes, sizeof(opcodes) );
block[i].mov2 = 0x408b; block[i].offset = (BLOCK_SIZE * num + i + 3) * sizeof(void *);
block[i].sixteen = 0x10;
block[i].mov3 = 0x04244489;
block[i].mov4 = 0x008b;
block[i].mov5 = 0x808b;
block[i].offset = (BLOCK_SIZE * num + i + 3) << 2;
block[i].jmp = 0xe0ff;
block[i].pad[0] = 0x8d;
block[i].pad[1] = 0x76;
block[i].pad[2] = 0x00;
} }
VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL ); VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL );
prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL );
@ -241,22 +259,6 @@ BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
return TRUE; return TRUE;
} }
#else /* __i386__ */
static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num)
{
ERR("delegated stubs are not supported on this architecture\n");
return FALSE;
}
BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
{
ERR("delegated proxies are not supported on this architecture\n");
return FALSE;
}
#endif /* __i386__ */
static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods) static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
{ {
IUnknownVtbl *ret; IUnknownVtbl *ret;

File diff suppressed because it is too large Load diff

View file

@ -309,13 +309,12 @@ void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
{ {
const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat);
ULONG size = 0; ULONG size = 0;
HRESULT hr;
TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
if (!LoadCOM()) return; if (!LoadCOM()) return;
hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory,
pStubMsg->dwDestContext, pStubMsg->pvDestContext, pStubMsg->dwDestContext, pStubMsg->pvDestContext,
MSHLFLAGS_NORMAL); MSHLFLAGS_NORMAL);
TRACE("size=%d\n", size); TRACE("size=%d\n", size);
pStubMsg->BufferLength += sizeof(DWORD) + size; pStubMsg->BufferLength += sizeof(DWORD) + size;
} }

View file

@ -173,7 +173,7 @@ static PFORMAT_STRING client_get_handle(
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else else
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
*phBinding = pGenPair->pfnBind(pObject); *phBinding = pGenPair->pfnBind(pObject);
@ -256,7 +256,7 @@ static void client_free_handle(
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else else
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
pGenPair->pfnUnbind(pObject, hBinding); pGenPair->pfnUnbind(pObject, hBinding);
@ -579,7 +579,7 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
void * This = NULL; void * This = NULL;
PFORMAT_STRING pHandleFormat; PFORMAT_STRING pHandleFormat;
/* correlation cache */ /* correlation cache */
unsigned long NdrCorrCache[256]; ULONG_PTR NdrCorrCache[256];
TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
@ -686,7 +686,8 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
* 4. PROXY_SENDRECEIVE - send/receive buffer * 4. PROXY_SENDRECEIVE - send/receive buffer
* 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
*/ */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) if ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) ||
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_HAS_COMM_OR_FAULT))
{ {
__TRY __TRY
{ {
@ -696,13 +697,56 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
switch (phase) switch (phase)
{ {
case PROXY_GETBUFFER: case PROXY_GETBUFFER:
/* allocate the buffer */ if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
NdrProxyGetBuffer(This, &stubMsg); {
/* allocate the buffer */
NdrProxyGetBuffer(This, &stubMsg);
}
else
{
/* allocate the buffer */
if (Oif_flags.HasPipes)
/* NdrGetPipeBuffer(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
#else
FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
#endif
else
NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
}
}
break; break;
case PROXY_SENDRECEIVE: case PROXY_SENDRECEIVE:
/* send the [in] params and receive the [out] and [retval] if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
* params */ {
NdrProxySendReceive(This, &stubMsg); /* send the [in] params and receive the [out] and [retval]
* params */
NdrProxySendReceive(This, &stubMsg);
}
else
{
/* send the [in] params and receive the [out] and [retval]
* params */
if (Oif_flags.HasPipes)
/* NdrPipesSendReceive(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
#else
FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
#endif
else
NdrSendReceive(&stubMsg, stubMsg.Buffer);
}
}
/* convert strings, floating point values and endianess into our /* convert strings, floating point values and endianess into our
* preferred format */ * preferred format */
@ -729,7 +773,33 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
} }
__EXCEPT_ALL __EXCEPT_ALL
{ {
RetVal = NdrProxyErrorHandler(GetExceptionCode()); if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
RetVal = NdrProxyErrorHandler(GetExceptionCode());
else
{
const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
ULONG *comm_status;
ULONG *fault_status;
TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
if (comm_fault_offsets->CommOffset == -1)
comm_status = (ULONG *)&RetVal;
else if (comm_fault_offsets->CommOffset >= 0)
comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
else
comm_status = NULL;
if (comm_fault_offsets->FaultOffset == -1)
fault_status = (ULONG *)&RetVal;
else if (comm_fault_offsets->FaultOffset >= 0)
fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
else
fault_status = NULL;
NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
GetExceptionCode());
}
} }
__ENDTRY __ENDTRY
} }
@ -867,9 +937,14 @@ __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigne
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
__ASM_GLOBAL_FUNC(call_server_func, __ASM_GLOBAL_FUNC(call_server_func,
"pushl %ebp\n\t" "pushl %ebp\n\t"
"movl %esp, %ebp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
"movl %esp,%ebp\n\t"
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
"pushl %edi\n\t" /* Save registers */ "pushl %edi\n\t" /* Save registers */
__ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
"pushl %esi\n\t" "pushl %esi\n\t"
__ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
"movl 16(%ebp), %eax\n\t" /* Get stack size */ "movl 16(%ebp), %eax\n\t" /* Get stack size */
"subl %eax, %esp\n\t" /* Make room in stack for arguments */ "subl %eax, %esp\n\t" /* Make room in stack for arguments */
"andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
@ -882,9 +957,13 @@ __ASM_GLOBAL_FUNC(call_server_func,
"call *8(%ebp)\n\t" /* Call function */ "call *8(%ebp)\n\t" /* Call function */
"leal -8(%ebp), %esp\n\t" /* Restore stack */ "leal -8(%ebp), %esp\n\t" /* Restore stack */
"popl %esi\n\t" /* Restore registers */ "popl %esi\n\t" /* Restore registers */
__ASM_CFI(".cfi_same_value %esi\n\t")
"popl %edi\n\t" "popl %edi\n\t"
__ASM_CFI(".cfi_same_value %edi\n\t")
"popl %ebp\n\t" "popl %ebp\n\t"
"ret\n" ) __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
#else #else
#warning call_server_func not implemented for your architecture #warning call_server_func not implemented for your architecture
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
@ -920,6 +999,18 @@ static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
size = ComplexStructSize(pStubMsg, pFormat); size = ComplexStructSize(pStubMsg, pFormat);
size *= pStubMsg->MaxCount; size *= pStubMsg->MaxCount;
break; break;
case RPC_FC_C_CSTRING:
case RPC_FC_C_WSTRING:
if (*pFormat == RPC_FC_C_CSTRING)
size = sizeof(CHAR);
else
size = sizeof(WCHAR);
if (pFormat[1] == RPC_FC_STRING_SIZED)
ComputeConformance(pStubMsg, NULL, pFormat + 2, 0);
else
pStubMsg->MaxCount = 0;
size *= pStubMsg->MaxCount;
break;
default: default:
FIXME("Unhandled type %02x\n", *pFormat); FIXME("Unhandled type %02x\n", *pFormat);
/* fallthrough */ /* fallthrough */
@ -1049,7 +1140,8 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
!pParam->param_attributes.IsByValue && !pParam->param_attributes.IsByValue &&
!pParam->param_attributes.ServerAllocSize) !pParam->param_attributes.ServerAllocSize)
{ {
pStubMsg->pfnFree(*(void **)pArg); if (*pTypeFormat != RPC_FC_BIND_CONTEXT)
pStubMsg->pfnFree(*(void **)pArg);
} }
if (pParam->param_attributes.ServerAllocSize) if (pParam->param_attributes.ServerAllocSize)
@ -1061,12 +1153,21 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
!pParam->param_attributes.ServerAllocSize && !pParam->param_attributes.ServerAllocSize &&
!pParam->param_attributes.IsByValue) !pParam->param_attributes.IsByValue)
{ {
DWORD size = calc_arg_size(pStubMsg, pTypeFormat); if (*pTypeFormat == RPC_FC_BIND_CONTEXT)
if(size)
{ {
*(void **)pArg = NdrAllocate(pStubMsg, size); NDR_SCONTEXT ctxt = NdrContextHandleInitialize(
memset(*(void **)pArg, 0, size); pStubMsg, pTypeFormat);
*(void **)pArg = NDRSContextValue(ctxt);
}
else
{
DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
if(size)
{
*(void **)pArg = NdrAllocate(pStubMsg, size);
memset(*(void **)pArg, 0, size);
}
} }
} }
break; break;
@ -1290,10 +1391,6 @@ LONG WINAPI NdrStubCall2(
TRACE("NDR Version: 0x%x\n", pStubDesc->Version); TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
/* create the full pointer translation tables, if requested */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
{ {
const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
@ -1368,6 +1465,10 @@ LONG WINAPI NdrStubCall2(
else else
NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
/* create the full pointer translation tables, if requested */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
/* store the RPC flags away */ /* store the RPC flags away */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
@ -1522,3 +1623,339 @@ void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
DWORD dwPhase; DWORD dwPhase;
NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
} }
struct async_call_data
{
MIDL_STUB_MESSAGE *pStubMsg;
const NDR_PROC_HEADER *pProcHeader;
PFORMAT_STRING pHandleFormat;
PFORMAT_STRING pParamFormat;
RPC_BINDING_HANDLE hBinding;
/* size of stack */
unsigned short stack_size;
/* number of parameters. optional for client to give it to us */
unsigned char number_of_params;
/* correlation cache */
ULONG_PTR NdrCorrCache[256];
};
LONG_PTR WINAPIV NdrAsyncClientCall(PMIDL_STUB_DESC pStubDesc,
PFORMAT_STRING pFormat, ...)
{
/* pointer to start of stack where arguments start */
PRPC_MESSAGE pRpcMsg;
PMIDL_STUB_MESSAGE pStubMsg;
RPC_ASYNC_STATE *pAsync;
struct async_call_data *async_call_data;
/* procedure number */
unsigned short procedure_number;
/* cache of Oif_flags from v2 procedure header */
INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
/* cache of extension flags from NDR_PROC_HEADER_EXTS */
INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
/* the type of pass we are currently doing */
int phase;
/* header for procedure string */
const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
/* -Oif or -Oicf generated format */
BOOL bV2Format = FALSE;
TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
/* Later NDR language versions probably won't be backwards compatible */
if (pStubDesc->Version > 0x50002)
{
FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
}
async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY);
async_call_data->number_of_params = ~0;
async_call_data->pProcHeader = pProcHeader;
async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
{
const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
async_call_data->stack_size = pProcHeader->stack_size;
procedure_number = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER_RPC);
}
else
{
async_call_data->stack_size = pProcHeader->stack_size;
procedure_number = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER);
}
TRACE("stack size: 0x%x\n", async_call_data->stack_size);
TRACE("proc num: %d\n", procedure_number);
/* create the full pointer translation tables, if requested */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
{
ERR("objects not supported\n");
I_RpcFree(async_call_data);
RpcRaiseException(RPC_X_BAD_STUB_DATA);
}
NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
/* needed for conformance of top-level objects */
#ifdef __i386__
pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
/* FIXME: this may read one more DWORD than is necessary, but it shouldn't hurt */
memcpy(pStubMsg->StackTop, *(unsigned char **)(&pFormat+1), async_call_data->stack_size);
#else
# warning Stack not retrieved for your CPU architecture
#endif
pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
pAsync->StubInfo = async_call_data;
async_call_data->pHandleFormat = pFormat;
pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding);
if (!pFormat) return 0;
bV2Format = (pStubDesc->Version >= 0x20000);
if (bV2Format)
{
const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
(const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
Oif_flags = pOIFHeader->Oi2Flags;
async_call_data->number_of_params = pOIFHeader->number_of_params;
pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
}
TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
if (Oif_flags.HasExtensions)
{
const NDR_PROC_HEADER_EXTS *pExtensions =
(const NDR_PROC_HEADER_EXTS *)pFormat;
ext_flags = pExtensions->Flags2;
pFormat += pExtensions->Size;
}
async_call_data->pParamFormat = pFormat;
pStubMsg->BufferLength = 0;
/* store the RPC flags away */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
/* use alternate memory allocation routines */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
NdrRpcSmSetClientToOsf(pStubMsg);
if (Oif_flags.HasPipes)
{
FIXME("pipes not supported yet\n");
RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
/* init pipes package */
/* NdrPipesInitialize(...) */
}
if (ext_flags.HasNewCorrDesc)
{
/* initialize extra correlation package */
NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
}
/* order of phases:
* 1. PROXY_CALCSIZE - calculate the buffer size
* 2. PROXY_GETBUFFER - allocate the buffer
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
* 4. PROXY_SENDRECEIVE - send buffer
* Then in NdrpCompleteAsyncClientCall:
* 1. PROXY_SENDRECEIVE - receive buffer
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
*/
for (phase = PROXY_CALCSIZE; phase <= PROXY_SENDRECEIVE; phase++)
{
RPC_STATUS status;
TRACE("phase = %d\n", phase);
switch (phase)
{
case PROXY_GETBUFFER:
/* allocate the buffer */
if (Oif_flags.HasPipes)
/* NdrGetPipeBuffer(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
#else
FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
#endif
else
NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
}
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
if (status != RPC_S_OK)
RpcRaiseException(status);
break;
case PROXY_SENDRECEIVE:
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
/* send the [in] params only */
if (Oif_flags.HasPipes)
/* NdrPipesSend(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
#else
FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
#endif
else
{
pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
status = I_RpcSend(pStubMsg->RpcMsg);
if (status != RPC_S_OK)
RpcRaiseException(status);
}
}
break;
case PROXY_CALCSIZE:
case PROXY_MARSHAL:
if (bV2Format)
client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop,
async_call_data->number_of_params, NULL);
else
client_do_args_old_format(pStubMsg, pFormat, phase,
pStubMsg->StackTop, async_call_data->stack_size, NULL,
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
break;
default:
ERR("shouldn't reach here. phase %d\n", phase);
break;
}
}
TRACE("returning 0\n");
return 0;
}
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
{
/* pointer to start of stack where arguments start */
PMIDL_STUB_MESSAGE pStubMsg;
struct async_call_data *async_call_data;
/* the type of pass we are currently doing */
int phase;
/* header for procedure string */
const NDR_PROC_HEADER * pProcHeader;
/* -Oif or -Oicf generated format */
BOOL bV2Format;
RPC_STATUS status = RPC_S_OK;
if (!pAsync->StubInfo)
return RPC_S_INVALID_ASYNC_HANDLE;
async_call_data = pAsync->StubInfo;
pStubMsg = async_call_data->pStubMsg;
pProcHeader = async_call_data->pProcHeader;
bV2Format = (pStubMsg->StubDesc->Version >= 0x20000);
/* order of phases:
* 1. PROXY_CALCSIZE - calculate the buffer size
* 2. PROXY_GETBUFFER - allocate the buffer
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
* 4. PROXY_SENDRECEIVE - send buffer
* Then in NdrpCompleteAsyncClientCall:
* 1. PROXY_SENDRECEIVE - receive buffer
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
*/
for (phase = PROXY_SENDRECEIVE; phase <= PROXY_UNMARSHAL; phase++)
{
switch (phase)
{
case PROXY_SENDRECEIVE:
pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
/* receive the [out] params */
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
#else
FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
#endif
else
{
status = I_RpcReceive(pStubMsg->RpcMsg);
if (status != RPC_S_OK)
goto cleanup;
pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
pStubMsg->Buffer = pStubMsg->BufferStart;
}
/* convert strings, floating point values and endianess into our
* preferred format */
#if 0
if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
NdrConvert(pStubMsg, pFormat);
#endif
break;
case PROXY_UNMARSHAL:
if (bV2Format)
client_do_args(pStubMsg, async_call_data->pParamFormat, phase, pStubMsg->StackTop,
async_call_data->number_of_params, Reply);
else
client_do_args_old_format(pStubMsg, async_call_data->pParamFormat, phase,
pStubMsg->StackTop, async_call_data->stack_size, Reply, FALSE, FALSE);
break;
default:
ERR("shouldn't reach here. phase %d\n", phase);
break;
}
}
cleanup:
if (pStubMsg->fHasNewCorrDesc)
{
/* free extra correlation package */
NdrCorrelationFree(pStubMsg);
}
/* free the full pointer translation tables */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
/* free marshalling buffer */
NdrFreeBuffer(pStubMsg);
client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
I_RpcFree(pStubMsg->StackTop);
I_RpcFree(async_call_data);
TRACE("-- 0x%x\n", status);
return status;
}
RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
DWORD * pdwStubPhase)
{
FIXME("unimplemented, expect crash!\n");
return 0;
}

View file

@ -85,7 +85,7 @@ typedef struct _NDR_PROC_HEADER_RPC
* RPCF_Asynchronous = 0x4000 - [async] MIDL attribute * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
* Reserved = 0x8000 * Reserved = 0x8000
*/ */
unsigned long rpc_flags; unsigned int rpc_flags;
unsigned short proc_num; unsigned short proc_num;
unsigned short stack_size; unsigned short stack_size;
@ -240,3 +240,4 @@ void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat, int phase, unsigned char *args, PFORMAT_STRING pFormat, int phase, unsigned char *args,
unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc, unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc,
BOOL ignore_retval); BOOL ignore_retval);
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply);

View file

@ -84,6 +84,15 @@ static RPC_STATUS RpcAssoc_Alloc(LPCSTR Protseq, LPCSTR NetworkAddr,
return RPC_S_OK; return RPC_S_OK;
} }
static BOOL compare_networkoptions(LPCWSTR opts1, LPCWSTR opts2)
{
if ((opts1 == NULL) && (opts2 == NULL))
return TRUE;
if ((opts1 == NULL) || (opts2 == NULL))
return FALSE;
return !strcmpW(opts1, opts2);
}
RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, LPCWSTR NetworkOptions, LPCSTR Endpoint, LPCWSTR NetworkOptions,
RpcAssoc **assoc_out) RpcAssoc **assoc_out)
@ -97,7 +106,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
if (!strcmp(Protseq, assoc->Protseq) && if (!strcmp(Protseq, assoc->Protseq) &&
!strcmp(NetworkAddr, assoc->NetworkAddr) && !strcmp(NetworkAddr, assoc->NetworkAddr) &&
!strcmp(Endpoint, assoc->Endpoint) && !strcmp(Endpoint, assoc->Endpoint) &&
((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) compare_networkoptions(NetworkOptions, assoc->NetworkOptions))
{ {
assoc->refs++; assoc->refs++;
*assoc_out = assoc; *assoc_out = assoc;
@ -125,7 +134,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, LPCWSTR NetworkOptions, LPCSTR Endpoint, LPCWSTR NetworkOptions,
unsigned long assoc_gid, ULONG assoc_gid,
RpcAssoc **assoc_out) RpcAssoc **assoc_out)
{ {
RpcAssoc *assoc; RpcAssoc *assoc;
@ -223,7 +232,7 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *
RPC_MESSAGE msg; RPC_MESSAGE msg;
RPC_STATUS status; RPC_STATUS status;
unsigned char *auth_data = NULL; unsigned char *auth_data = NULL;
unsigned long auth_length; ULONG auth_length;
TRACE("sending bind request to server\n"); TRACE("sending bind request to server\n");
@ -254,18 +263,19 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *
{ {
unsigned short remaining = msg.BufferLength - unsigned short remaining = msg.BufferLength -
ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4);
RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + RpcResultList *results = (RpcResultList*)((ULONG_PTR)server_address +
ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4));
if ((results->num_results == 1) && (remaining >= sizeof(*results))) if ((results->num_results == 1) &&
(remaining >= FIELD_OFFSET(RpcResultList, results[results->num_results])))
{ {
switch (results->results[0].result) switch (results->results[0].result)
{ {
case RESULT_ACCEPT: case RESULT_ACCEPT:
/* respond to authorization request */ /* respond to authorization request */
if (auth_length > sizeof(RpcAuthVerifier)) if (auth_length > sizeof(RpcAuthVerifier))
status = RPCRT4_AuthorizeConnection(conn, status = RPCRT4_ClientConnectionAuth(conn,
auth_data + sizeof(RpcAuthVerifier), auth_data + sizeof(RpcAuthVerifier),
auth_length); auth_length);
if (status == RPC_S_OK) if (status == RPC_S_OK)
{ {
conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; conn->assoc_group_id = response_hdr->bind_ack.assoc_gid;
@ -394,6 +404,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
NewConnection->assoc = assoc;
status = RPCRT4_OpenClientConnection(NewConnection); status = RPCRT4_OpenClientConnection(NewConnection);
if (status != RPC_S_OK) if (status != RPC_S_OK)
{ {
@ -416,6 +427,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
{ {
assert(!Connection->server); assert(!Connection->server);
Connection->async_state = NULL;
EnterCriticalSection(&assoc->cs); EnterCriticalSection(&assoc->cs);
if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id;
list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry); list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry);

View file

@ -34,6 +34,7 @@ typedef struct _RpcAssoc
/* id of this association group */ /* id of this association group */
ULONG assoc_group_id; ULONG assoc_group_id;
UUID http_uuid;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
@ -49,7 +50,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endp
RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection);
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection);
ULONG RpcAssoc_Release(RpcAssoc *assoc); ULONG RpcAssoc_Release(RpcAssoc *assoc);
RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, unsigned long assoc_gid, RpcAssoc **assoc_out); RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out);
RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext); RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext);
RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext); RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext);
RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine); RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine);

View file

@ -29,11 +29,17 @@
#include "rpc_binding.h" #include "rpc_binding.h"
#include "rpc_message.h" #include "rpc_message.h"
#include "ndr_stubless.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc); WINE_DEFAULT_DEBUG_CHANNEL(rpc);
#define RPC_ASYNC_SIGNATURE 0x43595341 #define RPC_ASYNC_SIGNATURE 0x43595341
static inline BOOL valid_async_handle(PRPC_ASYNC_STATE pAsync)
{
return pAsync->Signature == RPC_ASYNC_SIGNATURE;
}
/*********************************************************************** /***********************************************************************
* RpcAsyncInitializeHandle [RPCRT4.@] * RpcAsyncInitializeHandle [RPCRT4.@]
* *
@ -104,8 +110,14 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync)
*/ */
RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
{ {
FIXME("(%p, %p): stub\n", pAsync, Reply); TRACE("(%p, %p)\n", pAsync, Reply);
return RPC_S_INVALID_ASYNC_HANDLE;
if (!valid_async_handle(pAsync))
return RPC_S_INVALID_ASYNC_HANDLE;
/* FIXME: check completed */
return NdrpCompleteAsyncClientCall(pAsync, Reply);
} }
/*********************************************************************** /***********************************************************************

View file

@ -661,11 +661,11 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU
return RPC_S_OK; return RPC_S_OK;
fail: fail:
if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid); if (ObjUuid) RpcStringFreeA(ObjUuid);
if (Protseq) RpcStringFreeA((unsigned char**)Protseq); if (Protseq) RpcStringFreeA(Protseq);
if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr); if (NetworkAddr) RpcStringFreeA(NetworkAddr);
if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint); if (Endpoint) RpcStringFreeA(Endpoint);
if (Options) RpcStringFreeA((unsigned char**)Options); if (Options) RpcStringFreeA(Options);
return RPC_S_INVALID_STRING_BINDING; return RPC_S_INVALID_STRING_BINDING;
} }
@ -785,8 +785,11 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
{ {
RPC_STATUS status; RPC_STATUS status;
TRACE("(%p) = %p\n", Binding, *Binding); TRACE("(%p) = %p\n", Binding, *Binding);
status = RPCRT4_ReleaseBinding(*Binding); if (*Binding)
if (status == RPC_S_OK) *Binding = 0; status = RPCRT4_ReleaseBinding(*Binding);
else
status = RPC_S_INVALID_BINDING;
if (status == RPC_S_OK) *Binding = NULL;
return status; return status;
} }
@ -796,7 +799,7 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
{ {
RPC_STATUS status; RPC_STATUS status;
unsigned long c; ULONG c;
TRACE("(%p)\n", BindingVector); TRACE("(%p)\n", BindingVector);
for (c=0; c<(*BindingVector)->Count; c++) { for (c=0; c<(*BindingVector)->Count; c++) {
@ -812,7 +815,7 @@ RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
*/ */
RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
*ObjectUuid = bind->ObjectUuid; *ObjectUuid = bind->ObjectUuid;
@ -824,7 +827,7 @@ RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectU
*/ */
RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
@ -856,11 +859,11 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BIND
if (ret == RPC_S_OK) if (ret == RPC_S_OK)
ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options); ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
RpcStringFreeA((unsigned char**)&Options); RpcStringFreeA(&Options);
RpcStringFreeA((unsigned char**)&Endpoint); RpcStringFreeA(&Endpoint);
RpcStringFreeA((unsigned char**)&NetworkAddr); RpcStringFreeA(&NetworkAddr);
RpcStringFreeA((unsigned char**)&Protseq); RpcStringFreeA(&Protseq);
RpcStringFreeA((unsigned char**)&ObjectUuid); RpcStringFreeA(&ObjectUuid);
if (ret == RPC_S_OK) if (ret == RPC_S_OK)
*Binding = (RPC_BINDING_HANDLE)bind; *Binding = (RPC_BINDING_HANDLE)bind;
@ -915,7 +918,7 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BIND
RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
{ {
RPC_STATUS ret; RPC_STATUS ret;
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
RPC_CSTR ObjectUuid; RPC_CSTR ObjectUuid;
TRACE("(%p,%p)\n", Binding, StringBinding); TRACE("(%p,%p)\n", Binding, StringBinding);
@ -946,7 +949,7 @@ RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WS
TRACE("(%p,%p)\n", Binding, StringBinding); TRACE("(%p,%p)\n", Binding, StringBinding);
ret = RpcBindingToStringBindingA(Binding, &str); ret = RpcBindingToStringBindingA(Binding, &str);
*StringBinding = RPCRT4_strdupAtoW((char*)str); *StringBinding = RPCRT4_strdupAtoW((char*)str);
RpcStringFreeA((unsigned char**)&str); RpcStringFreeA(&str);
return ret; return ret;
} }
@ -969,7 +972,7 @@ RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsi
*/ */
RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
@ -986,7 +989,7 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy(
RPC_BINDING_HANDLE* DestinationBinding) RPC_BINDING_HANDLE* DestinationBinding)
{ {
RpcBinding *DestBinding; RpcBinding *DestBinding;
RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; RpcBinding *SrcBinding = SourceBinding;
RPC_STATUS status; RPC_STATUS status;
TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
@ -1049,9 +1052,17 @@ RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
*/ */
RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
{ {
FIXME("(%p): stub\n", BindingHandle); RpcBinding *bind;
ImpersonateSelf(SecurityImpersonation);
return RPC_S_OK; TRACE("(%p)\n", BindingHandle);
if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
if (!BindingHandle) return RPC_S_INVALID_BINDING;
bind = BindingHandle;
if (bind->FromConn)
return rpcrt4_conn_impersonate_client(bind->FromConn);
return RPC_S_WRONG_KIND_OF_BINDING;
} }
/*********************************************************************** /***********************************************************************
@ -1074,8 +1085,17 @@ RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
*/ */
RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
{ {
FIXME("(%p): stub\n", BindingHandle); RpcBinding *bind;
return RPC_S_OK;
TRACE("(%p)\n", BindingHandle);
if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
if (!BindingHandle) return RPC_S_INVALID_BINDING;
bind = BindingHandle;
if (bind->FromConn)
return rpcrt4_conn_revert_to_self(bind->FromConn);
return RPC_S_WRONG_KIND_OF_BINDING;
} }
static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
@ -1091,11 +1111,11 @@ static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
} }
} }
static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
CredHandle cred, TimeStamp exp, CredHandle cred, TimeStamp exp,
ULONG cbMaxToken, ULONG cbMaxToken,
RPC_AUTH_IDENTITY_HANDLE identity, RPC_AUTH_IDENTITY_HANDLE identity,
RpcAuthInfo **ret) RpcAuthInfo **ret)
{ {
RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo)); RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
if (!AuthInfo) if (!AuthInfo)
@ -1283,7 +1303,7 @@ static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BO
cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR)); cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR)); cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR)); cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error; if (!cred_dst->Password || !cred_dst->Domain) goto error;
MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength); MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength); MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength); MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
@ -1428,9 +1448,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali
*/ */
RPC_STATUS WINAPI RpcRevertToSelf(void) RPC_STATUS WINAPI RpcRevertToSelf(void)
{ {
FIXME("stub\n"); TRACE("\n");
RevertToSelf(); return RpcRevertToSelfEx(NULL);
return RPC_S_OK;
} }
/*********************************************************************** /***********************************************************************
@ -1450,9 +1469,22 @@ RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName,
ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
{ {
FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, RPC_STATUS status;
RPC_WSTR principal;
TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
return RPC_S_INVALID_BINDING;
status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
if (status == RPC_S_OK && ServerPrincName)
{
*ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
RpcStringFreeW(&principal);
if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
}
return status;
} }
/*********************************************************************** /***********************************************************************
@ -1463,9 +1495,38 @@ RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName,
ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
{ {
FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, RpcBinding *bind = Binding;
TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
return RPC_S_INVALID_BINDING;
if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
if (SecurityQOS)
{
FIXME("QOS not implemented\n");
return RPC_S_INVALID_BINDING;
}
if (ServerPrincName)
{
if (bind->AuthInfo->server_principal_name)
{
*ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name);
if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
}
else *ServerPrincName = NULL;
}
if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
if (AuthzSvc)
{
FIXME("authorization service not implemented\n");
*AuthzSvc = RPC_C_AUTHZ_NONE;
}
return RPC_S_OK;
} }
/*********************************************************************** /***********************************************************************
@ -1475,9 +1536,8 @@ RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
{ {
FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
AuthnSvc, AuthIdentity, AuthzSvc); AuthzSvc, 0, NULL);
return RPC_S_INVALID_BINDING;
} }
/*********************************************************************** /***********************************************************************
@ -1487,9 +1547,78 @@ RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
{ {
FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
AuthnSvc, AuthIdentity, AuthzSvc); AuthzSvc, 0, NULL);
return RPC_S_INVALID_BINDING; }
/***********************************************************************
* RpcBindingInqAuthClientA (RPCRT4.@)
*/
RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
ULONG *AuthzSvc )
{
return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
AuthnSvc, AuthzSvc, 0);
}
/***********************************************************************
* RpcBindingInqAuthClientW (RPCRT4.@)
*/
RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
ULONG *AuthzSvc )
{
return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
AuthnSvc, AuthzSvc, 0);
}
/***********************************************************************
* RpcBindingInqAuthClientExA (RPCRT4.@)
*/
RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
ULONG *AuthzSvc, ULONG Flags )
{
RPC_STATUS status;
RPC_WSTR principal;
TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
AuthnSvc, AuthzSvc, Flags);
status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
AuthnLevel, AuthnSvc, AuthzSvc, Flags);
if (status == RPC_S_OK && ServerPrincName)
{
*ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
if (!*ServerPrincName && principal) status = ERROR_OUTOFMEMORY;
RpcStringFreeW(&principal);
}
return status;
}
/***********************************************************************
* RpcBindingInqAuthClientExW (RPCRT4.@)
*/
RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
ULONG *AuthzSvc, ULONG Flags )
{
RpcBinding *bind = ClientBinding;
TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
AuthnSvc, AuthzSvc, Flags);
if (!bind->FromConn) return RPC_S_INVALID_BINDING;
return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
ServerPrincName, AuthnLevel,
AuthnSvc, AuthzSvc, Flags);
} }
/*********************************************************************** /***********************************************************************
@ -1501,7 +1630,7 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos ) RPC_SECURITY_QOS *SecurityQos )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
SECURITY_STATUS r; SECURITY_STATUS r;
CredHandle cred; CredHandle cred;
TimeStamp exp; TimeStamp exp;
@ -1631,7 +1760,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName,
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos ) RPC_SECURITY_QOS *SecurityQos )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
SECURITY_STATUS r; SECURITY_STATUS r;
CredHandle cred; CredHandle cred;
TimeStamp exp; TimeStamp exp;
@ -1640,7 +1769,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName,
PSecPkgInfoW packages; PSecPkgInfoW packages;
ULONG cbMaxToken; ULONG cbMaxToken;
TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
if (SecurityQos) if (SecurityQos)
@ -1772,7 +1901,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
{ {
TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
} }

View file

@ -24,8 +24,15 @@
#include "rpcndr.h" #include "rpcndr.h"
#include "security.h" #include "security.h"
#include "wine/list.h" #include "wine/list.h"
#include "rpc_defs.h"
enum secure_packet_direction
{
SECURE_PACKET_SEND,
SECURE_PACKET_RECEIVE
};
typedef struct _RpcAuthInfo typedef struct _RpcAuthInfo
{ {
LONG refs; LONG refs;
@ -66,6 +73,7 @@ typedef struct _RpcConnection
TimeStamp exp; TimeStamp exp;
ULONG attr; ULONG attr;
RpcAuthInfo *AuthInfo; RpcAuthInfo *AuthInfo;
ULONG auth_context_id;
ULONG encryption_auth_len; ULONG encryption_auth_len;
ULONG signature_auth_len; ULONG signature_auth_len;
RpcQualityOfService *QOS; RpcQualityOfService *QOS;
@ -74,6 +82,7 @@ typedef struct _RpcConnection
struct list conn_pool_entry; struct list conn_pool_entry;
ULONG assoc_group_id; /* association group returned during binding */ ULONG assoc_group_id; /* association group returned during binding */
RPC_ASYNC_STATE *async_state; RPC_ASYNC_STATE *async_state;
struct _RpcAssoc *assoc; /* association this connection is part of */
/* server-only */ /* server-only */
/* The active interface bound to server. */ /* The active interface bound to server. */
@ -96,6 +105,13 @@ struct connection_ops {
int (*wait_for_incoming_data)(RpcConnection *conn); int (*wait_for_incoming_data)(RpcConnection *conn);
size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint); size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint);
RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint); RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint);
RPC_STATUS (*receive_fragment)(RpcConnection *conn, RpcPktHdr **Header, void **Payload);
BOOL (*is_authorized)(RpcConnection *conn);
RPC_STATUS (*authorize)(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len);
RPC_STATUS (*secure_packet)(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, unsigned char *auth_value, unsigned int auth_value_size);
RPC_STATUS (*impersonate_client)(RpcConnection *conn);
RPC_STATUS (*revert_to_self)(RpcConnection *conn);
RPC_STATUS (*inquire_auth_client)(RpcConnection *, RPC_AUTHZ_HANDLE *, RPC_WSTR *, ULONG *, ULONG *, ULONG *, ULONG);
}; };
/* don't know what MS's structure looks like */ /* don't know what MS's structure looks like */
@ -128,6 +144,7 @@ void RPCRT4_strfree(LPSTR src);
#define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1) #define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)
#define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1) #define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)
RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, CredHandle cred, TimeStamp exp, ULONG cbMaxToken, RPC_AUTH_IDENTITY_HANDLE identity, RpcAuthInfo **ret);
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo); ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo); ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo);
BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2); BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2);
@ -181,6 +198,46 @@ static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnect
return old_conn->ops->handoff(old_conn, new_conn); return old_conn->ops->handoff(old_conn, new_conn);
} }
static inline BOOL rpcrt4_conn_is_authorized(RpcConnection *Connection)
{
return Connection->ops->is_authorized(Connection);
}
static inline RPC_STATUS rpcrt4_conn_authorize(
RpcConnection *conn, BOOL first_time, unsigned char *in_buffer,
unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len)
{
return conn->ops->authorize(conn, first_time, in_buffer, in_len, out_buffer, out_len);
}
static inline RPC_STATUS rpcrt4_conn_secure_packet(
RpcConnection *conn, enum secure_packet_direction dir,
RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data,
unsigned int stub_data_size, RpcAuthVerifier *auth_hdr,
unsigned char *auth_value, unsigned int auth_value_size)
{
return conn->ops->secure_packet(conn, dir, hdr, hdr_size, stub_data, stub_data_size, auth_hdr, auth_value, auth_value_size);
}
static inline RPC_STATUS rpcrt4_conn_impersonate_client(
RpcConnection *conn)
{
return conn->ops->impersonate_client(conn);
}
static inline RPC_STATUS rpcrt4_conn_revert_to_self(
RpcConnection *conn)
{
return conn->ops->revert_to_self(conn);
}
static inline RPC_STATUS rpcrt4_conn_inquire_auth_client(
RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name,
ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags)
{
return conn->ops->inquire_auth_client(conn, privs, server_princ_name, authn_level, authn_svc, authz_svc, flags);
}
/* floors 3 and up */ /* floors 3 and up */
RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint); RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint);
RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint); RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint);

View file

@ -22,6 +22,7 @@
#ifndef __WINE_RPC_DEFS_H #ifndef __WINE_RPC_DEFS_H
#define __WINE_RPC_DEFS_H #define __WINE_RPC_DEFS_H
#include "pshpack1.h"
typedef struct typedef struct
{ {
unsigned char rpc_ver; /* RPC major version (5) */ unsigned char rpc_ver; /* RPC major version (5) */
@ -31,13 +32,13 @@ typedef struct
unsigned char drep[4]; /* Data representation */ unsigned char drep[4]; /* Data representation */
unsigned short frag_len; /* Data size in bytes including header and tail. */ unsigned short frag_len; /* Data size in bytes including header and tail. */
unsigned short auth_len; /* Authentication length */ unsigned short auth_len; /* Authentication length */
unsigned long call_id; /* Call identifier. */ unsigned int call_id; /* Call identifier. */
} RpcPktCommonHdr; } RpcPktCommonHdr;
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned short opnum; unsigned short opnum;
} RpcPktRequestHdr; } RpcPktRequestHdr;
@ -45,7 +46,7 @@ typedef struct
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count; unsigned char cancel_count;
unsigned char reserved; unsigned char reserved;
@ -54,58 +55,68 @@ typedef struct
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count; /* Received cancel count */ unsigned char cancel_count; /* Received cancel count */
unsigned char reserved; /* Force alignment! */ unsigned char reserved; /* Force alignment! */
unsigned long status; /* Runtime fault code (RPC_STATUS) */ unsigned int status; /* Runtime fault code (RPC_STATUS) */
unsigned long reserved2; unsigned int reserved2;
} RpcPktFaultHdr; } RpcPktFaultHdr;
typedef struct
{
unsigned short context_id; /* Presentation context identifier */
unsigned char num_syntaxes; /* Number of syntaxes */
unsigned char reserved; /* For alignment */
RPC_SYNTAX_IDENTIFIER abstract_syntax;
RPC_SYNTAX_IDENTIFIER transfer_syntaxes[ANYSIZE_ARRAY]; /* size_is(num_syntaxes) */
} RpcContextElement;
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */
unsigned long assoc_gid; /* Associated group id */ unsigned int assoc_gid; /* Associated group id */
unsigned char num_elements; /* Number of elements */ unsigned char num_elements; /* Number of elements */
unsigned char padding[3]; /* Force alignment! */ unsigned char padding[3]; /* Force alignment! */
unsigned short context_id; /* Presentation context identifier */ /*
unsigned char num_syntaxes; /* Number of syntaxes */ * Following this header are these fields:
RPC_SYNTAX_IDENTIFIER abstract; * RpcContextElement context_elements[num_elements]
RPC_SYNTAX_IDENTIFIER transfer; */
} RpcPktBindHdr; } RpcPktBindHdr;
#include "pshpack1.h"
typedef struct typedef struct
{ {
unsigned short length; /* Length of the string including null terminator */ unsigned short length; /* Length of the string including null terminator */
char string[1]; /* String data in single byte, null terminated form */ char string[ANYSIZE_ARRAY]; /* String data in single byte, null terminated form */
} RpcAddressString; } RpcAddressString;
#include "poppack.h"
typedef struct
{
unsigned short result;
unsigned short reason;
RPC_SYNTAX_IDENTIFIER transfer_syntax;
} RpcResult;
typedef struct typedef struct
{ {
unsigned char num_results; /* Number of results */ unsigned char num_results; /* Number of results */
unsigned char reserved[3]; /* Force alignment! */ unsigned char reserved[3]; /* Force alignment! */
struct { RpcResult results[ANYSIZE_ARRAY]; /* size_is(num_results) */
unsigned short result; } RpcResultList;
unsigned short reason;
} results[1];
} RpcResults;
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */
unsigned long assoc_gid; /* Associated group id */ unsigned int assoc_gid; /* Associated group id */
/* /*
* Following this header are these fields: * Following this header are these fields:
* RpcAddressString server_address; * RpcAddressString server_address;
* [0 - 3 bytes of padding so that results is 4-byte aligned] * [0 - 3 bytes of padding so that results is 4-byte aligned]
* RpcResults results; * RpcResultList results;
* RPC_SYNTAX_IDENTIFIER transfer;
*/ */
} RpcPktBindAckHdr; } RpcPktBindAckHdr;
@ -117,9 +128,24 @@ typedef struct
struct { struct {
unsigned char rpc_ver; unsigned char rpc_ver;
unsigned char rpc_ver_minor; unsigned char rpc_ver_minor;
} protocols[1]; } protocols[ANYSIZE_ARRAY];
} RpcPktBindNAckHdr; } RpcPktBindNAckHdr;
/* undocumented packet sent during RPC over HTTP */
typedef struct
{
RpcPktCommonHdr common;
unsigned short flags;
unsigned short num_data_items;
} RpcPktHttpHdr;
/* AUTH3 packet */
typedef struct
{
RpcPktCommonHdr common;
unsigned int pad; /* ignored */
} RpcPktAuth3Hdr;
/* Union representing all possible packet headers */ /* Union representing all possible packet headers */
typedef union typedef union
{ {
@ -130,6 +156,8 @@ typedef union
RpcPktBindHdr bind; RpcPktBindHdr bind;
RpcPktBindAckHdr bind_ack; RpcPktBindAckHdr bind_ack;
RpcPktBindNAckHdr bind_nack; RpcPktBindNAckHdr bind_nack;
RpcPktHttpHdr http;
RpcPktAuth3Hdr auth3;
} RpcPktHdr; } RpcPktHdr;
typedef struct typedef struct
@ -138,8 +166,9 @@ typedef struct
unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */ unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */
unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */ unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */
unsigned char auth_reserved; /* reserved, must be zero */ unsigned char auth_reserved; /* reserved, must be zero */
unsigned long auth_context_id; /* unique value for the authenticated connection */ unsigned int auth_context_id; /* unique value for the authenticated connection */
} RpcAuthVerifier; } RpcAuthVerifier;
#include "poppack.h"
#define RPC_AUTH_VERIFIER_LEN(common_hdr) \ #define RPC_AUTH_VERIFIER_LEN(common_hdr) \
((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0) ((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0)
@ -154,26 +183,30 @@ typedef struct
#define RPC_MIN_PACKET_SIZE 0x1000 #define RPC_MIN_PACKET_SIZE 0x1000
#define RPC_MAX_PACKET_SIZE 0x16D0 #define RPC_MAX_PACKET_SIZE 0x16D0
#define PKT_REQUEST 0 enum rpc_packet_type
#define PKT_PING 1 {
#define PKT_RESPONSE 2 PKT_REQUEST = 0,
#define PKT_FAULT 3 PKT_PING = 1,
#define PKT_WORKING 4 PKT_RESPONSE = 2,
#define PKT_NOCALL 5 PKT_FAULT = 3,
#define PKT_REJECT 6 PKT_WORKING = 4,
#define PKT_ACK 7 PKT_NOCALL = 5,
#define PKT_CL_CANCEL 8 PKT_REJECT = 6,
#define PKT_FACK 9 PKT_ACK = 7,
#define PKT_CANCEL_ACK 10 PKT_CL_CANCEL = 8,
#define PKT_BIND 11 PKT_FACK = 9,
#define PKT_BIND_ACK 12 PKT_CANCEL_ACK = 10,
#define PKT_BIND_NACK 13 PKT_BIND = 11,
#define PKT_ALTER_CONTEXT 14 PKT_BIND_ACK = 12,
#define PKT_ALTER_CONTEXT_RESP 15 PKT_BIND_NACK = 13,
#define PKT_AUTH3 16 PKT_ALTER_CONTEXT = 14,
#define PKT_SHUTDOWN 17 PKT_ALTER_CONTEXT_RESP = 15,
#define PKT_CO_CANCEL 18 PKT_AUTH3 = 16,
#define PKT_ORPHANED 19 PKT_SHUTDOWN = 17,
PKT_CO_CANCEL = 18,
PKT_ORPHANED = 19,
PKT_HTTP = 20,
};
#define RESULT_ACCEPT 0 #define RESULT_ACCEPT 0
#define RESULT_USER_REJECTION 1 #define RESULT_USER_REJECTION 1

View file

@ -116,18 +116,18 @@ static BOOL start_rpcss(void)
static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle) static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
{ {
RpcBinding *bind = (RpcBinding *)handle; RpcBinding *bind = handle;
const char *protseq = bind->Protseq; const char *protseq = bind->Protseq;
const char *network_addr = bind->NetworkAddr; const char *network_addr = bind->NetworkAddr;
return ((!strcmp(protseq, "ncalrpc") && !network_addr) || return (!strcmp(protseq, "ncalrpc") ||
(!strcmp(protseq, "ncacn_np") && (!strcmp(protseq, "ncacn_np") &&
(!network_addr || !strcmp(network_addr, ".")))); (!network_addr || !strcmp(network_addr, "."))));
} }
static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle) static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle)
{ {
RpcBinding *bind = (RpcBinding *)handle; RpcBinding *bind = handle;
const char * pszEndpoint = NULL; const char * pszEndpoint = NULL;
RPC_STATUS status; RPC_STATUS status;
RpcBinding* epm_bind; RpcBinding* epm_bind;
@ -149,7 +149,7 @@ static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_H
status = RpcBindingCopy(handle, epm_handle); status = RpcBindingCopy(handle, epm_handle);
if (status != RPC_S_OK) return status; if (status != RPC_S_OK) return status;
epm_bind = (RpcBinding*)*epm_handle; epm_bind = *epm_handle;
if (epm_bind->AuthInfo) if (epm_bind->AuthInfo)
{ {
/* don't bother with authenticating against the EPM by default /* don't bother with authenticating against the EPM by default
@ -187,8 +187,8 @@ static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) UUID_VECTOR *UuidVector, RPC_CSTR Annotation )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
unsigned long i; ULONG i;
RPC_STATUS status = RPC_S_OK; RPC_STATUS status = RPC_S_OK;
error_status_t status2; error_status_t status2;
ept_entry_t *entries; ept_entry_t *entries;
@ -197,13 +197,13 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation));
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) { for (i=0; i<BindingVector->Count; i++) {
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
} }
if (UuidVector) { if (UuidVector) {
for (i=0; i<UuidVector->Count; i++) for (i=0; i<UuidVector->Count; i++)
TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
} }
if (!BindingVector->Count) return RPC_S_OK; if (!BindingVector->Count) return RPC_S_OK;
@ -222,10 +222,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
for (i = 0; i < BindingVector->Count; i++) for (i = 0; i < BindingVector->Count; i++)
{ {
unsigned j; unsigned j;
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{ {
int len = strlen((char *)Annotation);
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
bind->Protseq, bind->Endpoint, bind->Protseq, bind->Endpoint,
bind->NetworkAddr, bind->NetworkAddr,
@ -236,7 +235,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID)); memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID));
else else
memset(&entries[i].object, 0, sizeof(entries[i].object)); memset(&entries[i].object, 0, sizeof(entries[i].object));
memcpy(entries[i].annotation, Annotation, min(len + 1, ept_max_annotation_size)); if (Annotation)
memcpy(entries[i].annotation, Annotation,
min(strlen((char *)Annotation) + 1, ept_max_annotation_size));
} }
} }
@ -280,14 +281,29 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
return status; return status;
} }
/***********************************************************************
* RpcEpRegisterW (RPCRT4.@)
*/
RPC_STATUS WINAPI RpcEpRegisterW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector, RPC_WSTR Annotation )
{
LPSTR annA = RPCRT4_strdupWtoA(Annotation);
RPC_STATUS status;
status = RpcEpRegisterA(IfSpec, BindingVector, UuidVector, (RPC_CSTR)annA);
HeapFree(GetProcessHeap(), 0, annA);
return status;
}
/*********************************************************************** /***********************************************************************
* RpcEpUnregister (RPCRT4.@) * RpcEpUnregister (RPCRT4.@)
*/ */
RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector ) UUID_VECTOR *UuidVector )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
unsigned long i; ULONG i;
RPC_STATUS status = RPC_S_OK; RPC_STATUS status = RPC_S_OK;
error_status_t status2; error_status_t status2;
ept_entry_t *entries; ept_entry_t *entries;
@ -296,13 +312,13 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) { for (i=0; i<BindingVector->Count; i++) {
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
} }
if (UuidVector) { if (UuidVector) {
for (i=0; i<UuidVector->Count; i++) for (i=0; i<UuidVector->Count; i++)
TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
} }
entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1));
@ -319,7 +335,7 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
for (i = 0; i < BindingVector->Count; i++) for (i = 0; i < BindingVector->Count; i++)
{ {
unsigned j; unsigned j;
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{ {
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
@ -372,8 +388,8 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
*/ */
RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
{ {
PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; PRPC_CLIENT_INTERFACE If = IfSpec;
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
RPC_STATUS status; RPC_STATUS status;
error_status_t status2; error_status_t status2;
handle_t handle; handle_t handle;

File diff suppressed because it is too large Load diff

View file

@ -25,16 +25,36 @@
typedef unsigned int NCA_STATUS; typedef unsigned int NCA_STATUS;
RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status); RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status);
RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength); RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength);
RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId); RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId);
RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor); RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor, unsigned short RejectReason);
RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, const RPC_SYNTAX_IDENTIFIER *TransferId); RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG AssocGroupId, LPCSTR ServerAddress, unsigned char ResultCount, const RpcResult *Results);
RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, unsigned short flags, unsigned short num_data_items, unsigned int payload_size);
RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe, const UUID *connection_uuid, const UUID *pipe_uuid, const UUID *association_uuid);
RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, ULONG flow_control_increment, const UUID *pipe_uuid);
VOID RPCRT4_FreeHeader(RpcPktHdr *Header); VOID RPCRT4_FreeHeader(RpcPktHdr *Header);
RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength); RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength);
RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength, const void *Auth, unsigned int AuthLength);
RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg); RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg);
RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, unsigned long *auth_length_out); RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, ULONG *auth_length_out);
DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header);
RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr);
BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, unsigned short data_len);
RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, unsigned char *data, ULONG *field1);
RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, unsigned char *data, ULONG *field1, ULONG *bytes_until_next_packet, ULONG *field3);
RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, unsigned char *data, BOOL server, ULONG *bytes_transmitted, ULONG *flow_control_increment, UUID *pipe_uuid);
NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status); NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status);
RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, ULONG count);
RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, BOOL start, RpcAuthVerifier *auth_data_in, ULONG auth_length_in, unsigned char **auth_data_out, ULONG *auth_length_out);
RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count); RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count);
RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token);
RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_size, unsigned char *out_buffer, unsigned int *out_size);
BOOL RPCRT4_default_is_authorized(RpcConnection *Connection);
RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, unsigned char *auth_value, unsigned int auth_value_size);
RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn);
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn);
RPC_STATUS RPCRT4_default_inquire_auth_client(RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags);
#endif #endif

View file

@ -52,6 +52,8 @@ typedef struct _RpcPacket
struct _RpcConnection* conn; struct _RpcConnection* conn;
RpcPktHdr* hdr; RpcPktHdr* hdr;
RPC_MESSAGE* msg; RPC_MESSAGE* msg;
unsigned char *auth_data;
ULONG auth_length;
} RpcPacket; } RpcPacket;
typedef struct _RpcObjTypeMap typedef struct _RpcObjTypeMap
@ -67,6 +69,7 @@ static RpcObjTypeMap *RpcObjTypeMaps;
/* list of type RpcServerProtseq */ /* list of type RpcServerProtseq */
static struct list protseqs = LIST_INIT(protseqs); static struct list protseqs = LIST_INIT(protseqs);
static struct list server_interfaces = LIST_INIT(server_interfaces); static struct list server_interfaces = LIST_INIT(server_interfaces);
static struct list server_registered_auth_info = LIST_INIT(server_registered_auth_info);
static CRITICAL_SECTION server_cs; static CRITICAL_SECTION server_cs;
static CRITICAL_SECTION_DEBUG server_cs_debug = static CRITICAL_SECTION_DEBUG server_cs_debug =
@ -86,6 +89,15 @@ static CRITICAL_SECTION_DEBUG listen_cs_debug =
}; };
static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 };
static CRITICAL_SECTION server_auth_info_cs;
static CRITICAL_SECTION_DEBUG server_auth_info_cs_debug =
{
0, 0, &server_auth_info_cs,
{ &server_auth_info_cs_debug.ProcessLocksList, &server_auth_info_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": server_auth_info_cs") }
};
static CRITICAL_SECTION server_auth_info_cs = { &server_auth_info_cs_debug, -1, 0, 0, 0, 0 };
/* whether the server is currently listening */ /* whether the server is currently listening */
static BOOL std_listen; static BOOL std_listen;
/* number of manual listeners (calls to RpcServerListen) */ /* number of manual listeners (calls to RpcServerListen) */
@ -118,7 +130,8 @@ static inline UUID *LookupObjType(UUID *ObjUuid)
} }
static RpcServerInterface* RPCRT4_find_interface(UUID* object, static RpcServerInterface* RPCRT4_find_interface(UUID* object,
const RPC_SYNTAX_IDENTIFIER* if_id, const RPC_SYNTAX_IDENTIFIER *if_id,
const RPC_SYNTAX_IDENTIFIER *transfer_syntax,
BOOL check_object) BOOL check_object)
{ {
UUID* MgrType = NULL; UUID* MgrType = NULL;
@ -130,6 +143,7 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object,
EnterCriticalSection(&server_cs); EnterCriticalSection(&server_cs);
LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&
(!transfer_syntax || !memcmp(transfer_syntax, &cif->If->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER))) &&
(check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) && (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) &&
std_listen) { std_listen) {
InterlockedIncrement(&cif->CurrentCalls); InterlockedIncrement(&cif->CurrentCalls);
@ -156,64 +170,197 @@ static void RPCRT4_release_server_interface(RpcServerInterface *sif)
} }
} }
static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg) static RpcPktHdr *handle_bind_error(RpcConnection *conn, RPC_STATUS error)
{
unsigned int reject_reason;
switch (error)
{
case RPC_S_SERVER_TOO_BUSY:
reject_reason = REJECT_TEMPORARY_CONGESTION;
break;
case ERROR_OUTOFMEMORY:
case RPC_S_OUT_OF_RESOURCES:
reject_reason = REJECT_LOCAL_LIMIT_EXCEEDED;
break;
case RPC_S_PROTOCOL_ERROR:
reject_reason = REJECT_PROTOCOL_VERSION_NOT_SUPPORTED;
break;
case RPC_S_UNKNOWN_AUTHN_SERVICE:
reject_reason = REJECT_UNKNOWN_AUTHN_SERVICE;
break;
case ERROR_ACCESS_DENIED:
reject_reason = REJECT_INVALID_CHECKSUM;
break;
default:
FIXME("unexpected status value %d\n", error);
/* fall through */
case RPC_S_INVALID_BOUND:
reject_reason = REJECT_REASON_NOT_SPECIFIED;
break;
}
return RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_VER_MAJOR, RPC_VER_MINOR,
reject_reason);
}
static RPC_STATUS process_bind_packet_no_send(
RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg,
unsigned char *auth_data, ULONG auth_length, RpcPktHdr **ack_response,
unsigned char **auth_data_out, ULONG *auth_length_out)
{ {
RPC_STATUS status; RPC_STATUS status;
RpcServerInterface* sif; RpcContextElement *ctxt_elem;
RpcPktHdr *response = NULL; unsigned int i;
RpcResult *results;
/* validate data */
for (i = 0, ctxt_elem = msg->Buffer;
i < hdr->num_elements;
i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
{
if (((char *)ctxt_elem - (char *)msg->Buffer) > msg->BufferLength ||
((char *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes] - (char *)msg->Buffer) > msg->BufferLength)
{
ERR("inconsistent data in packet - packet length %d, num elements %d\n",
msg->BufferLength, hdr->num_elements);
return RPC_S_INVALID_BOUND;
}
}
/* FIXME: do more checks! */
if (hdr->max_tsize < RPC_MIN_PACKET_SIZE || if (hdr->max_tsize < RPC_MIN_PACKET_SIZE ||
!UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
conn->server_binding) { conn->server_binding)
{
TRACE("packet size less than min size, or active interface syntax guid non-null\n"); TRACE("packet size less than min size, or active interface syntax guid non-null\n");
sif = NULL;
} else {
/* create temporary binding */
if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK &&
RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
conn->NetworkAddr, conn->Endpoint,
conn->NetworkOptions,
hdr->assoc_gid,
&conn->server_binding->Assoc) == RPC_S_OK)
sif = RPCRT4_find_interface(NULL, &hdr->abstract, FALSE);
else
sif = NULL;
}
if (sif == NULL) {
TRACE("rejecting bind request on connection %p\n", conn);
/* Report failure to client. */
response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_VER_MAJOR, RPC_VER_MINOR);
} else {
TRACE("accepting bind request on connection %p for %s\n", conn,
debugstr_guid(&hdr->abstract.SyntaxGUID));
/* accept. */ return RPC_S_INVALID_BOUND;
response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_MAX_PACKET_SIZE,
RPC_MAX_PACKET_SIZE,
conn->server_binding->Assoc->assoc_group_id,
conn->Endpoint,
RESULT_ACCEPT, REASON_NONE,
&sif->If->TransferSyntax);
/* save the interface for later use */
conn->ActiveInterface = hdr->abstract;
conn->MaxTransmissionSize = hdr->max_tsize;
RPCRT4_release_server_interface(sif);
} }
if (response) results = HeapAlloc(GetProcessHeap(), 0,
status = RPCRT4_Send(conn, response, NULL, 0); hdr->num_elements * sizeof(*results));
if (!results)
return RPC_S_OUT_OF_RESOURCES;
for (i = 0, ctxt_elem = (RpcContextElement *)msg->Buffer;
i < hdr->num_elements;
i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
{
RpcServerInterface* sif = NULL;
unsigned int j;
for (j = 0; !sif && j < ctxt_elem->num_syntaxes; j++)
{
sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
&ctxt_elem->transfer_syntaxes[j], FALSE);
if (sif)
break;
}
if (sif)
{
RPCRT4_release_server_interface(sif);
TRACE("accepting bind request on connection %p for %s\n", conn,
debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
results[i].result = RESULT_ACCEPT;
results[i].reason = REASON_NONE;
results[i].transfer_syntax = ctxt_elem->transfer_syntaxes[j];
/* save the interface for later use */
/* FIXME: save linked list */
conn->ActiveInterface = ctxt_elem->abstract_syntax;
}
else if ((sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
NULL, FALSE)) != NULL)
{
RPCRT4_release_server_interface(sif);
TRACE("not accepting bind request on connection %p for %s - no transfer syntaxes supported\n",
conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
results[i].result = RESULT_PROVIDER_REJECTION;
results[i].reason = REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
}
else
{
TRACE("not accepting bind request on connection %p for %s - abstract syntax not supported\n",
conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
results[i].result = RESULT_PROVIDER_REJECTION;
results[i].reason = REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
}
}
/* create temporary binding */
status = RPCRT4_MakeBinding(&conn->server_binding, conn);
if (status != RPC_S_OK)
{
HeapFree(GetProcessHeap(), 0, results);
return status;
}
status = RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
conn->NetworkAddr, conn->Endpoint,
conn->NetworkOptions,
hdr->assoc_gid,
&conn->server_binding->Assoc);
if (status != RPC_S_OK)
{
HeapFree(GetProcessHeap(), 0, results);
return status;
}
if (auth_length)
{
status = RPCRT4_ServerConnectionAuth(conn, TRUE,
(RpcAuthVerifier *)auth_data,
auth_length, auth_data_out,
auth_length_out);
if (status != RPC_S_OK)
{
HeapFree(GetProcessHeap(), 0, results);
return status;
}
}
*ack_response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_MAX_PACKET_SIZE,
RPC_MAX_PACKET_SIZE,
conn->server_binding->Assoc->assoc_group_id,
conn->Endpoint, hdr->num_elements,
results);
HeapFree(GetProcessHeap(), 0, results);
if (*ack_response)
conn->MaxTransmissionSize = hdr->max_tsize;
else else
status = ERROR_OUTOFMEMORY; status = RPC_S_OUT_OF_RESOURCES;
RPCRT4_FreeHeader(response);
return status; return status;
} }
static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr,
RPC_MESSAGE *msg,
unsigned char *auth_data,
ULONG auth_length)
{
RPC_STATUS status;
RpcPktHdr *response = NULL;
unsigned char *auth_data_out = NULL;
ULONG auth_length_out = 0;
status = process_bind_packet_no_send(conn, hdr, msg, auth_data, auth_length,
&response, &auth_data_out,
&auth_length_out);
if (status != RPC_S_OK)
response = handle_bind_error(conn, status);
if (response)
status = RPCRT4_SendWithAuth(conn, response, NULL, 0, auth_data_out, auth_length_out);
else
status = ERROR_OUTOFMEMORY;
RPCRT4_FreeHeader(response);
return status;
}
static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg) static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg)
{ {
RPC_STATUS status; RPC_STATUS status;
@ -242,7 +389,7 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *
object_uuid = NULL; object_uuid = NULL;
} }
sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE); sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE);
if (!sif) { if (!sif) {
WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID)); WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID));
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
@ -327,7 +474,34 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *
return status; return status;
} }
static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg) static RPC_STATUS process_auth3_packet(RpcConnection *conn,
RpcPktCommonHdr *hdr,
RPC_MESSAGE *msg,
unsigned char *auth_data,
ULONG auth_length)
{
RPC_STATUS status;
if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
!auth_length || msg->BufferLength != 0)
status = RPC_S_PROTOCOL_ERROR;
else
{
status = RPCRT4_ServerConnectionAuth(conn, FALSE,
(RpcAuthVerifier *)auth_data,
auth_length, NULL, NULL);
}
/* FIXME: client doesn't expect a response to this message so must store
* status in connection so that fault packet can be returned when next
* packet is received */
return RPC_S_OK;
}
static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr,
RPC_MESSAGE* msg, unsigned char *auth_data,
ULONG auth_length)
{ {
RPC_STATUS status; RPC_STATUS status;
@ -337,7 +511,8 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
case PKT_BIND: case PKT_BIND:
TRACE("got bind packet\n"); TRACE("got bind packet\n");
status = process_bind_packet(conn, &hdr->bind, msg); status = process_bind_packet(conn, &hdr->bind, msg, auth_data,
auth_length);
break; break;
case PKT_REQUEST: case PKT_REQUEST:
@ -346,6 +521,12 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
status = process_request_packet(conn, &hdr->request, msg); status = process_request_packet(conn, &hdr->request, msg);
break; break;
case PKT_AUTH3:
TRACE("got auth3 packet\n");
status = process_auth3_packet(conn, &hdr->common, msg, auth_data,
auth_length);
break;
default: default:
FIXME("unhandled packet type %u\n", hdr->common.ptype); FIXME("unhandled packet type %u\n", hdr->common.ptype);
break; break;
@ -355,57 +536,96 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
I_RpcFree(msg->Buffer); I_RpcFree(msg->Buffer);
RPCRT4_FreeHeader(hdr); RPCRT4_FreeHeader(hdr);
HeapFree(GetProcessHeap(), 0, msg); HeapFree(GetProcessHeap(), 0, msg);
HeapFree(GetProcessHeap(), 0, auth_data);
} }
static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
{ {
RpcPacket *pkt = the_arg; RpcPacket *pkt = the_arg;
RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg); RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data,
pkt->auth_length);
HeapFree(GetProcessHeap(), 0, pkt); HeapFree(GetProcessHeap(), 0, pkt);
return 0; return 0;
} }
static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
{ {
RpcConnection* conn = (RpcConnection*)the_arg; RpcConnection* conn = the_arg;
RpcPktHdr *hdr; RpcPktHdr *hdr;
RPC_MESSAGE *msg; RPC_MESSAGE *msg;
RPC_STATUS status; RPC_STATUS status;
RpcPacket *packet; RpcPacket *packet;
unsigned char *auth_data;
ULONG auth_length;
TRACE("(%p)\n", conn); TRACE("(%p)\n", conn);
for (;;) { for (;;) {
msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE));
if (!msg) break;
status = RPCRT4_Receive(conn, &hdr, msg); status = RPCRT4_ReceiveWithAuth(conn, &hdr, msg, &auth_data, &auth_length);
if (status != RPC_S_OK) { if (status != RPC_S_OK) {
WARN("receive failed with error %x\n", status); WARN("receive failed with error %x\n", status);
HeapFree(GetProcessHeap(), 0, msg); HeapFree(GetProcessHeap(), 0, msg);
break; break;
} }
packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); switch (hdr->common.ptype) {
if (!packet) { case PKT_BIND:
I_RpcFree(msg->Buffer); TRACE("got bind packet\n");
RPCRT4_FreeHeader(hdr);
HeapFree(GetProcessHeap(), 0, msg); status = process_bind_packet(conn, &hdr->bind, msg, auth_data,
auth_length);
break; break;
}
packet->conn = conn; case PKT_REQUEST:
packet->hdr = hdr; TRACE("got request packet\n");
packet->msg = msg;
if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); if (!packet) {
I_RpcFree(msg->Buffer); I_RpcFree(msg->Buffer);
RPCRT4_FreeHeader(hdr); RPCRT4_FreeHeader(hdr);
HeapFree(GetProcessHeap(), 0, msg); HeapFree(GetProcessHeap(), 0, msg);
HeapFree(GetProcessHeap(), 0, packet); HeapFree(GetProcessHeap(), 0, auth_data);
goto exit;
}
packet->conn = conn;
packet->hdr = hdr;
packet->msg = msg;
packet->auth_data = auth_data;
packet->auth_length = auth_length;
if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) {
ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError());
HeapFree(GetProcessHeap(), 0, packet);
status = RPC_S_OUT_OF_RESOURCES;
} else {
continue;
}
break;
case PKT_AUTH3:
TRACE("got auth3 packet\n");
status = process_auth3_packet(conn, &hdr->common, msg, auth_data,
auth_length);
break;
default:
FIXME("unhandled packet type %u\n", hdr->common.ptype);
break; break;
} }
msg = NULL; I_RpcFree(msg->Buffer);
RPCRT4_FreeHeader(hdr);
HeapFree(GetProcessHeap(), 0, msg);
HeapFree(GetProcessHeap(), 0, auth_data);
if (status != RPC_S_OK) {
WARN("processing packet failed with error %u\n", status);
break;
}
} }
exit:
RPCRT4_DestroyConnection(conn); RPCRT4_DestroyConnection(conn);
return 0; return 0;
} }
@ -449,27 +669,23 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
/* start waiting */ /* start waiting */
res = cps->ops->wait_for_new_connection(cps, count, objs); res = cps->ops->wait_for_new_connection(cps, count, objs);
if (res == -1)
break; if (res == -1 || (res == 0 && !std_listen))
else if (res == 0)
{ {
if (!std_listen) /* cleanup */
{ cps->ops->free_wait_array(cps, objs);
EnterCriticalSection(&cps->cs);
for (conn = cps->conn; conn; conn = conn->Next)
RPCRT4_CloseConnection(conn);
LeaveCriticalSection(&cps->cs);
if (res == 0 && !std_listen)
SetEvent(cps->server_ready_event); SetEvent(cps->server_ready_event);
break; break;
}
set_ready_event = TRUE;
} }
else if (res == 0)
set_ready_event = TRUE;
} }
cps->ops->free_wait_array(cps, objs);
EnterCriticalSection(&cps->cs);
/* close connections */
conn = cps->conn;
while (conn) {
RPCRT4_CloseConnection(conn);
conn = conn->Next;
}
LeaveCriticalSection(&cps->cs);
return 0; return 0;
} }
@ -570,11 +786,32 @@ static void RPCRT4_stop_listen(BOOL auto_listen)
LeaveCriticalSection(&listen_cs); LeaveCriticalSection(&listen_cs);
} }
static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint) static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint)
{
RpcConnection *conn;
EnterCriticalSection(&protseq->cs);
for (conn = protseq->conn; conn; conn = conn->Next)
{
if (!endpoint || !strcmp(endpoint, conn->Endpoint))
break;
}
LeaveCriticalSection(&protseq->cs);
return (conn != NULL);
}
static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint)
{ {
RPC_STATUS status; RPC_STATUS status;
status = ps->ops->open_endpoint(ps, endpoint); EnterCriticalSection(&ps->cs);
if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint))
status = RPC_S_OK;
else
status = ps->ops->open_endpoint(ps, endpoint);
LeaveCriticalSection(&ps->cs);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
@ -608,11 +845,8 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
count = 0; count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs); EnterCriticalSection(&ps->cs);
conn = ps->conn; for (conn = ps->conn; conn; conn = conn->Next)
while (conn) {
count++; count++;
conn = conn->Next;
}
LeaveCriticalSection(&ps->cs); LeaveCriticalSection(&ps->cs);
} }
if (count) { if (count) {
@ -624,12 +858,10 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
count = 0; count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs); EnterCriticalSection(&ps->cs);
conn = ps->conn; for (conn = ps->conn; conn; conn = conn->Next) {
while (conn) {
RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
conn); conn);
count++; count++;
conn = conn->Next;
} }
LeaveCriticalSection(&ps->cs); LeaveCriticalSection(&ps->cs);
} }
@ -681,7 +913,7 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_W
* *
* Must be called with server_cs held. * Must be called with server_cs held.
*/ */
static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
{ {
const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
@ -695,7 +927,7 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr
if (!*ps) if (!*ps)
return RPC_S_OUT_OF_RESOURCES; return RPC_S_OUT_OF_RESOURCES;
(*ps)->MaxCalls = MaxCalls; (*ps)->MaxCalls = MaxCalls;
(*ps)->Protseq = Protseq; (*ps)->Protseq = RPCRT4_strdupA(Protseq);
(*ps)->ops = ops; (*ps)->ops = ops;
(*ps)->MaxCalls = 0; (*ps)->MaxCalls = 0;
(*ps)->conn = NULL; (*ps)->conn = NULL;
@ -711,8 +943,19 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr
return RPC_S_OK; return RPC_S_OK;
} }
/* must be called with server_cs held */
static void destroy_serverprotoseq(RpcServerProtseq *ps)
{
RPCRT4_strfree(ps->Protseq);
DeleteCriticalSection(&ps->cs);
CloseHandle(ps->mgr_mutex);
CloseHandle(ps->server_ready_event);
list_remove(&ps->entry);
HeapFree(GetProcessHeap(), 0, ps);
}
/* Finds a given protseq or creates a new one if one doesn't already exist */ /* Finds a given protseq or creates a new one if one doesn't already exist */
static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
{ {
RPC_STATUS status; RPC_STATUS status;
RpcServerProtseq *cps; RpcServerProtseq *cps;
@ -741,19 +984,18 @@ static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protse
RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor, RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor,
PRPC_POLICY lpPolicy ) PRPC_POLICY lpPolicy )
{ {
char *szps = (char*)Protseq, *szep = (char*)Endpoint;
RpcServerProtseq* ps; RpcServerProtseq* ps;
RPC_STATUS status; RPC_STATUS status;
TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a(szps), MaxCalls, TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq),
debugstr_a(szep), SecurityDescriptor, MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
return RPCRT4_use_protseq(ps, szep); return RPCRT4_use_protseq(ps, (const char *)Endpoint);
} }
/*********************************************************************** /***********************************************************************
@ -764,13 +1006,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC
{ {
RpcServerProtseq* ps; RpcServerProtseq* ps;
RPC_STATUS status; RPC_STATUS status;
LPSTR ProtseqA;
LPSTR EndpointA; LPSTR EndpointA;
TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls, TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls,
debugstr_w( Endpoint ), SecurityDescriptor, debugstr_w( Endpoint ), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupWtoA(Protseq), &ps); ProtseqA = RPCRT4_strdupWtoA(Protseq);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
RPCRT4_strfree(ProtseqA);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
@ -785,8 +1030,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC
*/ */
RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
{ {
RPC_STATUS status;
RpcServerProtseq* ps;
TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor);
return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
if (status != RPC_S_OK)
return status;
return RPCRT4_use_protseq(ps, NULL);
} }
/*********************************************************************** /***********************************************************************
@ -794,8 +1047,36 @@ RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls,
*/ */
RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
{ {
RPC_STATUS status;
RpcServerProtseq* ps;
LPSTR ProtseqA;
TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
ProtseqA = RPCRT4_strdupWtoA(Protseq);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
RPCRT4_strfree(ProtseqA);
if (status != RPC_S_OK)
return status;
return RPCRT4_use_protseq(ps, NULL);
}
void RPCRT4_destroy_all_protseqs(void)
{
RpcServerProtseq *cps, *cursor2;
if (listen_count != 0)
std_listen = FALSE;
EnterCriticalSection(&server_cs);
LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry)
{
if (listen_count != 0)
RPCRT4_sync_with_server_thread(cps);
destroy_serverprotoseq(cps);
}
LeaveCriticalSection(&server_cs);
} }
/*********************************************************************** /***********************************************************************
@ -823,7 +1104,7 @@ RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid
RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn ) UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
RpcServerInterface* sif; RpcServerInterface* sif;
unsigned int i; unsigned int i;
@ -876,7 +1157,7 @@ RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid,
*/ */
RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
HANDLE event = NULL; HANDLE event = NULL;
BOOL found = FALSE; BOOL found = FALSE;
BOOL completed = TRUE; BOOL completed = TRUE;
@ -996,15 +1277,114 @@ RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid )
return RPC_S_OK; return RPC_S_OK;
} }
struct rpc_server_registered_auth_info
{
struct list entry;
TimeStamp exp;
CredHandle cred;
ULONG max_token;
USHORT auth_type;
};
RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(
USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token)
{
RPC_STATUS status = RPC_S_UNKNOWN_AUTHN_SERVICE;
struct rpc_server_registered_auth_info *auth_info;
EnterCriticalSection(&server_auth_info_cs);
LIST_FOR_EACH_ENTRY(auth_info, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry)
{
if (auth_info->auth_type == auth_type)
{
*cred = auth_info->cred;
*exp = auth_info->exp;
*max_token = auth_info->max_token;
status = RPC_S_OK;
break;
}
}
LeaveCriticalSection(&server_auth_info_cs);
return status;
}
void RPCRT4_ServerFreeAllRegisteredAuthInfo(void)
{
struct rpc_server_registered_auth_info *auth_info, *cursor2;
EnterCriticalSection(&server_auth_info_cs);
LIST_FOR_EACH_ENTRY_SAFE(auth_info, cursor2, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry)
{
FreeCredentialsHandle(&auth_info->cred);
HeapFree(GetProcessHeap(), 0, auth_info);
}
LeaveCriticalSection(&server_auth_info_cs);
}
/*********************************************************************** /***********************************************************************
* RpcServerRegisterAuthInfoA (RPCRT4.@) * RpcServerRegisterAuthInfoA (RPCRT4.@)
*/ */
RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
LPVOID Arg ) LPVOID Arg )
{ {
FIXME( "(%s,%u,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg ); SECURITY_STATUS sec_status;
CredHandle cred;
return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ TimeStamp exp;
ULONG package_count;
ULONG i;
PSecPkgInfoA packages;
ULONG max_token;
struct rpc_server_registered_auth_info *auth_info;
TRACE("(%s,%u,%p,%p)\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg);
sec_status = EnumerateSecurityPackagesA(&package_count, &packages);
if (sec_status != SEC_E_OK)
{
ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n",
sec_status);
return RPC_S_SEC_PKG_ERROR;
}
for (i = 0; i < package_count; i++)
if (packages[i].wRPCID == AuthnSvc)
break;
if (i == package_count)
{
WARN("unsupported AuthnSvc %u\n", AuthnSvc);
FreeContextBuffer(packages);
return RPC_S_UNKNOWN_AUTHN_SERVICE;
}
TRACE("found package %s for service %u\n", packages[i].Name,
AuthnSvc);
sec_status = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName,
packages[i].Name,
SECPKG_CRED_INBOUND, NULL, NULL,
NULL, NULL, &cred, &exp);
max_token = packages[i].cbMaxToken;
FreeContextBuffer(packages);
if (sec_status != SEC_E_OK)
return RPC_S_SEC_PKG_ERROR;
auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info));
if (!auth_info)
{
FreeCredentialsHandle(&cred);
return RPC_S_OUT_OF_RESOURCES;
}
auth_info->exp = exp;
auth_info->cred = cred;
auth_info->max_token = max_token;
auth_info->auth_type = AuthnSvc;
EnterCriticalSection(&server_auth_info_cs);
list_add_tail(&server_registered_auth_info, &auth_info->entry);
LeaveCriticalSection(&server_auth_info_cs);
return RPC_S_OK;
} }
/*********************************************************************** /***********************************************************************
@ -1013,9 +1393,63 @@ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG Au
RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
LPVOID Arg ) LPVOID Arg )
{ {
FIXME( "(%s,%u,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg ); SECURITY_STATUS sec_status;
CredHandle cred;
return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ TimeStamp exp;
ULONG package_count;
ULONG i;
PSecPkgInfoW packages;
ULONG max_token;
struct rpc_server_registered_auth_info *auth_info;
TRACE("(%s,%u,%p,%p)\n", debugstr_w(ServerPrincName), AuthnSvc, GetKeyFn, Arg);
sec_status = EnumerateSecurityPackagesW(&package_count, &packages);
if (sec_status != SEC_E_OK)
{
ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n",
sec_status);
return RPC_S_SEC_PKG_ERROR;
}
for (i = 0; i < package_count; i++)
if (packages[i].wRPCID == AuthnSvc)
break;
if (i == package_count)
{
WARN("unsupported AuthnSvc %u\n", AuthnSvc);
FreeContextBuffer(packages);
return RPC_S_UNKNOWN_AUTHN_SERVICE;
}
TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name),
AuthnSvc);
sec_status = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName,
packages[i].Name,
SECPKG_CRED_INBOUND, NULL, NULL,
NULL, NULL, &cred, &exp);
max_token = packages[i].cbMaxToken;
FreeContextBuffer(packages);
if (sec_status != SEC_E_OK)
return RPC_S_SEC_PKG_ERROR;
auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info));
if (!auth_info)
{
FreeCredentialsHandle(&cred);
return RPC_S_OUT_OF_RESOURCES;
}
auth_info->exp = exp;
auth_info->cred = cred;
auth_info->max_token = max_token;
auth_info->auth_type = AuthnSvc;
EnterCriticalSection(&server_auth_info_cs);
list_add_tail(&server_registered_auth_info, &auth_info->entry);
LeaveCriticalSection(&server_auth_info_cs);
return RPC_S_OK;
} }
/*********************************************************************** /***********************************************************************

View file

@ -56,7 +56,7 @@ struct protseq_ops
* new connection was established */ * new connection was established */
int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array); int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array);
/* opens the endpoint and optionally begins listening */ /* opens the endpoint and optionally begins listening */
RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, LPSTR endpoint); RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, const char *endpoint);
}; };
typedef struct _RpcServerInterface typedef struct _RpcServerInterface
@ -79,4 +79,7 @@ typedef struct _RpcServerInterface
void RPCRT4_new_client(RpcConnection* conn); void RPCRT4_new_client(RpcConnection* conn);
const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq); const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq);
void RPCRT4_destroy_all_protseqs(void);
void RPCRT4_ServerFreeAllRegisteredAuthInfo(void);
#endif /* __WINE_RPC_SERVER_H */ #endif /* __WINE_RPC_SERVER_H */

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) @ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr)
@ stub CreateStubFromTypeInfo @ stdcall CreateStubFromTypeInfo(ptr ptr ptr ptr)
@ stdcall CStdStubBuffer_AddRef(ptr) @ stdcall CStdStubBuffer_AddRef(ptr)
@ stdcall CStdStubBuffer_Connect(ptr ptr) @ stdcall CStdStubBuffer_Connect(ptr ptr)
@ stdcall CStdStubBuffer_CountRefs(ptr) @ stdcall CStdStubBuffer_CountRefs(ptr)
@ -116,8 +116,9 @@
@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) @ stdcall NDRSContextUnmarshallEx(ptr ptr ptr)
@ stub NDRcopy @ stub NDRcopy
@ stdcall NdrAllocate(ptr long) @ stdcall NdrAllocate(ptr long)
@ stub NdrAsyncClientCall @ varargs NdrAsyncClientCall(ptr ptr)
@ stub NdrAsyncServerCall @ stub NdrAsyncServerCall
@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr)
@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) @ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr)
@ stdcall NdrByteCountPointerFree(ptr ptr ptr) @ stdcall NdrByteCountPointerFree(ptr ptr ptr)
@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) @ stdcall NdrByteCountPointerMarshall(ptr ptr ptr)
@ -340,10 +341,10 @@
@ stdcall RpcBindingFree(ptr) @ stdcall RpcBindingFree(ptr)
@ stdcall RpcBindingFromStringBindingA(str ptr) @ stdcall RpcBindingFromStringBindingA(str ptr)
@ stdcall RpcBindingFromStringBindingW(wstr ptr) @ stdcall RpcBindingFromStringBindingW(wstr ptr)
@ stub RpcBindingInqAuthClientA @ stdcall RpcBindingInqAuthClientA(ptr ptr ptr ptr ptr ptr)
@ stub RpcBindingInqAuthClientExA @ stdcall RpcBindingInqAuthClientExA(ptr ptr ptr ptr ptr ptr long)
@ stub RpcBindingInqAuthClientExW @ stdcall RpcBindingInqAuthClientExW(ptr ptr ptr ptr ptr ptr long)
@ stub RpcBindingInqAuthClientW @ stdcall RpcBindingInqAuthClientW(ptr ptr ptr ptr ptr ptr)
@ stdcall RpcBindingInqAuthInfoA(ptr ptr ptr ptr ptr ptr) @ stdcall RpcBindingInqAuthInfoA(ptr ptr ptr ptr ptr ptr)
@ stdcall RpcBindingInqAuthInfoExA(ptr ptr ptr ptr ptr ptr long ptr) @ stdcall RpcBindingInqAuthInfoExA(ptr ptr ptr ptr ptr ptr long ptr)
@ stdcall RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr) @ stdcall RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr)
@ -370,7 +371,7 @@
@ stdcall RpcEpRegisterA(ptr ptr ptr str) @ stdcall RpcEpRegisterA(ptr ptr ptr str)
@ stub RpcEpRegisterNoReplaceA @ stub RpcEpRegisterNoReplaceA
@ stub RpcEpRegisterNoReplaceW @ stub RpcEpRegisterNoReplaceW
@ stub RpcEpRegisterW @ stdcall RpcEpRegisterW(ptr ptr ptr wstr)
@ stdcall RpcEpResolveBinding(ptr ptr) @ stdcall RpcEpResolveBinding(ptr ptr)
@ stdcall RpcEpUnregister(ptr ptr ptr) @ stdcall RpcEpUnregister(ptr ptr ptr)
@ stub RpcErrorAddRecord # wxp @ stub RpcErrorAddRecord # wxp

View file

@ -42,7 +42,8 @@
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
#include "winnt.h" #include "winnt.h"
#include "winternl.h" #include "ntndk.h"
#include "ntsecapi.h"
#include "iptypes.h" #include "iptypes.h"
#include "iphlpapi.h" #include "iphlpapi.h"
#include "wine/unicode.h" #include "wine/unicode.h"
@ -53,6 +54,7 @@
#include "rpcproxy.h" #include "rpcproxy.h"
#include "rpc_binding.h" #include "rpc_binding.h"
#include "rpc_server.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -135,6 +137,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
RPCRT4_destroy_all_protseqs();
RPCRT4_ServerFreeAllRegisteredAuthInfo();
break; break;
} }
@ -280,6 +284,38 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
return RPC_S_OK; return RPC_S_OK;
} }
/*************************************************************************
* UuidCreate [RPCRT4.@]
*
* Creates a 128bit UUID.
*
* RETURNS
*
* RPC_S_OK if successful.
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
*
* NOTES
*
* Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
* Truly Random or Pseudo-Random Numbers)
*/
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
{
RtlGenRandom(Uuid, sizeof(*Uuid));
/* Clear the version bits and set the version (4) */
Uuid->Data3 &= 0x0fff;
Uuid->Data3 |= (4 << 12);
/* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
* specified in RFC 4122, section 4.4.
*/
Uuid->Data4[0] &= 0x3f;
Uuid->Data4[0] |= 0x80;
TRACE("%s\n", debugstr_guid(Uuid));
return RPC_S_OK;
}
/* Number of 100ns ticks per clock tick. To be safe, assume that the clock /* Number of 100ns ticks per clock tick. To be safe, assume that the clock
resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
#define TICKS_PER_CLOCK_TICK 1000 #define TICKS_PER_CLOCK_TICK 1000
@ -299,7 +335,7 @@ static void RPC_UuidGetSystemTime(ULONGLONG *time)
*time += TICKS_15_OCT_1582_TO_1601; *time += TICKS_15_OCT_1582_TO_1601;
} }
/* Assume that a hardware address is at least 6 bytes long */ /* Assume that a hardware address is at least 6 bytes long */
#define ADDRESS_BYTES_NEEDED 6 #define ADDRESS_BYTES_NEEDED 6
static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
@ -323,10 +359,7 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
/* We can't get a hardware address, just use random numbers. /* We can't get a hardware address, just use random numbers.
Set the multicast bit to prevent conflicts with real cards. */ Set the multicast bit to prevent conflicts with real cards. */
else { else {
for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { RtlGenRandom(address, ADDRESS_BYTES_NEEDED);
address[i] = rand() & 0xff;
}
address[0] |= 0x01; address[0] |= 0x01;
status = RPC_S_UUID_LOCAL_ONLY; status = RPC_S_UUID_LOCAL_ONLY;
} }
@ -336,7 +369,7 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
} }
/************************************************************************* /*************************************************************************
* UuidCreate [RPCRT4.@] * UuidCreateSequential [RPCRT4.@]
* *
* Creates a 128bit UUID. * Creates a 128bit UUID.
* *
@ -346,12 +379,12 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
* *
* FIXME: No compensation for changes across reloading * FIXME: No compensation for changes across reloading
* this dll or across reboots (e.g. clock going * this dll or across reboots (e.g. clock going
* backwards and swapped network cards). The RFC * backwards and swapped network cards). The RFC
* suggests using NVRAM for storing persistent * suggests using NVRAM for storing persistent
* values. * values.
*/ */
RPC_STATUS WINAPI UuidCreate(UUID *Uuid) RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
{ {
static int initialised, count; static int initialised, count;
@ -399,7 +432,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
/* Pack the information into the UUID structure. */ /* Pack the information into the UUID structure. */
Uuid->Data1 = (unsigned long)(time & 0xffffffff); Uuid->Data1 = (ULONG)(time & 0xffffffff);
Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff);
Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff);
@ -409,13 +442,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Uuid->Data4[0] = sequence & 0xff; Uuid->Data4[0] = sequence & 0xff;
Uuid->Data4[1] = (sequence & 0x3f00) >> 8; Uuid->Data4[1] = (sequence & 0x3f00) >> 8;
Uuid->Data4[1] |= 0x80; Uuid->Data4[1] |= 0x80;
memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED);
Uuid->Data4[2] = address[0];
Uuid->Data4[3] = address[1];
Uuid->Data4[4] = address[2];
Uuid->Data4[5] = address[3];
Uuid->Data4[6] = address[4];
Uuid->Data4[7] = address[5];
LeaveCriticalSection(&uuid_cs); LeaveCriticalSection(&uuid_cs);
@ -424,22 +451,6 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
return status; return status;
} }
/*************************************************************************
* UuidCreateSequential [RPCRT4.@]
*
* Creates a 128bit UUID.
*
* RETURNS
*
* RPC_S_OK if successful.
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
*
*/
RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
{
return UuidCreate(Uuid);
}
/************************************************************************* /*************************************************************************
* UuidHash [RPCRT4.@] * UuidHash [RPCRT4.@]

View file

@ -2,150 +2,9 @@
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
#include "unix_func.h"
int
poll(struct pollfd *fds,
unsigned long nfds,
int timo)
{
TIMEVAL timeout, *toptr;
FD_SET ifds, ofds, efds, *ip, *op;
int i, rc, n = -1;
ip = op = NULL;
FD_ZERO(&ifds);
FD_ZERO(&ofds);
FD_ZERO(&efds);
for (i = 0; i < nfds; ++i)
{
fds[i].revents = 0;
if (fds[i].fd < 0)
continue;
if (fds[i].fd > n)
n = fds[i].fd;
if (fds[i].events & (POLLIN|POLLPRI))
{
ip = &ifds;
FD_SET(fds[i].fd, ip);
}
if (fds[i].events & POLLOUT)
{
op = &ofds;
FD_SET(fds[i].fd, op);
}
FD_SET(fds[i].fd, &efds);
}
if (timo < 0)
toptr = 0;
else
{
toptr = &timeout;
timeout.tv_sec = timo / 1000;
timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
}
rc = select(++n, ip, op, &efds, toptr);
if (rc <= 0)
return rc;
for (i = 0, n = 0; i < nfds; ++i)
{
if (fds[i].fd < 0) continue;
if (fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(i, &ifds))
fds[i].revents |= POLLIN;
if (fds[i].events & POLLOUT && FD_ISSET(i, &ofds))
fds[i].revents |= POLLOUT;
if (FD_ISSET(i, &efds))
fds[i].revents |= POLLHUP;
}
return rc;
}
int socketpair(int af,
int type,
int protocol,
SOCKET socks[2])
{
struct sockaddr_in addr;
SOCKET listener;
int e;
int addrlen = sizeof(addr);
DWORD flags = 0; //(make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
if (socks == 0)
{
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
socks[0] = socks[1] = INVALID_SOCKET;
if ((listener = socket(af, type, 0)) == INVALID_SOCKET)
return SOCKET_ERROR;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(0x7f000001);
addr.sin_port = 0;
e = bind(listener, (const struct sockaddr*) &addr, sizeof(addr));
if (e == SOCKET_ERROR)
{
e = WSAGetLastError();
closesocket(listener);
WSASetLastError(e);
return SOCKET_ERROR;
}
e = getsockname(listener, (struct sockaddr*) &addr, &addrlen);
if (e == SOCKET_ERROR)
{
e = WSAGetLastError();
closesocket(listener);
WSASetLastError(e);
return SOCKET_ERROR;
}
do
{
if (listen(listener, 1) == SOCKET_ERROR)
break;
if ((socks[0] = WSASocket(af, type, 0, NULL, 0, flags)) == INVALID_SOCKET)
break;
if (connect(socks[0], (const struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR)
break;
if ((socks[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET)
break;
closesocket(listener);
return 0;
} while (0);
e = WSAGetLastError();
closesocket(listener);
closesocket(socks[0]);
closesocket(socks[1]);
WSASetLastError(e);
return SOCKET_ERROR;
}
const char * const char *
WSAAPI
inet_ntop (int af, inet_ntop (int af,
const void *src, const void *src,
char *dst, char *dst,
@ -168,10 +27,3 @@ inet_ntop (int af,
return 0; return 0;
} }
int fcntl(int fd,
int cmd,
long arg)
{
// Stub
return 0;
}