diff --git a/dll/win32/rpcrt4/cproxy.c b/dll/win32/rpcrt4/cproxy.c index 56ef84d2738..968c7b51568 100644 --- a/dll/win32/rpcrt4/cproxy.c +++ b/dll/win32/rpcrt4/cproxy.c @@ -19,9 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" - #include #define COBJMACROS @@ -36,6 +33,7 @@ #include "cpsf.h" #include "ndr_misc.h" #include "ndr_stubless.h" +#include "wine/asm.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -106,19 +104,21 @@ static inline void init_thunk( struct thunk *thunk, unsigned int index ) extern void call_stubless_func(void); __ASM_GLOBAL_FUNC(call_stubless_func, - "movq %rcx,0x8(%rsp)\n\t" - "movq %rdx,0x10(%rsp)\n\t" - "movq %r8,0x18(%rsp)\n\t" - "movq %r9,0x20(%rsp)\n\t" - "leaq 0x8(%rsp),%r8\n\t" /* &This */ + "subq $0x38,%rsp\n\t" + __ASM_SEH(".seh_stackalloc 0x38\n\t") + __ASM_SEH(".seh_endprologue\n\t") + __ASM_CFI(".cfi_adjust_cfa_offset 0x38\n\t") + "movq %rcx,0x40(%rsp)\n\t" + "movq %rdx,0x48(%rsp)\n\t" + "movq %r8,0x50(%rsp)\n\t" + "movq %r9,0x58(%rsp)\n\t" + "leaq 0x40(%rsp),%r8\n\t" /* &This */ "movq (%rcx),%rcx\n\t" /* This->lpVtbl */ "movq -0x10(%rcx),%rcx\n\t" /* MIDL_STUBLESS_PROXY_INFO */ "movq 0x10(%rcx),%rdx\n\t" /* info->FormatStringOffset */ "movzwq (%rdx,%r10,2),%rdx\n\t" /* FormatStringOffset[index] */ "addq 8(%rcx),%rdx\n\t" /* info->ProcFormatString + offset */ "movq (%rcx),%rcx\n\t" /* info->pStubDesc */ - "subq $0x38,%rsp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset 0x38\n\t") "movq %xmm1,0x20(%rsp)\n\t" "movq %xmm2,0x28(%rsp)\n\t" "movq %xmm3,0x30(%rsp)\n\t" @@ -196,6 +196,50 @@ static inline void init_thunk( struct thunk *thunk, unsigned int index ) thunk->func = call_stubless_func; } +#elif defined(__aarch64__) + +extern void call_stubless_func(void); +__ASM_GLOBAL_FUNC( call_stubless_func, + "stp x29, x30, [sp, #-0x90]!\n\t" + "mov x29, sp\n\t" + "stp d0, d1, [sp, #0x10]\n\t" + "stp d2, d3, [sp, #0x20]\n\t" + "stp d4, d5, [sp, #0x30]\n\t" + "stp d6, d7, [sp, #0x40]\n\t" + "stp x0, x1, [sp, #0x50]\n\t" + "stp x2, x3, [sp, #0x60]\n\t" + "stp x4, x5, [sp, #0x70]\n\t" + "stp x6, x7, [sp, #0x80]\n\t" + "ldr x0, [x0]\n\t" /* This->lpVtbl */ + "ldr x0, [x0, #-16]\n\t" /* MIDL_STUBLESS_PROXY_INFO */ + "ldp x1, x4, [x0, #8]\n\t" /* info->ProcFormatString, FormatStringOffset */ + "ldrh w4, [x4, x16, lsl #1]\n\t" /* info->FormatStringOffset[index] */ + "add x1, x1, x4\n\t" /* info->ProcFormatString + offset */ + "ldr x0, [x0]\n\t" /* info->pStubDesc */ + "add x2, sp, #0x50\n\t" /* stack */ + "add x3, sp, #0x10\n\t" /* fpu_stack */ + "bl " __ASM_NAME("ndr_client_call") "\n\t" + "ldp x29, x30, [sp], #0x90\n\t" + "ret" ) + +struct thunk +{ + DWORD ldr_index; /* ldr w16, index */ + DWORD ldr_func; /* ldr x17, func */ + DWORD br; /* br x17 */ + DWORD index; + void *func; +}; + +static inline void init_thunk( struct thunk *thunk, unsigned int index ) +{ + thunk->ldr_index = 0x18000070; /* ldr w16,index */ + thunk->ldr_func = 0x58000071; /* ldr x17,func */ + thunk->br = 0xd61f0220; /* br x17 */ + thunk->index = index; + thunk->func = call_stubless_func; +} + #else /* __i386__ */ #warning You must implement stubless proxies for your CPU @@ -457,6 +501,8 @@ void WINAPI NdrProxyInitialize(void *This, TRACE("(%p,%p,%p,%p,%d)\n", This, pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); StdProxy_GetChannel(This, &pStubMsg->pRpcChannelBuffer); + if (!pStubMsg->pRpcChannelBuffer) + RpcRaiseException(CO_E_OBJNOTCONNECTED); IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, &pStubMsg->dwDestContext, &pStubMsg->pvDestContext); diff --git a/dll/win32/rpcrt4/cpsf.c b/dll/win32/rpcrt4/cpsf.c index e92d226498c..0deb3beac74 100644 --- a/dll/win32/rpcrt4/cpsf.c +++ b/dll/win32/rpcrt4/cpsf.c @@ -18,9 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" - #include #include #include @@ -36,7 +33,6 @@ #include "rpcproxy.h" -#include "wine/unicode.h" #include "wine/debug.h" #include "cpsf.h" @@ -49,7 +45,7 @@ static void format_clsid( WCHAR *buffer, const CLSID *clsid ) '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X', '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','}',0}; - sprintfW( buffer, clsid_formatW, clsid->Data1, clsid->Data2, clsid->Data3, + swprintf( buffer, clsid_formatW, clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] ); @@ -261,14 +257,14 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, TRACE("registering %s %s => %s\n", debugstr_a(name), debugstr_guid(proxy->header.piid), debugstr_w(clsid)); - strcpyW( keyname, interfaceW ); - format_clsid( keyname + strlenW(keyname), proxy->header.piid ); + lstrcpyW( keyname, interfaceW ); + format_clsid( keyname + lstrlenW(keyname), proxy->header.piid ); if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) { WCHAR num[10]; if (name) RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE *)name, strlen(name)+1); RegSetValueW( key, clsid32W, REG_SZ, clsid, 0 ); - sprintfW(num, numformatW, proxy->header.DispatchTableCount); + swprintf(num, numformatW, proxy->header.DispatchTableCount); RegSetValueW( key, nummethodsW, REG_SZ, num, 0 ); RegCloseKey(key); } @@ -277,15 +273,15 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, } /* register clsid to point to module */ - strcpyW( keyname, clsidW ); - strcatW( keyname, clsid ); + lstrcpyW( keyname, clsidW ); + lstrcatW( keyname, clsid ); len = GetModuleFileNameW(hDll, module, ARRAY_SIZE(module)); if (len && len < sizeof(module)) { TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module)); if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) { RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW)); if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) { - RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR)); + RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (lstrlenW(module)+1)*sizeof(WCHAR)); RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW)); RegCloseKey(subkey); } @@ -325,16 +321,16 @@ HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll, TRACE("unregistering %s %s\n", debugstr_a(name), debugstr_guid(proxy->header.piid)); - strcpyW( keyname, interfaceW ); - format_clsid( keyname + strlenW(keyname), proxy->header.piid ); + lstrcpyW( keyname, interfaceW ); + format_clsid( keyname + lstrlenW(keyname), proxy->header.piid ); RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname); } pProxyFileList++; } /* unregister clsid */ - strcpyW( keyname, clsidW ); - strcatW( keyname, clsid ); + lstrcpyW( keyname, clsidW ); + lstrcatW( keyname, clsid ); RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname); return S_OK; diff --git a/dll/win32/rpcrt4/cstub.c b/dll/win32/rpcrt4/cstub.c index e33d499b155..7c351c002e8 100644 --- a/dll/win32/rpcrt4/cstub.c +++ b/dll/win32/rpcrt4/cstub.c @@ -19,9 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" - #include #define COBJMACROS @@ -186,6 +183,23 @@ typedef struct DWORD offset; } vtbl_method_t; +#elif defined(__aarch64__) + +static const DWORD opcodes[] = +{ + 0xf9401000, /* ldr x0, [x0,#32] */ + 0xf9400010, /* ldr x16, [x0] */ + 0x18000071, /* ldr w17, offset */ + 0xf8716a10, /* ldr x16, [x16,x17] */ + 0xd61f0200 /* br x16 */ +}; + +typedef struct +{ + DWORD opcodes[ARRAY_SIZE(opcodes)]; + DWORD offset; +} vtbl_method_t; + #else #warning You must implement delegated proxies/stubs for your CPU diff --git a/dll/win32/rpcrt4/ndr_contexthandle.c b/dll/win32/rpcrt4/ndr_contexthandle.c index a5e1ffc253d..848d924e970 100644 --- a/dll/win32/rpcrt4/ndr_contexthandle.c +++ b/dll/win32/rpcrt4/ndr_contexthandle.c @@ -263,9 +263,6 @@ void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding, if (!binding->server || !binding->Assoc) RpcRaiseException(RPC_S_INVALID_BINDING); - if (Flags & RPC_CONTEXT_HANDLE_FLAGS) - FIXME("unimplemented flags: 0x%x\n", Flags & RPC_CONTEXT_HANDLE_FLAGS); - if (SContext->userContext) { status = RpcServerAssoc_UpdateContextHandle(binding->Assoc, SContext, CtxGuard, userRunDownIn); @@ -337,9 +334,6 @@ NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding, if (!binding->server || !binding->Assoc) RpcRaiseException(RPC_S_INVALID_BINDING); - if (Flags & RPC_CONTEXT_HANDLE_FLAGS) - FIXME("unimplemented flags: 0x%x\n", Flags & RPC_CONTEXT_HANDLE_FLAGS); - if (!pBuff || (!context_ndr->attributes && UuidIsNil((UUID *)&context_ndr->uuid, &status))) status = RpcServerAssoc_AllocateContextHandle(binding->Assoc, CtxGuard, diff --git a/dll/win32/rpcrt4/ndr_marshall.c b/dll/win32/rpcrt4/ndr_marshall.c index 77bbf986ff3..764b304a047 100644 --- a/dll/win32/rpcrt4/ndr_marshall.c +++ b/dll/win32/rpcrt4/ndr_marshall.c @@ -42,7 +42,6 @@ #include "rpcndr.h" #include "ndrtypes.h" -#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -132,8 +131,6 @@ static inline void align_pointer_offset_clear( unsigned char **ptr, unsigned cha #define NDR_TABLE_SIZE 128 #define NDR_TABLE_MASK 127 -#define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL)) - static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); @@ -1873,7 +1870,7 @@ static inline void array_compute_and_size_conformance( else { TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; + pStubMsg->ActualCount = lstrlenW((LPCWSTR)pMemory)+1; } if (pFormat[1] == FC_STRING_SIZED) @@ -1996,7 +1993,7 @@ static inline void array_compute_and_write_conformance( else { TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; + pStubMsg->ActualCount = lstrlenW((LPCWSTR)pMemory)+1; } if (pFormat[1] == FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); @@ -7002,7 +6999,7 @@ static unsigned char *WINAPI NdrContextHandleMarshall( } else { - NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory); + NDR_SCONTEXT ctxt = CONTAINING_RECORD(pMemory, struct _NDR_SCONTEXT, userContext); NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]]; NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat); } @@ -7031,10 +7028,15 @@ static unsigned char *WINAPI NdrContextHandleUnmarshall( if (pStubMsg->IsClient) { + NDR_CCONTEXT *ccontext; + if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR) + ccontext = *(NDR_CCONTEXT **)ppMemory; + else + ccontext = (NDR_CCONTEXT *)ppMemory; /* [out]-only or [ret] param */ if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT) - **(NDR_CCONTEXT **)ppMemory = NULL; - NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); + *ccontext = NULL; + NdrClientContextUnmarshall(pStubMsg, ccontext, pStubMsg->RpcMsg->Handle); } else { @@ -7258,7 +7260,10 @@ NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, */ void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags) { - FIXME("(%p, %p, %d, 0x%x): semi-stub\n", pStubMsg, pMemory, CacheSize, Flags); + static int once; + + if (!once++) + FIXME("(%p, %p, %d, 0x%x): semi-stub\n", pStubMsg, pMemory, CacheSize, Flags); if (pStubMsg->CorrDespIncrement == 0) pStubMsg->CorrDespIncrement = 2; /* size of the normal (non-range) /robust payload */ @@ -7296,5 +7301,8 @@ void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg) */ void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg) { - FIXME("(%p): stub\n", pStubMsg); + static int once; + + if (!once++) + FIXME("(%p): stub\n", pStubMsg); } diff --git a/dll/win32/rpcrt4/ndr_stubless.c b/dll/win32/rpcrt4/ndr_stubless.c index c2f260c764a..cc52ee27e85 100644 --- a/dll/win32/rpcrt4/ndr_stubless.c +++ b/dll/win32/rpcrt4/ndr_stubless.c @@ -23,9 +23,6 @@ * - Some types of binding handles */ -#include "config.h" -#include "wine/port.h" - #include #include #include @@ -39,6 +36,7 @@ #include "rpcproxy.h" #include "wine/exception.h" +#include "wine/asm.h" #include "wine/debug.h" #include "cpsf.h" @@ -272,9 +270,22 @@ static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags #define ARG_FROM_OFFSET(args, offset) ((args) + (offset)) -static PFORMAT_STRING client_get_handle( - PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, - PFORMAT_STRING pFormat, handle_t *phBinding) +static size_t get_handle_desc_size(const NDR_PROC_HEADER *proc_header, PFORMAT_STRING format) +{ + if (!proc_header->handle_type) + { + if (*format == FC_BIND_PRIMITIVE) + return sizeof(NDR_EHD_PRIMITIVE); + else if (*format == FC_BIND_GENERIC) + return sizeof(NDR_EHD_GENERIC); + else if (*format == FC_BIND_CONTEXT) + return sizeof(NDR_EHD_CONTEXT); + } + return 0; +} + +static handle_t client_get_handle(const MIDL_STUB_MESSAGE *pStubMsg, + const NDR_PROC_HEADER *pProcHeader, const PFORMAT_STRING pFormat) { /* binding */ switch (pProcHeader->handle_type) @@ -290,10 +301,9 @@ static PFORMAT_STRING client_get_handle( TRACE("Explicit primitive handle @ %d\n", pDesc->offset); if (pDesc->flag) /* pointer to binding */ - *phBinding = **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); + return **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); else - *phBinding = *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); - return pFormat + sizeof(NDR_EHD_PRIMITIVE); + return *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); } case FC_BIND_GENERIC: /* explicit generic */ { @@ -310,8 +320,7 @@ static PFORMAT_STRING client_get_handle( 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); - return pFormat + sizeof(NDR_EHD_GENERIC); + return pGenPair->pfnBind(pObject); } case FC_BIND_CONTEXT: /* explicit context */ { @@ -326,7 +335,7 @@ static PFORMAT_STRING client_get_handle( else context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); - if (context_handle) *phBinding = NDRCContextBinding(context_handle); + if (context_handle) return NDRCContextBinding(context_handle); else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) { ERR("null context handle isn't allowed\n"); @@ -334,7 +343,6 @@ static PFORMAT_STRING client_get_handle( return NULL; } /* FIXME: should we store this structure in stubMsg.pContext? */ - return pFormat + sizeof(NDR_EHD_CONTEXT); } default: ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); @@ -347,28 +355,25 @@ static PFORMAT_STRING client_get_handle( break; case FC_BIND_PRIMITIVE: /* implicit primitive */ TRACE("Implicit primitive handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; - break; + return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; case FC_CALLBACK_HANDLE: /* implicit callback */ TRACE("FC_CALLBACK_HANDLE\n"); /* server calls callback procedures only in response to remote call, and most recent binding handle is used. Calling back to a client can potentially result in another callback with different current handle. */ - *phBinding = I_RpcGetCurrentCallHandle(); - break; + return I_RpcGetCurrentCallHandle(); case FC_AUTO_HANDLE: /* implicit auto handle */ /* strictly speaking, it isn't necessary to set hBinding here * since it isn't actually used (hence the automatic in its name), * but then why does MIDL generate a valid entry in the * MIDL_STUB_DESC for it? */ TRACE("Implicit auto handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; - break; + return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; default: ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); RpcRaiseException(RPC_X_BAD_STUB_DATA); } - return pFormat; + return NULL; } static void client_free_handle( @@ -649,13 +654,200 @@ PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFo return (PFORMAT_STRING)args; } +struct ndr_client_call_ctx +{ + MIDL_STUB_MESSAGE *stub_msg; + INTERPRETER_OPT_FLAGS Oif_flags; + INTERPRETER_OPT_FLAGS2 ext_flags; + const NDR_PROC_HEADER *proc_header; + void *This; + PFORMAT_STRING handle_format; + handle_t hbinding; +}; + +static void CALLBACK ndr_client_call_finally(BOOL normal, void *arg) +{ + struct ndr_client_call_ctx *ctx = arg; + + if (ctx->ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + NdrCorrelationFree(ctx->stub_msg); + } + + if (ctx->Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (ctx->proc_header->Oi_flags & Oi_FULL_PTR_USED) + NdrFullPointerXlatFree(ctx->stub_msg->FullPtrXlatTables); + + /* free marshalling buffer */ + if (ctx->proc_header->Oi_flags & Oi_OBJECT_PROC) + NdrProxyFreeBuffer(ctx->This, ctx->stub_msg); + else + { + NdrFreeBuffer(ctx->stub_msg); + client_free_handle(ctx->stub_msg, ctx->proc_header, ctx->handle_format, ctx->hbinding); + } +} + +/* Helper for ndr_client_call, to factor out the part that may or may not be + * guarded by a try/except block. */ +static LONG_PTR do_ndr_client_call( const MIDL_STUB_DESC *stub_desc, const PFORMAT_STRING format, + const PFORMAT_STRING handle_format, void **stack_top, void **fpu_stack, MIDL_STUB_MESSAGE *stub_msg, + unsigned short procedure_number, unsigned short stack_size, unsigned int number_of_params, + INTERPRETER_OPT_FLAGS Oif_flags, INTERPRETER_OPT_FLAGS2 ext_flags, const NDR_PROC_HEADER *proc_header ) +{ + struct ndr_client_call_ctx finally_ctx; + RPC_MESSAGE rpc_msg; + handle_t hbinding = NULL; + /* the value to return to the client from the remote procedure */ + LONG_PTR retval = 0; + /* the pointer to the object when in OLE mode */ + void *This = NULL; + /* correlation cache */ + ULONG_PTR NdrCorrCache[256]; + + /* create the full pointer translation tables, if requested */ + if (proc_header->Oi_flags & Oi_FULL_PTR_USED) + stub_msg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); + + if (proc_header->Oi_flags & Oi_OBJECT_PROC) + { + /* object is always the first argument */ + This = stack_top[0]; + NdrProxyInitialize(This, &rpc_msg, stub_msg, stub_desc, procedure_number); + } + + finally_ctx.stub_msg = stub_msg; + finally_ctx.Oif_flags = Oif_flags; + finally_ctx.ext_flags = ext_flags; + finally_ctx.proc_header = proc_header; + finally_ctx.This = This; + finally_ctx.handle_format = handle_format; + finally_ctx.hbinding = hbinding; + + __TRY + { + if (!(proc_header->Oi_flags & Oi_OBJECT_PROC)) + NdrClientInitializeNew(&rpc_msg, stub_msg, stub_desc, procedure_number); + + stub_msg->StackTop = (unsigned char *)stack_top; + + /* we only need a handle if this isn't an object method */ + if (!(proc_header->Oi_flags & Oi_OBJECT_PROC)) + { + hbinding = client_get_handle(stub_msg, proc_header, handle_format); + if (!hbinding) return 0; + } + + stub_msg->BufferLength = 0; + + /* store the RPC flags away */ + if (proc_header->Oi_flags & Oi_HAS_RPCFLAGS) + rpc_msg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)proc_header)->rpc_flags; + + /* use alternate memory allocation routines */ + if (proc_header->Oi_flags & Oi_RPCSS_ALLOC_USED) + NdrRpcSmSetClientToOsf(stub_msg); + + 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(stub_msg, NdrCorrCache, sizeof(NdrCorrCache), 0); + if (ext_flags.Unused & 0x2) /* has range on conformance */ + stub_msg->CorrDespIncrement = 12; + } + + /* order of phases: + * 1. INITOUT - zero [out] parameters (proxies only) + * 2. CALCSIZE - calculate the buffer size + * 3. GETBUFFER - allocate the buffer + * 4. MARSHAL - marshal [in] params into the buffer + * 5. SENDRECEIVE - send/receive buffer + * 6. UNMARSHAL - unmarshal [out] params from buffer + * 7. FREE - clear [out] parameters (for proxies, and only on error) + */ + + /* 1. INITOUT */ + if (proc_header->Oi_flags & Oi_OBJECT_PROC) + { + TRACE( "INITOUT\n" ); + client_do_args(stub_msg, format, STUBLESS_INITOUT, fpu_stack, + number_of_params, (unsigned char *)&retval); + } + + /* 2. CALCSIZE */ + TRACE( "CALCSIZE\n" ); + client_do_args(stub_msg, format, STUBLESS_CALCSIZE, fpu_stack, + number_of_params, (unsigned char *)&retval); + + /* 3. GETBUFFER */ + TRACE( "GETBUFFER\n" ); + if (proc_header->Oi_flags & Oi_OBJECT_PROC) + NdrProxyGetBuffer(This, stub_msg); + else if (Oif_flags.HasPipes) + FIXME("pipes not supported yet\n"); + else if (proc_header->handle_type == FC_AUTO_HANDLE) +#if 0 + NdrNsGetBuffer(stub_msg, stub_msg->BufferLength, hBinding); +#else + FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); +#endif + else + NdrGetBuffer(stub_msg, stub_msg->BufferLength, hbinding); + + /* 4. MARSHAL */ + TRACE( "MARSHAL\n" ); + client_do_args(stub_msg, format, STUBLESS_MARSHAL, fpu_stack, + number_of_params, (unsigned char *)&retval); + + /* 5. SENDRECEIVE */ + TRACE( "SENDRECEIVE\n" ); + if (proc_header->Oi_flags & Oi_OBJECT_PROC) + NdrProxySendReceive(This, stub_msg); + else if (Oif_flags.HasPipes) + /* NdrPipesSendReceive(...) */ + FIXME("pipes not supported yet\n"); + else if (proc_header->handle_type == FC_AUTO_HANDLE) +#if 0 + NdrNsSendReceive(stub_msg, stub_msg->Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); +#else + FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); +#endif + else + NdrSendReceive(stub_msg, stub_msg->Buffer); + + /* convert strings, floating point values and endianness into our + * preferred format */ + if ((rpc_msg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(stub_msg, format); + + /* 6. UNMARSHAL */ + TRACE( "UNMARSHAL\n" ); + client_do_args(stub_msg, format, STUBLESS_UNMARSHAL, fpu_stack, + number_of_params, (unsigned char *)&retval); + } + __FINALLY_CTX(ndr_client_call_finally, &finally_ctx) + + return retval; +} + LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top, void **fpu_stack ) { /* pointer to start of stack where arguments start */ - RPC_MESSAGE rpcMsg; MIDL_STUB_MESSAGE stubMsg; - handle_t hBinding = NULL; /* procedure number */ unsigned short procedure_number; /* size of stack */ @@ -670,11 +862,8 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; /* the value to return to the client from the remote procedure */ LONG_PTR RetVal = 0; - /* the pointer to the object when in OLE mode */ - void * This = NULL; PFORMAT_STRING pHandleFormat; - /* correlation cache */ - ULONG_PTR NdrCorrCache[256]; + NDR_PARAM_OIF old_args[256]; TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); @@ -695,32 +884,14 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM } TRACE("stack size: 0x%x\n", stack_size); TRACE("proc num: %d\n", procedure_number); - - /* create the full pointer translation tables, if requested */ - if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); - - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - { - /* object is always the first argument */ - This = stack_top[0]; - NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); - } - else - NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); - TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); - stubMsg.StackTop = (unsigned char *)stack_top; pHandleFormat = pFormat; /* we only need a handle if this isn't an object method */ if (!(pProcHeader->Oi_flags & Oi_OBJECT_PROC)) - { - pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding); - if (!pFormat) goto done; - } + pFormat += get_handle_desc_size(pProcHeader, pFormat); if (is_oicf_stubdesc(pStubDesc)) /* -Oicf format */ { @@ -758,251 +929,69 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM { pFormat = convert_old_args( &stubMsg, pFormat, stack_size, pProcHeader->Oi_flags & Oi_OBJECT_PROC, - /* reuse the correlation cache, it's not needed for v1 format */ - NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); + old_args, sizeof(old_args), &number_of_params ); } - stubMsg.BufferLength = 0; - - /* store the RPC flags away */ - if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) - rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; - - /* use alternate memory allocation routines */ - if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) - NdrRpcSmSetClientToOsf(&stubMsg); - - if (Oif_flags.HasPipes) + if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) { - 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(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0); - if (ext_flags.Unused & 0x2) /* has range on conformance */ - stubMsg.CorrDespIncrement = 12; - } - - /* order of phases: - * 1. INITOUT - zero [out] parameters (proxies only) - * 2. CALCSIZE - calculate the buffer size - * 3. GETBUFFER - allocate the buffer - * 4. MARSHAL - marshal [in] params into the buffer - * 5. SENDRECEIVE - send/receive buffer - * 6. UNMARSHAL - unmarshal [out] params from buffer - * 7. FREE - clear [out] parameters (for proxies, and only on error) - */ - if ((pProcHeader->Oi_flags & Oi_OBJECT_PROC) || - (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)) - { - /* 1. INITOUT */ - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - { - TRACE( "INITOUT\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_INITOUT, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - } - __TRY { - /* 2. CALCSIZE */ - TRACE( "CALCSIZE\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - - /* 3. GETBUFFER */ - TRACE( "GETBUFFER\n" ); - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - { - /* 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 == 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); - } - } - - /* 4. MARSHAL */ - TRACE( "MARSHAL\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - - /* 5. SENDRECEIVE */ - TRACE( "SENDRECEIVE\n" ); - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - { - /* 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 == 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 endianness into our - * preferred format */ - if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - /* 6. UNMARSHAL */ - TRACE( "UNMARSHAL\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, - number_of_params, (unsigned char *)&RetVal); + RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, + stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, + number_of_params, Oif_flags, ext_flags, pProcHeader); } __EXCEPT_ALL { - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - { - /* 7. FREE */ - TRACE( "FREE\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - RetVal = NdrProxyErrorHandler(GetExceptionCode()); - } + /* 7. FREE */ + TRACE( "FREE\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + RetVal = NdrProxyErrorHandler(GetExceptionCode()); + } + __ENDTRY + } + else if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT) + { + __TRY + { + RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, + stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, + number_of_params, Oif_flags, ext_flags, pProcHeader); + } + __EXCEPT_ALL + { + 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 - { - const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number]; - ULONG *comm_status; - ULONG *fault_status; + comm_status = NULL; - TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset); + 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->FaultOffset); + else + fault_status = NULL; - 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->FaultOffset); - else - fault_status = NULL; - - NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status, - GetExceptionCode()); - } + NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status, + GetExceptionCode()); } __ENDTRY } else { - /* 2. CALCSIZE */ - TRACE( "CALCSIZE\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - - /* 3. GETBUFFER */ - TRACE( "GETBUFFER\n" ); - if (Oif_flags.HasPipes) - /* NdrGetPipeBuffer(...) */ - FIXME("pipes not supported yet\n"); - else - { - if (pProcHeader->handle_type == 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); - } - - /* 4. MARSHAL */ - TRACE( "MARSHAL\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, - number_of_params, (unsigned char *)&RetVal); - - /* 5. SENDRECEIVE */ - TRACE( "SENDRECEIVE\n" ); - if (Oif_flags.HasPipes) - /* NdrPipesSendReceive(...) */ - FIXME("pipes not supported yet\n"); - else - { - if (pProcHeader->handle_type == 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 endianness into our - * preferred format */ - if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - /* 6. UNMARSHAL */ - TRACE( "UNMARSHAL\n" ); - client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, - number_of_params, (unsigned char *)&RetVal); + RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, + stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, + number_of_params, Oif_flags, ext_flags, pProcHeader); } - if (ext_flags.HasNewCorrDesc) - { - /* free extra correlation package */ - NdrCorrelationFree(&stubMsg); - } - - if (Oif_flags.HasPipes) - { - /* NdrPipesDone(...) */ - } - - /* free the full pointer translation tables */ - if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) - NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); - - /* free marshalling buffer */ - if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - NdrProxyFreeBuffer(This, &stubMsg); - else - { - NdrFreeBuffer(&stubMsg); - client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); - } - -done: TRACE("RetVal = 0x%lx\n", RetVal); return RetVal; } @@ -1103,13 +1092,18 @@ __ASM_GLOBAL_FUNC(call_server_func, LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); __ASM_GLOBAL_FUNC( call_server_func, "pushq %rbp\n\t" + __ASM_SEH(".seh_pushreg %rbp\n\t") __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") "movq %rsp,%rbp\n\t" + __ASM_SEH(".seh_setframe %rbp,0\n\t") __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") "pushq %rsi\n\t" + __ASM_SEH(".seh_pushreg %rsi\n\t") __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t") "pushq %rdi\n\t" + __ASM_SEH(".seh_pushreg %rdi\n\t") + __ASM_SEH(".seh_endprologue\n\t") __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t") "movq %rcx,%rax\n\t" /* function to call */ "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */ @@ -1175,6 +1169,35 @@ __ASM_GLOBAL_FUNC( call_server_func, "5:\tblx r4\n\t" "mov SP, r5\n\t" "pop {r4, r5, PC}" ) +#elif defined __aarch64__ +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size); +__ASM_GLOBAL_FUNC( call_server_func, + "stp x29, x30, [sp, #-16]!\n\t" + "mov x29, sp\n\t" + "add x3, x2, #15\n\t" + "lsr x3, x3, #4\n\t" + "sub sp, sp, x3, lsl #4\n\t" + "cbz x2, 2f\n" + "1:\tsub x2, x2, #8\n\t" + "ldr x4, [x1, x2]\n\t" + "str x4, [sp, x2]\n\t" + "cbnz x2, 1b\n" + "2:\tmov x8, x0\n\t" + "cbz x3, 3f\n\t" + "ldp x0, x1, [sp], #16\n\t" + "cmp x3, #1\n\t" + "b.le 3f\n\t" + "ldp x2, x3, [sp], #16\n\t" + "cmp x3, #2\n\t" + "b.le 3f\n\t" + "ldp x4, x5, [sp], #16\n\t" + "cmp x3, #3\n\t" + "b.le 3f\n\t" + "ldp x6, x7, [sp], #16\n" + "3:\tblr x8\n\t" + "mov sp, x29\n\t" + "ldp x29, x30, [sp], #16\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) @@ -1232,6 +1255,7 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, { NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat); *(void **)pArg = NDRSContextValue(ctxt); + if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)NDRSContextValue(ctxt); } else { @@ -1243,6 +1267,7 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, } } } + if (!retval_ptr && params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg; break; case STUBLESS_UNMARSHAL: if (params[i].attr.ServerAllocSize) @@ -1260,9 +1285,6 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, RpcRaiseException(RPC_S_INTERNAL_ERROR); } TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); - - /* make a note of the address of the return value parameter for later */ - if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg; } return retval_ptr; } @@ -1558,23 +1580,17 @@ void WINAPI NdrServerCall( PRPC_MESSAGE msg ) NdrStubCall( NULL, NULL, msg, &phase ); } -struct async_call_data +/*********************************************************************** + * NdrServerCallAll [RPCRT4.@] + */ +void WINAPI NdrServerCallAll( PRPC_MESSAGE msg ) { - 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 int number_of_params; - /* correlation cache */ - ULONG_PTR NdrCorrCache[256]; -}; + FIXME("%p stub\n", msg); +} -LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, - void **stack_top ) +/* Helper for ndr_async_client_call, to factor out the part that may or may not be + * guarded by a try/except block. */ +static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) { /* pointer to start of stack where arguments start */ PRPC_MESSAGE pRpcMsg; @@ -1591,8 +1607,6 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; RPC_STATUS status; - TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); - /* Later NDR language versions probably won't be backwards compatible */ if (pStubDesc->Version > 0x50002) { @@ -1647,8 +1661,11 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, 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) goto done; + TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType); + + pFormat += get_handle_desc_size(pProcHeader, pFormat); + async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat); + if (!async_call_data->hBinding) return; if (is_oicf_stubdesc(pStubDesc)) { @@ -1767,10 +1784,34 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, RpcRaiseException(status); } } +} -done: - TRACE("returning 0\n"); - return 0; +LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top ) +{ + LONG_PTR ret = 0; + const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + + TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); + + if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT) + { + __TRY + { + do_ndr_async_client_call( pStubDesc, pFormat, stack_top ); + } + __EXCEPT_ALL + { + FIXME("exception %x during ndr_async_client_call()\n", GetExceptionCode()); + ret = GetExceptionCode(); + } + __ENDTRY + } + else + do_ndr_async_client_call( pStubDesc, pFormat, stack_top); + + TRACE("returning %ld\n", ret); + return ret; } RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) @@ -1857,11 +1898,13 @@ cleanup: #ifdef __x86_64__ __ASM_GLOBAL_FUNC( NdrAsyncClientCall, - "movq %r8,0x18(%rsp)\n\t" - "movq %r9,0x20(%rsp)\n\t" - "leaq 0x18(%rsp),%r8\n\t" "subq $0x28,%rsp\n\t" + __ASM_SEH(".seh_stackalloc 0x28\n\t") + __ASM_SEH(".seh_endprologue\n\t") __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") + "movq %r8,0x40(%rsp)\n\t" + "movq %r9,0x48(%rsp)\n\t" + "leaq 0x40(%rsp),%r8\n\t" "call " __ASM_NAME("ndr_async_client_call") "\n\t" "addq $0x28,%rsp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") @@ -1895,5 +1938,269 @@ RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis, void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg) { - FIXME("unimplemented, %p\n", pRpcMsg); + const MIDL_SERVER_INFO *pServerInfo; + const MIDL_STUB_DESC *pStubDesc; + PFORMAT_STRING pFormat; + /* pointer to start of stack to pass into stub implementation */ + unsigned char *args; + /* header for procedure string */ + const NDR_PROC_HEADER *pProcHeader; + struct async_call_data *async_call_data; + PRPC_ASYNC_STATE pAsync; + RPC_STATUS status; + + TRACE("%p\n", pRpcMsg); + + pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; + + pStubDesc = pServerInfo->pStubDesc; + pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; + pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + + TRACE("NDR Version: 0x%x\n", pStubDesc->Version); + + async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); + if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY); + async_call_data->pProcHeader = pProcHeader; + + async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); + *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg; + + if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) + { + const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; + async_call_data->stack_size = header_rpc->stack_size; + pFormat += sizeof(NDR_PROC_HEADER_RPC); + } + else + { + async_call_data->stack_size = pProcHeader->stack_size; + pFormat += sizeof(NDR_PROC_HEADER); + } + + TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); + + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case 0: + switch (*pFormat) /* handle_type */ + { + case FC_BIND_PRIMITIVE: /* explicit primitive */ + pFormat += sizeof(NDR_EHD_PRIMITIVE); + break; + case FC_BIND_GENERIC: /* explicit generic */ + pFormat += sizeof(NDR_EHD_GENERIC); + break; + case FC_BIND_CONTEXT: /* explicit context */ + pFormat += sizeof(NDR_EHD_CONTEXT); + break; + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case FC_BIND_GENERIC: /* implicit generic */ + case FC_BIND_PRIMITIVE: /* implicit primitive */ + case FC_CALLBACK_HANDLE: /* implicit callback */ + case FC_AUTO_HANDLE: /* implicit auto handle */ + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) + { + ERR("objects not supported\n"); + I_RpcFree(async_call_data); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc); + + /* create the full pointer translation tables, if requested */ + if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) + async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER); + + /* use alternate memory allocation routines */ + if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) +#if 0 + NdrRpcSsEnableAllocate(&stubMsg); +#else + FIXME("Set RPCSS memory allocation routines\n"); +#endif + + TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size); + + args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, async_call_data->stack_size); + async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */ + + pAsync = I_RpcAllocate(sizeof(*pAsync)); + if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY); + + status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync)); + if (status != RPC_S_OK) + RpcRaiseException(status); + + pAsync->StubInfo = async_call_data; + TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); + + /* add the implicit pAsync pointer as the first arg to the function */ + *(void **)args = pAsync; + + if (is_oicf_stubdesc(pStubDesc)) + { + const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; + /* cache of Oif_flags from v2 procedure header */ + INTERPRETER_OPT_FLAGS Oif_flags; + /* cache of extension flags from NDR_PROC_HEADER_EXTS */ + INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; + + Oif_flags = pOIFHeader->Oi2Flags; + async_call_data->number_of_params = pOIFHeader->number_of_params; + + pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + + TRACE("Oif_flags = %s\n", debugstr_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; + } + + 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(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); + if (ext_flags.Unused & 0x2) /* has range on conformance */ + async_call_data->pStubMsg->CorrDespIncrement = 12; + } + } + else + { + pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size, + pProcHeader->Oi_flags & Oi_OBJECT_PROC, + /* reuse the correlation cache, it's not needed for v1 format */ + async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params ); + } + + /* convert strings, floating point values and endianness into our + * preferred format */ + if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(async_call_data->pStubMsg, pFormat); + + async_call_data->pHandleFormat = pFormat; + + /* 1. UNMARSHAL */ + TRACE("UNMARSHAL\n"); + stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params); + + /* 2. INITOUT */ + TRACE("INITOUT\n"); + async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params); + + /* 3. CALLSERVER */ + TRACE("CALLSERVER\n"); + if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) + pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg); + else + call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size); +} + +RPC_STATUS NdrpCompleteAsyncServerCall(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 */ + enum stubless_phase phase; + 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; + + TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); + + if (async_call_data->retval_ptr) + { + TRACE("stub implementation returned 0x%lx\n", *(LONG_PTR *)Reply); + *async_call_data->retval_ptr = *(LONG_PTR *)Reply; + } + else + TRACE("void stub implementation\n"); + + for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++) + { + TRACE("phase = %d\n", phase); + switch (phase) + { + case STUBLESS_GETBUFFER: + if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC) + { + ERR("objects not supported\n"); + HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); + I_RpcFree(async_call_data); + I_RpcFree(pAsync); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + else + { + pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; + /* allocate buffer for [out] and [ret] params */ + status = I_RpcGetBuffer(pStubMsg->RpcMsg); + if (status) + RpcRaiseException(status); + pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; + } + break; + + case STUBLESS_CALCSIZE: + case STUBLESS_MARSHAL: + case STUBLESS_MUSTFREE: + case STUBLESS_FREE: + stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params); + break; + default: + ERR("shouldn't reach here. phase %d\n", phase); + break; + } + } + +#if 0 /* FIXME */ + if (ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + NdrCorrelationFree(pStubMsg); + } + + if (Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED) + NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); +#endif + + /* free server function stack */ + HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); + I_RpcFree(async_call_data); + I_RpcFree(pAsync); + + return S_OK; } diff --git a/dll/win32/rpcrt4/ndr_stubless.h b/dll/win32/rpcrt4/ndr_stubless.h index 5212d9ce0ec..fa2c5e4ee61 100644 --- a/dll/win32/rpcrt4/ndr_stubless.h +++ b/dll/win32/rpcrt4/ndr_stubless.h @@ -204,8 +204,8 @@ typedef struct _NDR_EHD_CONTEXT * NDR_CONTEXT_HANDLE_SERIALIZE = 0x02 * NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04 * NDR_STRICT_CONTEXT_HANDLE = 0x08 + * HANDLE_PARAM_IS_RETURN = 0x10 * HANDLE_PARAM_IS_OUT = 0x20 - * HANDLE_PARAM_IS_RETURN = 0x21 * HANDLE_PARAM_IS_IN = 0x40 * HANDLE_PARAM_IS_VIA_PTR = 0x80 */ @@ -226,6 +226,23 @@ typedef struct _NDR_EHD_CONTEXT #include "poppack.h" +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 int number_of_params; + /* location to put retval into */ + LONG_PTR *retval_ptr; + /* correlation cache */ + ULONG_PTR NdrCorrCache[256]; +}; + enum stubless_phase { STUBLESS_UNMARSHAL, @@ -248,3 +265,4 @@ PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFo unsigned int stack_size, BOOL object_proc, void *buffer, unsigned int size, unsigned int *count ) DECLSPEC_HIDDEN; RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) DECLSPEC_HIDDEN; +RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply) DECLSPEC_HIDDEN; diff --git a/dll/win32/rpcrt4/ndr_typelib.c b/dll/win32/rpcrt4/ndr_typelib.c index a0855a5dc59..ac101067c8d 100644 --- a/dll/win32/rpcrt4/ndr_typelib.c +++ b/dll/win32/rpcrt4/ndr_typelib.c @@ -109,9 +109,13 @@ static unsigned short write_oleaut_tfs(VARTYPE vt) return 0; } -static unsigned char get_base_type(VARTYPE vt) +static unsigned char get_basetype(ITypeInfo *typeinfo, TYPEDESC *desc) { - switch (vt) + ITypeInfo *refinfo; + unsigned char ret; + TYPEATTR *attr; + + switch (desc->vt) { case VT_I1: return FC_SMALL; case VT_BOOL: @@ -129,6 +133,18 @@ static unsigned char get_base_type(VARTYPE vt) case VT_R4: return FC_FLOAT; case VT_DATE: case VT_R8: return FC_DOUBLE; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + if (attr->typekind == TKIND_ENUM) + ret = FC_ENUM32; + else if (attr->typekind == TKIND_ALIAS) + ret = get_basetype(refinfo, &attr->tdescAlias); + else + ret = 0; + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + return ret; default: return 0; } } @@ -192,34 +208,118 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) } } +static BOOL type_pointer_is_iface(ITypeInfo *typeinfo, TYPEDESC *tdesc) +{ + ITypeInfo *refinfo; + BOOL ret = FALSE; + TYPEATTR *attr; + + if (tdesc->vt == VT_USERDEFINED) + { + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_INTERFACE + || attr->typekind == TKIND_DISPATCH + || attr->typekind == TKIND_COCLASS) + ret = TRUE; + else if (attr->typekind == TKIND_ALIAS) + ret = type_pointer_is_iface(refinfo, &attr->tdescAlias); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } + + return ret; +} + static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc); +static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr); + +static unsigned char get_struct_member_fc(ITypeInfo *typeinfo, TYPEDESC *tdesc) +{ + unsigned char fc; + ITypeInfo *refinfo; + TYPEATTR *attr; + + switch (tdesc->vt) + { + case VT_BSTR: + case VT_SAFEARRAY: + return (sizeof(void *) == 4) ? FC_PSTRUCT : FC_BOGUS_STRUCT; + case VT_CY: + return FC_STRUCT; + case VT_VARIANT: + case VT_UNKNOWN: + case VT_DISPATCH: + return FC_BOGUS_STRUCT; + case VT_CARRAY: + if (get_array_fc(typeinfo, &tdesc->lpadesc->tdescElem) == FC_BOGUS_ARRAY) + return FC_BOGUS_STRUCT; + return FC_STRUCT; + case VT_PTR: + if (type_pointer_is_iface(typeinfo, tdesc)) + fc = FC_BOGUS_STRUCT; + else + fc = (sizeof(void *) == 4) ? FC_PSTRUCT : FC_BOGUS_STRUCT; + break; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + fc = FC_STRUCT; + break; + case TKIND_RECORD: + fc = get_struct_fc(refinfo, attr); + break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + fc = FC_BOGUS_STRUCT; + break; + case TKIND_ALIAS: + fc = get_struct_member_fc(refinfo, &attr->tdescAlias); + break; + default: + FIXME("Unhandled kind %#x.\n", attr->typekind); + fc = FC_BOGUS_STRUCT; + break; + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + if (get_basetype(typeinfo, tdesc)) + return FC_STRUCT; + else + { + FIXME("Unhandled type %u.\n", tdesc->vt); + return FC_BOGUS_STRUCT; + } + } + + return fc; +} static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) { - unsigned char fc = FC_STRUCT; + unsigned char fc = FC_STRUCT, member_fc; VARDESC *desc; - VARTYPE vt; WORD i; for (i = 0; i < attr->cVars; i++) { ITypeInfo_GetVarDesc(typeinfo, i, &desc); - vt = desc->elemdescVar.tdesc.vt; - switch (vt) - { - case VT_CARRAY: - if (get_array_fc(typeinfo, &desc->elemdescVar.tdesc.lpadesc->tdescElem) == FC_BOGUS_ARRAY) - fc = FC_BOGUS_STRUCT; - break; - default: - if (!get_base_type(vt)) - { - FIXME("unhandled type %u\n", vt); - fc = FC_BOGUS_STRUCT; - } - break; - } + member_fc = get_struct_member_fc(typeinfo, &desc->elemdescVar.tdesc); + if (member_fc == FC_BOGUS_STRUCT) + fc = FC_BOGUS_STRUCT; + else if (member_fc == FC_PSTRUCT && fc != FC_BOGUS_STRUCT) + fc = FC_PSTRUCT; ITypeInfo_ReleaseVarDesc(typeinfo, desc); } @@ -229,9 +329,13 @@ static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) { - if (get_base_type(desc->vt)) + switch (desc->vt) + { + case VT_CY: return FC_LGFARRAY; - else if (desc->vt == VT_USERDEFINED) + case VT_CARRAY: + return get_array_fc(typeinfo, &desc->lpadesc->tdescElem); + case VT_USERDEFINED: { ITypeInfo *refinfo; TYPEATTR *attr; @@ -244,6 +348,8 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) fc = FC_LGFARRAY; else if (attr->typekind == TKIND_RECORD && get_struct_fc(refinfo, attr) == FC_STRUCT) fc = FC_LGFARRAY; + else if (attr->typekind == TKIND_ALIAS) + fc = get_array_fc(refinfo, &attr->tdescAlias); else fc = FC_BOGUS_ARRAY; @@ -252,8 +358,244 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) return fc; } + default: + return get_basetype(typeinfo, desc) ? FC_LGFARRAY : FC_BOGUS_ARRAY; + } +} + +static BOOL type_is_non_iface_pointer(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + if (desc->vt == VT_PTR) + return !type_pointer_is_iface(typeinfo, desc->lptdesc); + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + BOOL ret; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = type_is_non_iface_pointer(refinfo, &attr->tdescAlias); + else + ret = FALSE; + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } else - return FC_BOGUS_ARRAY; + return FALSE; +} + +static void write_struct_members(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + unsigned int struct_offset = 0; + unsigned char basetype; + TYPEDESC *tdesc; + VARDESC *desc; + WORD i; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + tdesc = &desc->elemdescVar.tdesc; + + /* This may not match the intended alignment, but we don't have enough + * information to determine that. This should always give the correct + * layout. */ + if ((struct_offset & 7) && !(desc->oInst & 7)) + WRITE_CHAR(str, *len, FC_ALIGNM8); + else if ((struct_offset & 3) && !(desc->oInst & 3)) + WRITE_CHAR(str, *len, FC_ALIGNM4); + else if ((struct_offset & 1) && !(desc->oInst & 1)) + WRITE_CHAR(str, *len, FC_ALIGNM2); + struct_offset = desc->oInst + type_memsize(typeinfo, tdesc); + + if ((basetype = get_basetype(typeinfo, tdesc))) + WRITE_CHAR(str, *len, basetype); + else if (type_is_non_iface_pointer(typeinfo, tdesc)) + WRITE_CHAR(str, *len, FC_POINTER); + else + { + WRITE_CHAR(str, *len, FC_EMBEDDED_COMPLEX); + WRITE_CHAR(str, *len, 0); + WRITE_SHORT(str, *len, 0); + } + + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } + if (!(*len & 1)) + WRITE_CHAR (str, *len, FC_PAD); + WRITE_CHAR (str, *len, FC_END); +} + +static void write_simple_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + write_struct_members(typeinfo, str, len, attr); +} + +static BOOL type_needs_pointer_deref(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + if (desc->vt == VT_PTR || desc->vt == VT_UNKNOWN || desc->vt == VT_DISPATCH) + return TRUE; + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + BOOL ret = FALSE; + TYPEATTR *attr; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = type_needs_pointer_deref(refinfo, &attr->tdescAlias); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } + else + return FALSE; +} + +static void write_complex_struct_pointer_layout(ITypeInfo *typeinfo, + TYPEDESC *desc, unsigned char *str, size_t *len) +{ + unsigned char basetype; + + if (desc->vt == VT_PTR && !type_pointer_is_iface(typeinfo, desc->lptdesc)) + { + WRITE_CHAR(str, *len, FC_UP); + if ((basetype = get_basetype(typeinfo, desc->lptdesc))) + { + WRITE_CHAR(str, *len, FC_SIMPLE_POINTER); + WRITE_CHAR(str, *len, basetype); + WRITE_CHAR(str, *len, FC_PAD); + } + else + { + if (type_needs_pointer_deref(typeinfo, desc->lptdesc)) + WRITE_CHAR(str, *len, FC_POINTER_DEREF); + else + WRITE_CHAR(str, *len, 0); + WRITE_SHORT(str, *len, 0); + } + } + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + write_complex_struct_pointer_layout(refinfo, &attr->tdescAlias, str, len); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } +} + +static size_t write_complex_struct_pointer_ref(ITypeInfo *typeinfo, + TYPEDESC *desc, unsigned char *str, size_t *len) +{ + if (desc->vt == VT_PTR && !type_pointer_is_iface(typeinfo, desc->lptdesc) + && !get_basetype(typeinfo, desc->lptdesc)) + { + return write_type_tfs(typeinfo, str, len, desc->lptdesc, FALSE, FALSE); + } + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + size_t ret = 0; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = write_complex_struct_pointer_ref(refinfo, &attr->tdescAlias, str, len); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } + + return 0; +} + +static void write_complex_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + size_t pointer_layout_offset, pointer_layout, member_layout, ref; + unsigned int struct_offset = 0; + TYPEDESC *tdesc; + VARDESC *desc; + WORD i; + + WRITE_SHORT(str, *len, 0); /* conformant array description */ + pointer_layout_offset = *len; + WRITE_SHORT(str, *len, 0); /* pointer layout; will be filled in later */ + member_layout = *len; + + /* First pass: write the struct members and pointer layout, but do not yet + * write the offsets for embedded complexes and pointer refs. These must be + * handled after we write the whole struct description, since it must be + * contiguous. */ + + write_struct_members(typeinfo, str, len, attr); + + pointer_layout = *len; + if (str) *((short *)(str + pointer_layout_offset)) = pointer_layout - pointer_layout_offset; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + write_complex_struct_pointer_layout(typeinfo, &desc->elemdescVar.tdesc, str, len); + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } + + /* Second pass: write types for embedded complexes and non-simple pointers. */ + + struct_offset = 0; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + tdesc = &desc->elemdescVar.tdesc; + + if (struct_offset != desc->oInst) + member_layout++; /* alignment directive */ + struct_offset = desc->oInst + type_memsize(typeinfo, tdesc); + + if (get_basetype(typeinfo, tdesc)) + member_layout++; + else if (type_is_non_iface_pointer(typeinfo, tdesc)) + { + member_layout++; + if ((ref = write_complex_struct_pointer_ref(typeinfo, tdesc, str, len))) + { + if (str) *((short *)(str + pointer_layout + 2)) = ref - (pointer_layout + 2); + } + pointer_layout += 4; + } + else + { + ref = write_type_tfs(typeinfo, str, len, tdesc, FALSE, FALSE); + if (str) *((short *)(str + member_layout + 2)) = ref - (member_layout + 2); + member_layout += 4; + } + + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } } static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, @@ -262,14 +604,18 @@ static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, unsigned char fc = get_struct_fc(typeinfo, attr); size_t off = *len; - if (fc != FC_STRUCT) - FIXME("fc %02x not implemented\n", fc); + /* For the sake of simplicity, write pointer structs as complex structs. */ + if (fc == FC_PSTRUCT) + fc = FC_BOGUS_STRUCT; - WRITE_CHAR (str, *len, FC_STRUCT); + WRITE_CHAR (str, *len, fc); WRITE_CHAR (str, *len, attr->cbAlignment - 1); WRITE_SHORT(str, *len, attr->cbSizeInstance); - WRITE_CHAR (str, *len, FC_PAD); - WRITE_CHAR (str, *len, FC_END); + + if (fc == FC_STRUCT) + write_simple_struct_tfs(typeinfo, str, len, attr); + else if (fc == FC_BOGUS_STRUCT) + write_complex_struct_tfs(typeinfo, str, len, attr); return off; } @@ -278,15 +624,12 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str, size_t *len, ARRAYDESC *desc) { unsigned char fc = get_array_fc(typeinfo, &desc->tdescElem); - ULONG size = type_memsize(typeinfo, &desc->tdescElem); unsigned char basetype; size_t ref = 0, off; + ULONG size = 1; USHORT i; - if (fc != FC_LGFARRAY) - FIXME("complex arrays not implemented\n"); - - if (!(basetype = get_base_type(desc->tdescElem.vt))) + if (!(basetype = get_basetype(typeinfo, &desc->tdescElem))) ref = write_type_tfs(typeinfo, str, len, &desc->tdescElem, FALSE, FALSE); /* In theory arrays should be nested, but there's no reason not to marshal @@ -295,9 +638,20 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str, off = *len; - WRITE_CHAR(str, *len, FC_LGFARRAY); + WRITE_CHAR(str, *len, fc); WRITE_CHAR(str, *len, 0); - WRITE_INT (str, *len, size); + if (fc == FC_BOGUS_ARRAY) + { + WRITE_SHORT(str, *len, size); + WRITE_INT(str, *len, 0xffffffff); /* conformance */ + WRITE_INT(str, *len, 0xffffffff); /* variance */ + } + else + { + size *= type_memsize(typeinfo, &desc->tdescElem); + WRITE_INT(str, *len, size); + } + if (basetype) WRITE_CHAR(str, *len, basetype); else @@ -404,7 +758,7 @@ static size_t write_pointer_tfs(ITypeInfo *typeinfo, unsigned char *str, ITypeInfo_ReleaseTypeAttr(refinfo, attr); ITypeInfo_Release(refinfo); } - else if ((basetype = get_base_type(desc->vt))) + else if ((basetype = get_basetype(typeinfo, desc))) { assert(!toplevel); /* toplevel base-type pointers should use IsSimpleRef */ WRITE_CHAR(str, *len, FC_UP); @@ -457,6 +811,14 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, case TKIND_RECORD: off = write_struct_tfs(refinfo, str, len, attr); break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + assert(0); + break; + case TKIND_ALIAS: + off = write_type_tfs(refinfo, str, len, &attr->tdescAlias, toplevel, onstack); + break; default: FIXME("unhandled kind %u\n", attr->typekind); off = *len; @@ -469,7 +831,7 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, break; default: /* base types are always embedded directly */ - assert(!get_base_type(desc->vt)); + assert(!get_basetype(typeinfo, desc)); FIXME("unhandled type %u\n", desc->vt); off = *len; WRITE_SHORT(str, *len, 0); @@ -517,26 +879,10 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int break; case VT_PTR: *flags |= MustFree; - - if (tdesc->lptdesc->vt == VT_USERDEFINED) + if (type_pointer_is_iface(typeinfo, tdesc->lptdesc)) { - ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->lptdesc->hreftype, &refinfo); - ITypeInfo_GetTypeAttr(refinfo, &attr); - - switch (attr->typekind) - { - case TKIND_INTERFACE: - case TKIND_DISPATCH: - case TKIND_COCLASS: - if (is_in && is_out) - *server_size = sizeof(void *); - break; - default: + if (is_in && is_out) *server_size = sizeof(void *); - } - - ITypeInfo_ReleaseTypeAttr(refinfo, attr); - ITypeInfo_Release(refinfo); } else *server_size = sizeof(void *); @@ -587,7 +933,7 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int *tfs_tdesc = tdesc; if (!is_in && is_out) *server_size = type_memsize(typeinfo, tdesc); - if ((*basetype = get_base_type(tdesc->vt))) + if ((*basetype = get_basetype(typeinfo, tdesc))) *flags |= IsBasetype; break; } @@ -665,7 +1011,7 @@ static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, ITypeInfo_Release(refinfo); break; default: - if ((*basetype = get_base_type(tdesc->vt))) + if ((*basetype = get_basetype(typeinfo, tdesc))) *flags |= IsBasetype; else { @@ -752,7 +1098,7 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc, WRITE_SHORT(proc, *proclen, 0); /* NotifyIndex */ for (param_idx = 0; param_idx < desc->cParams && param_idx < 3; param_idx++) { - basetype = get_base_type(desc->lprgelemdescParam[param_idx].tdesc.vt); + basetype = get_basetype(typeinfo, &desc->lprgelemdescParam[param_idx].tdesc); if (basetype == FC_FLOAT) float_mask |= (1 << ((param_idx + 1) * 2)); else if (basetype == FC_DOUBLE) diff --git a/dll/win32/rpcrt4/precomp.h b/dll/win32/rpcrt4/precomp.h index cb90de9d38b..e0225805909 100644 --- a/dll/win32/rpcrt4/precomp.h +++ b/dll/win32/rpcrt4/precomp.h @@ -2,8 +2,6 @@ #ifndef _RPCRT4_PCH_ #define _RPCRT4_PCH_ -#include - #include #include #include @@ -19,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +26,6 @@ #include #include #include -#include #include "cpsf.h" #include "ncastatus.h" diff --git a/dll/win32/rpcrt4/rpc_assoc.c b/dll/win32/rpcrt4/rpc_assoc.c index 1230aed2b6a..0daa466238f 100644 --- a/dll/win32/rpcrt4/rpc_assoc.c +++ b/dll/win32/rpcrt4/rpc_assoc.c @@ -26,7 +26,6 @@ #include "rpcndr.h" #include "wine/winternl.h" -#include "wine/unicode.h" #include "wine/debug.h" #include "rpc_binding.h" @@ -93,7 +92,7 @@ static BOOL compare_networkoptions(LPCWSTR opts1, LPCWSTR opts2) return TRUE; if ((opts1 == NULL) || (opts2 == NULL)) return FALSE; - return !strcmpW(opts1, opts2); + return !wcscmp(opts1, opts2); } RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, @@ -154,7 +153,7 @@ RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, (!NetworkAddr || !assoc->NetworkAddr || !strcmp(NetworkAddr, assoc->NetworkAddr)) && !strcmp(Endpoint, assoc->Endpoint) && ((!assoc->NetworkOptions == !NetworkOptions) && - (!NetworkOptions || !strcmpW(NetworkOptions, assoc->NetworkOptions)))) + (!NetworkOptions || !wcscmp(NetworkOptions, assoc->NetworkOptions)))) { assoc->refs++; *assoc_out = assoc; diff --git a/dll/win32/rpcrt4/rpc_async.c b/dll/win32/rpcrt4/rpc_async.c index 891fc5ad725..00c2d6bede8 100644 --- a/dll/win32/rpcrt4/rpc_async.c +++ b/dll/win32/rpcrt4/rpc_async.c @@ -110,6 +110,8 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync) */ RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) { + struct async_call_data *data; + TRACE("(%p, %p)\n", pAsync, Reply); if (!valid_async_handle(pAsync)) @@ -117,7 +119,13 @@ RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) /* FIXME: check completed */ - return NdrpCompleteAsyncClientCall(pAsync, Reply); + TRACE("pAsync %p, pAsync->StubInfo %p\n", pAsync, pAsync->StubInfo); + + data = pAsync->StubInfo; + if (data->pStubMsg->IsClient) + return NdrpCompleteAsyncClientCall(pAsync, Reply); + + return NdrpCompleteAsyncServerCall(pAsync, Reply); } /*********************************************************************** diff --git a/dll/win32/rpcrt4/rpc_binding.c b/dll/win32/rpcrt4/rpc_binding.c index 51bfb97aba2..640e17673c6 100644 --- a/dll/win32/rpcrt4/rpc_binding.c +++ b/dll/win32/rpcrt4/rpc_binding.c @@ -31,7 +31,6 @@ #include "winnls.h" #include "winerror.h" #include "wine/winternl.h" -#include "wine/unicode.h" #include "rpc.h" #include "rpcndr.h" @@ -94,7 +93,7 @@ LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen) DWORD len; LPWSTR s; if (!src) return NULL; - if (slen == -1) slen = strlenW(src); + if (slen == -1) slen = lstrlenW(src); len = slen; s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); memcpy(s, src, len*sizeof(WCHAR)); @@ -322,7 +321,7 @@ static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src) static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) { - DWORD len = strlenW(dst), slen = strlenW(src); + DWORD len = lstrlenW(dst), slen = lstrlenW(src); LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR)); if (!ndst) { @@ -435,7 +434,7 @@ static RPC_WSTR unescape_string_binding_componentW( { RPC_WSTR component, p; - if (len == -1) len = strlenW(string_binding); + if (len == -1) len = lstrlenW(string_binding); component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component)); if (!component) return NULL; @@ -521,11 +520,11 @@ RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq, debugstr_w( Options ), StringBinding); /* overestimate for each component for escaping of delimiters */ - if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1; - if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1; - if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2; - if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2; - if (Options && *Options) len += strlenW(Options) * 2 + 2; + if (ObjUuid && *ObjUuid) len += lstrlenW(ObjUuid) * 2 + 1; + if (Protseq && *Protseq) len += lstrlenW(Protseq) * 2 + 1; + if (NetworkAddr && *NetworkAddr) len += lstrlenW(NetworkAddr) * 2; + if (Endpoint && *Endpoint) len += lstrlenW(Endpoint) * 2 + 2; + if (Options && *Options) len += lstrlenW(Options) * 2 + 2; data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); *StringBinding = data; @@ -741,7 +740,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU else HeapFree(GetProcessHeap(), 0, opt); endpoint_already_found = TRUE; } else { - if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) { + if (wcsncmp(opt, ep_opt, lstrlenW(ep_opt)) == 0) { /* endpoint option */ if (endpoint_already_found) goto fail; if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1); @@ -1320,7 +1319,7 @@ static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BO if (unicode) http_credentials_dst->ServerCertificateSubject = RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject, - strlenW(http_credentials_src->ServerCertificateSubject)); + lstrlenW(http_credentials_src->ServerCertificateSubject)); else http_credentials_dst->ServerCertificateSubject = RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject); diff --git a/dll/win32/rpcrt4/rpc_server.c b/dll/win32/rpcrt4/rpc_server.c index 91de3b95fa3..a7cad5e273f 100644 --- a/dll/win32/rpcrt4/rpc_server.c +++ b/dll/win32/rpcrt4/rpc_server.c @@ -20,9 +20,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" - #include #include #include @@ -702,10 +699,6 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) } LeaveCriticalSection(&cps->cs); - EnterCriticalSection(&listen_cs); - CloseHandle(cps->server_thread); - cps->server_thread = NULL; - LeaveCriticalSection(&listen_cs); TRACE("done\n"); return 0; } @@ -1573,7 +1566,10 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) { if ((wait_thread = protseq->server_thread)) + { + protseq->server_thread = NULL; break; + } } LeaveCriticalSection(&server_cs); if (!wait_thread) @@ -1582,6 +1578,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) TRACE("waiting for thread %u\n", GetThreadId(wait_thread)); LeaveCriticalSection(&listen_cs); WaitForSingleObject(wait_thread, INFINITE); + CloseHandle(wait_thread); EnterCriticalSection(&listen_cs); } if (listen_done_event == event) diff --git a/dll/win32/rpcrt4/rpc_transport.c b/dll/win32/rpcrt4/rpc_transport.c index f4a53ffa5ee..aee897644c9 100644 --- a/dll/win32/rpcrt4/rpc_transport.c +++ b/dll/win32/rpcrt4/rpc_transport.c @@ -42,7 +42,6 @@ #include "wininet.h" #include "wine/winternl.h" #include "winioctl.h" -#include "wine/unicode.h" #include "rpc.h" #include "rpcndr.h" @@ -528,10 +527,9 @@ static void rpcrt4_conn_np_cancel_call(RpcConnection *conn) CancelIoEx(connection->pipe, NULL); } -static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection) +static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *conn) { - /* FIXME: implement when named pipe writes use overlapped I/O */ - return -1; + return rpcrt4_conn_np_read(conn, NULL, 0); } static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, @@ -1976,38 +1974,38 @@ static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc) } for (option = httpc->common.NetworkOptions; option; - option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL)) + option = (wcschr(option, ',') ? wcschr(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, ARRAY_SIZE(wszRpcProxy)-1)) + if (!_wcsnicmp(option, wszRpcProxy, ARRAY_SIZE(wszRpcProxy)-1)) { const WCHAR *value_start = option + ARRAY_SIZE(wszRpcProxy)-1; const WCHAR *value_end; const WCHAR *p; - value_end = strchrW(option, ','); + value_end = wcschr(option, ','); if (!value_end) - value_end = value_start + strlenW(value_start); + value_end = value_start + lstrlenW(value_start); for (p = value_start; p < value_end; p++) if (*p == ':') { - port = atoiW(p+1); + port = wcstol(p+1, NULL, 10); 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, ARRAY_SIZE(wszHttpProxy)-1)) + else if (!_wcsnicmp(option, wszHttpProxy, ARRAY_SIZE(wszHttpProxy)-1)) { const WCHAR *value_start = option + ARRAY_SIZE(wszHttpProxy)-1; const WCHAR *value_end; - value_end = strchrW(option, ','); + value_end = wcschr(option, ','); if (!value_end) - value_end = value_start + strlenW(value_start); + value_end = value_start + lstrlenW(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); } @@ -2132,7 +2130,7 @@ static RPC_STATUS insert_content_length_header(HINTERNET request, DWORD len) {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','u','\r','\n',0}; WCHAR header[ARRAY_SIZE(fmtW) + 10]; - sprintfW(header, fmtW, len); + swprintf(header, fmtW, len); if ((HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD))) return RPC_S_OK; return RPC_S_SERVER_UNAVAILABLE; } @@ -2471,7 +2469,7 @@ static DWORD auth_scheme_from_header( const WCHAR *header ) unsigned int i; for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) { - if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) && + if (!_wcsnicmp( header, auth_schemes[i].str, auth_schemes[i].len ) && (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme; } return 0; @@ -2538,7 +2536,7 @@ static RPC_STATUS do_authorization(HINTERNET request, SEC_WCHAR *servername, if (creds->AuthnSchemes[0] == RPC_C_HTTP_AUTHN_SCHEME_NTLM) scheme = ntlmW; else scheme = negotiateW; - scheme_len = strlenW( scheme ); + scheme_len = lstrlenW( scheme ); if (!*auth_ptr) { @@ -2575,7 +2573,7 @@ static RPC_STATUS do_authorization(HINTERNET request, SEC_WCHAR *servername, p = auth_value + scheme_len; if (!first && *p == ' ') { - int len = strlenW(++p); + int len = lstrlenW(++p); in.cbBuffer = decode_base64(p, len, NULL); if (!(in.pvBuffer = HeapAlloc(GetProcessHeap(), 0, in.cbBuffer))) break; decode_base64(p, len, in.pvBuffer); @@ -2843,8 +2841,8 @@ static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection) memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix)); MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+ARRAY_SIZE(wszRpcProxyPrefix)-1, strlen(Connection->NetworkAddr)+1); - strcatW(url, wszColon); - MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1); + lstrcatW(url, wszColon); + MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+lstrlenW(url), strlen(Connection->Endpoint)+1); secure = is_secure(httpc); credentials = has_credentials(httpc); diff --git a/dll/win32/rpcrt4/rpcrt4_main.c b/dll/win32/rpcrt4/rpcrt4_main.c index a900201d9fe..67a3dbe595f 100644 --- a/dll/win32/rpcrt4/rpcrt4_main.c +++ b/dll/win32/rpcrt4/rpcrt4_main.c @@ -28,8 +28,6 @@ * NT-based native rpcrt4's. Commonly-used transport for self-to-self RPC's. */ -#include "config.h" - #include #include #include @@ -46,7 +44,6 @@ #include "ntsecapi.h" #include "iptypes.h" #include "iphlpapi.h" -#include "wine/unicode.h" #include "rpc.h" #include "ole2.h" @@ -618,7 +615,7 @@ RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid) if (!s) return UuidCreateNil( uuid ); - if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID; + if (lstrlenW(s) != 36) return RPC_S_INVALID_STRING_UUID; if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) return RPC_S_INVALID_STRING_UUID; diff --git a/media/doc/README.WINE b/media/doc/README.WINE index b390f9e7bbc..2be1fedf4a3 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -161,7 +161,7 @@ dll/win32/rasapi32 # Synced to WineStaging-3.3 dll/win32/resutils # Synced to WineStaging-3.3 dll/win32/riched20 # Synced to WineStaging-4.18 dll/win32/riched32 # Synced to WineStaging-3.3 -dll/win32/rpcrt4 # Synced to WineStaging-4.0 +dll/win32/rpcrt4 # Synced to WineStaging-4.18 dll/win32/rsabase # Synced to WineStaging-3.3 dll/win32/rsaenh # Synced to WineStaging-2.9 dll/win32/sccbase # Synced to WineStaging-3.3