unsigned char * __RPC_USER STGMEDIUM_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium) { TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, pStgMedium); ALIGN_POINTER(pBuffer, 3); *(DWORD *)pBuffer = pStgMedium->tymed; pBuffer += sizeof(DWORD); if (pStgMedium->tymed != TYMED_NULL) { *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->u.pstg; pBuffer += sizeof(DWORD); } *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->pUnkForRelease; pBuffer += sizeof(DWORD); switch (pStgMedium->tymed) { case TYMED_NULL: TRACE("TYMED_NULL\n"); break; case TYMED_HGLOBAL: TRACE("TYMED_HGLOBAL\n"); pBuffer = HGLOBAL_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal); break; case TYMED_FILE: FIXME("TYMED_FILE\n"); break; case TYMED_ISTREAM: FIXME("TYMED_ISTREAM\n"); break; case TYMED_ISTORAGE: FIXME("TYMED_ISTORAGE\n"); break; case TYMED_GDI: FIXME("TYMED_GDI\n"); break; case TYMED_MFPICT: FIXME("TYMED_MFPICT\n"); break; case TYMED_ENHMF: TRACE("TYMED_ENHMF\n"); pBuffer = HENHMETAFILE_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile); break; default: RaiseException(DV_E_TYMED, 0, 0, NULL); } if (pStgMedium->pUnkForRelease) FIXME("marshal pUnkForRelease\n"); return pBuffer; }
static void test_marshal_HGLOBAL(void) { USER_MARSHAL_CB umcb; MIDL_STUB_MESSAGE stub_msg; RPC_MESSAGE rpc_msg; unsigned char *buffer; ULONG size, block_size; HGLOBAL hglobal; HGLOBAL hglobal2; unsigned char *wirehglobal; int i; hglobal = NULL; init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal); /* native is poorly programmed and allocates 4/8 bytes more than it needs to * here - Wine doesn't have to emulate that */ ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %d\n", size); buffer = HeapAlloc(GetProcessHeap(), 0, size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal); wirehglobal = buffer; ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal); wirehglobal += sizeof(ULONG); ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n"); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); hglobal2 = NULL; HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2); ok(hglobal2 == hglobal, "Didn't unmarshal properly\n"); HeapFree(GetProcessHeap(), 0, buffer); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); HGLOBAL_UserFree(&umcb.Flags, &hglobal2); for(block_size = 0; block_size <= 17; block_size++) { ULONG actual_size, expected_size; hglobal = GlobalAlloc(0, block_size); buffer = GlobalLock(hglobal); for (i = 0; i < block_size; i++) buffer[i] = i; GlobalUnlock(hglobal); actual_size = GlobalSize(hglobal); expected_size = actual_size + 5 * sizeof(DWORD); trace("%d: actual size %d\n", block_size, actual_size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal); /* native is poorly programmed and allocates 4/8 bytes more than it needs to * here - Wine doesn't have to emulate that */ ok(size == expected_size || broken(size == expected_size + 4) || broken(size == expected_size + 8), "%d: got size %d\n", block_size, size); buffer = HeapAlloc(GetProcessHeap(), 0, size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal); wirehglobal = buffer; ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal); wirehglobal += sizeof(ULONG); ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n"); wirehglobal += sizeof(ULONG); ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x8 %08x\n", block_size, *(ULONG *)wirehglobal); wirehglobal += sizeof(ULONG); ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n"); wirehglobal += sizeof(ULONG); ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x10 %08x\n", block_size, *(ULONG *)wirehglobal); wirehglobal += sizeof(ULONG); for (i = 0; i < block_size; i++) ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); hglobal2 = NULL; HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2); ok(hglobal2 != NULL, "Didn't unmarshal properly\n"); HeapFree(GetProcessHeap(), 0, buffer); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); HGLOBAL_UserFree(&umcb.Flags, &hglobal2); GlobalFree(hglobal); } }