From ba086d41dd7e3cfd31d64661baa83859adaf86df Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Thu, 8 Jul 2010 18:39:18 +0000 Subject: [PATCH] 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 --- reactos/dll/win32/rpcrt4/cproxy.c | 21 + reactos/dll/win32/rpcrt4/cpsf.c | 20 +- reactos/dll/win32/rpcrt4/cstub.c | 78 +- reactos/dll/win32/rpcrt4/ndr_marshall.c | 735 +++++--- reactos/dll/win32/rpcrt4/ndr_ole.c | 7 +- reactos/dll/win32/rpcrt4/ndr_stubless.c | 481 ++++- reactos/dll/win32/rpcrt4/ndr_stubless.h | 3 +- reactos/dll/win32/rpcrt4/rpc_assoc.c | 30 +- reactos/dll/win32/rpcrt4/rpc_assoc.h | 3 +- reactos/dll/win32/rpcrt4/rpc_async.c | 16 +- reactos/dll/win32/rpcrt4/rpc_binding.c | 223 ++- reactos/dll/win32/rpcrt4/rpc_binding.h | 57 + reactos/dll/win32/rpcrt4/rpc_defs.h | 121 +- reactos/dll/win32/rpcrt4/rpc_epmap.c | 62 +- reactos/dll/win32/rpcrt4/rpc_message.c | 813 ++++++-- reactos/dll/win32/rpcrt4/rpc_message.h | 32 +- reactos/dll/win32/rpcrt4/rpc_server.c | 658 +++++-- reactos/dll/win32/rpcrt4/rpc_server.h | 5 +- reactos/dll/win32/rpcrt4/rpc_transport.c | 2201 ++++++++++++++++++---- reactos/dll/win32/rpcrt4/rpcrt4.spec | 15 +- reactos/dll/win32/rpcrt4/rpcrt4_main.c | 79 +- reactos/dll/win32/rpcrt4/unix_func.c | 150 +- 22 files changed, 4517 insertions(+), 1293 deletions(-) diff --git a/reactos/dll/win32/rpcrt4/cproxy.c b/reactos/dll/win32/rpcrt4/cproxy.c index 9ce555f7146..59ec80d5fd3 100644 --- a/reactos/dll/win32/rpcrt4/cproxy.c +++ b/reactos/dll/win32/rpcrt4/cproxy.c @@ -483,3 +483,24 @@ CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid, } 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; +} diff --git a/reactos/dll/win32/rpcrt4/cpsf.c b/reactos/dll/win32/rpcrt4/cpsf.c index ac1eccf56fa..d2efa012581 100644 --- a/reactos/dll/win32/rpcrt4/cpsf.c +++ b/reactos/dll/win32/rpcrt4/cpsf.c @@ -240,7 +240,16 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, DWORD len; 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 */ while (*pProxyFileList) { @@ -297,8 +306,15 @@ HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll, static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0}; static const WCHAR interfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; WCHAR keyname[50]; + WCHAR clsid[39]; 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 */ while (*pProxyFileList) { @@ -318,7 +334,7 @@ HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll, /* unregister clsid */ strcpyW( keyname, clsidW ); - format_clsid( keyname + strlenW(keyname), pclsid ); + strcatW( keyname, clsid ); RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname); return S_OK; diff --git a/reactos/dll/win32/rpcrt4/cstub.c b/reactos/dll/win32/rpcrt4/cstub.c index 95ac1d89af2..74801f69b70 100644 --- a/reactos/dll/win32/rpcrt4/cstub.c +++ b/reactos/dll/win32/rpcrt4/cstub.c @@ -137,27 +137,54 @@ static ULONG WINAPI delegating_Release(IUnknown *pUnk) return 1; } -#if defined(__i386__) - /* The idea here is to replace the first param on the stack ie. This (which will point to cstdstubbuffer_delegating_t) with This->stub_buffer.pvServerObject and then jump to the relevant offset in This->stub_buffer.pvServerObject's vtbl. */ +#ifdef __i386__ + #include "pshpack1.h" typedef struct { - DWORD mov1; /* mov 0x4(%esp), %eax 8b 44 24 04 */ - WORD mov2; /* mov 0x10(%eax), %eax 8b 40 */ - BYTE sixteen; /* 10 */ - DWORD mov3; /* mov %eax, 0x4(%esp) 89 44 24 04 */ - WORD mov4; /* mov (%eax), %eax 8b 00 */ - WORD mov5; /* mov offset(%eax), %eax 8b 80 */ - DWORD offset; /* xx xx xx xx */ - WORD jmp; /* jmp *%eax ff e0 */ - BYTE pad[3]; /* lea 0x0(%esi), %esi 8d 76 00 */ + BYTE mov1[4]; /* mov 0x4(%esp),%eax 8b 44 24 04 */ + BYTE mov2[3]; /* mov 0x10(%eax),%eax 8b 40 10 */ + BYTE mov3[4]; /* mov %eax,0x4(%esp) 89 44 24 04 */ + BYTE mov4[2]; /* mov (%eax),%eax 8b 00 */ + BYTE mov5[2]; /* jmp *offset(%eax) ff a0 offset */ + DWORD offset; + BYTE pad[1]; /* nop 90 */ } vtbl_method_t; #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 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++) { - block[i].mov1 = 0x0424448b; - block[i].mov2 = 0x408b; - 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; + memcpy( &block[i], opcodes, sizeof(opcodes) ); + block[i].offset = (BLOCK_SIZE * num + i + 3) * sizeof(void *); } VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL ); prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); @@ -241,22 +259,6 @@ BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) 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) { IUnknownVtbl *ret; diff --git a/reactos/dll/win32/rpcrt4/ndr_marshall.c b/reactos/dll/win32/rpcrt4/ndr_marshall.c index 9946bd13d57..3ad55aa95b3 100644 --- a/reactos/dll/win32/rpcrt4/ndr_marshall.c +++ b/reactos/dll/win32/rpcrt4/ndr_marshall.c @@ -27,6 +27,7 @@ * - Checks for integer addition overflow in user marshall functions */ +#include #include #include #include @@ -91,17 +92,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); LITTLE_ENDIAN_UINT32_READ(pchar) #endif -/* _Align must be the desired alignment, - * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */ -#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1)) -#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) -#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) -#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) -#define ALIGN_POINTER_CLEAR(_Ptr, _Align) \ - do { \ - memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \ - ALIGN_POINTER(_Ptr, _Align); \ - } while(0) +static inline void align_length( ULONG *len, unsigned int align ) +{ + *len = (*len + align - 1) & ~(align - 1); +} + +static inline void align_pointer( unsigned char **ptr, unsigned int align ) +{ + ULONG_PTR mask = align - 1; + *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask); +} + +static inline void align_pointer_clear( unsigned char **ptr, unsigned int align ) +{ + ULONG_PTR mask = align - 1; + memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask ); + *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask); +} #define STD_OVERFLOW_CHECK(_Msg) do { \ TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \ @@ -133,6 +140,27 @@ static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STR static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); +static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer, + unsigned char fMustAlloc); +static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); + const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { 0, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, @@ -377,7 +405,7 @@ void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len) void *p; NDR_MEMORY_LIST *mem_list; - aligned_len = ALIGNED_LENGTH(len, 8); + aligned_len = (len + 7) & ~7; adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); /* check for overflow */ if (adjusted_len < len) @@ -414,7 +442,7 @@ static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); @@ -435,7 +463,7 @@ static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_S goto done; } - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); @@ -464,7 +492,7 @@ done: /* writes the conformance value to the buffer */ static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount); @@ -474,7 +502,7 @@ static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) /* writes the variance values to the buffer */ static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset); @@ -486,7 +514,7 @@ static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) /* requests buffer space for the conformance value */ static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 4; @@ -495,7 +523,7 @@ static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) /* requests buffer space for the variance values */ static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 8; @@ -638,14 +666,16 @@ finish_conf: static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - if (IsConformanceOrVariancePresent(pFormat)) - { if (pStubMsg->fHasNewCorrDesc) pFormat += 6; else pFormat += 4; - } - return pFormat; + return pFormat; +} + +static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + return SkipConformance( pStubMsg, pFormat ); } /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if @@ -1047,7 +1077,7 @@ static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, } if (attr & RPC_FC_P_DEREF) { - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*)); + align_length(&pStubMsg->MemorySize, sizeof(void*)); pStubMsg->MemorySize += sizeof(void*); TRACE("deref\n"); } @@ -1482,7 +1512,7 @@ unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, * the buffer, and shouldn't write any additional pointer data to the wire */ if (*pFormat != RPC_FC_RP) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } @@ -1524,7 +1554,7 @@ unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, * as that is used by embedded pointers which already handle the incrementing * the buffer, and shouldn't read any additional pointer data from the * buffer */ - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } @@ -1548,7 +1578,7 @@ void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, * length, and shouldn't write anything more to the wire */ if (*pFormat != RPC_FC_RP) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } @@ -1564,10 +1594,10 @@ ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *Buffer = pStubMsg->Buffer; if (*pFormat != RPC_FC_RP) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); safe_buffer_increment(pStubMsg, 4); } - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); return PointerMemorySize(pStubMsg, Buffer, pFormat); } @@ -1604,7 +1634,7 @@ void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* unsigned char FormatChar ) { #define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + align_pointer(&pStubMsg->Buffer, sizeof(type)); \ TRACE("pMemory: %p\n", pMemory); \ *(type *)pMemory = *(type *)pStubMsg->Buffer; \ pStubMsg->Buffer += sizeof(type); @@ -1644,13 +1674,27 @@ void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory)); break; case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); TRACE("pMemory: %p\n", pMemory); /* 16-bits on the wire, but int in memory */ *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer; pStubMsg->Buffer += sizeof(USHORT); TRACE("value: 0x%08x\n", *(UINT *)pMemory); break; + case RPC_FC_INT3264: + align_pointer(&pStubMsg->Buffer, sizeof(INT)); + /* 32-bits on the wire, but int_ptr in memory */ + *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(INT); + TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory); + break; + case RPC_FC_UINT3264: + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + /* 32-bits on the wire, but int_ptr in memory */ + *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(UINT); + TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory); + break; case RPC_FC_IGNORE: break; default: @@ -1669,7 +1713,7 @@ unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned size = *(const WORD*)(pFormat+2); TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, size); @@ -1692,7 +1736,7 @@ unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *saved_buffer; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); @@ -1725,7 +1769,7 @@ void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned size = *(const WORD*)(pFormat+2); TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + align_length(&pStubMsg->BufferLength, pFormat[1] + 1); safe_buffer_length_increment(pStubMsg, size); if (pFormat[0] != RPC_FC_STRUCT) @@ -1742,7 +1786,7 @@ ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->MemorySize += size; safe_buffer_increment(pStubMsg, size); @@ -1769,6 +1813,8 @@ static inline void array_compute_and_size_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { + DWORD count; + switch (fc) { case RPC_FC_CARRAY: @@ -1800,6 +1846,13 @@ static inline void array_compute_and_size_conformance( SizeConformance(pStubMsg); break; + case RPC_FC_BOGUS_ARRAY: + count = *(const WORD *)(pFormat + 2); + pFormat += 4; + if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1810,7 +1863,7 @@ static inline void array_buffer_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { - DWORD size; + DWORD i, size; DWORD esize; unsigned char alignment; @@ -1822,7 +1875,7 @@ static inline void array_buffer_size( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); /* conformance value plus array */ @@ -1836,11 +1889,11 @@ static inline void array_buffer_size( alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); - pFormat = SkipConformance(pStubMsg, pFormat); + pFormat = SkipVariance(pStubMsg, pFormat); SizeVariance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); @@ -1860,6 +1913,18 @@ static inline void array_buffer_size( size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg); + pFormat = SkipVariance(pStubMsg, pFormat); + + align_length(&pStubMsg->BufferLength, alignment); + + size = pStubMsg->ActualCount; + for (i = 0; i < size; i++) + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1870,6 +1935,9 @@ static inline void array_compute_and_write_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { + ULONG def; + BOOL conformance_present; + switch (fc) { case RPC_FC_CARRAY: @@ -1900,6 +1968,14 @@ static inline void array_compute_and_write_conformance( pStubMsg->Offset = 0; WriteConformance(pStubMsg); break; + case RPC_FC_BOGUS_ARRAY: + def = *(const WORD *)(pFormat + 2); + pFormat += 4; + conformance_present = IsConformanceOrVariancePresent(pFormat); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + if (conformance_present) WriteConformance(pStubMsg); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1910,7 +1986,7 @@ static inline void array_write_variance_and_marshall( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { - DWORD size; + DWORD i, size; DWORD esize; unsigned char alignment; @@ -1922,7 +1998,7 @@ static inline void array_write_variance_and_marshall( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); if (fHasPointers) @@ -1936,14 +2012,12 @@ static inline void array_write_variance_and_marshall( esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; - /* conformance */ pFormat = SkipConformance(pStubMsg, pFormat + 4); - /* variance */ - pFormat = SkipConformance(pStubMsg, pFormat); + pFormat = SkipVariance(pStubMsg, pFormat); WriteVariance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); @@ -1966,6 +2040,18 @@ static inline void array_write_variance_and_marshall( size = safe_multiply(esize, pStubMsg->ActualCount); safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg); + pFormat = SkipVariance(pStubMsg, pFormat); + + align_pointer_clear(&pStubMsg->Buffer, alignment); + + size = pStubMsg->ActualCount; + for (i = 0; i < size; i++) + pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1975,7 +2061,8 @@ static inline void array_write_variance_and_marshall( static inline ULONG array_read_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - DWORD esize; + DWORD def, esize; + unsigned char alignment; switch (fc) { @@ -1999,6 +2086,21 @@ static inline ULONG array_read_conformance( else ReadConformance(pStubMsg, NULL); return safe_multiply(esize, pStubMsg->MaxCount); + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + def = *(const WORD *)(pFormat + 2); + pFormat += 4; + if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat); + else + { + pStubMsg->MaxCount = def; + pFormat = SkipConformance( pStubMsg, pFormat ); + } + pFormat = SkipVariance( pStubMsg, pFormat ); + + align_pointer(&pStubMsg->Buffer, alignment); + esize = ComplexStructSize(pStubMsg, pFormat); + return safe_multiply(pStubMsg->MaxCount, esize); default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2013,8 +2115,8 @@ static inline ULONG array_read_variance_and_unmarshall( ULONG bufsize, memsize; WORD esize; unsigned char alignment; - unsigned char *saved_buffer; - ULONG offset; + unsigned char *saved_buffer, *pMemory; + ULONG i, offset, count; switch (fc) { @@ -2026,7 +2128,7 @@ static inline ULONG array_read_variance_and_unmarshall( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fUnmarshall) { @@ -2058,7 +2160,7 @@ static inline ULONG array_read_variance_and_unmarshall( pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); memsize = safe_multiply(esize, pStubMsg->MaxCount); @@ -2133,6 +2235,31 @@ static inline ULONG array_read_variance_and_unmarshall( TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); } return bufsize; + + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + esize = ComplexStructSize(pStubMsg, pFormat); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + + assert( fUnmarshall ); + + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + align_pointer(&pStubMsg->Buffer, alignment); + saved_buffer = pStubMsg->Buffer; + + pMemory = *ppMemory; + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc); + return pStubMsg->Buffer - saved_buffer; + default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2143,6 +2270,7 @@ static inline void array_memory_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fHasPointers) { + ULONG i, count, SavedMemorySize; ULONG bufsize, memsize; DWORD esize; unsigned char alignment; @@ -2158,7 +2286,7 @@ static inline void array_memory_size( bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); @@ -2178,7 +2306,7 @@ static inline void array_memory_size( memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); @@ -2215,6 +2343,24 @@ static inline void array_memory_size( safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + align_pointer(&pStubMsg->Buffer, alignment); + + SavedMemorySize = pStubMsg->MemorySize; + + esize = ComplexStructSize(pStubMsg, pFormat); + memsize = safe_multiply(pStubMsg->MaxCount, esize); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + ComplexStructMemorySize(pStubMsg, pFormat, NULL); + + pStubMsg->MemorySize = SavedMemorySize + memsize; + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2225,6 +2371,8 @@ static inline void array_free( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { + DWORD i, count; + switch (fc) { case RPC_FC_CARRAY: @@ -2242,6 +2390,15 @@ static inline void array_free( case RPC_FC_C_WSTRING: /* No embedded pointers so nothing to do */ break; + case RPC_FC_BOGUS_ARRAY: + count = *(const WORD *)(pFormat + 2); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2395,24 +2552,22 @@ unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubM TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; if (*pFormat == RPC_FC_CSTRING) { - ULONG i; + ULONG i = 0; const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { - ULONG i; + ULONG i = 0; const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; @@ -2445,7 +2600,7 @@ unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStu TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); if (pStubMsg->Offset) @@ -2495,26 +2650,24 @@ void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; SizeVariance(pStubMsg); if (*pFormat == RPC_FC_CSTRING) { - ULONG i; + ULONG i = 0; const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { - ULONG i; + ULONG i = 0; const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; @@ -2538,7 +2691,7 @@ ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); @@ -2607,6 +2760,8 @@ static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg, case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: return sizeof(ULONG); case RPC_FC_FLOAT: return sizeof(float); @@ -2683,12 +2838,15 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, pMemory += 2; break; case RPC_FC_ENUM16: + { + USHORT val = *(DWORD *)pMemory; TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); - safe_copy_to_buffer(pStubMsg, pMemory, 2); + safe_copy_to_buffer(pStubMsg, &val, 2); pMemory += 4; break; + } case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: @@ -2696,6 +2854,15 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, safe_copy_to_buffer(pStubMsg, pMemory, 4); pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + { + UINT val = *(UINT_PTR *)pMemory; + TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT)); + pMemory += sizeof(UINT_PTR); + break; + } case RPC_FC_FLOAT: TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); @@ -2724,7 +2891,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -2752,13 +2919,13 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -2830,13 +2997,16 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pMemory += 2; break; case RPC_FC_ENUM16: - safe_copy_from_buffer(pStubMsg, pMemory, 2); - *(DWORD*)pMemory &= 0xffff; + { + WORD val; + safe_copy_from_buffer(pStubMsg, &val, 2); + *(DWORD*)pMemory = val; TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); pMemory += 4; break; + } case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: @@ -2844,6 +3014,24 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); pMemory += 4; break; + case RPC_FC_INT3264: + { + INT val; + safe_copy_from_buffer(pStubMsg, &val, 4); + *(INT_PTR *)pMemory = val; + TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory); + pMemory += sizeof(INT_PTR); + break; + } + case RPC_FC_UINT3264: + { + UINT val; + safe_copy_from_buffer(pStubMsg, &val, 4); + *(UINT_PTR *)pMemory = val; + TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory); + pMemory += sizeof(UINT_PTR); + break; + } case RPC_FC_FLOAT: safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float)); TRACE("float=%f => %p\n", *(float*)pMemory, pMemory); @@ -2871,7 +3059,7 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -2899,13 +3087,13 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_POINTER_CLEAR(pMemory, 2); + align_pointer_clear(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER_CLEAR(pMemory, 4); + align_pointer_clear(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER_CLEAR(pMemory, 8); + align_pointer_clear(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -2992,6 +3180,11 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_length_increment(pStubMsg, 4); pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + safe_buffer_length_increment(pStubMsg, 4); + pMemory += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: safe_buffer_length_increment(pStubMsg, 8); @@ -3017,7 +3210,7 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, } if (*pPointer != RPC_FC_RP) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } if (*pFormat == RPC_FC_POINTER) @@ -3027,13 +3220,13 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pMemory += sizeof(void*); break; case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3105,6 +3298,10 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_FLOAT: pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + pMemory += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: pMemory += 8; @@ -3124,13 +3321,13 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, pMemory += sizeof(void *); break; case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3205,6 +3402,11 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, size += 4; safe_buffer_increment(pStubMsg, 4); break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + size += sizeof(INT_PTR); + safe_buffer_increment(pStubMsg, 4); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: size += 8; @@ -3221,7 +3423,7 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -3250,13 +3452,13 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_LENGTH(size, 2); + align_length(&size, 2); break; case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); + align_length(&size, 4); break; case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); + align_length(&size, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3310,6 +3512,10 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) case RPC_FC_FLOAT: size += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + size += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: size += 8; @@ -3324,13 +3530,13 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) pFormat += 4; break; case RPC_FC_ALIGNM2: - ALIGN_LENGTH(size, 2); + align_length(&size, 2); break; case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); + align_length(&size, 4); break; case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); + align_length(&size, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3398,7 +3604,7 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = saved_buffer_length; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3484,7 +3690,7 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = saved_buffer; } - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3549,7 +3755,7 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + align_length(&pStubMsg->BufferLength, pFormat[1] + 1); if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { @@ -3627,7 +3833,7 @@ ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3918,9 +4124,6 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - ULONG i, count, def; - BOOL variance_present; - unsigned char alignment; int pointer_buffer_mark_set = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -3932,8 +4135,6 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - alignment = pFormat[1] + 1; - if (!pStubMsg->PointerBufferMark) { /* save buffer fields that may be changed by buffer sizer functions @@ -3963,25 +4164,9 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = saved_buffer_length; } - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - WriteConformance(pStubMsg); - if (variance_present) - WriteVariance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); + array_compute_and_write_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat); + array_write_variance_and_marshall(RPC_FC_BOGUS_ARRAY, pStubMsg, + pMemory, pFormat, TRUE /* fHasPointers */); STD_OVERFLOW_CHECK(pStubMsg); @@ -4002,9 +4187,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - ULONG i, count, size; - unsigned char alignment; - unsigned char *pMemory; unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; int saved_ignore_embedded; @@ -4018,8 +4200,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - alignment = pFormat[1] + 1; - saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; /* save buffer pointer */ saved_buffer = pStubMsg->Buffer; @@ -4028,7 +4208,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->IgnoreEmbeddedPointers = 1; pStubMsg->MemorySize = 0; NdrComplexArrayMemorySize(pStubMsg, pFormat); - size = pStubMsg->MemorySize; pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer)); @@ -4041,22 +4220,9 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, /* restore the original buffer */ pStubMsg->Buffer = saved_buffer; - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - if (!fMustAlloc && !*ppMemory) - fMustAlloc = TRUE; - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pMemory = *ppMemory; - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc); + array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_BOGUS_ARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc, + TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); if (pointer_buffer_mark_set) { @@ -4074,9 +4240,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - ULONG i, count, def; - unsigned char alignment; - BOOL variance_present; int pointer_length_set = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -4088,8 +4251,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, return; } - alignment = pFormat[1] + 1; - if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { /* save buffer fields that may be changed by buffer sizer functions @@ -4116,25 +4277,9 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->MaxCount = saved_max_count; pStubMsg->BufferLength = saved_buffer_length; } - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - SizeConformance(pStubMsg); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - if (variance_present) - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); + array_compute_and_size_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat); + array_buffer_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); if(pointer_length_set) { @@ -4149,9 +4294,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - ULONG i, count, esize, SavedMemorySize, MemorySize; - unsigned char alignment; - TRACE("(%p,%p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_BOGUS_ARRAY) @@ -4161,29 +4303,9 @@ ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, return 0; } - alignment = pFormat[1] + 1; - - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - SavedMemorySize = pStubMsg->MemorySize; - - esize = ComplexStructSize(pStubMsg, pFormat); - - MemorySize = safe_multiply(pStubMsg->MaxCount, esize); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - ComplexStructMemorySize(pStubMsg, pFormat, NULL); - - pStubMsg->MemorySize = SavedMemorySize; - - pStubMsg->MemorySize += MemorySize; - return MemorySize; + array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat); + array_memory_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */); + return pStubMsg->MemorySize; } /*********************************************************************** @@ -4255,7 +4377,7 @@ unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) @@ -4264,10 +4386,10 @@ unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); + align_pointer_clear(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer_clear(&pStubMsg->Buffer, (flags & 0xf) + 1); pStubMsg->Buffer = pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( @@ -4306,7 +4428,7 @@ unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); /* skip pointer prefix */ pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) @@ -4315,10 +4437,10 @@ unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } - ALIGN_POINTER(pStubMsg->Buffer, 8); + align_pointer(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; @@ -4362,7 +4484,7 @@ void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); /* skip pointer prefix */ safe_buffer_length_increment(pStubMsg, 4); if (pStubMsg->IgnoreEmbeddedPointers) @@ -4373,10 +4495,10 @@ void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } - ALIGN_LENGTH(pStubMsg->BufferLength, 8); + align_length(&pStubMsg->BufferLength, 8); } else - ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); + align_length(&pStubMsg->BufferLength, (flags & 0xf) + 1); if (bufsize) { TRACE("size=%d\n", bufsize); @@ -4413,15 +4535,15 @@ ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); /* skip pointer prefix */ pStubMsg->Buffer += 4; if (pStubMsg->IgnoreEmbeddedPointers) return pStubMsg->MemorySize; - ALIGN_POINTER(pStubMsg->Buffer, 8); + align_pointer(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1); if (!bufsize) FIXME("not implemented for varying buffer size\n"); @@ -4578,7 +4700,7 @@ unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, WriteConformance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4633,7 +4755,7 @@ unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMs pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); - ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4702,7 +4824,7 @@ void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); SizeConformance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4791,7 +4913,7 @@ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pS pMemory + pCVStructFormat->memory_size, pCVArrayFormat); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4839,7 +4961,7 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE memsize = array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4913,7 +5035,7 @@ void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4949,7 +5071,7 @@ ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, pCVStructFormat->offset_to_array_description; array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -5031,7 +5153,7 @@ unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5075,7 +5197,7 @@ unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5129,7 +5251,7 @@ void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, return; } - ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5166,7 +5288,7 @@ ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, return 0; } - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5269,7 +5391,7 @@ unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, WriteVariance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); pStubMsg->BufferMark = pStubMsg->Buffer; @@ -5328,7 +5450,7 @@ unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pFormat = ReadVariance(pStubMsg, pFormat, elements); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); offset = pStubMsg->Offset; @@ -5397,7 +5519,7 @@ void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, SizeVariance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); @@ -5447,7 +5569,7 @@ ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, pFormat = ReadVariance(pStubMsg, pFormat, elements); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); pStubMsg->MemorySize += size; @@ -5522,6 +5644,9 @@ static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) case RPC_FC_ULONG: case RPC_FC_ENUM32: return *(const ULONG *)pMemory; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + return *(const ULONG_PTR *)pMemory; default: FIXME("Unhandled base type: 0x%02x\n", fc); return 0; @@ -5595,7 +5720,7 @@ static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned c case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -5663,7 +5788,7 @@ static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -5729,7 +5854,7 @@ static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ if (!pStubMsg->IgnoreEmbeddedPointers) { @@ -5783,10 +5908,10 @@ static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); if (!pStubMsg->IgnoreEmbeddedPointers) PointerMemorySize(pStubMsg, saved_buffer, pFormat); @@ -5855,7 +5980,7 @@ unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); + align_pointer_clear(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); @@ -5887,7 +6012,7 @@ unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubM increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER(pStubMsg->Buffer, increment); + align_pointer(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); @@ -5929,7 +6054,7 @@ void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_LENGTH(pStubMsg->BufferLength, increment); + align_length(&pStubMsg->BufferLength, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); @@ -5954,7 +6079,7 @@ ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER(pStubMsg->Buffer, increment); + align_pointer(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); @@ -6034,7 +6159,7 @@ static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_USHORT: { USHORT d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; @@ -6043,7 +6168,7 @@ static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_ULONG: { ULONG d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONG)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; @@ -6268,7 +6393,7 @@ static unsigned char *WINAPI NdrRangeMarshall( unsigned char *pMemory, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); @@ -6294,7 +6419,7 @@ unsigned char *WINAPI NdrRangeUnmarshall( PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); @@ -6313,7 +6438,7 @@ unsigned char *WINAPI NdrRangeUnmarshall( #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \ do \ { \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \ + align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \ if (!fMustAlloc && !*ppMemory) \ fMustAlloc = TRUE; \ if (fMustAlloc) \ @@ -6391,7 +6516,7 @@ static void WINAPI NdrRangeBufferSize( unsigned char *pMemory, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); @@ -6413,7 +6538,7 @@ static ULONG WINAPI NdrRangeMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; if (pRange->type != RPC_FC_RANGE) @@ -6461,7 +6586,7 @@ static unsigned char *WINAPI NdrBaseTypeMarshall( case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT)); TRACE("value: 0x%04x\n", *(USHORT *)pMemory); break; @@ -6469,34 +6594,42 @@ static unsigned char *WINAPI NdrBaseTypeMarshall( case RPC_FC_ULONG: case RPC_FC_ERROR_STATUS_T: case RPC_FC_ENUM32: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG)); TRACE("value: 0x%08x\n", *(ULONG *)pMemory); break; case RPC_FC_FLOAT: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(float)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); break; case RPC_FC_DOUBLE: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(double)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double)); break; case RPC_FC_HYPER: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG)); TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); break; case RPC_FC_ENUM16: + { + USHORT val = *(UINT *)pMemory; /* only 16-bits on the wire, so do a sanity check */ if (*(UINT *)pMemory > SHRT_MAX) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); - if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; - pStubMsg->Buffer += sizeof(USHORT); + align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_to_buffer(pStubMsg, &val, sizeof(val)); TRACE("value: 0x%04x\n", *(UINT *)pMemory); break; + } + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + { + UINT val = *(UINT_PTR *)pMemory; + align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT)); + safe_copy_to_buffer(pStubMsg, &val, sizeof(val)); + break; + } case RPC_FC_IGNORE: break; default: @@ -6518,8 +6651,8 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( { TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); -#define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ +#define BASE_TYPE_UNMARSHALL(type) do { \ + align_pointer(&pStubMsg->Buffer, sizeof(type)); \ if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \ { \ *ppMemory = pStubMsg->Buffer; \ @@ -6532,7 +6665,8 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ TRACE("*ppMemory: %p\n", *ppMemory); \ safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \ - } + } \ + } while (0) switch(*pFormat) { @@ -6569,19 +6703,49 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); break; case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + { + USHORT val; + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); - if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - TRACE("*ppMemory: %p\n", *ppMemory); + safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT)); /* 16-bits on the wire, but int in memory */ - **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; - pStubMsg->Buffer += sizeof(USHORT); + **(UINT **)ppMemory = val; TRACE("value: 0x%08x\n", **(UINT **)ppMemory); break; + } + case RPC_FC_INT3264: + if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT); + else + { + INT val; + align_pointer(&pStubMsg->Buffer, sizeof(INT)); + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR)); + safe_copy_from_buffer(pStubMsg, &val, sizeof(INT)); + **(INT_PTR **)ppMemory = val; + TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory); + } + break; + case RPC_FC_UINT3264: + if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT); + else + { + UINT val; + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR)); + safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT)); + **(UINT_PTR **)ppMemory = val; + TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory); + } + break; case RPC_FC_IGNORE: break; default: @@ -6616,29 +6780,31 @@ static void WINAPI NdrBaseTypeBufferSize( case RPC_FC_SHORT: case RPC_FC_USHORT: case RPC_FC_ENUM16: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT)); + align_length(&pStubMsg->BufferLength, sizeof(USHORT)); safe_buffer_length_increment(pStubMsg, sizeof(USHORT)); break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + align_length(&pStubMsg->BufferLength, sizeof(ULONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); break; case RPC_FC_FLOAT: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); + align_length(&pStubMsg->BufferLength, sizeof(float)); safe_buffer_length_increment(pStubMsg, sizeof(float)); break; case RPC_FC_DOUBLE: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); + align_length(&pStubMsg->BufferLength, sizeof(double)); safe_buffer_length_increment(pStubMsg, sizeof(double)); break; case RPC_FC_HYPER: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); + align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG)); break; case RPC_FC_ERROR_STATUS_T: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); + align_length(&pStubMsg->BufferLength, sizeof(error_status_t)); safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); break; case RPC_FC_IGNORE: @@ -6669,51 +6835,58 @@ static ULONG WINAPI NdrBaseTypeMemorySize( case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT)); + align_length(&pStubMsg->MemorySize, sizeof(USHORT)); pStubMsg->MemorySize += sizeof(USHORT); return sizeof(USHORT); case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONG)); safe_buffer_increment(pStubMsg, sizeof(ULONG)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG)); + align_length(&pStubMsg->MemorySize, sizeof(ULONG)); pStubMsg->MemorySize += sizeof(ULONG); return sizeof(ULONG); case RPC_FC_FLOAT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(float)); + align_pointer(&pStubMsg->Buffer, sizeof(float)); safe_buffer_increment(pStubMsg, sizeof(float)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float)); + align_length(&pStubMsg->MemorySize, sizeof(float)); pStubMsg->MemorySize += sizeof(float); return sizeof(float); case RPC_FC_DOUBLE: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(double)); + align_pointer(&pStubMsg->Buffer, sizeof(double)); safe_buffer_increment(pStubMsg, sizeof(double)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double)); + align_length(&pStubMsg->MemorySize, sizeof(double)); pStubMsg->MemorySize += sizeof(double); return sizeof(double); case RPC_FC_HYPER: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG)); safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG)); + align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG)); pStubMsg->MemorySize += sizeof(ULONGLONG); return sizeof(ULONGLONG); case RPC_FC_ERROR_STATUS_T: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t)); + align_pointer(&pStubMsg->Buffer, sizeof(error_status_t)); safe_buffer_increment(pStubMsg, sizeof(error_status_t)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t)); + align_length(&pStubMsg->MemorySize, sizeof(error_status_t)); pStubMsg->MemorySize += sizeof(error_status_t); return sizeof(error_status_t); case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT)); + align_length(&pStubMsg->MemorySize, sizeof(UINT)); pStubMsg->MemorySize += sizeof(UINT); return sizeof(UINT); + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + safe_buffer_increment(pStubMsg, sizeof(UINT)); + align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR)); + pStubMsg->MemorySize += sizeof(UINT_PTR); + return sizeof(UINT_PTR); case RPC_FC_IGNORE: - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); return sizeof(void *); default: @@ -6749,7 +6922,7 @@ static void WINAPI NdrContextHandleBufferSize( ERR("invalid format type %x\n", *pFormat); RpcRaiseException(RPC_S_INTERNAL_ERROR); } - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, cbNDRContext); } @@ -6835,7 +7008,7 @@ void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6860,7 +7033,7 @@ void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -6879,7 +7052,7 @@ void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6900,7 +7073,7 @@ NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) TRACE("(%p)\n", pStubMsg); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6958,7 +7131,7 @@ void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6991,7 +7164,7 @@ NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p, %p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { diff --git a/reactos/dll/win32/rpcrt4/ndr_ole.c b/reactos/dll/win32/rpcrt4/ndr_ole.c index a4c23c2c5c2..090be052d34 100644 --- a/reactos/dll/win32/rpcrt4/ndr_ole.c +++ b/reactos/dll/win32/rpcrt4/ndr_ole.c @@ -309,13 +309,12 @@ void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, { const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); ULONG size = 0; - HRESULT hr; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (!LoadCOM()) return; - hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, - pStubMsg->dwDestContext, pStubMsg->pvDestContext, - MSHLFLAGS_NORMAL); + COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, + pStubMsg->dwDestContext, pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL); TRACE("size=%d\n", size); pStubMsg->BufferLength += sizeof(DWORD) + size; } diff --git a/reactos/dll/win32/rpcrt4/ndr_stubless.c b/reactos/dll/win32/rpcrt4/ndr_stubless.c index 645a0ca4729..ed7912fcb19 100644 --- a/reactos/dll/win32/rpcrt4/ndr_stubless.c +++ b/reactos/dll/win32/rpcrt4/ndr_stubless.c @@ -173,7 +173,7 @@ static PFORMAT_STRING client_get_handle( if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 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); pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; *phBinding = pGenPair->pfnBind(pObject); @@ -256,7 +256,7 @@ static void client_free_handle( if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 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); pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair->pfnUnbind(pObject, hBinding); @@ -579,7 +579,7 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma void * This = NULL; PFORMAT_STRING pHandleFormat; /* correlation cache */ - unsigned long NdrCorrCache[256]; + ULONG_PTR NdrCorrCache[256]; 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 * 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 { @@ -696,13 +697,56 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma switch (phase) { case PROXY_GETBUFFER: - /* allocate the buffer */ - NdrProxyGetBuffer(This, &stubMsg); + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* 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; case PROXY_SENDRECEIVE: - /* send the [in] params and receive the [out] and [retval] - * params */ - NdrProxySendReceive(This, &stubMsg); + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* 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 * preferred format */ @@ -729,7 +773,33 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma } __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 } @@ -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); __ASM_GLOBAL_FUNC(call_server_func, "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 */ + __ASM_CFI(".cfi_rel_offset %edi,-4\n\t") "pushl %esi\n\t" + __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") "movl 16(%ebp), %eax\n\t" /* Get stack size */ "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 */ @@ -882,9 +957,13 @@ __ASM_GLOBAL_FUNC(call_server_func, "call *8(%ebp)\n\t" /* Call function */ "leal -8(%ebp), %esp\n\t" /* Restore stack */ "popl %esi\n\t" /* Restore registers */ + __ASM_CFI(".cfi_same_value %esi\n\t") "popl %edi\n\t" + __ASM_CFI(".cfi_same_value %edi\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 #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) @@ -920,6 +999,18 @@ static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) size = ComplexStructSize(pStubMsg, pFormat); size *= pStubMsg->MaxCount; 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: FIXME("Unhandled type %02x\n", *pFormat); /* fallthrough */ @@ -1049,7 +1140,8 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, !pParam->param_attributes.IsByValue && !pParam->param_attributes.ServerAllocSize) { - pStubMsg->pfnFree(*(void **)pArg); + if (*pTypeFormat != RPC_FC_BIND_CONTEXT) + pStubMsg->pfnFree(*(void **)pArg); } 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.IsByValue) { - DWORD size = calc_arg_size(pStubMsg, pTypeFormat); - - if(size) + if (*pTypeFormat == RPC_FC_BIND_CONTEXT) { - *(void **)pArg = NdrAllocate(pStubMsg, size); - memset(*(void **)pArg, 0, size); + NDR_SCONTEXT ctxt = NdrContextHandleInitialize( + 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; @@ -1290,10 +1391,6 @@ LONG WINAPI NdrStubCall2( 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) { const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; @@ -1368,6 +1465,10 @@ LONG WINAPI NdrStubCall2( else 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 */ if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; @@ -1522,3 +1623,339 @@ void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) DWORD 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; +} diff --git a/reactos/dll/win32/rpcrt4/ndr_stubless.h b/reactos/dll/win32/rpcrt4/ndr_stubless.h index 9a6fb444783..87f603b6065 100644 --- a/reactos/dll/win32/rpcrt4/ndr_stubless.h +++ b/reactos/dll/win32/rpcrt4/ndr_stubless.h @@ -85,7 +85,7 @@ typedef struct _NDR_PROC_HEADER_RPC * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute * Reserved = 0x8000 */ - unsigned long rpc_flags; + unsigned int rpc_flags; unsigned short proc_num; 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, unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc, BOOL ignore_retval); +RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply); diff --git a/reactos/dll/win32/rpcrt4/rpc_assoc.c b/reactos/dll/win32/rpcrt4/rpc_assoc.c index 32e951a929a..8364a9a4f36 100644 --- a/reactos/dll/win32/rpcrt4/rpc_assoc.c +++ b/reactos/dll/win32/rpcrt4/rpc_assoc.c @@ -84,6 +84,15 @@ static RPC_STATUS RpcAssoc_Alloc(LPCSTR Protseq, LPCSTR NetworkAddr, 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, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc_out) @@ -97,7 +106,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, if (!strcmp(Protseq, assoc->Protseq) && !strcmp(NetworkAddr, assoc->NetworkAddr) && !strcmp(Endpoint, assoc->Endpoint) && - ((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) + compare_networkoptions(NetworkOptions, assoc->NetworkOptions)) { assoc->refs++; *assoc_out = assoc; @@ -125,7 +134,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, - unsigned long assoc_gid, + ULONG assoc_gid, RpcAssoc **assoc_out) { RpcAssoc *assoc; @@ -223,7 +232,7 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection * RPC_MESSAGE msg; RPC_STATUS status; unsigned char *auth_data = NULL; - unsigned long auth_length; + ULONG auth_length; 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 - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); - RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); - if ((results->num_results == 1) && (remaining >= sizeof(*results))) + RpcResultList *results = (RpcResultList*)((ULONG_PTR)server_address + + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + if ((results->num_results == 1) && + (remaining >= FIELD_OFFSET(RpcResultList, results[results->num_results]))) { switch (results->results[0].result) { case RESULT_ACCEPT: /* respond to authorization request */ if (auth_length > sizeof(RpcAuthVerifier)) - status = RPCRT4_AuthorizeConnection(conn, - auth_data + sizeof(RpcAuthVerifier), - auth_length); + status = RPCRT4_ClientConnectionAuth(conn, + auth_data + sizeof(RpcAuthVerifier), + auth_length); if (status == RPC_S_OK) { 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) return status; + NewConnection->assoc = assoc; status = RPCRT4_OpenClientConnection(NewConnection); if (status != RPC_S_OK) { @@ -416,6 +427,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) { assert(!Connection->server); + Connection->async_state = NULL; EnterCriticalSection(&assoc->cs); if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry); diff --git a/reactos/dll/win32/rpcrt4/rpc_assoc.h b/reactos/dll/win32/rpcrt4/rpc_assoc.h index 1ce1f135638..70fb664e31d 100644 --- a/reactos/dll/win32/rpcrt4/rpc_assoc.h +++ b/reactos/dll/win32/rpcrt4/rpc_assoc.h @@ -34,6 +34,7 @@ typedef struct _RpcAssoc /* id of this association group */ ULONG assoc_group_id; + UUID http_uuid; 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); void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); 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_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); diff --git a/reactos/dll/win32/rpcrt4/rpc_async.c b/reactos/dll/win32/rpcrt4/rpc_async.c index 33fdc774304..891fc5ad725 100644 --- a/reactos/dll/win32/rpcrt4/rpc_async.c +++ b/reactos/dll/win32/rpcrt4/rpc_async.c @@ -29,11 +29,17 @@ #include "rpc_binding.h" #include "rpc_message.h" +#include "ndr_stubless.h" WINE_DEFAULT_DEBUG_CHANNEL(rpc); #define RPC_ASYNC_SIGNATURE 0x43595341 +static inline BOOL valid_async_handle(PRPC_ASYNC_STATE pAsync) +{ + return pAsync->Signature == RPC_ASYNC_SIGNATURE; +} + /*********************************************************************** * RpcAsyncInitializeHandle [RPCRT4.@] * @@ -104,8 +110,14 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync) */ RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) { - FIXME("(%p, %p): stub\n", pAsync, Reply); - return RPC_S_INVALID_ASYNC_HANDLE; + TRACE("(%p, %p)\n", pAsync, Reply); + + if (!valid_async_handle(pAsync)) + return RPC_S_INVALID_ASYNC_HANDLE; + + /* FIXME: check completed */ + + return NdrpCompleteAsyncClientCall(pAsync, Reply); } /*********************************************************************** diff --git a/reactos/dll/win32/rpcrt4/rpc_binding.c b/reactos/dll/win32/rpcrt4/rpc_binding.c index 696887cb7b3..d83f53b2bc5 100644 --- a/reactos/dll/win32/rpcrt4/rpc_binding.c +++ b/reactos/dll/win32/rpcrt4/rpc_binding.c @@ -661,11 +661,11 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU return RPC_S_OK; fail: - if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid); - if (Protseq) RpcStringFreeA((unsigned char**)Protseq); - if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr); - if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint); - if (Options) RpcStringFreeA((unsigned char**)Options); + if (ObjUuid) RpcStringFreeA(ObjUuid); + if (Protseq) RpcStringFreeA(Protseq); + if (NetworkAddr) RpcStringFreeA(NetworkAddr); + if (Endpoint) RpcStringFreeA(Endpoint); + if (Options) RpcStringFreeA(Options); return RPC_S_INVALID_STRING_BINDING; } @@ -785,8 +785,11 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) { RPC_STATUS status; TRACE("(%p) = %p\n", Binding, *Binding); - status = RPCRT4_ReleaseBinding(*Binding); - if (status == RPC_S_OK) *Binding = 0; + if (*Binding) + status = RPCRT4_ReleaseBinding(*Binding); + else + status = RPC_S_INVALID_BINDING; + if (status == RPC_S_OK) *Binding = NULL; return status; } @@ -796,7 +799,7 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) { RPC_STATUS status; - unsigned long c; + ULONG c; TRACE("(%p)\n", BindingVector); 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 ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&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 ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); 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) ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options); - RpcStringFreeA((unsigned char**)&Options); - RpcStringFreeA((unsigned char**)&Endpoint); - RpcStringFreeA((unsigned char**)&NetworkAddr); - RpcStringFreeA((unsigned char**)&Protseq); - RpcStringFreeA((unsigned char**)&ObjectUuid); + RpcStringFreeA(&Options); + RpcStringFreeA(&Endpoint); + RpcStringFreeA(&NetworkAddr); + RpcStringFreeA(&Protseq); + RpcStringFreeA(&ObjectUuid); if (ret == RPC_S_OK) *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 ret; - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; RPC_CSTR ObjectUuid; 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); ret = RpcBindingToStringBindingA(Binding, &str); *StringBinding = RPCRT4_strdupAtoW((char*)str); - RpcStringFreeA((unsigned char**)&str); + RpcStringFreeA(&str); 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) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); @@ -986,7 +989,7 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy( RPC_BINDING_HANDLE* DestinationBinding) { RpcBinding *DestBinding; - RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; + RpcBinding *SrcBinding = SourceBinding; RPC_STATUS status; 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) { - FIXME("(%p): stub\n", BindingHandle); - ImpersonateSelf(SecurityImpersonation); - return RPC_S_OK; + RpcBinding *bind; + + 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) { - FIXME("(%p): stub\n", BindingHandle); - return RPC_S_OK; + RpcBinding *bind; + + 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) @@ -1091,11 +1111,11 @@ static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) } } -static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, - CredHandle cred, TimeStamp exp, - ULONG cbMaxToken, - RPC_AUTH_IDENTITY_HANDLE identity, - RpcAuthInfo **ret) +RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, + CredHandle cred, TimeStamp exp, + ULONG cbMaxToken, + RPC_AUTH_IDENTITY_HANDLE identity, + RpcAuthInfo **ret) { RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*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->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * 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->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); @@ -1428,9 +1448,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali */ RPC_STATUS WINAPI RpcRevertToSelf(void) { - FIXME("stub\n"); - RevertToSelf(); - return RPC_S_OK; + TRACE("\n"); + return RpcRevertToSelfEx(NULL); } /*********************************************************************** @@ -1450,9 +1469,22 @@ RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, 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); - 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 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); - 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, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) { - FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, - AuthnSvc, AuthIdentity, AuthzSvc); - return RPC_S_INVALID_BINDING; + return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, + AuthzSvc, 0, NULL); } /*********************************************************************** @@ -1487,9 +1547,78 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) { - FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, - AuthnSvc, AuthIdentity, AuthzSvc); - return RPC_S_INVALID_BINDING; + return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, + AuthzSvc, 0, NULL); +} + +/*********************************************************************** + * 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_SECURITY_QOS *SecurityQos ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; SECURITY_STATUS r; CredHandle cred; TimeStamp exp; @@ -1631,7 +1760,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, RPC_SECURITY_QOS *SecurityQos ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; SECURITY_STATUS r; CredHandle cred; TimeStamp exp; @@ -1640,7 +1769,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, PSecPkgInfoW packages; 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); if (SecurityQos) @@ -1772,7 +1901,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, 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); return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); } diff --git a/reactos/dll/win32/rpcrt4/rpc_binding.h b/reactos/dll/win32/rpcrt4/rpc_binding.h index 5aa83079d51..e523ba69778 100644 --- a/reactos/dll/win32/rpcrt4/rpc_binding.h +++ b/reactos/dll/win32/rpcrt4/rpc_binding.h @@ -24,8 +24,15 @@ #include "rpcndr.h" #include "security.h" #include "wine/list.h" +#include "rpc_defs.h" +enum secure_packet_direction +{ + SECURE_PACKET_SEND, + SECURE_PACKET_RECEIVE +}; + typedef struct _RpcAuthInfo { LONG refs; @@ -66,6 +73,7 @@ typedef struct _RpcConnection TimeStamp exp; ULONG attr; RpcAuthInfo *AuthInfo; + ULONG auth_context_id; ULONG encryption_auth_len; ULONG signature_auth_len; RpcQualityOfService *QOS; @@ -74,6 +82,7 @@ typedef struct _RpcConnection struct list conn_pool_entry; ULONG assoc_group_id; /* association group returned during binding */ RPC_ASYNC_STATE *async_state; + struct _RpcAssoc *assoc; /* association this connection is part of */ /* server-only */ /* The active interface bound to server. */ @@ -96,6 +105,13 @@ struct connection_ops { int (*wait_for_incoming_data)(RpcConnection *conn); 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 (*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 */ @@ -128,6 +144,7 @@ void RPCRT4_strfree(LPSTR src); #define RPCRT4_strdupA(x) RPCRT4_strndupA((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_Release(RpcAuthInfo *AuthInfo); 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); } +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 */ 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); diff --git a/reactos/dll/win32/rpcrt4/rpc_defs.h b/reactos/dll/win32/rpcrt4/rpc_defs.h index cae77c4f356..434d39699ee 100644 --- a/reactos/dll/win32/rpcrt4/rpc_defs.h +++ b/reactos/dll/win32/rpcrt4/rpc_defs.h @@ -22,6 +22,7 @@ #ifndef __WINE_RPC_DEFS_H #define __WINE_RPC_DEFS_H +#include "pshpack1.h" typedef struct { unsigned char rpc_ver; /* RPC major version (5) */ @@ -31,13 +32,13 @@ typedef struct unsigned char drep[4]; /* Data representation */ unsigned short frag_len; /* Data size in bytes including header and tail. */ unsigned short auth_len; /* Authentication length */ - unsigned long call_id; /* Call identifier. */ + unsigned int call_id; /* Call identifier. */ } RpcPktCommonHdr; typedef struct { 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 opnum; } RpcPktRequestHdr; @@ -45,7 +46,7 @@ typedef struct typedef struct { 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 char cancel_count; unsigned char reserved; @@ -54,58 +55,68 @@ typedef struct typedef struct { 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 char cancel_count; /* Received cancel count */ unsigned char reserved; /* Force alignment! */ - unsigned long status; /* Runtime fault code (RPC_STATUS) */ - unsigned long reserved2; + unsigned int status; /* Runtime fault code (RPC_STATUS) */ + unsigned int reserved2; } 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 { RpcPktCommonHdr common; unsigned short max_tsize; /* Maximum transmission 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 padding[3]; /* Force alignment! */ - unsigned short context_id; /* Presentation context identifier */ - unsigned char num_syntaxes; /* Number of syntaxes */ - RPC_SYNTAX_IDENTIFIER abstract; - RPC_SYNTAX_IDENTIFIER transfer; + /* + * Following this header are these fields: + * RpcContextElement context_elements[num_elements] + */ } RpcPktBindHdr; -#include "pshpack1.h" typedef struct { 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; -#include "poppack.h" + +typedef struct +{ + unsigned short result; + unsigned short reason; + RPC_SYNTAX_IDENTIFIER transfer_syntax; +} RpcResult; typedef struct { unsigned char num_results; /* Number of results */ unsigned char reserved[3]; /* Force alignment! */ - struct { - unsigned short result; - unsigned short reason; - } results[1]; -} RpcResults; + RpcResult results[ANYSIZE_ARRAY]; /* size_is(num_results) */ +} RpcResultList; typedef struct { RpcPktCommonHdr common; unsigned short max_tsize; /* Maximum transmission 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: * RpcAddressString server_address; * [0 - 3 bytes of padding so that results is 4-byte aligned] - * RpcResults results; - * RPC_SYNTAX_IDENTIFIER transfer; + * RpcResultList results; */ } RpcPktBindAckHdr; @@ -117,9 +128,24 @@ typedef struct struct { unsigned char rpc_ver; unsigned char rpc_ver_minor; - } protocols[1]; + } protocols[ANYSIZE_ARRAY]; } 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 */ typedef union { @@ -130,6 +156,8 @@ typedef union RpcPktBindHdr bind; RpcPktBindAckHdr bind_ack; RpcPktBindNAckHdr bind_nack; + RpcPktHttpHdr http; + RpcPktAuth3Hdr auth3; } RpcPktHdr; typedef struct @@ -138,8 +166,9 @@ typedef struct unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */ unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */ 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; +#include "poppack.h" #define RPC_AUTH_VERIFIER_LEN(common_hdr) \ ((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_MAX_PACKET_SIZE 0x16D0 -#define PKT_REQUEST 0 -#define PKT_PING 1 -#define PKT_RESPONSE 2 -#define PKT_FAULT 3 -#define PKT_WORKING 4 -#define PKT_NOCALL 5 -#define PKT_REJECT 6 -#define PKT_ACK 7 -#define PKT_CL_CANCEL 8 -#define PKT_FACK 9 -#define PKT_CANCEL_ACK 10 -#define PKT_BIND 11 -#define PKT_BIND_ACK 12 -#define PKT_BIND_NACK 13 -#define PKT_ALTER_CONTEXT 14 -#define PKT_ALTER_CONTEXT_RESP 15 -#define PKT_AUTH3 16 -#define PKT_SHUTDOWN 17 -#define PKT_CO_CANCEL 18 -#define PKT_ORPHANED 19 +enum rpc_packet_type +{ + PKT_REQUEST = 0, + PKT_PING = 1, + PKT_RESPONSE = 2, + PKT_FAULT = 3, + PKT_WORKING = 4, + PKT_NOCALL = 5, + PKT_REJECT = 6, + PKT_ACK = 7, + PKT_CL_CANCEL = 8, + PKT_FACK = 9, + PKT_CANCEL_ACK = 10, + PKT_BIND = 11, + PKT_BIND_ACK = 12, + PKT_BIND_NACK = 13, + PKT_ALTER_CONTEXT = 14, + PKT_ALTER_CONTEXT_RESP = 15, + PKT_AUTH3 = 16, + PKT_SHUTDOWN = 17, + PKT_CO_CANCEL = 18, + PKT_ORPHANED = 19, + PKT_HTTP = 20, +}; #define RESULT_ACCEPT 0 #define RESULT_USER_REJECTION 1 diff --git a/reactos/dll/win32/rpcrt4/rpc_epmap.c b/reactos/dll/win32/rpcrt4/rpc_epmap.c index 286ffbf9973..d326e8e29d1 100644 --- a/reactos/dll/win32/rpcrt4/rpc_epmap.c +++ b/reactos/dll/win32/rpcrt4/rpc_epmap.c @@ -116,18 +116,18 @@ static BOOL start_rpcss(void) 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 *network_addr = bind->NetworkAddr; - return ((!strcmp(protseq, "ncalrpc") && !network_addr) || - (!strcmp(protseq, "ncacn_np") && + return (!strcmp(protseq, "ncalrpc") || + (!strcmp(protseq, "ncacn_np") && (!network_addr || !strcmp(network_addr, ".")))); } 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; RPC_STATUS status; 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); if (status != RPC_S_OK) return status; - epm_bind = (RpcBinding*)*epm_handle; + epm_bind = *epm_handle; if (epm_bind->AuthInfo) { /* 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, UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long i; + PRPC_SERVER_INTERFACE If = IfSpec; + ULONG i; RPC_STATUS status = RPC_S_OK; error_status_t status2; 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(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); for (i=0; iCount; i++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); - TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); + RpcBinding* bind = BindingVector->BindingH[i]; + TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint)); } if (UuidVector) { for (i=0; iCount; 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; @@ -222,10 +222,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind for (i = 0; i < BindingVector->Count; i++) { unsigned j; - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + RpcBinding* bind = BindingVector->BindingH[i]; for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) { - int len = strlen((char *)Annotation); status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, bind->Protseq, bind->Endpoint, 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)); else 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; } +/*********************************************************************** + * 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.@) */ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, UUID_VECTOR *UuidVector ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long i; + PRPC_SERVER_INTERFACE If = IfSpec; + ULONG i; RPC_STATUS status = RPC_S_OK; error_status_t status2; 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(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); for (i=0; iCount; i++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); - TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); + RpcBinding* bind = BindingVector->BindingH[i]; + TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint)); } if (UuidVector) { for (i=0; iCount; 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)); @@ -319,7 +335,7 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin for (i = 0; i < BindingVector->Count; i++) { unsigned j; - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + RpcBinding* bind = BindingVector->BindingH[i]; for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) { 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 ) { - PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; - RpcBinding* bind = (RpcBinding*)Binding; + PRPC_CLIENT_INTERFACE If = IfSpec; + RpcBinding* bind = Binding; RPC_STATUS status; error_status_t status2; handle_t handle; diff --git a/reactos/dll/win32/rpcrt4/rpc_message.c b/reactos/dll/win32/rpcrt4/rpc_message.c index e4f96a9179e..0144f85dbfd 100644 --- a/reactos/dll/win32/rpcrt4/rpc_message.c +++ b/reactos/dll/win32/rpcrt4/rpc_message.c @@ -51,32 +51,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc); (((alignment) - (((value) % (alignment)))) % (alignment)) #define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) -enum secure_packet_direction -{ - SECURE_PACKET_SEND, - SECURE_PACKET_RECEIVE -}; - static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg); -static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) +DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) { static const DWORD header_sizes[] = { sizeof(Header->request), 0, sizeof(Header->response), sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind), sizeof(Header->bind_ack), sizeof(Header->bind_nack), - 0, 0, 0, 0, 0 + 0, 0, sizeof(Header->auth3), 0, 0, 0, sizeof(Header->http) }; ULONG ret = 0; if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) { ret = header_sizes[Header->common.ptype]; if (ret == 0) - FIXME("unhandled packet type\n"); + FIXME("unhandled packet type %u\n", Header->common.ptype); if (Header->common.flags & RPC_FLG_OBJECT_UUID) ret += sizeof(UUID); } else { - TRACE("invalid packet type\n"); + WARN("invalid packet type %u\n", Header->common.ptype); } return ret; @@ -95,8 +89,23 @@ static int packet_has_auth_verifier(const RpcPktHdr *Header) !(Header->common.ptype == PKT_SHUTDOWN); } +static int packet_does_auth_negotiation(const RpcPktHdr *Header) +{ + switch (Header->common.ptype) + { + case PKT_BIND: + case PKT_BIND_ACK: + case PKT_AUTH3: + case PKT_ALTER_CONTEXT: + case PKT_ALTER_CONTEXT_RESP: + return TRUE; + default: + return FALSE; + } +} + static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, - unsigned long DataRepresentation) + ULONG DataRepresentation) { Header->common.rpc_ver = RPC_VER_MAJOR; Header->common.rpc_ver_minor = RPC_VER_MINOR; @@ -111,8 +120,8 @@ static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType /* Flags and fragment length are computed in RPCRT4_Send. */ } -static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, - unsigned long BufferLength, +static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation, + ULONG BufferLength, unsigned short ProcNum, UUID *ObjectUuid) { @@ -141,8 +150,7 @@ static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, - unsigned long BufferLength) +RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength) { RpcPktHdr *header; @@ -158,8 +166,7 @@ RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, - RPC_STATUS Status) +RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status) { RpcPktHdr *header; @@ -175,63 +182,66 @@ RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, - unsigned long AssocGroupId, + ULONG AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId) { RpcPktHdr *header; + RpcContextElement *ctxt_elem; - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind)); + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1])); if (header == NULL) { return NULL; } + ctxt_elem = (RpcContextElement *)(&header->bind + 1); RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); - header->common.frag_len = sizeof(header->bind); + header->common.frag_len = sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1]); header->bind.max_tsize = MaxTransmissionSize; header->bind.max_rsize = MaxReceiveSize; header->bind.assoc_gid = AssocGroupId; header->bind.num_elements = 1; - header->bind.num_syntaxes = 1; - header->bind.abstract = *AbstractId; - header->bind.transfer = *TransferId; + ctxt_elem->num_syntaxes = 1; + ctxt_elem->abstract_syntax = *AbstractId; + ctxt_elem->transfer_syntaxes[0] = *TransferId; return header; } -static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation) +static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation) { RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(header->common) + 12); + sizeof(header->auth3)); if (header == NULL) return NULL; RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); - header->common.frag_len = 0x14; - header->common.auth_len = 0; + header->common.frag_len = sizeof(header->auth3); return header; } -RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, unsigned char RpcVersion, - unsigned char RpcVersionMinor) + unsigned char RpcVersionMinor, + unsigned short RejectReason) { RpcPktHdr *header; - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack)); + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1])); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); - header->common.frag_len = sizeof(header->bind_nack); - header->bind_nack.reject_reason = REJECT_REASON_NOT_SPECIFIED; + header->common.frag_len = FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1]); + header->bind_nack.reject_reason = RejectReason; header->bind_nack.protocols_count = 1; header->bind_nack.protocols[0].rpc_ver = RpcVersion; header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; @@ -239,25 +249,22 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, - unsigned long AssocGroupId, + ULONG AssocGroupId, LPCSTR ServerAddress, - unsigned long Result, - unsigned long Reason, - const RPC_SYNTAX_IDENTIFIER *TransferId) + unsigned char ResultCount, + const RpcResult *Results) { RpcPktHdr *header; - unsigned long header_size; + ULONG header_size; RpcAddressString *server_address; - RpcResults *results; - RPC_SYNTAX_IDENTIFIER *transfer_id; + RpcResultList *results; header_size = sizeof(header->bind_ack) + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + - sizeof(RpcResults) + - sizeof(RPC_SYNTAX_IDENTIFIER); + FIELD_OFFSET(RpcResultList, results[ResultCount]); header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); if (header == NULL) { @@ -273,16 +280,125 @@ RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, server_address->length = strlen(ServerAddress) + 1; strcpy(server_address->string, ServerAddress); /* results is 4-byte aligned */ - results = (RpcResults*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); - results->num_results = 1; - results->results[0].result = Result; - results->results[0].reason = Reason; - transfer_id = (RPC_SYNTAX_IDENTIFIER*)(results + 1); - *transfer_id = *TransferId; + results = (RpcResultList*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + results->num_results = ResultCount; + memcpy(&results->results[0], Results, ResultCount * sizeof(*Results)); return header; } +RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, + unsigned short flags, + unsigned short num_data_items, + unsigned int payload_size) +{ + RpcPktHdr *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->http) + payload_size); + if (header == NULL) { + ERR("failed to allocate memory\n"); + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_HTTP, DataRepresentation); + /* since the packet isn't current sent using RPCRT4_Send, set the flags + * manually here */ + header->common.flags = RPC_FLG_FIRST|RPC_FLG_LAST; + header->common.call_id = 0; + header->common.frag_len = sizeof(header->http) + payload_size; + header->http.flags = flags; + header->http.num_data_items = num_data_items; + + return header; +} + +#define WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, type, value) \ + do { \ + *(unsigned int *)(payload) = (type); \ + (payload) += 4; \ + *(unsigned int *)(payload) = (value); \ + (payload) += 4; \ + } while (0) + +#define WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, type, uuid) \ + do { \ + *(unsigned int *)(payload) = (type); \ + (payload) += 4; \ + *(UUID *)(payload) = (uuid); \ + (payload) += sizeof(UUID); \ + } while (0) + +#define WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, flow_control_increment, uuid) \ + do { \ + *(unsigned int *)(payload) = 0x00000001; \ + (payload) += 4; \ + *(unsigned int *)(payload) = (bytes_transmitted); \ + (payload) += 4; \ + *(unsigned int *)(payload) = (flow_control_increment); \ + (payload) += 4; \ + *(UUID *)(payload) = (uuid); \ + (payload) += sizeof(UUID); \ + } while (0) + +RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe, + const UUID *connection_uuid, + const UUID *pipe_uuid, + const UUID *association_uuid) +{ + RpcPktHdr *header; + unsigned int size; + char *payload; + + size = 8 + 4 + sizeof(UUID) + 4 + sizeof(UUID) + 8; + if (!out_pipe) + size += 8 + 4 + sizeof(UUID); + + header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, flags, + out_pipe ? 4 : 6, size); + if (!header) return NULL; + payload = (char *)(&header->http+1); + + /* FIXME: what does this part of the payload do? */ + WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000006, 0x00000001); + + WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *connection_uuid); + WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *pipe_uuid); + + if (out_pipe) + /* FIXME: what does this part of the payload do? */ + WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000000, 0x00010000); + else + { + /* FIXME: what does this part of the payload do? */ + WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000004, 0x40000000); + /* FIXME: what does this part of the payload do? */ + WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000005, 0x000493e0); + + WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x0000000c, *association_uuid); + } + + return header; +} + +RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, + ULONG flow_control_increment, + const UUID *pipe_uuid) +{ + RpcPktHdr *header; + char *payload; + + header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x2, 2, + 5 * sizeof(ULONG) + sizeof(UUID)); + if (!header) return NULL; + payload = (char *)(&header->http+1); + + WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x0000000d, (server ? 0x0 : 0x3)); + + WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, + flow_control_increment, *pipe_uuid); + return header; +} + VOID RPCRT4_FreeHeader(RpcPktHdr *Header) { HeapFree(GetProcessHeap(), 0, Header); @@ -362,7 +478,207 @@ static RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) } } -static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, +/* assumes the common header fields have already been validated */ +BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, + unsigned short data_len) +{ + unsigned short i; + BYTE *p = data; + + for (i = 0; i < hdr->http.num_data_items; i++) + { + ULONG type; + + if (data_len < sizeof(ULONG)) + return FALSE; + + type = *(ULONG *)p; + p += sizeof(ULONG); + data_len -= sizeof(ULONG); + + switch (type) + { + case 0x3: + case 0xc: + if (data_len < sizeof(GUID)) + return FALSE; + p += sizeof(GUID); + data_len -= sizeof(GUID); + break; + case 0x0: + case 0x2: + case 0x4: + case 0x5: + case 0x6: + case 0xd: + if (data_len < sizeof(ULONG)) + return FALSE; + p += sizeof(ULONG); + data_len -= sizeof(ULONG); + break; + case 0x1: + if (data_len < 24) + return FALSE; + p += 24; + data_len -= 24; + break; + default: + FIXME("unimplemented type 0x%x\n", type); + break; + } + } + return TRUE; +} + +/* assumes the HTTP packet has been validated */ +static unsigned char *RPCRT4_NextHttpHeaderField(unsigned char *data) +{ + ULONG type; + + type = *(ULONG *)data; + data += sizeof(ULONG); + + switch (type) + { + case 0x3: + case 0xc: + return data + sizeof(GUID); + case 0x0: + case 0x2: + case 0x4: + case 0x5: + case 0x6: + case 0xd: + return data + sizeof(ULONG); + case 0x1: + return data + 24; + default: + FIXME("unimplemented type 0x%x\n", type); + return data; + } +} + +#define READ_HTTP_PAYLOAD_FIELD_TYPE(data) *(ULONG *)(data) +#define GET_HTTP_PAYLOAD_FIELD_DATA(data) ((data) + sizeof(ULONG)) + +/* assumes the HTTP packet has been validated */ +RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, + unsigned char *data, ULONG *field1) +{ + ULONG type; + if (header->http.flags != 0x0) + { + ERR("invalid flags 0x%x\n", header->http.flags); + return RPC_S_PROTOCOL_ERROR; + } + if (header->http.num_data_items != 1) + { + ERR("invalid number of data items %d\n", header->http.num_data_items); + return RPC_S_PROTOCOL_ERROR; + } + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x00000002) + { + ERR("invalid type 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); + return RPC_S_OK; +} + +/* assumes the HTTP packet has been validated */ +RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, + unsigned char *data, ULONG *field1, + ULONG *bytes_until_next_packet, + ULONG *field3) +{ + ULONG type; + if (header->http.flags != 0x0) + { + ERR("invalid flags 0x%x\n", header->http.flags); + return RPC_S_PROTOCOL_ERROR; + } + if (header->http.num_data_items != 3) + { + ERR("invalid number of data items %d\n", header->http.num_data_items); + return RPC_S_PROTOCOL_ERROR; + } + + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x00000006) + { + ERR("invalid type for field 1: 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); + data = RPCRT4_NextHttpHeaderField(data); + + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x00000000) + { + ERR("invalid type for field 2: 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + *bytes_until_next_packet = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); + data = RPCRT4_NextHttpHeaderField(data); + + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x00000002) + { + ERR("invalid type for field 3: 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + *field3 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, + unsigned char *data, BOOL server, + ULONG *bytes_transmitted, + ULONG *flow_control_increment, + UUID *pipe_uuid) +{ + ULONG type; + if (header->http.flags != 0x2) + { + ERR("invalid flags 0x%x\n", header->http.flags); + return RPC_S_PROTOCOL_ERROR; + } + if (header->http.num_data_items != 2) + { + ERR("invalid number of data items %d\n", header->http.num_data_items); + return RPC_S_PROTOCOL_ERROR; + } + + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x0000000d) + { + ERR("invalid type for field 1: 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + if (*(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data) != (server ? 0x3 : 0x0)) + { + ERR("invalid type for 0xd field data: 0x%08x\n", *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data)); + return RPC_S_PROTOCOL_ERROR; + } + data = RPCRT4_NextHttpHeaderField(data); + + type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); + if (type != 0x00000001) + { + ERR("invalid type for field 2: 0x%08x\n", type); + return RPC_S_PROTOCOL_ERROR; + } + *bytes_transmitted = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); + *flow_control_increment = *(ULONG *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 4); + *pipe_uuid = *(UUID *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 8); + + return RPC_S_OK; +} + + +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, @@ -441,9 +757,9 @@ static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, * * Transmit a packet with authorization data over connection in acceptable fragments. */ -static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, - void *Buffer, unsigned int BufferLength, - const void *Auth, unsigned int AuthLength) +RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, + void *Buffer, unsigned int BufferLength, + const void *Auth, unsigned int AuthLength) { PUCHAR buffer_pos; DWORD hdr_size; @@ -500,7 +816,7 @@ static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Head memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - auth_pad_len - alen); /* add the authorization info */ - if (Connection->AuthInfo && packet_has_auth_verifier(Header)) + if (Header->common.auth_len) { RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; @@ -509,13 +825,13 @@ static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Head auth_hdr->auth_pad_length = auth_pad_len; auth_hdr->auth_reserved = 0; /* a unique number... */ - auth_hdr->auth_context_id = (unsigned long)Connection; + auth_hdr->auth_context_id = Connection->auth_context_id; if (AuthLength) memcpy(auth_hdr + 1, Auth, AuthLength); else { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND, + status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_SEND, (RpcPktHdr *)pkt, hdr_size, pkt + hdr_size, Header->common.frag_len - hdr_size - alen, auth_hdr, @@ -548,43 +864,84 @@ write: } /*********************************************************************** - * RPCRT4_ClientAuthorize (internal) + * RPCRT4_default_authorize (internal) * - * Authorize a client connection. A NULL in param signifies a new connection. + * Authorize a client connection. */ -static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, - SecBuffer *out) +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) { SECURITY_STATUS r; SecBufferDesc out_desc; SecBufferDesc inp_desc; SecPkgContext_Sizes secctx_sizes; BOOL continue_needed; - ULONG context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | - ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; + ULONG context_req; + SecBuffer in, out; - if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) - context_req |= ISC_REQ_INTEGRITY; - else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) - context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; + if (!out_buffer) + { + *out_size = conn->AuthInfo->cbMaxToken; + return RPC_S_OK; + } - out->BufferType = SECBUFFER_TOKEN; - out->cbBuffer = conn->AuthInfo->cbMaxToken; - out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer); - if (!out->pvBuffer) return ERROR_OUTOFMEMORY; + in.BufferType = SECBUFFER_TOKEN; + in.pvBuffer = in_buffer; + in.cbBuffer = in_size; + + out.BufferType = SECBUFFER_TOKEN; + out.pvBuffer = out_buffer; + out.cbBuffer = *out_size; out_desc.ulVersion = 0; out_desc.cBuffers = 1; - out_desc.pBuffers = out; + out_desc.pBuffers = &out; - inp_desc.cBuffers = 1; - inp_desc.pBuffers = in; inp_desc.ulVersion = 0; + inp_desc.cBuffers = 1; + inp_desc.pBuffers = ∈ - r = InitializeSecurityContextW(&conn->AuthInfo->cred, in ? &conn->ctx : NULL, - in ? NULL : conn->AuthInfo->server_principal_name, context_req, 0, - SECURITY_NETWORK_DREP, in ? &inp_desc : NULL, 0, &conn->ctx, - &out_desc, &conn->attr, &conn->exp); + if (conn->server) + { + context_req = ASC_REQ_CONNECTION | ASC_REQ_USE_DCE_STYLE | + ASC_REQ_DELEGATE; + + if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) + context_req |= ASC_REQ_INTEGRITY; + else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + context_req |= ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY; + + r = AcceptSecurityContext(&conn->AuthInfo->cred, + first_time ? NULL : &conn->ctx, + &inp_desc, context_req, SECURITY_NETWORK_DREP, + &conn->ctx, + &out_desc, &conn->attr, &conn->exp); + if (r == SEC_E_OK || r == SEC_I_COMPLETE_NEEDED) + { + /* authorisation done, so nothing more to send */ + out.cbBuffer = 0; + } + } + else + { + context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | + ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; + + if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) + context_req |= ISC_REQ_INTEGRITY; + else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; + + r = InitializeSecurityContextW(&conn->AuthInfo->cred, + first_time ? NULL: &conn->ctx, + first_time ? conn->AuthInfo->server_principal_name : NULL, + context_req, 0, SECURITY_NETWORK_DREP, + first_time ? NULL : &inp_desc, 0, &conn->ctx, + &out_desc, &conn->attr, &conn->exp); + } if (FAILED(r)) { WARN("InitializeSecurityContext failed with error 0x%08x\n", r); @@ -606,7 +963,7 @@ static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, } } - TRACE("cbBuffer = %d\n", out->cbBuffer); + TRACE("cbBuffer = %d\n", out.cbBuffer); if (!continue_needed) { @@ -620,45 +977,240 @@ static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; } + *out_size = out.cbBuffer; return RPC_S_OK; failed: - HeapFree(GetProcessHeap(), 0, out->pvBuffer); - out->pvBuffer = NULL; + *out_size = 0; return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ } /*********************************************************************** - * RPCRT4_AuthorizeBinding (internal) + * RPCRT4_ClientConnectionAuth (internal) */ -RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, - ULONG count) +RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, + ULONG count) { - SecBuffer inp, out; RpcPktHdr *resp_hdr; RPC_STATUS status; + unsigned char *out_buffer; + unsigned int out_len = 0; TRACE("challenge %s, %d bytes\n", challenge, count); - inp.BufferType = SECBUFFER_TOKEN; - inp.pvBuffer = challenge; - inp.cbBuffer = count; - - status = RPCRT4_ClientAuthorize(conn, &inp, &out); + status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, NULL, &out_len); + if (status) return status; + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_len); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, out_buffer, &out_len); if (status) return status; resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); - if (!resp_hdr) - return E_OUTOFMEMORY; - status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer); + if (resp_hdr) + status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out_buffer, out_len); + else + status = RPC_S_OUT_OF_RESOURCES; - HeapFree(GetProcessHeap(), 0, out.pvBuffer); + HeapFree(GetProcessHeap(), 0, out_buffer); RPCRT4_FreeHeader(resp_hdr); return status; } +/*********************************************************************** + * RPCRT4_ServerConnectionAuth (internal) + */ +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) +{ + unsigned char *out_buffer; + unsigned int out_size; + RPC_STATUS status; + + if (start) + { + /* remove any existing authentication information */ + if (conn->AuthInfo) + { + RpcAuthInfo_Release(conn->AuthInfo); + conn->AuthInfo = NULL; + } + if (SecIsValidHandle(&conn->ctx)) + { + DeleteSecurityContext(&conn->ctx); + SecInvalidateHandle(&conn->ctx); + } + if (auth_length_in >= sizeof(RpcAuthVerifier)) + { + CredHandle cred; + TimeStamp exp; + ULONG max_token; + + status = RPCRT4_ServerGetRegisteredAuthInfo( + auth_data_in->auth_type, &cred, &exp, &max_token); + if (status != RPC_S_OK) + { + ERR("unknown authentication service %u\n", auth_data_in->auth_type); + return status; + } + + status = RpcAuthInfo_Create(auth_data_in->auth_level, + auth_data_in->auth_type, cred, exp, + max_token, NULL, &conn->AuthInfo); + if (status != RPC_S_OK) + return status; + + /* FIXME: should auth_data_in->auth_context_id be checked in the !start case? */ + conn->auth_context_id = auth_data_in->auth_context_id; + } + } + + if (auth_length_in < sizeof(RpcAuthVerifier)) + return RPC_S_OK; + + if (!conn->AuthInfo) + /* should have filled in authentication info by now */ + return RPC_S_PROTOCOL_ERROR; + + status = rpcrt4_conn_authorize( + conn, start, (unsigned char *)(auth_data_in + 1), + auth_length_in - sizeof(RpcAuthVerifier), NULL, &out_size); + if (status) return status; + + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + + status = rpcrt4_conn_authorize( + conn, start, (unsigned char *)(auth_data_in + 1), + auth_length_in - sizeof(RpcAuthVerifier), out_buffer, &out_size); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, out_buffer); + return status; + } + + if (out_size && !auth_length_out) + { + ERR("expected authentication to be complete but SSP returned data of " + "%u bytes to be sent back to client\n", out_size); + HeapFree(GetProcessHeap(), 0, out_buffer); + return RPC_S_SEC_PKG_ERROR; + } + else + { + *auth_data_out = out_buffer; + *auth_length_out = out_size; + } + + return status; +} + +/*********************************************************************** + * RPCRT4_default_is_authorized (internal) + * + * Has a connection started the process of authorizing with the server? + */ +BOOL RPCRT4_default_is_authorized(RpcConnection *Connection) +{ + return Connection->AuthInfo && SecIsValidHandle(&Connection->ctx); +} + +/*********************************************************************** + * RPCRT4_default_impersonate_client (internal) + * + */ +RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn) +{ + SECURITY_STATUS sec_status; + + TRACE("(%p)\n", conn); + + if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) + return RPC_S_NO_CONTEXT_AVAILABLE; + sec_status = ImpersonateSecurityContext(&conn->ctx); + if (sec_status != SEC_E_OK) + WARN("ImpersonateSecurityContext returned 0x%08x\n", sec_status); + switch (sec_status) + { + case SEC_E_UNSUPPORTED_FUNCTION: + return RPC_S_CANNOT_SUPPORT; + case SEC_E_NO_IMPERSONATION: + return RPC_S_NO_CONTEXT_AVAILABLE; + case SEC_E_OK: + return RPC_S_OK; + default: + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RPCRT4_default_revert_to_self (internal) + * + */ +RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn) +{ + SECURITY_STATUS sec_status; + + TRACE("(%p)\n", conn); + + if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) + return RPC_S_NO_CONTEXT_AVAILABLE; + sec_status = RevertSecurityContext(&conn->ctx); + if (sec_status != SEC_E_OK) + WARN("RevertSecurityContext returned 0x%08x\n", sec_status); + switch (sec_status) + { + case SEC_E_UNSUPPORTED_FUNCTION: + return RPC_S_CANNOT_SUPPORT; + case SEC_E_NO_IMPERSONATION: + return RPC_S_NO_CONTEXT_AVAILABLE; + case SEC_E_OK: + return RPC_S_OK; + default: + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RPCRT4_default_inquire_auth_client (internal) + * + * Default function to retrieve the authentication details that the client + * is using to call the server. + */ +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) +{ + if (!conn->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; + + if (privs) + { + FIXME("privs not implemented\n"); + *privs = NULL; + } + if (server_princ_name) + { + *server_princ_name = RPCRT4_strdupW(conn->AuthInfo->server_principal_name); + if (!*server_princ_name) return ERROR_OUTOFMEMORY; + } + if (authn_level) *authn_level = conn->AuthInfo->AuthnLevel; + if (authn_svc) *authn_svc = conn->AuthInfo->AuthnSvc; + if (authz_svc) + { + FIXME("authorization service not implemented\n"); + *authz_svc = RPC_C_AUTHZ_NONE; + } + if (flags) + FIXME("flags 0x%x not implemented\n", flags); + + return RPC_S_OK; +} + /*********************************************************************** * RPCRT4_Send (internal) * @@ -668,26 +1220,35 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength) { RPC_STATUS r; - SecBuffer out; - if (!Connection->AuthInfo || SecIsValidHandle(&Connection->ctx)) + if (packet_does_auth_negotiation(Header) && + Connection->AuthInfo && + !rpcrt4_conn_is_authorized(Connection)) { - return RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); - } + unsigned int out_size = 0; + unsigned char *out_buffer; - /* tack on a negotiate packet */ - r = RPCRT4_ClientAuthorize(Connection, NULL, &out); - if (r == RPC_S_OK) - { - r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer); - HeapFree(GetProcessHeap(), 0, out.pvBuffer); + r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, NULL, &out_size); + if (r != RPC_S_OK) return r; + + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + + /* tack on a negotiate packet */ + r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, out_buffer, &out_size); + if (r == RPC_S_OK) + r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out_buffer, out_size); + + HeapFree(GetProcessHeap(), 0, out_buffer); } + else + r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); return r; } /* validates version and frag_len fields */ -static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) +RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) { DWORD hdr_length; @@ -716,11 +1277,11 @@ static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) } /*********************************************************************** - * RPCRT4_receive_fragment (internal) + * RPCRT4_default_receive_fragment (internal) * * Receive a fragment from a connection. */ -static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) +static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) { RPC_STATUS status; DWORD hdr_length; @@ -794,6 +1355,14 @@ fail: return status; } +static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) +{ + if (Connection->ops->receive_fragment) + return Connection->ops->receive_fragment(Connection, Header, Payload); + else + return RPCRT4_default_receive_fragment(Connection, Header, Payload); +} + /*********************************************************************** * RPCRT4_ReceiveWithAuth (internal) * @@ -803,20 +1372,22 @@ fail: RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, - unsigned long *auth_length_out) + ULONG *auth_length_out) { RPC_STATUS status; DWORD hdr_length; unsigned short first_flag; - unsigned long data_length; - unsigned long buffer_length; - unsigned long auth_length = 0; + ULONG data_length; + ULONG buffer_length; + ULONG auth_length = 0; unsigned char *auth_data = NULL; RpcPktHdr *CurrentHeader = NULL; void *payload = NULL; *Header = NULL; pMsg->Buffer = NULL; + if (auth_data_out) *auth_data_out = NULL; + if (auth_length_out) *auth_length_out = 0; TRACE("(%p, %p, %p, %p)\n", Connection, Header, pMsg, auth_data_out); @@ -874,7 +1445,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, } if (CurrentHeader->common.auth_len != auth_length) { - WARN("auth_len header field changed from %ld to %d\n", + WARN("auth_len header field changed from %d to %d\n", auth_length, CurrentHeader->common.auth_len); status = RPC_S_PROTOCOL_ERROR; goto fail; @@ -888,7 +1459,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len; if (data_length + buffer_length > pMsg->BufferLength) { - TRACE("allocation hint exceeded, new buffer length = %ld\n", + TRACE("allocation hint exceeded, new buffer length = %d\n", data_length + buffer_length); pMsg->BufferLength = data_length + buffer_length; status = I_RpcReAllocateBuffer(pMsg); @@ -914,9 +1485,9 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, /* these packets are handled specially, not by the generic SecurePacket * function */ - if (!auth_data_out && SecIsValidHandle(&Connection->ctx)) + if (!packet_does_auth_negotiation(*Header) && rpcrt4_conn_is_authorized(Connection)) { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, + status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_RECEIVE, CurrentHeader, hdr_length, (unsigned char *)pMsg->Buffer + buffer_length, data_length, (RpcAuthVerifier *)auth_data, @@ -998,7 +1569,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, */ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection* conn; RPC_STATUS status = RPC_S_OK; @@ -1063,7 +1634,7 @@ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) { RPC_STATUS status; - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); @@ -1120,7 +1691,7 @@ static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) */ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); @@ -1214,7 +1785,7 @@ static DWORD WINAPI async_notifier_proc(LPVOID p) */ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection* conn; RPC_STATUS status; RpcPktHdr *hdr; @@ -1268,7 +1839,7 @@ static inline BOOL is_hard_error(RPC_STATUS status) */ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RPC_STATUS status; RpcPktHdr *hdr = NULL; RpcConnection *conn; @@ -1287,7 +1858,7 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) case PKT_RESPONSE: break; case PKT_FAULT: - ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status); + ERR ("we got fault packet with status 0x%x\n", hdr->fault.status); status = NCA2RPC_STATUS(hdr->fault.status); if (is_hard_error(status)) goto fail; @@ -1360,7 +1931,7 @@ RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) */ RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection *conn; TRACE("(%p, %p)\n", pMsg, pAsync); diff --git a/reactos/dll/win32/rpcrt4/rpc_message.h b/reactos/dll/win32/rpcrt4/rpc_message.h index e4033882feb..2509527e65e 100644 --- a/reactos/dll/win32/rpcrt4/rpc_message.h +++ b/reactos/dll/win32/rpcrt4/rpc_message.h @@ -25,16 +25,36 @@ typedef unsigned int NCA_STATUS; -RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status); -RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long 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_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor); -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_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status); +RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength); +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(ULONG DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor, unsigned short RejectReason); +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); 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_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); +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_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 diff --git a/reactos/dll/win32/rpcrt4/rpc_server.c b/reactos/dll/win32/rpcrt4/rpc_server.c index 473c7ba9328..2a16fe56e21 100644 --- a/reactos/dll/win32/rpcrt4/rpc_server.c +++ b/reactos/dll/win32/rpcrt4/rpc_server.c @@ -52,6 +52,8 @@ typedef struct _RpcPacket struct _RpcConnection* conn; RpcPktHdr* hdr; RPC_MESSAGE* msg; + unsigned char *auth_data; + ULONG auth_length; } RpcPacket; typedef struct _RpcObjTypeMap @@ -67,6 +69,7 @@ static RpcObjTypeMap *RpcObjTypeMaps; /* list of type RpcServerProtseq */ static struct list protseqs = LIST_INIT(protseqs); 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_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 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 */ static BOOL std_listen; /* number of manual listeners (calls to RpcServerListen) */ @@ -118,7 +130,8 @@ static inline UUID *LookupObjType(UUID *ObjUuid) } 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) { UUID* MgrType = NULL; @@ -130,6 +143,7 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object, EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { 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)) && std_listen) { 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; - RpcServerInterface* sif; - RpcPktHdr *response = NULL; + RpcContextElement *ctxt_elem; + 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 || !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"); - 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. */ - 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); + return RPC_S_INVALID_BOUND; } - if (response) - status = RPCRT4_Send(conn, response, NULL, 0); + results = HeapAlloc(GetProcessHeap(), 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 - status = ERROR_OUTOFMEMORY; - RPCRT4_FreeHeader(response); + status = RPC_S_OUT_OF_RESOURCES; 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) { RPC_STATUS status; @@ -242,7 +389,7 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr * object_uuid = NULL; } - sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE); + sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE); if (!sif) { WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID)); response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, @@ -327,7 +474,34 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr * 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; @@ -337,7 +511,8 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA case PKT_BIND: 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; 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); 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; @@ -355,57 +536,96 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA I_RpcFree(msg->Buffer); RPCRT4_FreeHeader(hdr); HeapFree(GetProcessHeap(), 0, msg); + HeapFree(GetProcessHeap(), 0, auth_data); } static DWORD CALLBACK RPCRT4_worker_thread(LPVOID 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); return 0; } static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) { - RpcConnection* conn = (RpcConnection*)the_arg; + RpcConnection* conn = the_arg; RpcPktHdr *hdr; RPC_MESSAGE *msg; RPC_STATUS status; RpcPacket *packet; + unsigned char *auth_data; + ULONG auth_length; TRACE("(%p)\n", conn); for (;;) { 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) { WARN("receive failed with error %x\n", status); HeapFree(GetProcessHeap(), 0, msg); break; } - packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); - if (!packet) { - I_RpcFree(msg->Buffer); - RPCRT4_FreeHeader(hdr); - HeapFree(GetProcessHeap(), 0, msg); + switch (hdr->common.ptype) { + case PKT_BIND: + TRACE("got bind packet\n"); + + status = process_bind_packet(conn, &hdr->bind, msg, auth_data, + auth_length); break; - } - packet->conn = conn; - packet->hdr = hdr; - packet->msg = msg; - if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { - ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); - I_RpcFree(msg->Buffer); - RPCRT4_FreeHeader(hdr); - HeapFree(GetProcessHeap(), 0, msg); - HeapFree(GetProcessHeap(), 0, packet); + + case PKT_REQUEST: + TRACE("got request packet\n"); + + packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); + if (!packet) { + I_RpcFree(msg->Buffer); + RPCRT4_FreeHeader(hdr); + HeapFree(GetProcessHeap(), 0, msg); + 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; } - 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); return 0; } @@ -449,27 +669,23 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) /* start waiting */ res = cps->ops->wait_for_new_connection(cps, count, objs); - if (res == -1) - break; - else if (res == 0) + + if (res == -1 || (res == 0 && !std_listen)) { - 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); - break; - } - set_ready_event = TRUE; + break; } + 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; } @@ -570,11 +786,32 @@ static void RPCRT4_stop_listen(BOOL auto_listen) 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; - 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) return status; @@ -608,11 +845,8 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { + for (conn = ps->conn; conn; conn = conn->Next) count++; - conn = conn->Next; - } LeaveCriticalSection(&ps->cs); } if (count) { @@ -624,12 +858,10 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { + for (conn = ps->conn; conn; conn = conn->Next) { RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], conn); count++; - conn = conn->Next; } 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. */ -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); @@ -695,7 +927,7 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr if (!*ps) return RPC_S_OUT_OF_RESOURCES; (*ps)->MaxCalls = MaxCalls; - (*ps)->Protseq = Protseq; + (*ps)->Protseq = RPCRT4_strdupA(Protseq); (*ps)->ops = ops; (*ps)->MaxCalls = 0; (*ps)->conn = NULL; @@ -711,8 +943,19 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr 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 */ -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; 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, PRPC_POLICY lpPolicy ) { - char *szps = (char*)Protseq, *szep = (char*)Endpoint; RpcServerProtseq* ps; RPC_STATUS status; - TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a(szps), MaxCalls, - debugstr_a(szep), SecurityDescriptor, + TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq), + MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor, 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) 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; RPC_STATUS status; + LPSTR ProtseqA; LPSTR EndpointA; TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor, 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) 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 status; + RpcServerProtseq* ps; + 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 status; + RpcServerProtseq* ps; + LPSTR ProtseqA; + 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, 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; 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 ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + PRPC_SERVER_INTERFACE If = IfSpec; HANDLE event = NULL; BOOL found = FALSE; BOOL completed = TRUE; @@ -996,15 +1277,114 @@ RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) 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.@) */ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, LPVOID Arg ) { - FIXME( "(%s,%u,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg ); - - return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ + SECURITY_STATUS sec_status; + CredHandle cred; + 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, LPVOID Arg ) { - FIXME( "(%s,%u,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg ); - - return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ + SECURITY_STATUS sec_status; + CredHandle cred; + 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; } /*********************************************************************** diff --git a/reactos/dll/win32/rpcrt4/rpc_server.h b/reactos/dll/win32/rpcrt4/rpc_server.h index ffd5b016e4b..07fb6234cea 100644 --- a/reactos/dll/win32/rpcrt4/rpc_server.h +++ b/reactos/dll/win32/rpcrt4/rpc_server.h @@ -56,7 +56,7 @@ struct protseq_ops * new connection was established */ int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array); /* 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 @@ -79,4 +79,7 @@ typedef struct _RpcServerInterface void RPCRT4_new_client(RpcConnection* conn); 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 */ diff --git a/reactos/dll/win32/rpcrt4/rpc_transport.c b/reactos/dll/win32/rpcrt4/rpc_transport.c index 2da72909c23..9f89e427280 100644 --- a/reactos/dll/win32/rpcrt4/rpc_transport.c +++ b/reactos/dll/win32/rpcrt4/rpc_transport.c @@ -40,6 +40,8 @@ # ifndef EAGAIN # define EAGAIN WSAEWOULDBLOCK # endif +# undef errno +# define errno WSAGetLastError() #else # include # ifdef HAVE_UNISTD_H @@ -64,16 +66,21 @@ # ifdef HAVE_SYS_POLL_H # include # endif +# ifdef HAVE_SYS_FILIO_H +# include +# endif +# ifdef HAVE_SYS_IOCTL_H +# include +# endif # define closesocket close +# define ioctlsocket ioctl #endif /* defined(__MINGW32__) || defined (_MSC_VER) */ -#include -#include - #include "windef.h" #include "winbase.h" #include "winnls.h" #include "winerror.h" +#include "wininet.h" #include "winternl.h" #include "wine/unicode.h" @@ -83,16 +90,17 @@ #include "wine/debug.h" #include "rpc_binding.h" +#include "rpc_assoc.h" #include "rpc_message.h" #include "rpc_server.h" #include "epm_towers.h" -#include "unix_func.h" - #ifndef SOL_TCP # define SOL_TCP IPPROTO_TCP #endif +#define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000) + WINE_DEFAULT_DEBUG_CHANNEL(rpc); static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); @@ -258,12 +266,23 @@ static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) return r; } -static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint) +static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint) { static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; RPC_STATUS r; LPSTR pname; RpcConnection *Connection; + char generated_endpoint[22]; + + if (!endpoint) + { + static LONG lrpc_nameless_id; + DWORD process_id = GetCurrentProcessId(); + ULONG id = InterlockedIncrement(&lrpc_nameless_id); + snprintf(generated_endpoint, sizeof(generated_endpoint), + "LRPC%08x.%08x", process_id, id); + endpoint = generated_endpoint; + } r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, endpoint, NULL, NULL, NULL); @@ -305,12 +324,23 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) return r; } -static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) +static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) { static const char prefix[] = "\\\\."; RPC_STATUS r; LPSTR pname; RpcConnection *Connection; + char generated_endpoint[21]; + + if (!endpoint) + { + static LONG np_nameless_id; + DWORD process_id = GetCurrentProcessId(); + ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 ); + snprintf(generated_endpoint, sizeof(generated_endpoint), + "\\\\pipe\\\\%08x.%03x", process_id, id); + endpoint = generated_endpoint; + } r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, endpoint, NULL, NULL, NULL); @@ -571,6 +601,48 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_ return RPC_S_OK; } +static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn) +{ + RpcConnection_np *npc = (RpcConnection_np *)conn; + BOOL ret; + + TRACE("(%p)\n", conn); + + if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) + return RPCRT4_default_impersonate_client(conn); + + ret = ImpersonateNamedPipeClient(npc->pipe); + if (!ret) + { + DWORD error = GetLastError(); + WARN("ImpersonateNamedPipeClient failed with error %u\n", error); + switch (error) + { + case ERROR_CANNOT_IMPERSONATE: + return RPC_S_NO_CONTEXT_AVAILABLE; + } + } + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn) +{ + BOOL ret; + + TRACE("(%p)\n", conn); + + if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) + return RPCRT4_default_revert_to_self(conn); + + ret = RevertToSelf(); + if (!ret) + { + WARN("RevertToSelf failed with error %u\n", GetLastError()); + return RPC_S_NO_CONTEXT_AVAILABLE; + } + return RPC_S_OK; +} + typedef struct _RpcServerProtseq_np { RpcServerProtseq common; @@ -754,379 +826,71 @@ static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_d return RPC_S_OK; } +static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn) +{ + return FALSE; +} + +static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, + unsigned char *in_buffer, + unsigned int in_size, + unsigned char *out_buffer, + unsigned int *out_size) +{ + /* since this protocol is local to the machine there is no need to + * authenticate the caller */ + *out_size = 0; + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncalrpc_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) +{ + /* since this protocol is local to the machine there is no need to secure + * the packet */ + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncalrpc_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) +{ + TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs, + server_princ_name, authn_level, authn_svc, authz_svc, flags); + + if (privs) + { + FIXME("privs not implemented\n"); + *privs = NULL; + } + if (server_princ_name) + { + FIXME("server_princ_name not implemented\n"); + *server_princ_name = NULL; + } + if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; + if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT; + if (authz_svc) + { + FIXME("authorization service not implemented\n"); + *authz_svc = RPC_C_AUTHZ_NONE; + } + if (flags) + FIXME("flags 0x%x not implemented\n", flags); + + return RPC_S_OK; +} + /**** ncacn_ip_tcp support ****/ -#ifdef HAVE_SOCKETPAIR - -typedef struct _RpcConnection_tcp -{ - RpcConnection common; - int sock; - SOCKET cancel_fds[2]; -} RpcConnection_tcp; - -static RpcConnection *rpcrt4_conn_tcp_alloc(void) -{ - RpcConnection_tcp *tcpc; - tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); - if (tcpc == NULL) - return NULL; - tcpc->sock = -1; - if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0) - { - ERR("socketpair() failed: %s\n", strerror(errno)); - HeapFree(GetProcessHeap(), 0, tcpc); - return NULL; - } - return &tcpc->common; -} - -static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int sock; - int ret; - struct addrinfo *ai; - struct addrinfo *ai_cur; - struct addrinfo hints; - - TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); - - if (tcpc->sock != -1) - return RPC_S_OK; - - hints.ai_flags = 0; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); - if (ret) - { - ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, - Connection->Endpoint, gai_strerror(ret)); - return RPC_S_SERVER_UNAVAILABLE; - } - - for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) - { - char val; - - if (TRACE_ON(rpc)) - { - char host[256]; - char service[256]; - getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, - host, sizeof(host), service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV); - TRACE("trying %s:%s\n", host, service); - } - - sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); - if (sock == -1) - { - WARN("socket() failed: %s\n", strerror(errno)); - continue; - } - - if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) - { - WARN("connect() failed: %s\n", strerror(errno)); - closesocket(sock); - continue; - } - - /* RPC depends on having minimal latency so disable the Nagle algorithm */ - val = 1; - setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val)); - fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ - - tcpc->sock = sock; - - freeaddrinfo(ai); - TRACE("connected\n"); - return RPC_S_OK; - } - - freeaddrinfo(ai); - ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); - return RPC_S_SERVER_UNAVAILABLE; -} - -static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) -{ - RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; - int sock; - int ret; - struct addrinfo *ai; - struct addrinfo *ai_cur; - struct addrinfo hints; - RpcConnection *first_connection = NULL; - - TRACE("(%p, %s)\n", protseq, endpoint); - - hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - ret = getaddrinfo(NULL, endpoint, &hints, &ai); - if (ret) - { - ERR("getaddrinfo for port %s failed: %s\n", endpoint, - gai_strerror(ret)); - if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) - return RPC_S_INVALID_ENDPOINT_FORMAT; - return RPC_S_CANT_CREATE_ENDPOINT; - } - - for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) - { - RpcConnection_tcp *tcpc; - RPC_STATUS create_status; - - if (TRACE_ON(rpc)) - { - char host[256]; - char service[256]; - getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, - host, sizeof(host), service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV); - TRACE("trying %s:%s\n", host, service); - } - - sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); - if (sock == -1) - { - WARN("socket() failed: %s\n", strerror(errno)); - status = RPC_S_CANT_CREATE_ENDPOINT; - continue; - } - - ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); - if (ret < 0) - { - WARN("bind failed: %s\n", strerror(errno)); - closesocket(sock); - if (errno == EADDRINUSE) - status = RPC_S_DUPLICATE_ENDPOINT; - else - status = RPC_S_CANT_CREATE_ENDPOINT; - continue; - } - create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, - protseq->Protseq, NULL, - endpoint, NULL, NULL, NULL); - if (create_status != RPC_S_OK) - { - closesocket(sock); - status = create_status; - continue; - } - - tcpc->sock = sock; - ret = listen(sock, protseq->MaxCalls); - if (ret < 0) - { - WARN("listen failed: %s\n", strerror(errno)); - RPCRT4_DestroyConnection(&tcpc->common); - status = RPC_S_OUT_OF_RESOURCES; - continue; - } - /* need a non-blocking socket, otherwise accept() has a potential - * race-condition (poll() says it is readable, connection drops, - * and accept() blocks until the next connection comes...) - */ - ret = fcntl(sock, F_SETFL, O_NONBLOCK); - if (ret < 0) - { - WARN("couldn't make socket non-blocking, error %d\n", ret); - RPCRT4_DestroyConnection(&tcpc->common); - status = RPC_S_OUT_OF_RESOURCES; - continue; - } - - tcpc->common.Next = first_connection; - first_connection = &tcpc->common; - } - - freeaddrinfo(ai); - - /* if at least one connection was created for an endpoint then - * return success */ - if (first_connection) - { - RpcConnection *conn; - - /* find last element in list */ - for (conn = first_connection; conn->Next; conn = conn->Next) - ; - - EnterCriticalSection(&protseq->cs); - conn->Next = protseq->conn; - protseq->conn = first_connection; - LeaveCriticalSection(&protseq->cs); - - TRACE("listening on %s\n", endpoint); - return RPC_S_OK; - } - - ERR("couldn't listen on port %s\n", endpoint); - return status; -} - -static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) -{ - int ret; - struct sockaddr_in address; - socklen_t addrsize; - RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; - RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; - - addrsize = sizeof(address); - ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); - if (ret < 0) - { - ERR("Failed to accept a TCP connection: error %d\n", ret); - return RPC_S_OUT_OF_RESOURCES; - } - /* reset to blocking behaviour */ - fcntl(ret, F_SETFL, 0); - client->sock = ret; - TRACE("Accepted a new TCP connection\n"); - return RPC_S_OK; -} - -static int rpcrt4_conn_tcp_read(RpcConnection *Connection, - void *buffer, unsigned int count) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int bytes_read = 0; - do - { - int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0); - if (!r) - return -1; - else if (r > 0) - bytes_read += r; - else if (errno != EAGAIN) - { - WARN("recv() failed: %s\n", strerror(errno)); - return -1; - } - else - { - struct pollfd pfds[2]; - pfds[0].fd = tcpc->sock; - pfds[0].events = POLLIN; - pfds[1].fd = tcpc->cancel_fds[0]; - pfds[1].events = POLLIN; - if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR) - { - ERR("poll() failed: %s\n", strerror(errno)); - return -1; - } - if (pfds[1].revents & POLLIN) /* canceled */ - { - char dummy; - read(pfds[1].fd, &dummy, sizeof(dummy)); - return -1; - } - } - } while (bytes_read != count); - TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read); - return bytes_read; -} - -static int rpcrt4_conn_tcp_write(RpcConnection *Connection, - const void *buffer, unsigned int count) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int bytes_written = 0; - do - { - int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0); - if (r >= 0) - bytes_written += r; - else if (errno != EAGAIN) - return -1; - else - { - struct pollfd pfd; - pfd.fd = tcpc->sock; - pfd.events = POLLOUT; - if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR) - { - ERR("poll() failed: %s\n", strerror(errno)); - return -1; - } - } - } while (bytes_written != count); - TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written); - return bytes_written; -} - -static int rpcrt4_conn_tcp_close(RpcConnection *Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - - TRACE("%d\n", tcpc->sock); - - if (tcpc->sock != -1) - closesocket(tcpc->sock); - tcpc->sock = -1; - close(tcpc->cancel_fds[0]); - close(tcpc->cancel_fds[1]); - return 0; -} - -static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - SOCKET dummy = 1; - - TRACE("%p\n", Connection); - - write(tcpc->cancel_fds[1], &dummy, 1); -} - -static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - struct pollfd pfds[2]; - - TRACE("%p\n", Connection); - - pfds[0].fd = tcpc->sock; - pfds[0].events = POLLIN; - pfds[1].fd = tcpc->cancel_fds[0]; - pfds[1].events = POLLIN; - if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR) - { - ERR("poll() failed: %s\n", strerror(errno)); - return -1; - } - if (pfds[1].revents & POLLIN) /* canceled */ - { - char dummy; - read(pfds[1].fd, &dummy, sizeof(dummy)); - return -1; - } - - return 0; -} - -static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, - const char *networkaddr, - const char *endpoint) +static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + unsigned char tcp_protid, + const char *endpoint) { twr_tcp_floor_t *tcp_floor; twr_ipv4_floor_t *ipv4_floor; @@ -1146,7 +910,7 @@ static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, ipv4_floor = (twr_ipv4_floor_t *)tower_data; tcp_floor->count_lhs = sizeof(tcp_floor->protid); - tcp_floor->protid = EPM_PROTOCOL_TCP; + tcp_floor->protid = tcp_protid; tcp_floor->count_rhs = sizeof(tcp_floor->port); ipv4_floor->count_lhs = sizeof(ipv4_floor->protid); @@ -1191,10 +955,11 @@ static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, return size; } -static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, - size_t tower_size, - char **networkaddr, - char **endpoint) +static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + unsigned char tcp_protid, + char **endpoint) { const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; const twr_ipv4_floor_t *ipv4_floor; @@ -1214,7 +979,7 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *to ipv4_floor = (const twr_ipv4_floor_t *)tower_data; if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || - (tcp_floor->protid != EPM_PROTOCOL_TCP) || + (tcp_floor->protid != tcp_protid) || (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || (ipv4_floor->protid != EPM_PROTOCOL_IP) || @@ -1259,6 +1024,528 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *to return RPC_S_OK; } +typedef struct _RpcConnection_tcp +{ + RpcConnection common; + int sock; +#ifdef HAVE_SOCKETPAIR + int cancel_fds[2]; +#else + HANDLE sock_event; + HANDLE cancel_event; +#endif +} RpcConnection_tcp; + +#ifdef HAVE_SOCKETPAIR + +static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) +{ + if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0) + { + ERR("socketpair() failed: %s\n", strerror(errno)); + return FALSE; + } + return TRUE; +} + +static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc) +{ + struct pollfd pfds[2]; + pfds[0].fd = tcpc->sock; + pfds[0].events = POLLIN; + pfds[1].fd = tcpc->cancel_fds[0]; + pfds[1].events = POLLIN; + if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR) + { + ERR("poll() failed: %s\n", strerror(errno)); + return FALSE; + } + if (pfds[1].revents & POLLIN) /* canceled */ + { + char dummy; + read(pfds[1].fd, &dummy, sizeof(dummy)); + return FALSE; + } + return TRUE; +} + +static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc) +{ + struct pollfd pfd; + pfd.fd = tcpc->sock; + pfd.events = POLLOUT; + if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR) + { + ERR("poll() failed: %s\n", strerror(errno)); + return FALSE; + } + return TRUE; +} + +static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc) +{ + char dummy = 1; + + write(tcpc->cancel_fds[1], &dummy, 1); +} + +static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc) +{ + close(tcpc->cancel_fds[0]); + close(tcpc->cancel_fds[1]); +} + +#else /* HAVE_SOCKETPAIR */ + +static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) +{ + static BOOL wsa_inited; + if (!wsa_inited) + { + WSADATA wsadata; + WSAStartup(MAKEWORD(2, 2), &wsadata); + /* Note: WSAStartup can be called more than once so we don't bother with + * making accesses to wsa_inited thread-safe */ + wsa_inited = TRUE; + } + tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL); + tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!tcpc->sock_event || !tcpc->cancel_event) + { + ERR("event creation failed\n"); + if (tcpc->sock_event) CloseHandle(tcpc->sock_event); + return FALSE; + } + return TRUE; +} + +static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc) +{ + HANDLE wait_handles[2]; + DWORD res; + if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR) + { + ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); + return FALSE; + } + wait_handles[0] = tcpc->sock_event; + wait_handles[1] = tcpc->cancel_event; + res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE); + switch (res) + { + case WAIT_OBJECT_0: + return TRUE; + case WAIT_OBJECT_0 + 1: + return FALSE; + default: + ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); + return FALSE; + } +} + +static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc) +{ + DWORD res; + if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR) + { + ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); + return FALSE; + } + res = WaitForSingleObject(tcpc->sock_event, INFINITE); + switch (res) + { + case WAIT_OBJECT_0: + return TRUE; + default: + ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); + return FALSE; + } +} + +static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc) +{ + SetEvent(tcpc->cancel_event); +} + +static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc) +{ + CloseHandle(tcpc->sock_event); + CloseHandle(tcpc->cancel_event); +} + +#endif + +static RpcConnection *rpcrt4_conn_tcp_alloc(void) +{ + RpcConnection_tcp *tcpc; + tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); + if (tcpc == NULL) + return NULL; + tcpc->sock = -1; + if (!rpcrt4_sock_wait_init(tcpc)) + { + HeapFree(GetProcessHeap(), 0, tcpc); + return NULL; + } + return &tcpc->common; +} + +static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int sock; + int ret; + struct addrinfo *ai; + struct addrinfo *ai_cur; + struct addrinfo hints; + + TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); + + if (tcpc->sock != -1) + return RPC_S_OK; + + hints.ai_flags = 0; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); + if (ret) + { + ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, + Connection->Endpoint, gai_strerror(ret)); + return RPC_S_SERVER_UNAVAILABLE; + } + + for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) + { + int val; + u_long nonblocking; + + if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) + { + TRACE("skipping non-IP/IPv6 address family\n"); + continue; + } + + if (TRACE_ON(rpc)) + { + char host[256]; + char service[256]; + getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + TRACE("trying %s:%s\n", host, service); + } + + sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); + if (sock == -1) + { + WARN("socket() failed: %s\n", strerror(errno)); + continue; + } + + if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) + { + WARN("connect() failed: %s\n", strerror(errno)); + closesocket(sock); + continue; + } + + /* RPC depends on having minimal latency so disable the Nagle algorithm */ + val = 1; + setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); + nonblocking = 1; + ioctlsocket(sock, FIONBIO, &nonblocking); + + tcpc->sock = sock; + + freeaddrinfo(ai); + TRACE("connected\n"); + return RPC_S_OK; + } + + freeaddrinfo(ai); + ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); + return RPC_S_SERVER_UNAVAILABLE; +} + +static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) +{ + RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; + int sock; + int ret; + struct addrinfo *ai; + struct addrinfo *ai_cur; + struct addrinfo hints; + RpcConnection *first_connection = NULL; + + TRACE("(%p, %s)\n", protseq, endpoint); + + hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai); + if (ret) + { + ERR("getaddrinfo for port %s failed: %s\n", endpoint, + gai_strerror(ret)); + if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) + return RPC_S_INVALID_ENDPOINT_FORMAT; + return RPC_S_CANT_CREATE_ENDPOINT; + } + + for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) + { + RpcConnection_tcp *tcpc; + RPC_STATUS create_status; + struct sockaddr_storage sa; + socklen_t sa_len; + char service[NI_MAXSERV]; + u_long nonblocking; + + if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) + { + TRACE("skipping non-IP/IPv6 address family\n"); + continue; + } + + if (TRACE_ON(rpc)) + { + char host[256]; + getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + TRACE("trying %s:%s\n", host, service); + } + + sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); + if (sock == -1) + { + WARN("socket() failed: %s\n", strerror(errno)); + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + + ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); + if (ret < 0) + { + WARN("bind failed: %s\n", strerror(errno)); + closesocket(sock); + if (errno == EADDRINUSE) + status = RPC_S_DUPLICATE_ENDPOINT; + else + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + + sa_len = sizeof(sa); + if (getsockname(sock, (struct sockaddr *)&sa, &sa_len)) + { + WARN("getsockname() failed: %s\n", strerror(errno)); + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + + ret = getnameinfo((struct sockaddr *)&sa, sa_len, + NULL, 0, service, sizeof(service), + NI_NUMERICSERV); + if (ret) + { + WARN("getnameinfo failed: %s\n", gai_strerror(ret)); + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + + create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, + protseq->Protseq, NULL, + service, NULL, NULL, NULL); + if (create_status != RPC_S_OK) + { + closesocket(sock); + status = create_status; + continue; + } + + tcpc->sock = sock; + ret = listen(sock, protseq->MaxCalls); + if (ret < 0) + { + WARN("listen failed: %s\n", strerror(errno)); + RPCRT4_DestroyConnection(&tcpc->common); + status = RPC_S_OUT_OF_RESOURCES; + continue; + } + /* need a non-blocking socket, otherwise accept() has a potential + * race-condition (poll() says it is readable, connection drops, + * and accept() blocks until the next connection comes...) + */ + nonblocking = 1; + ret = ioctlsocket(sock, FIONBIO, &nonblocking); + if (ret < 0) + { + WARN("couldn't make socket non-blocking, error %d\n", ret); + RPCRT4_DestroyConnection(&tcpc->common); + status = RPC_S_OUT_OF_RESOURCES; + continue; + } + + tcpc->common.Next = first_connection; + first_connection = &tcpc->common; + + /* since IPv4 and IPv6 share the same port space, we only need one + * successful bind to listen for both */ + break; + } + + freeaddrinfo(ai); + + /* if at least one connection was created for an endpoint then + * return success */ + if (first_connection) + { + RpcConnection *conn; + + /* find last element in list */ + for (conn = first_connection; conn->Next; conn = conn->Next) + ; + + EnterCriticalSection(&protseq->cs); + conn->Next = protseq->conn; + protseq->conn = first_connection; + LeaveCriticalSection(&protseq->cs); + + TRACE("listening on %s\n", endpoint); + return RPC_S_OK; + } + + ERR("couldn't listen on port %s\n", endpoint); + return status; +} + +static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + int ret; + struct sockaddr_in address; + socklen_t addrsize; + RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; + RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; + u_long nonblocking; + + addrsize = sizeof(address); + ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); + if (ret < 0) + { + ERR("Failed to accept a TCP connection: error %d\n", ret); + return RPC_S_OUT_OF_RESOURCES; + } + nonblocking = 1; + ioctlsocket(ret, FIONBIO, &nonblocking); + client->sock = ret; + TRACE("Accepted a new TCP connection\n"); + return RPC_S_OK; +} + +static int rpcrt4_conn_tcp_read(RpcConnection *Connection, + void *buffer, unsigned int count) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int bytes_read = 0; + while (bytes_read != count) + { + int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0); + if (!r) + return -1; + else if (r > 0) + bytes_read += r; + else if (errno != EAGAIN) + { + WARN("recv() failed: %s\n", strerror(errno)); + return -1; + } + else + { + if (!rpcrt4_sock_wait_for_recv(tcpc)) + return -1; + } + } + TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read); + return bytes_read; +} + +static int rpcrt4_conn_tcp_write(RpcConnection *Connection, + const void *buffer, unsigned int count) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int bytes_written = 0; + while (bytes_written != count) + { + int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0); + if (r >= 0) + bytes_written += r; + else if (errno != EAGAIN) + return -1; + else + { + if (!rpcrt4_sock_wait_for_send(tcpc)) + return -1; + } + } + TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written); + return bytes_written; +} + +static int rpcrt4_conn_tcp_close(RpcConnection *Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + + TRACE("%d\n", tcpc->sock); + + if (tcpc->sock != -1) + closesocket(tcpc->sock); + tcpc->sock = -1; + rpcrt4_sock_wait_destroy(tcpc); + return 0; +} + +static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + TRACE("%p\n", Connection); + rpcrt4_sock_wait_cancel(tcpc); +} + +static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + + TRACE("%p\n", Connection); + + if (!rpcrt4_sock_wait_for_recv(tcpc)) + return -1; + return 0; +} + +static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + const char *endpoint) +{ + return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, + EPM_PROTOCOL_TCP, endpoint); +} + +#ifdef HAVE_SOCKETPAIR + typedef struct _RpcServerProtseq_sock { RpcServerProtseq common; @@ -1271,7 +1558,7 @@ static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); if (ps) { - SOCKET fds[2]; + int fds[2]; if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) { fcntl(fds[0], F_SETFL, O_NONBLOCK); @@ -1398,8 +1685,1103 @@ static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq return 1; } +#else /* HAVE_SOCKETPAIR */ + +typedef struct _RpcServerProtseq_sock +{ + RpcServerProtseq common; + HANDLE mgr_event; +} RpcServerProtseq_sock; + +static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) +{ + RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); + if (ps) + { + static BOOL wsa_inited; + if (!wsa_inited) + { + WSADATA wsadata; + WSAStartup(MAKEWORD(2, 2), &wsadata); + /* Note: WSAStartup can be called more than once so we don't bother with + * making accesses to wsa_inited thread-safe */ + wsa_inited = TRUE; + } + ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); + } + return &ps->common; +} + +static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) +{ + RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); + SetEvent(sockps->mgr_event); +} + +static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) +{ + HANDLE *objs = prev_array; + RpcConnection_tcp *conn; + RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); + + EnterCriticalSection(&protseq->cs); + + /* open and count connections */ + *count = 1; + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); + while (conn) + { + if (conn->sock != -1) + (*count)++; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); + } + + /* make array of connections */ + if (objs) + objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); + else + objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); + if (!objs) + { + ERR("couldn't allocate objs\n"); + LeaveCriticalSection(&protseq->cs); + return NULL; + } + + objs[0] = sockps->mgr_event; + *count = 1; + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); + while (conn) + { + if (conn->sock != -1) + { + int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT); + if (res == SOCKET_ERROR) + ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); + else + { + objs[*count] = conn->sock_event; + (*count)++; + } + } + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); + } + LeaveCriticalSection(&protseq->cs); + return objs; +} + +static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) +{ + HeapFree(GetProcessHeap(), 0, array); +} + +static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) +{ + HANDLE b_handle; + HANDLE *objs = wait_array; + DWORD res; + RpcConnection *cconn; + RpcConnection_tcp *conn; + + if (!objs) + return -1; + + do + { + /* an alertable wait isn't strictly necessary, but due to our + * overlapped I/O implementation in Wine we need to free some memory + * by the file user APC being called, even if no completion routine was + * specified at the time of starting the async operation */ + res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); + } while (res == WAIT_IO_COMPLETION); + + if (res == WAIT_OBJECT_0) + return 0; + else if (res == WAIT_FAILED) + { + ERR("wait failed with error %d\n", GetLastError()); + return -1; + } + else + { + b_handle = objs[res - WAIT_OBJECT_0]; + /* find which connection got a RPC */ + EnterCriticalSection(&protseq->cs); + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); + while (conn) + { + if (b_handle == conn->sock_event) break; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); + } + cconn = NULL; + if (conn) + RPCRT4_SpawnConnection(&cconn, &conn->common); + else + ERR("failed to locate connection for handle %p\n", b_handle); + LeaveCriticalSection(&protseq->cs); + if (cconn) + { + RPCRT4_new_client(cconn); + return 1; + } + else return -1; + } +} + #endif /* HAVE_SOCKETPAIR */ +static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + char **endpoint) +{ + return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, + networkaddr, EPM_PROTOCOL_TCP, + endpoint); +} + +#if 0 +/**** ncacn_http support ****/ + +/* 60 seconds is the period native uses */ +#define HTTP_IDLE_TIME 60000 + +/* reference counted to avoid a race between a cancelled call's connection + * being destroyed and the asynchronous InternetReadFileEx call being + * completed */ +typedef struct _RpcHttpAsyncData +{ + LONG refs; + HANDLE completion_event; + INTERNET_BUFFERSA inet_buffers; + void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be + * copied into when the call completes */ + CRITICAL_SECTION cs; +} RpcHttpAsyncData; + +static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data) +{ + return InterlockedIncrement(&data->refs); +} + +static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data) +{ + ULONG refs = InterlockedDecrement(&data->refs); + if (!refs) + { + TRACE("destroying async data %p\n", data); + CloseHandle(data->completion_event); + HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer); + DeleteCriticalSection(&data->cs); + HeapFree(GetProcessHeap(), 0, data); + } + return refs; +} + +typedef struct _RpcConnection_http +{ + RpcConnection common; + HINTERNET app_info; + HINTERNET session; + HINTERNET in_request; + HINTERNET out_request; + HANDLE timer_cancelled; + HANDLE cancel_event; + DWORD last_sent_time; + ULONG bytes_received; + ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */ + ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */ + UUID connection_uuid; + UUID in_pipe_uuid; + UUID out_pipe_uuid; + RpcHttpAsyncData *async_data; +} RpcConnection_http; + +static RpcConnection *rpcrt4_ncacn_http_alloc(void) +{ + RpcConnection_http *httpc; + httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc)); + if (!httpc) return NULL; + httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData)); + if (!httpc->async_data) + { + HeapFree(GetProcessHeap(), 0, httpc); + return NULL; + } + TRACE("async data = %p\n", httpc->async_data); + httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); + httpc->async_data->refs = 1; + httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); + httpc->async_data->inet_buffers.lpvBuffer = NULL; + httpc->async_data->destination_buffer = NULL; + InitializeCriticalSection(&httpc->async_data->cs); + return &httpc->common; +} + +typedef struct _HttpTimerThreadData +{ + PVOID timer_param; + DWORD *last_sent_time; + HANDLE timer_cancelled; +} HttpTimerThreadData; + +static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy) +{ + HINTERNET in_request = param; + RpcPktHdr *idle_pkt; + + idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001, + 0, 0); + if (idle_pkt) + { + DWORD bytes_written; + InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written); + RPCRT4_FreeHeader(idle_pkt); + } +} + +static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time) +{ + DWORD cur_time = GetTickCount(); + DWORD cached_last_sent_time = *last_sent_time; + return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time); +} + +static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param) +{ + HttpTimerThreadData *data_in = param; + HttpTimerThreadData data; + DWORD timeout; + + data = *data_in; + HeapFree(GetProcessHeap(), 0, data_in); + + for (timeout = HTTP_IDLE_TIME; + WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT; + timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time)) + { + /* are we too soon after last send? */ + if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time) + continue; + rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE); + } + + CloseHandle(data.timer_cancelled); + return 0; +} + +static VOID WINAPI rpcrt4_http_internet_callback( + HINTERNET hInternet, + DWORD_PTR dwContext, + DWORD dwInternetStatus, + LPVOID lpvStatusInformation, + DWORD dwStatusInformationLength) +{ + RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext; + + switch (dwInternetStatus) + { + case INTERNET_STATUS_REQUEST_COMPLETE: + TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n"); + if (async_data) + { + if (async_data->inet_buffers.lpvBuffer) + { + EnterCriticalSection(&async_data->cs); + if (async_data->destination_buffer) + { + memcpy(async_data->destination_buffer, + async_data->inet_buffers.lpvBuffer, + async_data->inet_buffers.dwBufferLength); + async_data->destination_buffer = NULL; + } + LeaveCriticalSection(&async_data->cs); + } + HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer); + async_data->inet_buffers.lpvBuffer = NULL; + SetEvent(async_data->completion_event); + RpcHttpAsyncData_Release(async_data); + } + break; + } +} + +static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor) +{ + BOOL ret; + DWORD status_code; + DWORD size; + DWORD index; + WCHAR buf[32]; + WCHAR *status_text = buf; + TRACE("\n"); + + index = 0; + size = sizeof(status_code); + ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index); + if (!ret) + return GetLastError(); + if (status_code < 400) + return RPC_S_OK; + index = 0; + size = sizeof(buf); + ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); + if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + status_text = HeapAlloc(GetProcessHeap(), 0, size); + ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); + } + + ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : ""); + if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text); + + if (status_code == HTTP_STATUS_DENIED) + return ERROR_ACCESS_DENIED; + return RPC_S_SERVER_UNAVAILABLE; +} + +static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc) +{ + static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0}; + LPWSTR proxy = NULL; + LPWSTR user = NULL; + LPWSTR password = NULL; + LPWSTR servername = NULL; + const WCHAR *option; + INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */ + + if (httpc->common.QOS && + (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)) + { + const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials; + if (http_cred->TransportCredentials) + { + WCHAR *p; + const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials; + ULONG len = cred->DomainLength + 1 + cred->UserLength; + user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + if (!user) + return RPC_S_OUT_OF_RESOURCES; + p = user; + if (cred->DomainLength) + { + memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR)); + p += cred->DomainLength; + *p = '\\'; + p++; + } + memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR)); + p[cred->UserLength] = 0; + + password = RPCRT4_strndupW(cred->Password, cred->PasswordLength); + } + } + + for (option = httpc->common.NetworkOptions; option; + option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL)) + { + static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0}; + static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0}; + + if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1)) + { + const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1; + const WCHAR *value_end; + const WCHAR *p; + + value_end = strchrW(option, ','); + if (!value_end) + value_end = value_start + strlenW(value_start); + for (p = value_start; p < value_end; p++) + if (*p == ':') + { + port = atoiW(p+1); + value_end = p; + break; + } + TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); + servername = RPCRT4_strndupW(value_start, value_end-value_start); + } + else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1)) + { + const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1; + const WCHAR *value_end; + + value_end = strchrW(option, ','); + if (!value_end) + value_end = value_start + strlenW(value_start); + TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); + proxy = RPCRT4_strndupW(value_start, value_end-value_start); + } + else + FIXME("unhandled option %s\n", debugstr_w(option)); + } + + httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG, + NULL, NULL, INTERNET_FLAG_ASYNC); + if (!httpc->app_info) + { + HeapFree(GetProcessHeap(), 0, password); + HeapFree(GetProcessHeap(), 0, user); + ERR("InternetOpenW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback); + + /* if no RpcProxy option specified, set the HTTP server address to the + * RPC server address */ + if (!servername) + { + servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR)); + if (!servername) + { + HeapFree(GetProcessHeap(), 0, password); + HeapFree(GetProcessHeap(), 0, user); + return RPC_S_OUT_OF_RESOURCES; + } + MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1); + } + + httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password, + INTERNET_SERVICE_HTTP, 0, 0); + + HeapFree(GetProcessHeap(), 0, password); + HeapFree(GetProcessHeap(), 0, user); + HeapFree(GetProcessHeap(), 0, servername); + + if (!httpc->session) + { + ERR("InternetConnectW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + + return RPC_S_OK; +} + +/* prepare the in pipe for use by RPC packets */ +static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, + const UUID *connection_uuid, + const UUID *in_pipe_uuid, + const UUID *association_uuid) +{ + BYTE packet[44]; + BOOL ret; + RPC_STATUS status; + RpcPktHdr *hdr; + INTERNET_BUFFERSW buffers_in; + DWORD bytes_read, bytes_written; + + /* prepare in pipe */ + ResetEvent(async_data->completion_event); + RpcHttpAsyncData_AddRef(async_data); + ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0); + if (!ret) + { + if (GetLastError() == ERROR_IO_PENDING) + WaitForSingleObject(async_data->completion_event, INFINITE); + else + { + RpcHttpAsyncData_Release(async_data); + ERR("HttpSendRequestW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + } + status = rpcrt4_http_check_response(in_request); + if (status != RPC_S_OK) return status; + + InternetReadFile(in_request, packet, 20, &bytes_read); + /* FIXME: do something with retrieved data */ + + memset(&buffers_in, 0, sizeof(buffers_in)); + buffers_in.dwStructSize = sizeof(buffers_in); + /* FIXME: get this from the registry */ + buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */ + ResetEvent(async_data->completion_event); + RpcHttpAsyncData_AddRef(async_data); + ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0); + if (!ret) + { + if (GetLastError() == ERROR_IO_PENDING) + WaitForSingleObject(async_data->completion_event, INFINITE); + else + { + RpcHttpAsyncData_Release(async_data); + ERR("HttpSendRequestExW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + } + + TRACE("sending HTTP connect header to server\n"); + hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid); + if (!hdr) return RPC_S_OUT_OF_RESOURCES; + ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written); + RPCRT4_FreeHeader(hdr); + if (!ret) + { + ERR("InternetWriteFile failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data) +{ + BOOL ret; + DWORD bytes_read; + unsigned short data_len; + + ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read); + if (!ret) + return RPC_S_SERVER_UNAVAILABLE; + if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http)) + { + ERR("wrong packet type received %d or wrong frag_len %d\n", + hdr->common.ptype, hdr->common.frag_len); + return RPC_S_PROTOCOL_ERROR; + } + + ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read); + if (!ret) + return RPC_S_SERVER_UNAVAILABLE; + + data_len = hdr->common.frag_len - sizeof(hdr->http); + if (data_len) + { + *data = HeapAlloc(GetProcessHeap(), 0, data_len); + if (!*data) + return RPC_S_OUT_OF_RESOURCES; + ret = InternetReadFile(request, *data, data_len, &bytes_read); + if (!ret) + { + HeapFree(GetProcessHeap(), 0, *data); + return RPC_S_SERVER_UNAVAILABLE; + } + } + else + *data = NULL; + + if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len)) + { + ERR("invalid http packet\n"); + return RPC_S_PROTOCOL_ERROR; + } + + return RPC_S_OK; +} + +/* prepare the out pipe for use by RPC packets */ +static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, + RpcHttpAsyncData *async_data, + const UUID *connection_uuid, + const UUID *out_pipe_uuid, + ULONG *flow_control_increment) +{ + BYTE packet[20]; + BOOL ret; + RPC_STATUS status; + RpcPktHdr *hdr; + DWORD bytes_read; + BYTE *data_from_server; + RpcPktHdr pkt_from_server; + ULONG field1, field3; + + ResetEvent(async_data->completion_event); + RpcHttpAsyncData_AddRef(async_data); + ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0); + if (!ret) + { + if (GetLastError() == ERROR_IO_PENDING) + WaitForSingleObject(async_data->completion_event, INFINITE); + else + { + RpcHttpAsyncData_Release(async_data); + ERR("HttpSendRequestW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + } + status = rpcrt4_http_check_response(out_request); + if (status != RPC_S_OK) return status; + + InternetReadFile(out_request, packet, 20, &bytes_read); + /* FIXME: do something with retrieved data */ + + hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL); + if (!hdr) return RPC_S_OUT_OF_RESOURCES; + ResetEvent(async_data->completion_event); + RpcHttpAsyncData_AddRef(async_data); + ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len); + if (!ret) + { + if (GetLastError() == ERROR_IO_PENDING) + WaitForSingleObject(async_data->completion_event, INFINITE); + else + { + RpcHttpAsyncData_Release(async_data); + ERR("HttpSendRequestW failed with error %d\n", GetLastError()); + RPCRT4_FreeHeader(hdr); + return RPC_S_SERVER_UNAVAILABLE; + } + } + RPCRT4_FreeHeader(hdr); + status = rpcrt4_http_check_response(out_request); + if (status != RPC_S_OK) return status; + + status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server, + &data_from_server); + if (status != RPC_S_OK) return status; + status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server, + &field1); + HeapFree(GetProcessHeap(), 0, data_from_server); + if (status != RPC_S_OK) return status; + TRACE("received (%d) from first prepare header\n", field1); + + status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server, + &data_from_server); + if (status != RPC_S_OK) return status; + status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server, + &field1, flow_control_increment, + &field3); + HeapFree(GetProcessHeap(), 0, data_from_server); + if (status != RPC_S_OK) return status; + TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3); + + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection) +{ + RpcConnection_http *httpc = (RpcConnection_http *)Connection; + static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0}; + static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0}; + static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0}; + static const WCHAR wszColon[] = {':',0}; + static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0}; + LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL }; + WCHAR *url; + RPC_STATUS status; + BOOL secure; + HttpTimerThreadData *timer_data; + HANDLE thread; + + TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); + + if (Connection->server) + { + ERR("ncacn_http servers not supported yet\n"); + return RPC_S_SERVER_UNAVAILABLE; + } + + if (httpc->in_request) + return RPC_S_OK; + + httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL); + + status = UuidCreate(&httpc->connection_uuid); + status = UuidCreate(&httpc->in_pipe_uuid); + status = UuidCreate(&httpc->out_pipe_uuid); + + status = rpcrt4_http_internet_connect(httpc); + if (status != RPC_S_OK) + return status; + + url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR)); + if (!url) + return RPC_S_OUT_OF_MEMORY; + memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix)); + MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1); + strcatW(url, wszColon); + MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1); + + secure = httpc->common.QOS && + (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) && + (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL); + + httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, + wszAcceptTypes, + (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE, + (DWORD_PTR)httpc->async_data); + if (!httpc->in_request) + { + ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, + wszAcceptTypes, + (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE, + (DWORD_PTR)httpc->async_data); + if (!httpc->out_request) + { + ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); + return RPC_S_SERVER_UNAVAILABLE; + } + + status = rpcrt4_http_prepare_in_pipe(httpc->in_request, + httpc->async_data, + &httpc->connection_uuid, + &httpc->in_pipe_uuid, + &Connection->assoc->http_uuid); + if (status != RPC_S_OK) + return status; + + status = rpcrt4_http_prepare_out_pipe(httpc->out_request, + httpc->async_data, + &httpc->connection_uuid, + &httpc->out_pipe_uuid, + &httpc->flow_control_increment); + if (status != RPC_S_OK) + return status; + + httpc->flow_control_mark = httpc->flow_control_increment / 2; + httpc->last_sent_time = GetTickCount(); + httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL); + + timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data)); + if (!timer_data) + return ERROR_OUTOFMEMORY; + timer_data->timer_param = httpc->in_request; + timer_data->last_sent_time = &httpc->last_sent_time; + timer_data->timer_cancelled = httpc->timer_cancelled; + /* FIXME: should use CreateTimerQueueTimer when implemented */ + thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL); + if (!thread) + { + HeapFree(GetProcessHeap(), 0, timer_data); + return GetLastError(); + } + CloseHandle(thread); + + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + assert(0); + return RPC_S_SERVER_UNAVAILABLE; +} + +static int rpcrt4_ncacn_http_read(RpcConnection *Connection, + void *buffer, unsigned int count) +{ + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + char *buf = buffer; + BOOL ret = TRUE; + unsigned int bytes_left = count; + + ResetEvent(httpc->async_data->completion_event); + while (bytes_left) + { + RpcHttpAsyncData_AddRef(httpc->async_data); + httpc->async_data->inet_buffers.dwBufferLength = bytes_left; + httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left); + httpc->async_data->destination_buffer = buf; + ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0); + if (ret) + { + /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our + * async ref now */ + RpcHttpAsyncData_Release(httpc->async_data); + memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer, + httpc->async_data->inet_buffers.dwBufferLength); + HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer); + httpc->async_data->inet_buffers.lpvBuffer = NULL; + httpc->async_data->destination_buffer = NULL; + } + else + { + if (GetLastError() == ERROR_IO_PENDING) + { + HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event }; + DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT); + if (result == WAIT_OBJECT_0) + ret = TRUE; + else + { + TRACE("call cancelled\n"); + EnterCriticalSection(&httpc->async_data->cs); + httpc->async_data->destination_buffer = NULL; + LeaveCriticalSection(&httpc->async_data->cs); + break; + } + } + else + { + HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer); + httpc->async_data->inet_buffers.lpvBuffer = NULL; + httpc->async_data->destination_buffer = NULL; + RpcHttpAsyncData_Release(httpc->async_data); + break; + } + } + if (!httpc->async_data->inet_buffers.dwBufferLength) + break; + bytes_left -= httpc->async_data->inet_buffers.dwBufferLength; + buf += httpc->async_data->inet_buffers.dwBufferLength; + } + TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE"); + return ret ? count : -1; +} + +static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) +{ + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + RPC_STATUS status; + DWORD hdr_length; + LONG dwRead; + RpcPktCommonHdr common_hdr; + + *Header = NULL; + + TRACE("(%p, %p, %p)\n", Connection, Header, Payload); + +again: + /* read packet common header */ + dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr)); + if (dwRead != sizeof(common_hdr)) { + WARN("Short read of header, %d bytes\n", dwRead); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) || + !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0"))) + { + FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr)); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + status = RPCRT4_ValidateCommonHeader(&common_hdr); + if (status != RPC_S_OK) goto fail; + + hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); + if (hdr_length == 0) { + WARN("header length == 0\n"); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); + if (!*Header) + { + status = RPC_S_OUT_OF_RESOURCES; + goto fail; + } + memcpy(*Header, &common_hdr, sizeof(common_hdr)); + + /* read the rest of packet header */ + dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); + if (dwRead != hdr_length - sizeof(common_hdr)) { + WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + if (common_hdr.frag_len - hdr_length) + { + *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length); + if (!*Payload) + { + status = RPC_S_OUT_OF_RESOURCES; + goto fail; + } + + dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length); + if (dwRead != common_hdr.frag_len - hdr_length) + { + WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + } + else + *Payload = NULL; + + if ((*Header)->common.ptype == PKT_HTTP) + { + if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length)) + { + ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + if ((*Header)->http.flags == 0x0001) + { + TRACE("http idle packet, waiting for real packet\n"); + if ((*Header)->http.num_data_items != 0) + { + ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + } + else if ((*Header)->http.flags == 0x0002) + { + ULONG bytes_transmitted; + ULONG flow_control_increment; + UUID pipe_uuid; + status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload, + Connection->server, + &bytes_transmitted, + &flow_control_increment, + &pipe_uuid); + if (status != RPC_S_OK) + goto fail; + TRACE("received http flow control header (0x%x, 0x%x, %s)\n", + bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid)); + /* FIXME: do something with parsed data */ + } + else + { + FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + RPCRT4_FreeHeader(*Header); + *Header = NULL; + HeapFree(GetProcessHeap(), 0, *Payload); + *Payload = NULL; + goto again; + } + + /* success */ + status = RPC_S_OK; + + httpc->bytes_received += common_hdr.frag_len; + + TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received); + + if (httpc->bytes_received > httpc->flow_control_mark) + { + RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server, + httpc->bytes_received, + httpc->flow_control_increment, + &httpc->out_pipe_uuid); + if (hdr) + { + DWORD bytes_written; + BOOL ret2; + TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received); + ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written); + RPCRT4_FreeHeader(hdr); + if (ret2) + httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2; + } + } + +fail: + if (status != RPC_S_OK) { + RPCRT4_FreeHeader(*Header); + *Header = NULL; + HeapFree(GetProcessHeap(), 0, *Payload); + *Payload = NULL; + } + return status; +} + +static int rpcrt4_ncacn_http_write(RpcConnection *Connection, + const void *buffer, unsigned int count) +{ + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + DWORD bytes_written; + BOOL ret; + + httpc->last_sent_time = ~0U; /* disable idle packet sending */ + ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written); + httpc->last_sent_time = GetTickCount(); + TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE"); + return ret ? bytes_written : -1; +} + +static int rpcrt4_ncacn_http_close(RpcConnection *Connection) +{ + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + + TRACE("\n"); + + SetEvent(httpc->timer_cancelled); + if (httpc->in_request) + InternetCloseHandle(httpc->in_request); + httpc->in_request = NULL; + if (httpc->out_request) + InternetCloseHandle(httpc->out_request); + httpc->out_request = NULL; + if (httpc->app_info) + InternetCloseHandle(httpc->app_info); + httpc->app_info = NULL; + if (httpc->session) + InternetCloseHandle(httpc->session); + httpc->session = NULL; + RpcHttpAsyncData_Release(httpc->async_data); + if (httpc->cancel_event) + CloseHandle(httpc->cancel_event); + + return 0; +} + +static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection) +{ + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + + SetEvent(httpc->cancel_event); +} + +static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection) +{ + BOOL ret; + RpcConnection_http *httpc = (RpcConnection_http *) Connection; + + RpcHttpAsyncData_AddRef(httpc->async_data); + ret = InternetQueryDataAvailable(httpc->out_request, + &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0); + if (ret) + { + /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our + * async ref now */ + RpcHttpAsyncData_Release(httpc->async_data); + } + else + { + if (GetLastError() == ERROR_IO_PENDING) + { + HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event }; + DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT); + if (result != WAIT_OBJECT_0) + { + TRACE("call cancelled\n"); + return -1; + } + } + else + { + RpcHttpAsyncData_Release(httpc->async_data); + return -1; + } + } + + /* success */ + return 0; +} + +static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + const char *endpoint) +{ + return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, + EPM_PROTOCOL_HTTP, endpoint); +} + +static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + char **endpoint) +{ + return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, + networkaddr, EPM_PROTOCOL_HTTP, + endpoint); +} + +#endif /* end http support */ + static const struct connection_ops conn_protseq_list[] = { { "ncacn_np", { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, @@ -1413,6 +2795,13 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_np_wait_for_incoming_data, rpcrt4_ncacn_np_get_top_of_tower, rpcrt4_ncacn_np_parse_top_of_tower, + NULL, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + rpcrt4_conn_np_impersonate_client, + rpcrt4_conn_np_revert_to_self, + RPCRT4_default_inquire_auth_client, }, { "ncalrpc", { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, @@ -1426,8 +2815,14 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_np_wait_for_incoming_data, rpcrt4_ncalrpc_get_top_of_tower, rpcrt4_ncalrpc_parse_top_of_tower, + NULL, + rpcrt4_ncalrpc_is_authorized, + rpcrt4_ncalrpc_authorize, + rpcrt4_ncalrpc_secure_packet, + rpcrt4_conn_np_impersonate_client, + rpcrt4_conn_np_revert_to_self, + rpcrt4_ncalrpc_inquire_auth_client, }, -#ifdef HAVE_SOCKETPAIR { "ncacn_ip_tcp", { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, rpcrt4_conn_tcp_alloc, @@ -1440,7 +2835,35 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_tcp_wait_for_incoming_data, rpcrt4_ncacn_ip_tcp_get_top_of_tower, rpcrt4_ncacn_ip_tcp_parse_top_of_tower, - } + NULL, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + RPCRT4_default_impersonate_client, + RPCRT4_default_revert_to_self, + RPCRT4_default_inquire_auth_client, + }, +#if 0 + { "ncacn_http", + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP }, + rpcrt4_ncacn_http_alloc, + rpcrt4_ncacn_http_open, + rpcrt4_ncacn_http_handoff, + rpcrt4_ncacn_http_read, + rpcrt4_ncacn_http_write, + rpcrt4_ncacn_http_close, + rpcrt4_ncacn_http_cancel_call, + rpcrt4_ncacn_http_wait_for_incoming_data, + rpcrt4_ncacn_http_get_top_of_tower, + rpcrt4_ncacn_http_parse_top_of_tower, + rpcrt4_ncacn_http_receive_fragment, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + RPCRT4_default_impersonate_client, + RPCRT4_default_revert_to_self, + RPCRT4_default_inquire_auth_client, + }, #endif }; @@ -1465,7 +2888,6 @@ static const struct protseq_ops protseq_list[] = rpcrt4_protseq_np_wait_for_new_connection, rpcrt4_protseq_ncalrpc_open_endpoint, }, -#ifdef HAVE_SOCKETPAIR { "ncacn_ip_tcp", rpcrt4_protseq_sock_alloc, @@ -1475,7 +2897,6 @@ static const struct protseq_ops protseq_list[] = rpcrt4_protseq_sock_wait_for_new_connection, rpcrt4_protseq_ncacn_ip_tcp_open_endpoint, }, -#endif }; #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) @@ -1524,6 +2945,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) { + static LONG next_id; const struct connection_ops *ops; RpcConnection* NewConnection; @@ -1551,6 +2973,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, NewConnection->attr = 0; if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); NewConnection->AuthInfo = AuthInfo; + NewConnection->auth_context_id = InterlockedIncrement( &next_id ); NewConnection->encryption_auth_len = 0; NewConnection->signature_auth_len = 0; if (QOS) RpcQualityOfService_AddRef(QOS); diff --git a/reactos/dll/win32/rpcrt4/rpcrt4.spec b/reactos/dll/win32/rpcrt4/rpcrt4.spec index 4550889f62a..477b3f0734d 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4.spec +++ b/reactos/dll/win32/rpcrt4/rpcrt4.spec @@ -1,5 +1,5 @@ @ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) -@ stub CreateStubFromTypeInfo +@ stdcall CreateStubFromTypeInfo(ptr ptr ptr ptr) @ stdcall CStdStubBuffer_AddRef(ptr) @ stdcall CStdStubBuffer_Connect(ptr ptr) @ stdcall CStdStubBuffer_CountRefs(ptr) @@ -116,8 +116,9 @@ @ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) @ stub NDRcopy @ stdcall NdrAllocate(ptr long) -@ stub NdrAsyncClientCall +@ varargs NdrAsyncClientCall(ptr ptr) @ stub NdrAsyncServerCall +@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr) @ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) @ stdcall NdrByteCountPointerFree(ptr ptr ptr) @ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) @@ -340,10 +341,10 @@ @ stdcall RpcBindingFree(ptr) @ stdcall RpcBindingFromStringBindingA(str ptr) @ stdcall RpcBindingFromStringBindingW(wstr ptr) -@ stub RpcBindingInqAuthClientA -@ stub RpcBindingInqAuthClientExA -@ stub RpcBindingInqAuthClientExW -@ stub RpcBindingInqAuthClientW +@ stdcall RpcBindingInqAuthClientA(ptr ptr ptr ptr ptr ptr) +@ stdcall RpcBindingInqAuthClientExA(ptr ptr ptr ptr ptr ptr long) +@ stdcall RpcBindingInqAuthClientExW(ptr ptr ptr ptr ptr ptr long) +@ stdcall RpcBindingInqAuthClientW(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 RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr) @@ -370,7 +371,7 @@ @ stdcall RpcEpRegisterA(ptr ptr ptr str) @ stub RpcEpRegisterNoReplaceA @ stub RpcEpRegisterNoReplaceW -@ stub RpcEpRegisterW +@ stdcall RpcEpRegisterW(ptr ptr ptr wstr) @ stdcall RpcEpResolveBinding(ptr ptr) @ stdcall RpcEpUnregister(ptr ptr ptr) @ stub RpcErrorAddRecord # wxp diff --git a/reactos/dll/win32/rpcrt4/rpcrt4_main.c b/reactos/dll/win32/rpcrt4/rpcrt4_main.c index 537a00537bc..d499f475617 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4_main.c +++ b/reactos/dll/win32/rpcrt4/rpcrt4_main.c @@ -42,7 +42,8 @@ #include "winbase.h" #include "winuser.h" #include "winnt.h" -#include "winternl.h" +#include "ntndk.h" +#include "ntsecapi.h" #include "iptypes.h" #include "iphlpapi.h" #include "wine/unicode.h" @@ -53,6 +54,7 @@ #include "rpcproxy.h" #include "rpc_binding.h" +#include "rpc_server.h" #include "wine/debug.h" @@ -135,6 +137,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) break; case DLL_PROCESS_DETACH: + RPCRT4_destroy_all_protseqs(); + RPCRT4_ServerFreeAllRegisteredAuthInfo(); break; } @@ -280,6 +284,38 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) 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 resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ #define TICKS_PER_CLOCK_TICK 1000 @@ -299,7 +335,7 @@ static void RPC_UuidGetSystemTime(ULONGLONG *time) *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 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. Set the multicast bit to prevent conflicts with real cards. */ else { - for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { - address[i] = rand() & 0xff; - } - + RtlGenRandom(address, ADDRESS_BYTES_NEEDED); address[0] |= 0x01; 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. * @@ -346,12 +379,12 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * * 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 - * suggests using NVRAM for storing persistent + * suggests using NVRAM for storing persistent * values. */ -RPC_STATUS WINAPI UuidCreate(UUID *Uuid) +RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid) { static int initialised, count; @@ -399,7 +432,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) /* 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->Data3 = (unsigned short)((time >> 48) & 0x0fff); @@ -409,13 +442,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) Uuid->Data4[0] = sequence & 0xff; Uuid->Data4[1] = (sequence & 0x3f00) >> 8; Uuid->Data4[1] |= 0x80; - - 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]; + memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED); LeaveCriticalSection(&uuid_cs); @@ -424,22 +451,6 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) 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.@] diff --git a/reactos/dll/win32/rpcrt4/unix_func.c b/reactos/dll/win32/rpcrt4/unix_func.c index ad4de8b1fbb..e64af84f2e6 100644 --- a/reactos/dll/win32/rpcrt4/unix_func.c +++ b/reactos/dll/win32/rpcrt4/unix_func.c @@ -2,150 +2,9 @@ #include #include #include -#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 * +WSAAPI inet_ntop (int af, const void *src, char *dst, @@ -168,10 +27,3 @@ inet_ntop (int af, return 0; } -int fcntl(int fd, - int cmd, - long arg) -{ - // Stub - return 0; -}