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; -}