📄 ndr_marshall.c
字号:
{ BYTE dtype = pFormat[0] & 0xf; short ofs = *(const short *)&pFormat[2]; LPVOID ptr = NULL; DWORD data = 0; if (!IsConformanceOrVariancePresent(pFormat)) { /* null descriptor */ *pCount = def; goto finish_conf; } switch (pFormat[0] & 0xf0) { case RPC_FC_NORMAL_CONFORMANCE: TRACE("normal conformance, ofs=%d\n", ofs); ptr = pMemory; break; case RPC_FC_POINTER_CONFORMANCE: TRACE("pointer conformance, ofs=%d\n", ofs); ptr = pStubMsg->Memory; break; case RPC_FC_TOP_LEVEL_CONFORMANCE: TRACE("toplevel conformance, ofs=%d\n", ofs); if (pStubMsg->StackTop) { ptr = pStubMsg->StackTop; } else { /* -Os mode, *pCount is already set */ goto finish_conf; } break; case RPC_FC_CONSTANT_CONFORMANCE: data = ofs | ((DWORD)pFormat[1] << 16); TRACE("constant conformance, val=%d\n", data); *pCount = data; goto finish_conf; case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); if (pStubMsg->StackTop) { ptr = pStubMsg->StackTop; } else { /* ? */ goto done_conf_grab; } break; default: FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); } switch (pFormat[1]) { case RPC_FC_DEREFERENCE: ptr = *(LPVOID*)((char *)ptr + ofs); break; case RPC_FC_CALLBACK: { unsigned char *old_stack_top = pStubMsg->StackTop; pStubMsg->StackTop = ptr; /* ofs is index into StubDesc->apfnExprEval */ TRACE("callback conformance into apfnExprEval[%d]\n", ofs); pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); pStubMsg->StackTop = old_stack_top; /* the callback function always stores the computed value in MaxCount */ *pCount = pStubMsg->MaxCount; goto finish_conf; } default: ptr = (char *)ptr + ofs; break; } switch (dtype) { case RPC_FC_LONG: case RPC_FC_ULONG: data = *(DWORD*)ptr; break; case RPC_FC_SHORT: data = *(SHORT*)ptr; break; case RPC_FC_USHORT: data = *(USHORT*)ptr; break; case RPC_FC_CHAR: case RPC_FC_SMALL: data = *(CHAR*)ptr; break; case RPC_FC_BYTE: case RPC_FC_USMALL: data = *(UCHAR*)ptr; break; default: FIXME("unknown conformance data type %x\n", dtype); goto done_conf_grab; } TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);done_conf_grab: switch (pFormat[1]) { case RPC_FC_DEREFERENCE: /* already handled */ case 0: /* no op */ *pCount = data; break; case RPC_FC_ADD_1: *pCount = data + 1; break; case RPC_FC_SUB_1: *pCount = data - 1; break; case RPC_FC_MULT_2: *pCount = data * 2; break; case RPC_FC_DIV_2: *pCount = data / 2; break; default: FIXME("unknown conformance op %d\n", pFormat[1]); goto finish_conf; }finish_conf: TRACE("resulting conformance is %ld\n", *pCount); if (pStubMsg->fHasNewCorrDesc) return pFormat+6; else return pFormat+4;}/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if * the result overflows 32-bits */static inline ULONG safe_multiply(ULONG a, ULONG b){ ULONGLONG ret = (ULONGLONG)a * b; if (ret > 0xffffffff) { RpcRaiseException(RPC_S_INVALID_BOUND); return 0; } return ret;}/* * NdrConformantString: * * What MS calls a ConformantString is, in DCE terminology, * a Varying-Conformant String. * [ * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') * offset: DWORD (actual string data begins at (offset) CHARTYPE's * into unmarshalled string) * length: DWORD (# of CHARTYPE characters, inclusive of '\0') * [ * data: CHARTYPE[maxlen] * ] * ], where CHARTYPE is the appropriate character type (specified externally) * *//*********************************************************************** * NdrConformantStringMarshall [RPCRT4.@] */unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pszMessage, PFORMAT_STRING pFormat){ ULONG esize, size; TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); if (*pFormat == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((char*)pszMessage)); pStubMsg->ActualCount = strlen((char*)pszMessage)+1; esize = 1; } else if (*pFormat == RPC_FC_C_WSTRING) { TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; esize = 2; } else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception. */ return NULL; } if (pFormat[1] == RPC_FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); else pStubMsg->MaxCount = pStubMsg->ActualCount; pStubMsg->Offset = 0; WriteConformance(pStubMsg); WriteVariance(pStubMsg); size = safe_multiply(esize, pStubMsg->ActualCount); memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */ pStubMsg->Buffer += size; STD_OVERFLOW_CHECK(pStubMsg); /* success */ return NULL; /* is this always right? */}/*********************************************************************** * NdrConformantStringBufferSize [RPCRT4.@] */void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat){ ULONG esize; TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); SizeConformance(pStubMsg); SizeVariance(pStubMsg); if (*pFormat == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((char*)pMemory)); pStubMsg->ActualCount = strlen((char*)pMemory)+1; esize = 1; } else if (*pFormat == RPC_FC_C_WSTRING) { TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; esize = 2; } else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ return; } if (pFormat[1] == RPC_FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); else pStubMsg->MaxCount = pStubMsg->ActualCount; pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);}/************************************************************************ * NdrConformantStringMemorySize [RPCRT4.@] */ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ){ ULONG rslt = 0; FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); assert(pStubMsg && pFormat); if (*pFormat == RPC_FC_C_CSTRING) { rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */ } else if (*pFormat == RPC_FC_C_WSTRING) { rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */ } else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ } if (pFormat[1] != RPC_FC_PAD) { FIXME("sized string format=%d\n", pFormat[1]); } TRACE(" --> %u\n", rslt); return rslt;}/************************************************************************ * NdrConformantStringUnmarshall [RPCRT4.@] */unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ){ ULONG bufsize, memsize, esize, i; TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); assert(pFormat && ppMemory && pStubMsg); ReadConformance(pStubMsg, NULL); ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); if (*pFormat == RPC_FC_C_CSTRING) esize = 1; else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ esize = 0; } memsize = safe_multiply(esize, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); /* strings must always have null terminating bytes */ if (bufsize < esize) { ERR("invalid string length of %d\n", pStubMsg->ActualCount); RpcRaiseException(RPC_S_INVALID_BOUND); return NULL; } for (i = bufsize - esize; i < bufsize; i++) if (pStubMsg->Buffer[i] != 0) { ERR("string not null-terminated at byte position %d, data is 0x%x\n", i, pStubMsg->Buffer[i]); RpcRaiseException(RPC_S_INVALID_BOUND); return NULL; } if (fMustAlloc || !*ppMemory) *ppMemory = NdrAllocate(pStubMsg, memsize); memcpy(*ppMemory, pStubMsg->Buffer, bufsize); pStubMsg->Buffer += bufsize; if (*pFormat == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); } else if (*pFormat == RPC_FC_C_WSTRING) { TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); } return NULL; /* FIXME: is this always right? */}/*********************************************************************** * NdrNonConformantStringMarshall [RPCRT4.@] */unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat){ FIXME("stub\n"); return NULL;}/*********************************************************************** * NdrNonConformantStringUnmarshall [RPCRT4.@] */unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc){ FIXME("stub\n"); return NULL;}/*********************************************************************** * NdrNonConformantStringBufferSize [RPCRT4.@] */void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat){ FIXME("stub\n");}/*********************************************************************** * NdrNonConformantStringMemorySize [RPCRT4.@] */ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat){ FIXME("stub\n"); return 0;}static inline void dump_pointer_attr(unsigned char attr){ if (attr & RPC_FC_P_ALLOCALLNODES) TRACE(" RPC_FC_P_ALLOCALLNODES"); if (attr & RPC_FC_P_DONTFREE) TRACE(" RPC_FC_P_DONTFREE"); if (attr & RPC_FC_P_ONSTACK) TRACE(" RPC_FC_P_ONSTACK"); if (attr & RPC_FC_P_SIMPLEPOINTER) TRACE(" RPC_FC_P_SIMPLEPOINTER"); if (attr & RPC_FC_P_DEREF) TRACE(" RPC_FC_P_DEREF"); TRACE("\n");}/*********************************************************************** * PointerMarshall [internal] */static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *Buffer, unsigned char *Pointer, PFORMAT_STRING pFormat){ unsigned type = pFormat[0], attr = pFormat[1]; PFORMAT_STRING desc; NDR_MARSHALL m; ULONG pointer_id; int pointer_needs_marshaling; TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); pFormat += 2; if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; else desc = pFormat + *(const SHORT*)pFormat; switch (type) { case RPC_FC_RP: /* ref pointer (always non-null) */#if 0 /* this causes problems for InstallShield so is disabled - we need more tests */ if (!Pointer) RpcRaiseException(RPC_X_NULL_REF_POINTER);#endif pointer_needs_marshaling = 1; break; case RPC_FC_UP: /* unique pointer */ case RPC_FC_OP: /* object pointer - same as unique here */ if (Pointer) pointer_needs_marshaling = 1; else pointer_needs_marshaling = 0; pointer_id = (ULONG)Pointer; TRACE("writing 0x%08x to buffer\n", pointer_id); NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); break; case RPC_FC_FP:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -