1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

Compare commits

...

55 Commits

Author SHA1 Message Date
cjy880927
b8b18a676d
Merge 5235686be0 into 1953d1e774 2024-06-20 02:35:57 +03:00
Alfred Agrell
1953d1e774 mf/tests: Clobber the alignment and bytes per second, to test if the DMO fixes it. 2024-06-19 21:05:58 +02:00
Alfred Agrell
1b702aea3c winegstreamer: Recalculate alignment and bytes per second, instead of copying from input. 2024-06-19 21:05:58 +02:00
Alfred Agrell
73f2e64fd4 quartz/tests: Test that avi_decompressor_source_qc_Notify does not deadlock if called from a foreign thread during IMemInput_Receive. 2024-06-19 21:05:52 +02:00
Alfred Agrell
c4a162a8fe quartz: Allow concurrent calls to AVI decoder qc_Notify and Receive.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
1543fc8d1b msvfw32/tests: Test that Cinepak rejects unsupported output types. 2024-06-19 21:05:52 +02:00
Alfred Agrell
640698e432 iccvid: Reject unsupported output types.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
66ceeed861 quartz/tests: Add Cinepak test to avi splitter. 2024-06-19 21:05:52 +02:00
Alfred Agrell
fb523ed66f winegstreamer: Make AVI splitter use end of previous frame if the current frame doesn't have a timestamp.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
ed819cc973 winegstreamer: Implement AM_MEDIA_TYPE to wg_format converter for Cinepak video.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Brendan McGrath
427e848d0d mf: Handle an error during Media Session Close.
Fixes the missing MESessionClosed event in this scenario.
2024-06-19 21:05:16 +02:00
Brendan McGrath
02ca366b5a mf: Handle MediaSession Close when state is SESSION_STATE_RESTARTING_SOURCES.
Fixes the missing MESessionClosed event in this scenario.
2024-06-19 21:05:15 +02:00
Brendan McGrath
af565ce846 mf/tests: Add additional tests for MESessionClosed event. 2024-06-19 21:05:15 +02:00
Hans Leidekker
bb46d4a621 odbc32: Rebind parameters when the result length array is resized. 2024-06-19 21:05:05 +02:00
Alexandre Julliard
2ac86fb8c3 kernelbase: Don't use WRITECOPY protection on anonymous mappings. 2024-06-19 21:01:47 +02:00
Alistair Leslie-Hughes
0a83c4f287 msado15: Use the correct version when loading the typelib. 2024-06-19 18:44:47 +02:00
Alexandros Frantzis
2e5b4ff32a winex11: Use default wglGetPixelFormatAttribivARB implementation.
Populate all the ARB related fields of advertised pixel formats, so that
the default implementation of wglGetPixelFormatAttribivARB (in opengl32)
will be used to get the pixel format attributes.
2024-06-19 18:43:07 +02:00
Alexandros Frantzis
8934fbcdbd winex11: Pass wgl_pixel_format to describe_pixel_format. 2024-06-19 18:43:07 +02:00
Alexandros Frantzis
35801043df winex11: Update describe_pixel_format coding style. 2024-06-19 18:43:07 +02:00
Alexandros Frantzis
3ecd3ff853 opengl32: Add default implementation for wglGetPixelFormatAttribfvARB.
The default implementation is always used, and never calls the driver
implementation of this function, so we can remove all the driver
implementations.
2024-06-19 18:42:45 +02:00
Alexandros Frantzis
5b126f7806 opengl32: Add default implementation for wglGetPixelFormatAttribivARB.
Extend the wgl_pixel_format struct with extra fields required to
implement wglGetPixelFormatAttribivARB in opengl32.dll. The default
implementation will be used automatically if the driver populates the
extra fields.
2024-06-19 18:40:29 +02:00
Eric Pouech
6d6fee9dda cmd: Fix delay expansion in FOR loop for filesets.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:10 +02:00
Eric Pouech
2e2a3f4539 cmd: Split parsing from executing FOR loops for filesets (/F).
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:09 +02:00
Eric Pouech
53f7a59992 cmd: Fix delay expansion in FOR /L loops.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:07 +02:00
Eric Pouech
9ba05f5e5b cmd: Split parsing from executing FOR loops for numbers (/L).
Introducing CMD_FOR_CONTROL structure to store parsing output
for consumption in execution.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:05 +02:00
Brendan Shanks
4a3365daff dbghelp: Add ARM/ARM64 machine types for Mach-O. 2024-06-19 11:15:32 +02:00
Elizabeth Figura
1200a80d76 ntdll/tests: Test IOSB handling with NtFlushBuffersFile. 2024-06-19 11:14:07 +02:00
Elizabeth Figura
898253af36 ntdll/tests: Test IOSB handling for a synchronous write which cannot be satisfied immediately. 2024-06-19 11:14:07 +02:00
Elizabeth Figura
d72567c626 ntdll/tests: Use NtReadFile to test WoW64 IOSB handling.
The current ioctls don't reliably return synchronously for overlapped handles
on Windows, which makes some of the conclusions drawn by the tests less clear.

Use NtReadFile instead, which will always return synchronously if there is data
in the pipe.
2024-06-19 11:14:06 +02:00
Alfred Agrell
e4e5d22145 quartz: Implement AMT/WMT differences for WMV media type.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56769
2024-06-19 11:13:29 +02:00
Rémi Bernon
96d294aa12 winex11: Don't use the vulkan driver interface for xrandr. 2024-06-18 21:17:11 +02:00
Rémi Bernon
2c4db92151 win32u: Use the vulkan functions directly from d3dkmt. 2024-06-18 21:17:11 +02:00
Connor McAdams
1215ee0241 d3dx9: Add support for specifying which mip level to get pixel data from to d3dx_image_get_pixels().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
be746bee64 d3dx9: Cleanup texture value argument handling in D3DXCreateTextureFromFileInMemoryEx().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
86a87b0403 d3dx9: Add support for specifying a starting mip level when initializing a d3dx_image structure.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
8d4024ca7e d3dx9: Use struct volume inside of struct d3dx_image for storing dimensions.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
f89b00c878 d3dx9: Use d3dx_image structure inside of D3DXCreateTextureFromFileInMemoryEx().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
fd2861252c d3dx9: Refactor texture creation and cleanup in D3DXCreateTextureFromFileInMemoryEx().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
acf797f669 d3dx9/tests: Add more tests for loading files with multiple mip levels into textures.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Connor McAdams
52e71f3e07 d3dx9/tests: Add tests for the source info argument of D3DXCreateTextureFromFileInMemoryEx().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
2024-06-18 21:17:11 +02:00
Rémi Bernon
6cb63e996e kernel32/tests: Break debugger loop on unexpected result.
Avoid infinite loop that sometimes happen on macOS and make the test
spew hundred of thousand of "Test failed" lines.
2024-06-18 21:17:11 +02:00
Rémi Bernon
299490ed7b dwrite/tests: Ignore macOS specific "flip" sbix format. 2024-06-18 21:17:11 +02:00
Daniel Lehman
a23b754f06 odbc32: StrLen_or_Ind passed to SQLBindCol can be NULL. 2024-06-18 21:17:11 +02:00
Daniel Lehman
133f14415f odbc32: Numeric attribute pointer may be null if not a numeric type in SQLColAttribute(). 2024-06-18 21:17:11 +02:00
Daniel Lehman
f68e91966c odbc32: Handle both directions for SQLBindParameter().
Pointers can be filled after the call to SQLBindParameter() so it needs to be read at SQLExecute().
2024-06-18 21:17:11 +02:00
Alexandre Julliard
9c6fb2b30c kernelbase: Send cross process notifications in FlushInstructionCache on ARM64. 2024-06-18 21:17:11 +02:00
Alexandre Julliard
2c7f4181bc kernelbase: Send cross process notifications in WriteProcessMemory on ARM64. 2024-06-18 21:17:11 +02:00
Alexandre Julliard
6ea77ec086 kernelbase: Make memory writable in WriteProcessMemory if necessary. 2024-06-18 21:17:11 +02:00
Alexandre Julliard
b639319830 kernel32/tests: Add some tests for WriteProcessMemory/NtWriteVirtualMemory. 2024-06-18 21:17:11 +02:00
Alexandre Julliard
6eefb42a41 ntdll/tests: Add test for cross-process notifications on ARM64EC. 2024-06-18 21:17:11 +02:00
Alistair Leslie-Hughes
68e8eaa4b7 oledb32: When creating a Data Source, handle non fatal errors.
The Jet4 driver doesn't handle the DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO
property which is passed in SetProperties.  On return that property is marked
as DBPROPSTATUS_NOTSUPPORTED and returns DB_S_ERRORSOCCURRED.

In this case, we dont care that isn't not supported and should allow
the DataSource to succeed.
2024-06-18 21:17:11 +02:00
Alistair Leslie-Hughes
43f6ba56d0 oledb32: Support multiple values when parsing the property Mode.
The "Mode" can be a mix of any of the flags.
2024-06-18 21:17:08 +02:00
Elizabeth Figura
aa0ab31571 server: Directly wake up wait asyncs when the serial mask changes. 2024-06-18 10:47:22 +02:00
Elizabeth Figura
6b7834d407 server: Check for an existing serial wait ioctl within the ioctl handler. 2024-06-18 10:47:19 +02:00
chenjiangyi
5235686be0 ntdll: Support Ctrl-C stop debuggee and attach 32-bit process in wow64 mode.
Signed-off-by: chenjiangyi <chenjiangyi@uniontech.com>
2023-11-05 17:13:16 +08:00
53 changed files with 2866 additions and 1106 deletions

View File

@ -104,9 +104,7 @@ struct d3dx_image
D3DRESOURCETYPE resource_type;
D3DFORMAT format;
uint32_t width;
uint32_t height;
uint32_t depth;
struct volume size;
uint32_t mip_levels;
BYTE *pixels;
@ -122,6 +120,12 @@ struct d3dx_image
D3DXIMAGE_FILEFORMAT image_file_format;
};
HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image,
uint32_t starting_mip_level, uint32_t flags);
void d3dx_image_cleanup(struct d3dx_image *image);
HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels);
void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image);
struct d3dx_include_from_file
{
ID3DXInclude ID3DXInclude_iface;
@ -168,9 +172,6 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size,
const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette);
HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette,
DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels,
unsigned int *loaded_miplevels);
HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data,
const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info);
HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,

View File

@ -437,6 +437,20 @@ static HRESULT d3dformat_to_dds_pixel_format(struct dds_pixel_format *pixel_form
return E_NOTIMPL;
}
static void d3dx_get_next_mip_level_size(struct volume *size)
{
size->width = max(size->width / 2, 1);
size->height = max(size->height / 2, 1);
size->depth = max(size->depth / 2, 1);
}
static const char *debug_volume(const struct volume *volume)
{
if (!volume)
return "(null)";
return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth);
}
static HRESULT d3dx_calculate_pixels_size(D3DFORMAT format, uint32_t width, uint32_t height,
uint32_t *pitch, uint32_t *size)
{
@ -570,63 +584,6 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d
row_pitch, slice_pitch, NULL, src_box, filter, color_key);
}
HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette,
DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels,
unsigned int *loaded_miplevels)
{
HRESULT hr;
RECT src_rect;
UINT src_pitch;
UINT mip_level;
UINT mip_levels;
UINT mip_level_size;
UINT width, height;
IDirect3DSurface9 *surface;
const struct dds_header *header = src_data;
const BYTE *pixels = (BYTE *)(header + 1);
/* Loading a cube texture as a simple texture is also supported
* (only first face texture is taken). Same with volume textures. */
if ((src_info->ResourceType != D3DRTYPE_TEXTURE)
&& (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)
&& (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE))
{
WARN("Trying to load a %u resource as a 2D texture, returning failure.\n", src_info->ResourceType);
return D3DXERR_INVALIDDATA;
}
width = src_info->Width;
height = src_info->Height;
mip_levels = min(src_info->MipLevels, IDirect3DTexture9_GetLevelCount(texture));
if (src_info->ResourceType == D3DRTYPE_VOLUMETEXTURE)
mip_levels = 1;
for (mip_level = 0; mip_level < mip_levels + skip_levels; ++mip_level)
{
hr = d3dx_calculate_pixels_size(src_info->Format, width, height, &src_pitch, &mip_level_size);
if (FAILED(hr)) return hr;
if (mip_level >= skip_levels)
{
SetRect(&src_rect, 0, 0, width, height);
IDirect3DTexture9_GetSurfaceLevel(texture, mip_level - skip_levels, &surface);
hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch,
NULL, &src_rect, filter, color_key);
IDirect3DSurface9_Release(surface);
if (FAILED(hr))
return hr;
}
pixels += mip_level_size;
width = max(1, width / 2);
height = max(1, height / 2);
}
*loaded_miplevels = mip_levels - skip_levels;
return D3D_OK;
}
HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data,
const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
{
@ -733,7 +690,7 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co
}
static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size,
struct d3dx_image *image)
struct d3dx_image *image, uint32_t starting_mip_level)
{
const struct dds_header *header = src_data;
uint32_t expected_src_data_size;
@ -743,9 +700,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
return D3DXERR_INVALIDDATA;
TRACE("File type is DDS.\n");
image->width = header->width;
image->height = header->height;
image->depth = 1;
set_volume_struct(&image->size, header->width, header->height, 1);
image->mip_levels = header->miplevels ? header->miplevels : 1;
image->format = dds_pixel_format_to_d3dformat(&header->pixel_format);
@ -755,7 +710,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
TRACE("Pixel format is %#x.\n", image->format);
if (header->caps2 & DDS_CAPS2_VOLUME)
{
image->depth = header->depth;
image->size.depth = header->depth;
image->resource_type = D3DRTYPE_VOLUMETEXTURE;
}
else if (header->caps2 & DDS_CAPS2_CUBEMAP)
@ -773,8 +728,8 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
else
image->resource_type = D3DRTYPE_TEXTURE;
expected_src_data_size = calculate_dds_file_size(image->format, image->width, image->height,
image->depth, image->mip_levels, faces);
expected_src_data_size = calculate_dds_file_size(image->format, image->size.width, image->size.height,
image->size.depth, image->mip_levels, faces);
if (src_data_size < expected_src_data_size)
{
WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size);
@ -783,6 +738,27 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
image->pixels = ((BYTE *)src_data) + sizeof(*header);
image->image_file_format = D3DXIFF_DDS;
if (starting_mip_level && (image->mip_levels > 1))
{
uint32_t i, row_pitch, slice_pitch, initial_mip_levels;
const struct volume initial_size = image->size;
initial_mip_levels = image->mip_levels;
for (i = 0; i < starting_mip_level; i++)
{
d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
image->pixels += slice_pitch * image->size.depth;
d3dx_get_next_mip_level_size(&image->size);
if (--image->mip_levels == 1)
break;
}
TRACE("Requested starting mip level %u, actual starting mip level is %u (of %u total in image).\n",
starting_mip_level, (initial_mip_levels - image->mip_levels), initial_mip_levels);
TRACE("Original dimensions %s, new dimensions %s.\n", debug_volume(&initial_size), debug_volume(&image->size));
}
return D3D_OK;
}
@ -863,18 +839,18 @@ static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image
&& image->image_file_format != D3DXIFF_TGA))
return FALSE;
size = image->width * image->height * 4;
size = image->size.width * image->size.height * 4;
if (!(buffer = malloc(size)))
return FALSE;
if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->width * 4, size, buffer)))
if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->size.width * 4, size, buffer)))
{
ERR("Failed to copy pixels, hr %#lx.\n", hr);
free(buffer);
return FALSE;
}
for (i = 0; i < image->width * image->height; ++i)
for (i = 0; i < image->size.width * image->size.height; ++i)
{
if (buffer[i * 4 + 3])
{
@ -952,7 +928,7 @@ static HRESULT d3dx_image_wic_frame_decode(struct d3dx_image *image,
HRESULT hr;
fmt_desc = get_format_info(image->format);
hr = d3dx_calculate_pixels_size(image->format, image->width, image->height, &row_pitch, &slice_pitch);
hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
if (FAILED(hr))
return hr;
@ -1088,7 +1064,7 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src
if (FAILED(hr))
goto exit;
hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->width, &image->height);
hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->size.width, &image->size.height);
if (FAILED(hr))
goto exit;
@ -1113,7 +1089,7 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src
goto exit;
}
image->depth = 1;
image->size.depth = 1;
image->mip_levels = 1;
image->resource_type = D3DRTYPE_TEXTURE;
@ -1132,48 +1108,66 @@ exit:
return hr;
}
static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size,
struct d3dx_image *image, uint32_t flags)
HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image,
uint32_t starting_mip_level, uint32_t flags)
{
if (!src_data || !src_data_size || !image)
return D3DERR_INVALIDCALL;
memset(image, 0, sizeof(*image));
if ((src_data_size >= 4) && !memcmp(src_data, "DDS ", 4))
return d3dx_initialize_image_from_dds(src_data, src_data_size, image);
return d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level);
return d3dx_initialize_image_from_wic(src_data, src_data_size, image, flags);
}
static void d3dx_image_cleanup(struct d3dx_image *image)
void d3dx_image_cleanup(struct d3dx_image *image)
{
free(image->image_buf);
free(image->palette);
}
static HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels)
HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels)
{
uint32_t row_pitch, slice_pitch;
struct volume mip_level_size = image->size;
const BYTE *pixels_ptr = image->pixels;
uint32_t row_pitch, slice_pitch, i;
RECT unaligned_rect;
HRESULT hr = S_OK;
hr = d3dx_calculate_pixels_size(image->format, image->width, image->height, &row_pitch, &slice_pitch);
if (FAILED(hr))
return hr;
if (mip_level >= image->mip_levels)
{
ERR("Tried to retrieve mip level %u, but image only has %u mip levels.\n", mip_level, image->mip_levels);
return E_FAIL;
}
SetRect(&unaligned_rect, 0, 0, image->width, image->height);
set_d3dx_pixels(pixels, image->pixels, row_pitch, slice_pitch, image->palette, image->width, image->height,
image->depth, &unaligned_rect);
slice_pitch = row_pitch = 0;
for (i = 0; i < image->mip_levels; i++)
{
hr = d3dx_calculate_pixels_size(image->format, mip_level_size.width, mip_level_size.height, &row_pitch, &slice_pitch);
if (FAILED(hr))
return hr;
if (i == mip_level)
break;
pixels_ptr += slice_pitch * mip_level_size.depth;
d3dx_get_next_mip_level_size(&mip_level_size);
}
SetRect(&unaligned_rect, 0, 0, mip_level_size.width, mip_level_size.height);
set_d3dx_pixels(pixels, pixels_ptr, row_pitch, slice_pitch, image->palette, mip_level_size.width,
mip_level_size.height, mip_level_size.depth, &unaligned_rect);
return D3D_OK;
}
static void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image)
void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image)
{
info->ImageFileFormat = image->image_file_format;
info->Width = image->width;
info->Height = image->height;
info->Depth = image->depth;
info->Width = image->size.width;
info->Height = image->size.height;
info->Depth = image->size.depth;
info->MipLevels = image->mip_levels;
info->Format = image->format;
info->ResourceType = image->resource_type;
@ -1213,7 +1207,7 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize,
if (!info)
return D3D_OK;
hr = d3dx_image_init(data, datasize, &image, D3DX_IMAGE_INFO_ONLY);
hr = d3dx_image_init(data, datasize, &image, 0, D3DX_IMAGE_INFO_ONLY);
if (FAILED(hr)) {
TRACE("Invalid or unsupported image file\n");
return D3DXERR_INVALIDDATA;
@ -1362,7 +1356,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
if (!pDestSurface || !pSrcData || !SrcDataSize)
return D3DERR_INVALIDCALL;
hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0);
hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0);
if (FAILED(hr))
return D3DXERR_INVALIDDATA;
@ -1372,7 +1366,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
else
SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height);
hr = d3dx_image_get_pixels(&image, &pixels);
hr = d3dx_image_get_pixels(&image, 0, &pixels);
if (FAILED(hr))
goto exit;

View File

@ -24,6 +24,7 @@
#include "wine/test.h"
#include "d3dx9tex.h"
#include "resources.h"
#include <stdint.h>
static int has_2d_dxt1, has_2d_dxt3, has_2d_dxt5, has_cube_dxt5, has_3d_dxt3;
@ -127,6 +128,91 @@ static const unsigned char png_grayscale[] =
0x60, 0x82
};
/*
* 4x4x4 24-bit volume dds, 3 mipmaps. Level 0 is red, level 1 is green, level 2 is
* blue.
*/
static const BYTE dds_volume_24bit_4_4_4[] =
{
0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x0f,0x10,0x82,0x00,0x04,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00,
0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0x00
};
/*
* 4x4x4 DXT3 volume dds. 3 mipmaps. Level 0 is red, level 1 is green, level 2 is
* blue.
*/
static const BYTE dds_volume_dxt3_4_4_4[] =
{
0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00,
0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x07,0xe0,0x07,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x07,0xe0,0x07,0xaa,0xaa,0xaa,0xaa,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x1f,0x00,0xaa,0xaa,0xaa,0xaa,
};
/*
* 8x8 24-bit dds, 4 mipmaps. Level 0 is red, level 1 is green, level 2 is
* blue, and level 3 is black.
*/
static const BYTE dds_24bit_8_8[] =
{
0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x08,0x00,0x00,0x00,
0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,
0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,
0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00
};
#define ADMITTED_ERROR 0.0001f
static inline float relative_error(float expected, float got)
@ -146,6 +232,92 @@ static inline void expect_vec4_(unsigned int line, const D3DXVECTOR4 *expected,
got->x, got->y, got->z, got->w);
}
#define check_image_info(info, width, height, depth, mip_levels, format, resource_type, image_file_format, wine_todo) \
check_image_info_(__LINE__, info, width, height, depth, mip_levels, format, resource_type, image_file_format, \
wine_todo)
static inline void check_image_info_(uint32_t line, const D3DXIMAGE_INFO *info, uint32_t width, uint32_t height,
uint32_t depth, uint32_t mip_levels, D3DFORMAT format, D3DRESOURCETYPE resource_type,
D3DXIMAGE_FILEFORMAT image_file_format, BOOL wine_todo)
{
const D3DXIMAGE_INFO expected_info = { width, height, depth, mip_levels, format, resource_type, image_file_format };
BOOL matched;
matched = !memcmp(&expected_info, info, sizeof(*info));
todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected image info values.\n");
if (matched)
return;
todo_wine_if(wine_todo && info->Width != width)
ok_(__FILE__, line)(info->Width == width, "Expected width %u, got %u.\n", width, info->Width);
todo_wine_if(wine_todo && info->Height != height)
ok_(__FILE__, line)(info->Height == height, "Expected height %u, got %u.\n", height, info->Height);
todo_wine_if(wine_todo && info->Depth != depth)
ok_(__FILE__, line)(info->Depth == depth, "Expected depth %u, got %u.\n", depth, info->Depth);
todo_wine_if(wine_todo && info->MipLevels != mip_levels)
ok_(__FILE__, line)(info->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels,
info->MipLevels);
ok_(__FILE__, line)(info->Format == format, "Expected texture format %d, got %d.\n", format, info->Format);
ok_(__FILE__, line)(info->ResourceType == resource_type, "Expected resource_type %d, got %d.\n", resource_type,
info->ResourceType);
ok_(__FILE__, line)(info->ImageFileFormat == image_file_format, "Expected image_file_format %d, got %d.\n",
image_file_format, info->ImageFileFormat);
}
#define check_texture_level_desc(tex, level, format, usage, pool, multi_sample_type, multi_sample_quality, width, \
height, wine_todo) \
check_texture_level_desc_(__LINE__, tex, level, format, usage, pool, multi_sample_type, multi_sample_quality, \
width, height, wine_todo)
static inline void check_texture_level_desc_(uint32_t line, IDirect3DTexture9 *tex, uint32_t level, D3DFORMAT format,
uint32_t usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multi_sample_type,
uint32_t multi_sample_quality, uint32_t width, uint32_t height, BOOL wine_todo)
{
const D3DSURFACE_DESC expected_desc = { format, D3DRTYPE_SURFACE, usage, pool, multi_sample_type,
multi_sample_quality, width, height };
D3DSURFACE_DESC desc;
BOOL matched;
HRESULT hr;
hr = IDirect3DTexture9_GetLevelDesc(tex, level, &desc);
todo_wine_if(wine_todo && FAILED(hr))
ok_(__FILE__, line)(hr == S_OK, "Failed to get texture level desc with hr %#lx.\n", hr);
if (FAILED(hr))
return;
matched = !memcmp(&expected_desc, &desc, sizeof(desc));
todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected surface desc values.\n");
if (matched)
return;
todo_wine_if(wine_todo && desc.Format != format)
ok_(__FILE__, line)(desc.Format == format, "Expected surface format %d, got %d.\n", format, desc.Format);
ok_(__FILE__, line)(desc.Type == D3DRTYPE_SURFACE, "Expected D3DRTYPE_SURFACE, got %d.\n", desc.Type);
todo_wine_if(wine_todo && desc.Usage != usage)
ok_(__FILE__, line)(desc.Usage == usage, "Expected usage %u, got %lu.\n", usage, desc.Usage);
todo_wine_if(wine_todo && desc.Pool != pool)
ok_(__FILE__, line)(desc.Pool == pool, "Expected pool %d, got %d.\n", pool, desc.Pool);
todo_wine_if(wine_todo && desc.MultiSampleType != multi_sample_type)
ok_(__FILE__, line)(desc.MultiSampleType == multi_sample_type, "Expected multi sample type %d, got %d.\n",
multi_sample_type, desc.MultiSampleType);
todo_wine_if(wine_todo && desc.MultiSampleQuality != multi_sample_quality)
ok_(__FILE__, line)(desc.MultiSampleQuality == multi_sample_quality, "Expected multi sample quality %u, got %lu.\n",
multi_sample_quality, desc.MultiSampleQuality);
todo_wine_if(wine_todo && desc.Width != width)
ok_(__FILE__, line)(desc.Width == width, "Expected width %u, got %u.\n", width, desc.Width);
todo_wine_if(wine_todo && desc.Height != height)
ok_(__FILE__, line)(desc.Height == height, "Expected height %u, got %u.\n", height, desc.Height);
}
#define check_texture_mip_levels(tex, expected_mip_levels, wine_todo) \
check_texture_mip_levels_(__LINE__, ((IDirect3DBaseTexture9 *)tex), expected_mip_levels, wine_todo)
static inline void check_texture_mip_levels_(uint32_t line, IDirect3DBaseTexture9 *tex, uint32_t expected_mip_levels,
BOOL wine_todo)
{
uint32_t mip_levels = IDirect3DBaseTexture9_GetLevelCount(tex);
todo_wine_if(wine_todo) ok_(__FILE__, line)(mip_levels == expected_mip_levels, "Got miplevels %u, expected %u.\n",
mip_levels, expected_mip_levels);
}
static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
{
unsigned int diff = x > y ? x - y : y - x;
@ -161,6 +333,88 @@ static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff)
&& compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
}
struct surface_readback
{
IDirect3DSurface9 *surface;
D3DLOCKED_RECT locked_rect;
};
static uint32_t get_readback_color(struct surface_readback *rb, uint32_t x, uint32_t y)
{
return rb->locked_rect.pBits
? ((uint32_t *)rb->locked_rect.pBits)[y * rb->locked_rect.Pitch / sizeof(uint32_t) + x] : 0xdeadbeef;
}
static void release_surface_readback(struct surface_readback *rb)
{
HRESULT hr;
if (!rb->surface)
return;
if (rb->locked_rect.pBits && FAILED(hr = IDirect3DSurface9_UnlockRect(rb->surface)))
trace("Can't unlock the readback surface, hr %#lx.\n", hr);
IDirect3DSurface9_Release(rb->surface);
}
static void get_texture_surface_readback(IDirect3DDevice9 *device, IDirect3DTexture9 *texture, uint32_t mip_level,
struct surface_readback *rb)
{
IDirect3DSurface9 *surface;
D3DSURFACE_DESC desc;
HRESULT hr;
memset(rb, 0, sizeof(*rb));
hr = IDirect3DTexture9_GetSurfaceLevel(texture, mip_level, &surface);
if (FAILED(hr))
{
trace("Failed to get surface for mip level %d, hr %#lx.\n", mip_level, hr);
return;
}
hr = IDirect3DSurface9_GetDesc(surface, &desc);
if (FAILED(hr))
{
trace("Failed to get surface description, hr %#lx.\n", hr);
goto exit;
}
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
&rb->surface, NULL);
if (FAILED(hr))
{
trace("Can't create the readback surface, hr %#lx.\n", hr);
goto exit;
}
hr = D3DXLoadSurfaceFromSurface(rb->surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0);
if (FAILED(hr))
{
trace("Can't load the readback surface, hr %#lx.\n", hr);
goto exit;
}
hr = IDirect3DSurface9_LockRect(rb->surface, &rb->locked_rect, NULL, D3DLOCK_READONLY);
if (FAILED(hr))
trace("Can't lock the readback surface, hr %#lx.\n", hr);
exit:
IDirect3DSurface9_Release(surface);
if (FAILED(hr))
{
if (rb->surface)
IDirect3DSurface9_Release(rb->surface);
rb->surface = NULL;
}
}
#define check_readback_pixel_4bpp(rb, x, y, color, todo) _check_readback_pixel_4bpp(__LINE__, rb, x, y, color, todo)
static inline void _check_readback_pixel_4bpp(uint32_t line, struct surface_readback *rb, uint32_t x,
uint32_t y, uint32_t expected_color, BOOL todo)
{
uint32_t color = get_readback_color(rb, x, y);
todo_wine_if(todo) ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x.\n", color, expected_color);
}
static BOOL is_autogenmipmap_supported(IDirect3DDevice9 *device, D3DRESOURCETYPE resource_type)
{
HRESULT hr;
@ -1676,6 +1930,10 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const uint32_t dds_volume_dxt3_4_4_4_expected_uncompressed[] =
{
0xffff0000, 0xff00ff00, 0xff0000ff,
};
IDirect3DSurface9 *surface, *uncompressed_surface;
IDirect3DTexture9 *texture;
D3DLOCKED_RECT lock_rect;
@ -1900,7 +2158,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
type = IDirect3DTexture9_GetType(texture);
ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u.\n", type, D3DRTYPE_TEXTURE);
level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture);
todo_wine ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count);
ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count);
hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#lx, expected %#lx.\n", hr, D3D_OK);
ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width);
@ -1925,17 +2183,70 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
ok(desc.Format == D3DFMT_A8R8G8B8, "Unexpected texture format %#x.\n", desc.Format);
skip("D3DFMT_DXT3 volume textures are not supported, skipping a test.\n");
}
/* The lower texture levels are apparently generated by filtering the level 0 surface
* I.e. following levels from the file are ignored. */
IDirect3DTexture9_Release(texture);
/*
* All mip levels are pulled from the texture file, even in the case of a
* volume texture file.
*/
hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4), &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 3, FALSE);
if (has_2d_dxt3)
{
struct surface_readback surface_rb;
uint32_t mip_level;
check_texture_level_desc(texture, 0, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE);
check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, FALSE);
check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, FALSE);
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level)
{
const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level];
uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc);
get_texture_surface_readback(device, texture, mip_level, &surface_rb);
for (y = 0; y < desc.Height; ++y)
{
for (x = 0; x < desc.Width; ++x)
{
check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE);
}
}
release_surface_readback(&surface_rb);
}
}
else
{
check_texture_level_desc(texture, 0, D3DFMT_A8R8G8B8, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE);
skip("D3DFMT_DXT3 textures are not supported, skipping a test.\n");
}
IDirect3DTexture9_Release(texture);
}
static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
{
static const uint32_t dds_24bit_8_8_expected[] =
{
0xffff0000, 0xff00ff00, 0xff0000ff, 0xff000000,
};
static const uint32_t dds_volume_24bit_4_4_4_expected[] =
{
0xffff0000, 0xff00ff00, 0xff0000ff,
};
static const uint32_t dds_volume_dxt3_4_4_4_expected_uncompressed[] =
{
0xffff0000, 0xff00ff00, 0xff0000ff,
};
HRESULT hr;
struct surface_readback surface_rb;
uint32_t miplevels, mip_level;
IDirect3DTexture9 *texture;
unsigned int miplevels;
IDirect3DSurface9 *surface;
D3DXIMAGE_INFO img_info;
D3DSURFACE_DESC desc;
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
@ -2056,6 +2367,154 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
ok(desc.Format == D3DFMT_L8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_L8);
IDirect3DSurface9_Release(surface);
IDirect3DTexture9_Release(texture);
/* Test values returned in the D3DXIMAGE_INFO structure. */
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(0, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 2, FALSE);
check_image_info(&img_info, 2, 2, 1, 2, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE);
check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
IDirect3DTexture9_Release(texture);
/*
* The values returned in the D3DXIMAGE_INFO structure represent the mip
* level the texture data was retrieved from, i.e if we skip the first mip
* level, we will get the values of the second mip level.
*/
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(1, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 1, FALSE);
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
IDirect3DTexture9_Release(texture);
/*
* Request skipping 3 mip levels in a file that only has 2 mip levels. In this
* case, it stops at the final mip level.
*/
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(3, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 1, FALSE);
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
IDirect3DTexture9_Release(texture);
/*
* Load multiple mip levels from a file and check the resulting pixel
* values.
*/
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8),
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 4, FALSE);
check_image_info(&img_info, 8, 8, 1, 4, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 8, 8, FALSE);
check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE);
check_texture_level_desc(texture, 2, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE);
check_texture_level_desc(texture, 3, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_24bit_8_8_expected); ++mip_level)
{
const uint32_t expected_color = dds_24bit_8_8_expected[mip_level];
uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc);
get_texture_surface_readback(device, texture, mip_level, &surface_rb);
for (y = 0; y < desc.Height; ++y)
{
for (x = 0; x < desc.Width; ++x)
{
check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE);
}
}
release_surface_readback(&surface_rb);
}
IDirect3DTexture9_Release(texture);
/* Volume DDS with mips into regular texture tests. */
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_volume_24bit_4_4_4, sizeof(dds_volume_24bit_4_4_4),
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 3, FALSE);
check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_R8G8B8, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE);
check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE);
check_texture_level_desc(texture, 2, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_24bit_4_4_4_expected); ++mip_level)
{
const uint32_t expected_color = dds_volume_24bit_4_4_4_expected[mip_level];
uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc);
get_texture_surface_readback(device, texture, mip_level, &surface_rb);
for (y = 0; y < desc.Height; ++y)
{
for (x = 0; x < desc.Width; ++x)
{
check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE);
}
}
release_surface_readback(&surface_rb);
}
IDirect3DTexture9_Release(texture);
/* DXT3 volume DDS with mips into a regular texture. */
if (has_2d_dxt3)
{
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4),
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 3, FALSE);
check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_DXT3, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE);
check_texture_level_desc(texture, 0, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE);
check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE);
check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level)
{
const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level];
uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc);
get_texture_surface_readback(device, texture, mip_level, &surface_rb);
for (y = 0; y < desc.Height; ++y)
{
for (x = 0; x < desc.Width; ++x)
{
check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE);
}
}
release_surface_readback(&surface_rb);
}
IDirect3DTexture9_Release(texture);
}
else
{
skip("D3DFMT_DXT3 textures are not supported, skipping tests.\n");
}
}
static void test_D3DXCreateCubeTextureFromFileInMemory(IDirect3DDevice9 *device)

View File

@ -567,11 +567,11 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
{
const struct pixel_format_desc *src_fmt_desc, *dst_fmt_desc;
BOOL dynamic_texture, format_specified = FALSE;
unsigned int loaded_miplevels, skip_levels;
IDirect3DSurface9 *surface;
IDirect3DTexture9 **texptr;
IDirect3DTexture9 *buftex;
uint32_t loaded_miplevels, skip_levels, i;
IDirect3DTexture9 *staging_tex, *tex;
struct d3dx_image image;
D3DXIMAGE_INFO imginfo;
D3DCAPS9 caps;
HRESULT hr;
@ -586,160 +586,134 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
if (!device || !texture || !srcdata || !srcdatasize)
return D3DERR_INVALIDCALL;
hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
staging_tex = tex = *texture = NULL;
skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0;
hr = d3dx_image_init(srcdata, srcdatasize, &image, skip_levels, 0);
if (FAILED(hr))
{
FIXME("Unrecognized file format, returning failure.\n");
*texture = NULL;
return hr;
}
d3dximage_info_from_d3dx_image(&imginfo, &image);
/* handle default values */
if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
width = imginfo.Width;
if (!width || width == D3DX_DEFAULT_NONPOW2 || width == D3DX_FROM_FILE || width == D3DX_DEFAULT)
width = (width == D3DX_DEFAULT) ? make_pow2(imginfo.Width) : imginfo.Width;
if (!height || height == D3DX_DEFAULT_NONPOW2 || height == D3DX_FROM_FILE || height == D3DX_DEFAULT)
height = (height == D3DX_DEFAULT) ? make_pow2(imginfo.Height) : imginfo.Height;
if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
height = imginfo.Height;
if (width == D3DX_DEFAULT)
width = make_pow2(imginfo.Width);
if (height == D3DX_DEFAULT)
height = make_pow2(imginfo.Height);
if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT);
if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
format = imginfo.Format;
else
format_specified = TRUE;
if (width == D3DX_FROM_FILE)
{
width = imginfo.Width;
}
if (height == D3DX_FROM_FILE)
{
height = imginfo.Height;
}
if (format == D3DFMT_FROM_FILE)
{
format = imginfo.Format;
}
if (miplevels == D3DX_FROM_FILE)
{
miplevels = imginfo.MipLevels;
}
skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0;
if (skip_levels && imginfo.MipLevels > skip_levels)
{
TRACE("Skipping the first %u (of %u) levels of a DDS mipmapped texture.\n",
skip_levels, imginfo.MipLevels);
TRACE("Texture level 0 dimensions are %ux%u.\n", imginfo.Width, imginfo.Height);
width >>= skip_levels;
height >>= skip_levels;
miplevels -= skip_levels;
}
else
{
skip_levels = 0;
}
miplevels = (miplevels == D3DX_FROM_FILE) ? imginfo.MipLevels : miplevels;
/* Fix up texture creation parameters. */
hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
if (FAILED(hr))
{
FIXME("Couldn't find suitable texture parameters.\n");
*texture = NULL;
return hr;
goto err;
}
if (colorkey && !format_specified)
format = get_alpha_replacement_format(format);
if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE
&& D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1)
{
FIXME("Generation of mipmaps for compressed volume textures is not implemented yet.\n");
miplevels = 1;
}
if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
return D3DERR_INVALIDCALL;
{
hr = D3DERR_INVALIDCALL;
goto err;
}
/* Create the to-be-filled texture */
dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
{
hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &buftex);
texptr = &buftex;
TRACE("Creating staging texture.\n");
hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &staging_tex);
tex = staging_tex;
}
else
{
hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
texptr = texture;
hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, &tex);
}
if (FAILED(hr))
{
FIXME("Texture creation failed.\n");
*texture = NULL;
return hr;
goto err;
}
TRACE("Texture created correctly. Now loading the texture data into it.\n");
if (imginfo.ImageFileFormat != D3DXIFF_DDS)
dst_fmt_desc = get_format_info(format);
src_fmt_desc = get_format_info(imginfo.Format);
loaded_miplevels = min(imginfo.MipLevels, IDirect3DTexture9_GetLevelCount(tex));
for (i = 0; i < loaded_miplevels; i++)
{
IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
IDirect3DSurface9_Release(surface);
loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
}
else
{
hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo, skip_levels,
&loaded_miplevels);
struct d3dx_pixels src_pixels, dst_pixels;
D3DSURFACE_DESC dst_surface_desc;
D3DLOCKED_RECT dst_locked_rect;
RECT dst_rect;
hr = d3dx_image_get_pixels(&image, i, &src_pixels);
if (FAILED(hr))
break;
hr = IDirect3DTexture9_LockRect(tex, i, &dst_locked_rect, NULL, 0);
if (FAILED(hr))
break;
IDirect3DTexture9_GetLevelDesc(tex, i, &dst_surface_desc);
SetRect(&dst_rect, 0, 0, dst_surface_desc.Width, dst_surface_desc.Height);
set_d3dx_pixels(&dst_pixels, dst_locked_rect.pBits, dst_locked_rect.Pitch, 0, palette,
dst_surface_desc.Width, dst_surface_desc.Height, 1, &dst_rect);
hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, &src_pixels, src_fmt_desc, filter, colorkey);
IDirect3DTexture9_UnlockRect(tex, i);
if (FAILED(hr))
break;
}
if (FAILED(hr))
{
FIXME("Texture loading failed.\n");
IDirect3DTexture9_Release(*texptr);
*texture = NULL;
return hr;
goto err;
}
hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)tex, palette, loaded_miplevels - 1, mipfilter);
if (FAILED(hr))
{
FIXME("Texture filtering failed.\n");
IDirect3DTexture9_Release(*texptr);
*texture = NULL;
return hr;
goto err;
}
/* Move the data to the actual texture if necessary */
if (texptr == &buftex)
if (staging_tex)
{
hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
if (FAILED(hr))
{
IDirect3DTexture9_Release(buftex);
*texture = NULL;
return hr;
}
goto err;
IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
IDirect3DTexture9_Release(buftex);
IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)staging_tex, (IDirect3DBaseTexture9 *)(*texture));
IDirect3DTexture9_Release(staging_tex);
}
else
{
*texture = tex;
}
d3dx_image_cleanup(&image);
if (srcinfo)
*srcinfo = imginfo;
return D3D_OK;
return hr;
err:
d3dx_image_cleanup(&image);
if (tex)
IDirect3DTexture9_Release(tex);
return hr;
}
HRESULT WINAPI D3DXCreateTextureFromFileInMemory(struct IDirect3DDevice9 *device,

View File

@ -153,6 +153,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
#define MACHO_CPU_TYPE_X86 0x00000007
#define MACHO_CPU_TYPE_X86_64 0x01000007
#define MACHO_CPU_TYPE_ARM 0x0000000c
#define MACHO_CPU_TYPE_ARM64 0x0100000c
#define MACHO_MH_EXECUTE 0x2
#define MACHO_MH_DYLIB 0x6
@ -212,6 +214,8 @@ static USHORT macho_cpu_to_machine(unsigned cpu)
{
case MACHO_CPU_TYPE_X86: return IMAGE_FILE_MACHINE_I386;
case MACHO_CPU_TYPE_X86_64: return IMAGE_FILE_MACHINE_AMD64;
case MACHO_CPU_TYPE_ARM: return IMAGE_FILE_MACHINE_ARMNT;
case MACHO_CPU_TYPE_ARM64: return IMAGE_FILE_MACHINE_ARM64;
default:
FIXME("Untranslated Mach-O CPU %x\n", cpu);
return IMAGE_FILE_MACHINE_UNKNOWN;

View File

@ -9297,6 +9297,9 @@ static DWORD get_sbix_formats(IDWriteFontFace4 *fontface)
case MS_TIFF_TAG:
ret |= DWRITE_GLYPH_IMAGE_FORMATS_TIFF;
break;
case DWRITE_MAKE_OPENTYPE_TAG('f','l','i','p'):
/* ignore macOS-specific tag */
break;
default:
ok(0, "unexpected format, %#lx\n", GET_BE_DWORD(format));
}

View File

@ -797,26 +797,21 @@ static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBIT
if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
return ICERR_BADFORMAT;
switch( out->bmiHeader.biBitCount )
switch( out->bmiHeader.biCompression )
{
case 16:
if ( out->bmiHeader.biCompression == BI_BITFIELDS )
{
if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) &&
!ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
{
TRACE("unsupported output bit field(s) for 16-bit colors\n");
return ICERR_BADFORMAT;
}
}
case BI_RGB:
if ( out->bmiHeader.biBitCount == 16 || out->bmiHeader.biBitCount == 24 || out->bmiHeader.biBitCount == 32 )
return ICERR_OK;
break;
case 24:
case 32:
case BI_BITFIELDS:
if ( out->bmiHeader.biBitCount == 16 && ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) )
return ICERR_OK;
if ( out->bmiHeader.biBitCount == 16 && ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
return ICERR_OK;
break;
default:
TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount );
return ICERR_BADFORMAT;
}
TRACE("unsupported output format\n");
return ICERR_BADFORMAT;
}
return ICERR_OK;

View File

@ -2190,8 +2190,10 @@ static void test_debugger(const char *argv0)
{
next_event(&ctx, WAIT_EVENT_TIMEOUT);
ok (ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "got exception\n");
if (ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) break;
}
while (ctx.ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
if (ctx.ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) TerminateProcess(pi.hProcess, 0);
ret = CloseHandle(event);
ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());

View File

@ -51,6 +51,8 @@ static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE,const void *,void *,SIZE_T, SIZE_T *);
static NTSTATUS (WINAPI *pNtWriteVirtualMemory)(HANDLE, void *, const void *, SIZE_T, SIZE_T *);
static BOOL (WINAPI *pPrefetchVirtualMemory)(HANDLE, ULONG_PTR, PWIN32_MEMORY_RANGE_ENTRY, ULONG);
/* ############################### */
@ -83,6 +85,7 @@ static void test_VirtualAllocEx(void)
DWORD old_prot;
MEMORY_BASIC_INFORMATION info;
HANDLE hProcess;
NTSTATUS status;
/* Same process */
addr1 = VirtualAllocEx(GetCurrentProcess(), NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
@ -113,6 +116,16 @@ static void test_VirtualAllocEx(void)
b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
ok(b && (bytes_read == alloc_size), "%Iu bytes read\n", bytes_read);
ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
ok( bytes_written == alloc_size, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
memset( dst, 0, alloc_size );
status = pNtReadVirtualMemory( hProcess, addr1, dst, alloc_size, &bytes_read );
ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
ok( bytes_read == alloc_size, "%Iu bytes read\n", bytes_read );
ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
/* test 0 length */
bytes_written = 0xdeadbeef;
@ -121,43 +134,126 @@ static void test_VirtualAllocEx(void)
bytes_read = 0xdeadbeef;
b = ReadProcessMemory(hProcess, addr1, src, 0, &bytes_read);
ok(b && !bytes_read, "read failed: %lu\n", GetLastError());
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, 0, &bytes_written );
ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
status = pNtReadVirtualMemory( hProcess, addr1, src, 0, &bytes_read );
ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
ok( !bytes_read, "%Iu bytes read\n", bytes_read );
/* test invalid source buffers */
b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
ok( b, "VirtualProtect failed error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
ok( !b, "WriteProcessMemory succeeded\n" );
ok( GetLastError() == ERROR_NOACCESS ||
GetLastError() == ERROR_PARTIAL_COPY, /* vista */
"wrong error %lu\n", GetLastError() );
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
ok( !b, "ReadProcessMemory succeeded\n" );
ok( GetLastError() == ERROR_NOACCESS ||
GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */
"wrong error %lu\n", GetLastError() );
if (GetLastError() == ERROR_NOACCESS)
ok( bytes_read == 0, "%Iu bytes written\n", bytes_read );
ok( bytes_read == 0, "%Iu bytes read\n", bytes_read );
else
ok( bytes_read == 0x2000, "%Iu bytes read\n", bytes_read );
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
ok( status == STATUS_PARTIAL_COPY, "wrong status %lx\n", status );
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
status = pNtReadVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_read );
ok( status == STATUS_PARTIAL_COPY || status == STATUS_ACCESS_VIOLATION, "wrong status %lx\n", status );
ok( bytes_read == (status == STATUS_PARTIAL_COPY ? 0x2000 : 0), "%Iu bytes read\n", bytes_read );
b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
ok( b, "VirtualProtect failed error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
ok( !b, "WriteProcessMemory succeeded\n" );
ok( GetLastError() == ERROR_NOACCESS ||
GetLastError() == ERROR_PARTIAL_COPY, /* vista */
"wrong error %lu\n", GetLastError() );
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
ok( !b, "ReadProcessMemory succeeded\n" );
ok( GetLastError() == ERROR_NOACCESS ||
GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */
"wrong error %lu\n", GetLastError() );
if (GetLastError() == ERROR_NOACCESS)
ok( bytes_read == 0, "%Iu bytes written\n", bytes_read );
ok( bytes_read == 0, "%Iu bytes read\n", bytes_read );
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
ok( status == STATUS_PARTIAL_COPY, "wrong status %lx\n", status );
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
bytes_read = 0xdeadbeef;
status = pNtReadVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_read );
ok( status == STATUS_PARTIAL_COPY || status == STATUS_ACCESS_VIOLATION, "wrong status %lx\n", status );
ok( bytes_read == 0, "%Iu bytes read\n", bytes_read );
b = VirtualProtect( src, alloc_size, PAGE_READWRITE, &old_prot );
ok( b, "VirtualProtect failed error %lu\n", GetLastError() );
b = VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
ok(b != 0, "VirtualFreeEx, error %lu\n", GetLastError());
/* test readonly buffers */
b = VirtualProtectEx( hProcess, addr1, alloc_size, PAGE_READONLY, &old_prot );
ok( b, "VirtualProtectEx, error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
ok( !b, "WriteProcessMemory succeeded\n" );
if (!b) ok( GetLastError() == ERROR_NOACCESS, "wrong error %lu\n", GetLastError() );
ok( bytes_written == 0xdeadbeef, "%Iu bytes written\n", bytes_written );
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
todo_wine
ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION),
"wrong status %lx\n", status );
todo_wine
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
b = VirtualProtectEx( hProcess, addr1, alloc_size, PAGE_EXECUTE_READ, &old_prot );
ok( b, "VirtualProtectEx, error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
ok( b, "WriteProcessMemory failed\n" );
ok( bytes_written == alloc_size, "%Iu bytes written\n", bytes_written );
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
todo_wine
ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION),
"wrong status %lx\n", status );
todo_wine
ok( bytes_written == 0, "%Iu bytes written\n", bytes_written );
b = VirtualProtectEx( hProcess, addr1, 0x2000, PAGE_EXECUTE_READWRITE, &old_prot );
ok( b, "VirtualProtectEx, error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
todo_wine
ok( !b || broken(b), /* <= win10 1507 */ "WriteProcessMemory succeeded\n" );
bytes_written = 0xdeadbeef;
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
todo_wine
ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_SUCCESS), /* <= win10 1507 */
"wrong status %lx\n", status );
ok( bytes_written == (status ? 0x2000 : alloc_size), "%Iu bytes written\n", bytes_written );
b = VirtualProtectEx( hProcess, (char *)addr1 + 0x2000, alloc_size - 0x2000, PAGE_READONLY, &old_prot );
ok( b, "VirtualProtectEx, error %lu\n", GetLastError() );
bytes_written = 0xdeadbeef;
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
todo_wine
ok( !b || broken(b), /* <= win10 1507 */ "WriteProcessMemory succeeded\n" );
status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written );
todo_wine
ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_SUCCESS), /* <= win10 1507 */
"wrong status %lx\n", status );
ok( bytes_written == (status ? 0x2000 : alloc_size), "%Iu bytes written\n", bytes_written );
VirtualFree( src, 0, MEM_RELEASE );
VirtualFree( dst, 0, MEM_RELEASE );
@ -4324,6 +4420,8 @@ START_TEST(virtual)
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
pNtWriteVirtualMemory = (void *)GetProcAddress( hntdll, "NtWriteVirtualMemory" );
pPrefetchVirtualMemory = (void *)GetProcAddress( hkernelbase, "PrefetchVirtualMemory" );
GetSystemInfo(&si);

View File

@ -42,10 +42,60 @@ WINE_DECLARE_DEBUG_CHANNEL(virtual);
WINE_DECLARE_DEBUG_CHANNEL(globalmem);
static CROSS_PROCESS_WORK_LIST *open_cross_process_connection( HANDLE process )
{
#ifdef __aarch64__
CROSS_PROCESS_WORK_LIST *list;
HANDLE section;
RtlOpenCrossProcessEmulatorWorkConnection( process, &section, (void **)&list );
if (section) NtClose( section );
return list;
#else
return NULL;
#endif
}
static void close_cross_process_connection( CROSS_PROCESS_WORK_LIST *list )
{
if (list) NtUnmapViewOfSection( GetCurrentProcess(), list );
}
static void send_cross_process_notification( CROSS_PROCESS_WORK_LIST *list, UINT id,
const void *addr, SIZE_T size, int nb_args, ... )
{
#ifdef __aarch64__
CROSS_PROCESS_WORK_ENTRY *entry;
void *unused;
va_list args;
int i;
if (!list) return;
if ((entry = RtlWow64PopCrossProcessWorkFromFreeList( &list->free_list )))
{
entry->id = id;
entry->addr = (ULONG_PTR)addr;
entry->size = size;
if (nb_args)
{
va_start( args, nb_args );
for (i = 0; i < nb_args; i++) entry->args[i] = va_arg( args, int );
va_end( args );
}
RtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, entry, &unused );
}
#endif
}
/***********************************************************************
* Virtual memory functions
***********************************************************************/
static const SIZE_T page_mask = 0xfff;
#define ROUND_ADDR(addr) ((void *)((UINT_PTR)(addr) & ~page_mask))
#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
/***********************************************************************
* DiscardVirtualMemory (kernelbase.@)
@ -72,6 +122,22 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size )
}
/****************************************************************************
* FlushInstructionCache (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH FlushInstructionCache( HANDLE process, LPCVOID addr, SIZE_T size )
{
CROSS_PROCESS_WORK_LIST *list;
if ((list = open_cross_process_connection( process )))
{
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
close_cross_process_connection( list );
}
return set_ntstatus( NtFlushInstructionCache( process, addr, size ));
}
/***********************************************************************
* GetLargePageMinimum (kernelbase.@)
*/
@ -537,7 +603,69 @@ BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
SIZE_T size, SIZE_T *bytes_written )
{
return set_ntstatus( NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ));
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE;
MEMORY_BASIC_INFORMATION info;
void *base_addr;
SIZE_T region_size;
NTSTATUS status, status2;
if (!VirtualQueryEx( process, addr, &info, sizeof(info) ))
{
close_cross_process_connection( list );
return FALSE;
}
switch (info.Protect)
{
case PAGE_READWRITE:
case PAGE_WRITECOPY:
case PAGE_EXECUTE_READWRITE:
case PAGE_EXECUTE_WRITECOPY:
/* already writable */
if ((status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ))) break;
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
NtFlushInstructionCache( process, addr, size );
break;
case PAGE_EXECUTE:
case PAGE_EXECUTE_READ:
/* make it writable */
base_addr = ROUND_ADDR( addr );
region_size = ROUND_SIZE( addr, size );
region_size = min( region_size, (char *)info.BaseAddress + info.RegionSize - (char *)base_addr );
prot |= (info.Type == MEM_PRIVATE) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_WRITECOPY;
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
base_addr, region_size, 1, prot );
status = NtProtectVirtualMemory( process, &base_addr, &region_size, prot, &old_prot );
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
base_addr, region_size, 2, prot, status );
if (status) break;
status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written );
if (!status)
{
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
NtFlushInstructionCache( process, addr, size );
}
prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | old_prot;
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
base_addr, region_size, 1, prot );
status2 = NtProtectVirtualMemory( process, &base_addr, &region_size, prot, &old_prot );
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
base_addr, region_size, 2, prot, status2 );
break;
default:
/* not writable */
status = STATUS_ACCESS_VIOLATION;
break;
}
close_cross_process_connection( list );
return set_ntstatus( status );
}

View File

@ -737,15 +737,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle( HANDLE source_process, HANDLE sou
}
/****************************************************************************
* FlushInstructionCache (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH FlushInstructionCache( HANDLE process, LPCVOID addr, SIZE_T size )
{
return set_ntstatus( NtFlushInstructionCache( process, addr, size ));
}
/***********************************************************************
* GetApplicationRestartSettings (kernelbase.@)
*/

View File

@ -1274,6 +1274,7 @@ static void session_close(struct media_session *session)
switch (session->state)
{
case SESSION_STATE_STOPPED:
case SESSION_STATE_RESTARTING_SOURCES:
hr = session_finalize_sinks(session);
break;
case SESSION_STATE_STARTED:
@ -3192,8 +3193,15 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
break;
}
if (session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION || FAILED(hr))
if (session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION)
session_set_stopped(session, hr);
else if (FAILED(hr))
{
if (session->presentation.flags & SESSION_FLAG_FINALIZE_SINKS)
session_set_closed(session, hr);
else
session_set_stopped(session, hr);
}
break;
default:

View File

@ -6249,6 +6249,8 @@ static void test_media_session_Start(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* Media session is shut down */
hr = IMFMediaSource_Shutdown(source);
@ -6331,6 +6333,8 @@ static void test_media_session_Start(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Shutdown(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSource_Shutdown(source);
@ -6534,6 +6538,88 @@ static void test_MFEnumDeviceSources(void)
CoUninitialize();
}
static void test_media_session_Close(void)
{
media_type_desc video_rgb32_desc =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
};
struct test_grabber_callback *grabber_callback;
IMFPresentationClock *presentation_clock;
IMFActivate *sink_activate;
IMFAsyncCallback *callback;
IMFMediaType *output_type;
IMFMediaSession *session;
IMFMediaSource *source;
IMFTopology *topology;
PROPVARIANT propvar;
IMFClock *clock;
UINT64 duration;
HRESULT hr;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
if (!(source = create_media_source(L"test.mp4", L"video/mp4")))
{
todo_wine /* Gitlab CI Debian runner */
win_skip("MP4 media source is not supported, skipping tests.\n");
MFShutdown();
return;
}
grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
hr = MFCreateMediaType(&output_type);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
init_media_type(output_type, video_rgb32_desc, -1);
hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate);
ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
IMFMediaType_Release(output_type);
hr = MFCreateMediaSession(NULL, &session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
topology = create_test_topology(source, sink_activate, &duration);
hr = IMFMediaSession_SetTopology(session, 0, topology);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFTopology_Release(topology);
hr = IMFMediaSession_GetClock(session, &clock);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFClock_Release(clock);
propvar.vt = VT_EMPTY;
hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
callback = create_test_callback(TRUE);
hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSource_Shutdown(source);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event_until_blocking(session, callback, MESessionClosed, 5000, &propvar);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Shutdown(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFPresentationClock_Release(presentation_clock);
IMFAsyncCallback_Release(callback);
IMFMediaSession_Release(session);
IMFActivate_ShutdownObject(sink_activate);
IMFActivate_Release(sink_activate);
IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface);
IMFMediaSource_Release(source);
hr = MFShutdown();
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
}
START_TEST(mf)
{
init_functions();
@ -6568,4 +6654,5 @@ START_TEST(mf)
test_MFCreateSequencerSegmentOffset();
test_media_session_Start();
test_MFEnumDeviceSources();
test_media_session_Close();
}

View File

@ -3585,6 +3585,8 @@ static void test_wma_decoder_dmo_output_type(void)
good_output_type = (void *)buffer_good_output;
bad_output_type = (void *)buffer_bad_output;
init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate, 16);
((WAVEFORMATEX *)(input_type + 1))->nBlockAlign = 640;
((WAVEFORMATEX *)(input_type + 1))->nAvgBytesPerSec = 2000;
init_dmo_media_type_audio(good_output_type, &MEDIASUBTYPE_PCM, channel_count, rate, bits_per_sample);
memset(bad_output_type, 0, sizeof(buffer_bad_output));

View File

@ -159,7 +159,7 @@ static HRESULT load_typelib(void)
if(typelib)
return S_OK;
hres = LoadRegTypeLib(&LIBID_ADODB, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
hres = LoadRegTypeLib(&LIBID_ADODB, 2, 8, LOCALE_SYSTEM_DEFAULT, &tl);
if(FAILED(hres)) {
ERR("LoadRegTypeLib failed: %08lx\n", hres);
return hres;

View File

@ -190,6 +190,13 @@ static void test_Locate(void)
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;
bo.biCompression = mmioFOURCC('U','Y','V','Y');
bo.biBitCount = bi.biBitCount = 16;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
ok(h == 0, "cvid->UYVY succeeded\n");
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biCompression = BI_RGB;
bo.biBitCount = bi.biBitCount = 32;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
ok(h != 0, "cvid->RGB32 failed\n");

View File

@ -712,16 +712,6 @@ NTSTATUS WINAPI DbgUiIssueRemoteBreakin( HANDLE process )
status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
DbgUiRemoteBreakin, NULL, 0, 0, 0, 0, NULL );
#ifdef _WIN64
/* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
if (status == STATUS_INVALID_PARAMETER)
{
ULONG_PTR wow;
if (!NtQueryInformationProcess( process, ProcessWow64Information, &wow, sizeof(wow), NULL ) && wow)
status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
(void *)0x7ffe1000, NULL, 0, 0, 0, 0, NULL );
}
#endif
if (!status) NtClose( handle );
return status;
}

View File

@ -454,6 +454,7 @@ static CROSS_PROCESS_WORK_ENTRY *expect_cross_work_entry_( CROSS_PROCESS_WORK_LI
ok_(__FILE__,line)( entry != NULL, "no more entries in list\n" );
if (!entry) return NULL;
ok_(__FILE__,line)( entry->id == id, "wrong type %u / %u\n", entry->id, id );
ok_(__FILE__,line)( entry->addr == (ULONG_PTR)addr, "wrong address %s / %p\n",
wine_dbgstr_longlong(entry->addr), addr );
ok_(__FILE__,line)( entry->size == size, "wrong size %s / %Ix\n",
@ -468,19 +469,59 @@ static CROSS_PROCESS_WORK_ENTRY *expect_cross_work_entry_( CROSS_PROCESS_WORK_LI
return next;
}
static void test_cross_process_notifications( HANDLE process, void *ptr )
static void test_cross_process_notifications( HANDLE process, ULONG_PTR section, ULONG_PTR ptr )
{
CROSS_PROCESS_WORK_ENTRY *entry;
CROSS_PROCESS_WORK_LIST *list = ptr;
CROSS_PROCESS_WORK_LIST *list;
UINT pos;
void *addr, *addr2;
SIZE_T size;
void *addr = NULL, *addr2;
SIZE_T size = 0;
DWORD old_prot;
LARGE_INTEGER offset;
HANDLE file, mapping;
NTSTATUS status;
BOOL ret;
BYTE data[] = { 0xcc, 0xcc, 0xcc };
ret = DuplicateHandle( process, (HANDLE)section, GetCurrentProcess(), &mapping,
0, FALSE, DUPLICATE_SAME_ACCESS );
ok( ret, "DuplicateHandle failed %lu\n", GetLastError() );
status = NtMapViewOfSection( mapping, GetCurrentProcess(), &addr, 0, 0, NULL,
&size, ViewShare, 0, PAGE_READWRITE );
ok( !status, "NtMapViewOfSection failed %lx\n", status );
ok( size == 0x4000, "unexpected size %Ix\n", size );
list = addr;
addr2 = malloc( size );
ret = ReadProcessMemory( process, (void *)ptr, addr2, size, &size );
ok( ret, "ReadProcessMemory failed %lu\n", GetLastError() );
ok( !memcmp( addr2, addr, size ), "wrong data\n" );
free( addr2 );
CloseHandle( mapping );
if (pRtlOpenCrossProcessEmulatorWorkConnection)
{
pRtlOpenCrossProcessEmulatorWorkConnection( process, &mapping, &addr2 );
ok( mapping != 0, "got 0 handle\n" );
ok( addr2 != NULL, "got NULL data\n" );
ok( !memcmp( addr2, addr, size ), "wrong data\n" );
UnmapViewOfFile( addr2 );
addr2 = NULL;
size = 0;
status = NtMapViewOfSection( mapping, GetCurrentProcess(), &addr2, 0, 0, NULL,
&size, ViewShare, 0, PAGE_READWRITE );
ok( !status, "NtMapViewOfSection failed %lx\n", status );
ok( !memcmp( addr2, addr, size ), "wrong data\n" );
ok( CloseHandle( mapping ), "invalid handle\n" );
UnmapViewOfFile( addr2 );
mapping = (HANDLE)0xdead;
addr2 = (void *)0xdeadbeef;
pRtlOpenCrossProcessEmulatorWorkConnection( GetCurrentProcess(), &mapping, &addr2 );
ok( !mapping, "got handle %p\n", mapping );
ok( !addr2, "got data %p\n", addr2 );
}
else skip( "RtlOpenCrossProcessEmulatorWorkConnection not supported\n" );
NtSuspendProcess( process );
/* set argument values in free list to detect changes */
@ -672,7 +713,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )
FlushInstructionCache( process, addr, 0x1234 );
entry = pop_from_work_list( &list->work_list );
todo_wine_if (current_machine == IMAGE_FILE_MACHINE_ARM64)
entry = expect_cross_work_entry( list, entry, CrossProcessFlushCache, addr, 0x1234,
0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc );
ok( !entry, "not at end of list\n" );
@ -688,8 +728,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )
WriteProcessMemory( process, (char *)addr + 0x1ffe, data, sizeof(data), &size );
entry = pop_from_work_list( &list->work_list );
todo_wine
{
entry = expect_cross_work_entry( list, entry, CrossProcessPreVirtualProtect,
(char *)addr + 0x1000, 0x2000, 0x60000000 | PAGE_EXECUTE_WRITECOPY,
(current_machine != IMAGE_FILE_MACHINE_ARM64) ? 0 : 0xcccccccc,
@ -707,7 +745,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )
entry = expect_cross_work_entry( list, entry, CrossProcessPostVirtualProtect,
(char *)addr + 0x1000, 0x2000,
0x60000000 | PAGE_EXECUTE_READ, 0, 0xcccccccc, 0xcccccccc );
}
ok( !entry, "not at end of list\n" );
status = NtUnmapViewOfSection( process, addr );
@ -717,6 +754,99 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )
CloseHandle( mapping );
CloseHandle( file );
UnmapViewOfFile( list );
}
static void test_wow64_shared_info( HANDLE process )
{
ULONG i, peb_data[0x200], buffer[16];
WOW64INFO *info = (WOW64INFO *)buffer;
ULONG_PTR peb_ptr;
NTSTATUS status;
SIZE_T res;
BOOLEAN wow64 = 0xcc;
NtQueryInformationProcess( process, ProcessWow64Information, &peb_ptr, sizeof(peb_ptr), NULL );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlWow64GetSharedInfoProcess( process, &wow64, info );
ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
ok( wow64 == TRUE, "wrong wow64 %u\n", wow64 );
todo_wine_if (!info->NativeSystemPageSize) /* not set in old wow64 */
{
ok( info->NativeSystemPageSize == 0x1000, "wrong page size %lx\n",
info->NativeSystemPageSize );
ok( info->CpuFlags == (native_machine == IMAGE_FILE_MACHINE_AMD64 ? WOW64_CPUFLAGS_MSFT64 : WOW64_CPUFLAGS_SOFTWARE),
"wrong flags %lx\n", info->CpuFlags );
ok( info->NativeMachineType == native_machine, "wrong machine %x / %x\n",
info->NativeMachineType, native_machine );
ok( info->EmulatedMachineType == IMAGE_FILE_MACHINE_I386, "wrong machine %x\n",
info->EmulatedMachineType );
}
ok( buffer[sizeof(*info) / sizeof(ULONG)] == 0xcccccccc, "buffer set %lx\n",
buffer[sizeof(*info) / sizeof(ULONG)] );
if (ReadProcessMemory( process, (void *)peb_ptr, peb_data, sizeof(peb_data), &res ))
{
ULONG limit = (sizeof(peb_data) - sizeof(info)) / sizeof(ULONG);
for (i = 0; i < limit; i++)
{
if (!memcmp( peb_data + i, info, sizeof(*info) ))
{
trace( "wow64info found at %lx\n", i * 4 );
break;
}
}
ok( i < limit, "wow64info not found in PEB\n" );
}
if (info->SectionHandle && info->CrossProcessWorkList)
test_cross_process_notifications( process, info->SectionHandle, info->CrossProcessWorkList );
else
trace( "no WOW64INFO section handle\n" );
}
static void test_amd64_shared_info( HANDLE process )
{
ULONG i, peb_data[0x200], buffer[16];
PROCESS_BASIC_INFORMATION proc_info;
NTSTATUS status;
SIZE_T res;
BOOLEAN wow64 = 0xcc;
struct arm64ec_shared_info
{
ULONG Wow64ExecuteFlags;
USHORT NativeMachineType;
USHORT EmulatedMachineType;
ULONGLONG SectionHandle;
ULONGLONG CrossProcessWorkList;
ULONGLONG unknown;
} *info = NULL;
NtQueryInformationProcess( process, ProcessBasicInformation, &proc_info, sizeof(proc_info), NULL );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlWow64GetSharedInfoProcess( process, &wow64, (WOW64INFO *)buffer );
ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
ok( !wow64, "wrong wow64 %u\n", wow64 );
ok( buffer[0] == 0xcccccccc, "buffer initialized %lx\n", buffer[0] );
if (ReadProcessMemory( process, (void *)proc_info.PebBaseAddress, peb_data, sizeof(peb_data), &res ))
{
ULONG limit = (sizeof(peb_data) - sizeof(*info)) / sizeof(ULONG);
for (i = 0; i < limit; i++)
{
info = (struct arm64ec_shared_info *)(peb_data + i);
if (info->NativeMachineType == IMAGE_FILE_MACHINE_ARM64 &&
info->EmulatedMachineType == IMAGE_FILE_MACHINE_AMD64)
{
trace( "shared info found at %lx\n", i * 4 );
break;
}
}
ok( i < limit, "shared info not found in PEB\n" );
}
if (info && info->SectionHandle && info->CrossProcessWorkList)
test_cross_process_notifications( process, info->SectionHandle, info->CrossProcessWorkList );
else
trace( "no shared info section handle\n" );
}
static void test_peb_teb(void)
@ -834,91 +964,7 @@ static void test_peb_teb(void)
ResumeThread( pi.hThread );
WaitForInputIdle( pi.hProcess, 1000 );
if (pRtlWow64GetSharedInfoProcess)
{
ULONG i, peb_data[0x200];
wow64 = 0xcc;
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlWow64GetSharedInfoProcess( pi.hProcess, &wow64, wow64info );
ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
ok( wow64 == TRUE, "wrong wow64 %u\n", wow64 );
todo_wine_if (!wow64info->NativeSystemPageSize) /* not set in old wow64 */
{
ok( wow64info->NativeSystemPageSize == 0x1000, "wrong page size %lx\n",
wow64info->NativeSystemPageSize );
ok( wow64info->CpuFlags == (native_machine == IMAGE_FILE_MACHINE_AMD64 ? WOW64_CPUFLAGS_MSFT64 : WOW64_CPUFLAGS_SOFTWARE),
"wrong flags %lx\n", wow64info->CpuFlags );
ok( wow64info->NativeMachineType == native_machine, "wrong machine %x / %x\n",
wow64info->NativeMachineType, native_machine );
ok( wow64info->EmulatedMachineType == IMAGE_FILE_MACHINE_I386, "wrong machine %x\n",
wow64info->EmulatedMachineType );
}
ok( buffer[sizeof(*wow64info) / sizeof(ULONG)] == 0xcccccccc, "buffer set %lx\n",
buffer[sizeof(*wow64info) / sizeof(ULONG)] );
if (ReadProcessMemory( pi.hProcess, (void *)peb_ptr, peb_data, sizeof(peb_data), &res ))
{
ULONG limit = (sizeof(peb_data) - sizeof(wow64info)) / sizeof(ULONG);
for (i = 0; i < limit; i++)
{
if (!memcmp( peb_data + i, wow64info, sizeof(*wow64info) ))
{
trace( "wow64info found at %lx\n", i * 4 );
break;
}
}
ok( i < limit, "wow64info not found in PEB\n" );
}
if (wow64info->SectionHandle && wow64info->CrossProcessWorkList)
{
HANDLE handle;
void *data, *addr = NULL;
SIZE_T size = 0;
ret = DuplicateHandle( pi.hProcess, (HANDLE)(ULONG_PTR)wow64info->SectionHandle,
GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS );
ok( ret, "DuplicateHandle failed %lu\n", GetLastError() );
status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, NULL,
&size, ViewShare, 0, PAGE_READWRITE );
ok( !status, "NtMapViewOfSection failed %lx\n", status );
ok( size == 0x4000, "unexpected size %Ix\n", size );
data = malloc( size );
ret = ReadProcessMemory( pi.hProcess, (void *)(ULONG_PTR)wow64info->CrossProcessWorkList,
data, size, &size );
ok( ret, "ReadProcessMemory failed %lu\n", GetLastError() );
ok( !memcmp( data, addr, size ), "wrong data\n" );
free( data );
CloseHandle( handle );
if (pRtlOpenCrossProcessEmulatorWorkConnection)
{
pRtlOpenCrossProcessEmulatorWorkConnection( pi.hProcess, &handle, &data );
ok( handle != 0, "got 0 handle\n" );
ok( data != NULL, "got NULL data\n" );
ok( !memcmp( data, addr, size ), "wrong data\n" );
UnmapViewOfFile( data );
data = NULL;
size = 0;
status = NtMapViewOfSection( handle, GetCurrentProcess(), &data, 0, 0, NULL,
&size, ViewShare, 0, PAGE_READWRITE );
ok( !status, "NtMapViewOfSection failed %lx\n", status );
ok( !memcmp( data, addr, size ), "wrong data\n" );
ok( CloseHandle( handle ), "invalid handle\n" );
UnmapViewOfFile( data );
handle = (HANDLE)0xdead;
data = (void *)0xdeadbeef;
pRtlOpenCrossProcessEmulatorWorkConnection( GetCurrentProcess(), &handle, &data );
ok( !handle, "got handle %p\n", handle );
ok( !data, "got data %p\n", data );
}
else skip( "RtlOpenCrossProcessEmulatorWorkConnection not supported\n" );
test_cross_process_notifications( pi.hProcess, addr );
UnmapViewOfFile( addr );
}
else trace( "no WOW64INFO section handle\n" );
}
if (pRtlWow64GetSharedInfoProcess) test_wow64_shared_info( pi.hProcess );
else win_skip( "RtlWow64GetSharedInfoProcess not supported\n" );
ret = DebugActiveProcess( pi.dwProcessId );
@ -938,6 +984,44 @@ static void test_peb_teb(void)
CloseHandle( pi.hThread );
}
if (is_win64 && native_machine == IMAGE_FILE_MACHINE_ARM64 &&
create_process_machine( (char *)"C:\\windows\\system32\\regsvr32.exe /?", CREATE_SUSPENDED,
IMAGE_FILE_MACHINE_AMD64, &pi ))
{
memset( &info, 0xcc, sizeof(info) );
status = NtQueryInformationThread( pi.hThread, ThreadBasicInformation, &info, sizeof(info), NULL );
ok( !status, "ThreadBasicInformation failed %lx\n", status );
if (!ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &teb, sizeof(teb), &res )) res = 0;
ok( res == sizeof(teb), "wrong len %Ix\n", res );
ok( teb.Tib.Self == info.TebBaseAddress, "wrong teb %p / %p\n", teb.Tib.Self, info.TebBaseAddress );
ok( !teb.GdiBatchCount, "GdiBatchCount set\n" );
ok( !teb.WowTebOffset, "wrong teb offset %ld\n", teb.WowTebOffset );
ok( !teb.Tib.ExceptionList, "wrong Tib.ExceptionList %p\n", (char *)teb.Tib.ExceptionList );
status = NtQueryInformationProcess( pi.hProcess, ProcessBasicInformation,
&proc_info, sizeof(proc_info), NULL );
ok( !status, "ProcessBasicInformation failed %lx\n", status );
ok( proc_info.PebBaseAddress == teb.Peb, "wrong peb %p / %p\n", proc_info.PebBaseAddress, teb.Peb );
status = NtQueryInformationProcess( pi.hProcess, ProcessWow64Information,
&peb_ptr, sizeof(peb_ptr), NULL );
ok( !status, "ProcessWow64Information failed %lx\n", status );
ok( !peb_ptr, "wrong peb %p\n", (void *)peb_ptr );
if (!ReadProcessMemory( pi.hProcess, proc_info.PebBaseAddress, &peb, sizeof(peb), &res )) res = 0;
ok( res == sizeof(peb), "wrong len %Ix\n", res );
ok( !peb.BeingDebugged, "BeingDebugged is %u\n", peb.BeingDebugged );
ResumeThread( pi.hThread );
WaitForInputIdle( pi.hProcess, 1000 );
test_amd64_shared_info( pi.hProcess );
TerminateProcess( pi.hProcess, 0 );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
if (CreateProcessA( "C:\\windows\\system32\\msinfo32.exe", NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi ))
{
@ -2041,14 +2125,31 @@ static void test_init_block(void)
}
static DWORD WINAPI iosb_delayed_write_thread(void *arg)
{
HANDLE client = arg;
DWORD size;
BOOL ret;
Sleep(100);
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
return 0;
}
static void test_iosb(void)
{
static const char pipe_name[] = "\\\\.\\pipe\\wow64iosbnamedpipe";
HANDLE client, server;
HANDLE client, server, thread;
NTSTATUS status;
ULONG64 func;
DWORD id;
ULONG64 read_func, flush_func;
IO_STATUS_BLOCK iosb32;
char buffer[6];
DWORD size;
BOOL ret;
struct
{
union
@ -2058,66 +2159,89 @@ static void test_iosb(void)
};
ULONG64 Information;
} iosb64;
ULONG64 args[] = { 0, 0, 0, 0, (ULONG_PTR)&iosb64, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 };
ULONG64 args[] = { 0, 0, 0, 0, (ULONG_PTR)&iosb64, (ULONG_PTR)buffer, sizeof(buffer), 0, 0 };
ULONG64 flush_args[] = { 0, (ULONG_PTR)&iosb64 };
if (!is_wow64) return;
if (!code_mem) return;
if (!ntdll_module) return;
func = get_proc_address64( ntdll_module, "NtFsControlFile" );
read_func = get_proc_address64( ntdll_module, "NtReadFile" );
flush_func = get_proc_address64( ntdll_module, "NtFlushBuffersFile" );
/* async calls set iosb32 but not iosb64 */
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4, 1024, 1024, 1000, NULL );
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING, "NtFsControlFile returned %lx\n", status );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING, "NtReadFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
ok( iosb32.Status == 0, "Wrong iostatus %lx\n", iosb32.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb32.Information == sizeof("data"), "Wrong information %Ix\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb32.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == sizeof("data"), "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
if (iosb32.Information == sizeof("data"))
ok( !memcmp( buffer, "data", iosb32.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
}
/* syscalls which are always synchronous set iosb64 but not iosb32 */
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
id = 0xdeadbeef;
args[5] = FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE;
args[6] = (ULONG_PTR)"ClientProcessId";
args[7] = sizeof("ClientProcessId");
args[8] = (ULONG_PTR)&id;
args[9] = sizeof(id);
flush_args[0] = (LONG_PTR)server;
status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0, "info changed to %lx\n", (ULONG_PTR)iosb64.Information );
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING || status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == sizeof(id), "info changed to %Ix\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
}
ok( id == GetCurrentProcessId(), "wrong id %lx / %lx\n", id, GetCurrentProcessId() );
CloseHandle( client );
CloseHandle( server );
/* synchronous calls set iosb64 but not iosb32 */
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND,
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4, 1024, 1024, 1000, NULL );
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
@ -2126,19 +2250,60 @@ static void test_iosb(void)
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
id = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "status changed to %lx\n", iosb64.Status );
ok( iosb64.Information == sizeof(id), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( id == GetCurrentProcessId(), "wrong id %lx / %lx\n", id, GetCurrentProcessId() );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb64.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
thread = CreateThread( NULL, 0, iosb_delayed_write_thread, client, 0, NULL );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb64.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
}
ret = WaitForSingleObject( thread, 1000 );
ok(!ret, "got %d\n", ret );
CloseHandle( thread );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
flush_args[0] = (LONG_PTR)server;
status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0, "info changed to %lx\n", (ULONG_PTR)iosb64.Information );
CloseHandle( client );
CloseHandle( server );
}

View File

@ -1583,7 +1583,7 @@ static void load_ntdll_wow64_functions( HMODULE module )
GET_FUNC( RtlpFreezeTimeBias );
GET_FUNC( RtlpQueryProcessDebugInformationRemote );
#undef GET_FUNC
pDbgUiRemoteBreakin = (void *)find_named_export( module, exports, "DbgUiRemoteBreakin" );
p__wine_ctrl_routine = (void *)find_named_export( module, exports, "__wine_ctrl_routine" );
#ifdef _WIN64

View File

@ -452,21 +452,7 @@ static NTSTATUS get_status(int fd, SERIAL_STATUS* ss)
return status;
}
static void stop_waiting( HANDLE handle )
{
unsigned int status;
SERVER_START_REQ( set_serial_info )
{
req->handle = wine_server_obj_handle( handle );
req->flags = SERIALINFO_PENDING_WAIT;
if ((status = wine_server_call( req )))
ERR("failed to clear waiting state: %#x\n", status);
}
SERVER_END_REQ;
}
static NTSTATUS get_wait_mask(HANDLE hDevice, UINT *mask, UINT *cookie, BOOL *pending_write, BOOL start_wait)
static NTSTATUS get_wait_mask( HANDLE hDevice, UINT *mask, BOOL *pending_write )
{
unsigned int status;
@ -474,11 +460,9 @@ static NTSTATUS get_wait_mask(HANDLE hDevice, UINT *mask, UINT *cookie, BOOL *pe
{
req->handle = wine_server_obj_handle( hDevice );
req->flags = pending_write ? SERIALINFO_PENDING_WRITE : 0;
if (start_wait) req->flags |= SERIALINFO_PENDING_WAIT;
if (!(status = wine_server_call( req )))
{
*mask = reply->eventmask;
if (cookie) *cookie = reply->cookie;
if (pending_write) *pending_write = reply->pending_write;
}
}
@ -982,7 +966,6 @@ typedef struct async_commio
struct async_fileio io;
DWORD* events;
UINT evtmask;
UINT cookie;
UINT mstat;
BOOL pending_write;
serial_irq_info irq_info;
@ -1095,7 +1078,7 @@ static BOOL async_wait_proc( void *user, ULONG_PTR *info, unsigned int *status )
if (!server_get_unix_fd( commio->io.handle, FILE_READ_DATA | FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL ))
{
serial_irq_info new_irq_info;
UINT new_mstat, dummy, cookie;
UINT new_mstat, dummy;
TRACE( "device=%p fd=0x%08x mask=0x%08x buffer=%p irq_info=%p\n",
commio->io.handle, fd, commio->evtmask, commio->events, &commio->irq_info );
@ -1126,24 +1109,14 @@ static BOOL async_wait_proc( void *user, ULONG_PTR *info, unsigned int *status )
}
else
{
get_wait_mask( commio->io.handle, &dummy, &cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL, FALSE );
if (commio->cookie != cookie)
{
*commio->events = 0;
*status = STATUS_CANCELLED;
*info = 0;
}
else
{
if (needs_close) close( fd );
return FALSE;
}
get_wait_mask( commio->io.handle, &dummy, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL );
if (needs_close) close( fd );
return FALSE;
}
}
if (needs_close) close( fd );
}
stop_waiting( commio->io.handle );
release_fileio( &commio->io );
return TRUE;
}
@ -1161,7 +1134,7 @@ static NTSTATUS wait_on( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE ap
commio->events = out_buffer;
commio->pending_write = 0;
status = get_wait_mask( handle, &commio->evtmask, &commio->cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL, TRUE );
status = get_wait_mask( handle, &commio->evtmask, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL );
if (status)
{
free( commio );

View File

@ -640,7 +640,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
(ULONG_PTR)func == call->create_thread.func && (ULONG_PTR)arg == call->create_thread.arg)
{
/* FIXME: hack for debugging 32-bit process without a 64-bit ntdll */
if (is_old_wow64() && func == (void *)0x7ffe1000) func = pDbgUiRemoteBreakin;
if (is_wow64()) func = pDbgUiRemoteBreakin;
attr->TotalLength = sizeof(buffer);
attr->Attributes[0].Attribute = PS_ATTRIBUTE_CLIENT_ID;
attr->Attributes[0].Size = sizeof(id);

View File

@ -198,7 +198,7 @@ static const char *debugstr_sqllen( SQLLEN len )
}
#define MAX_BINDING_PARAMS 1024
static BOOL alloc_binding( struct param_binding *binding, UINT column, UINT row_count )
static BOOL alloc_binding( struct param_binding *binding, USHORT type, UINT column, UINT row_count )
{
if (column > MAX_BINDING_PARAMS)
{
@ -208,6 +208,7 @@ static BOOL alloc_binding( struct param_binding *binding, UINT column, UINT row_
if (!binding->param && !(binding->param = calloc( MAX_BINDING_PARAMS, sizeof(*binding->param)))) return FALSE;
if (!(binding->param[column - 1].len = calloc( row_count, sizeof(UINT64) ))) return FALSE;
binding->param[column - 1].type = type;
binding->count = column;
return TRUE;
}
@ -232,10 +233,13 @@ SQLRETURN WINAPI SQLBindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber,
FIXME( "column 0 not handled\n" );
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_col, ColumnNumber, handle->row_count )) return SQL_ERROR;
if (!alloc_binding( &handle->bind_col, SQL_PARAM_INPUT_OUTPUT, ColumnNumber, handle->row_count )) return SQL_ERROR;
handle->bind_col.param[i].col.target_type = TargetType;
handle->bind_col.param[i].col.target_value = TargetValue;
handle->bind_col.param[i].col.buffer_length = BufferLength;
params.StatementHandle = handle->unix_handle;
params.StrLen_or_Ind = handle->bind_col.param[i].len;
*(UINT64 *)params.StrLen_or_Ind = *StrLen_or_Ind;
if (StrLen_or_Ind) params.StrLen_or_Ind = handle->bind_col.param[i].len;
if (SUCCESS(( ret = ODBC_CALL( SQLBindCol, &params )))) handle->bind_col.param[i].ptr = StrLen_or_Ind;
TRACE ("Returning %d\n", ret);
return ret;
@ -273,7 +277,12 @@ SQLRETURN WINAPI SQLBindParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNu
FIXME( "parameter 0 not handled\n" );
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_param, ParameterNumber, handle->row_count )) return SQL_ERROR;
if (!alloc_binding( &handle->bind_param, SQL_PARAM_INPUT, ParameterNumber, handle->row_count )) return SQL_ERROR;
handle->bind_param.param[i].param.value_type = ValueType;
handle->bind_param.param[i].param.parameter_type = ParameterType;
handle->bind_param.param[i].param.length_precision = LengthPrecision;
handle->bind_param.param[i].param.parameter_scale = ParameterScale;
handle->bind_param.param[i].param.parameter_value = ParameterValue;
params.StatementHandle = handle->unix_handle;
params.StrLen_or_Ind = handle->bind_param.param[i].len;
@ -342,7 +351,7 @@ SQLRETURN WINAPI SQLColAttribute(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNu
params.StatementHandle = handle->unix_handle;
params.NumericAttribute = &num_attr;
if (SUCCESS(( ret = ODBC_CALL( SQLColAttribute, &params )))) *NumericAttribute = num_attr;
if (SUCCESS(( ret = ODBC_CALL( SQLColAttribute, &params ))) && NumericAttribute) *NumericAttribute = num_attr;
TRACE("Returning %d\n", ret);
return ret;
}
@ -586,6 +595,66 @@ SQLRETURN WINAPI SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText,
return ret;
}
static void len_to_user( SQLLEN *ptr, UINT8 *len, UINT row_count, UINT width )
{
UINT i;
for (i = 0; i < row_count; i++)
{
*ptr++ = *(SQLLEN *)(len + i * width);
}
}
static void len_from_user( UINT8 *len, SQLLEN *ptr, UINT row_count, UINT width )
{
UINT i;
for (i = 0; i < row_count; i++)
{
*(SQLLEN *)(len + i * width) = *ptr++;
}
}
static void update_result_lengths( struct handle *handle, USHORT type )
{
UINT i, width = sizeof(void *) == 8 ? 8 : is_wow64 ? 8 : 4;
switch (type)
{
case SQL_PARAM_OUTPUT:
for (i = 0; i < handle->bind_col.count; i++)
{
len_to_user( handle->bind_col.param[i].ptr, handle->bind_col.param[i].len, handle->row_count, width );
}
for (i = 0; i < handle->bind_param.count; i++)
{
len_to_user( handle->bind_param.param[i].ptr, handle->bind_param.param[i].len, handle->row_count, width );
}
for (i = 0; i < handle->bind_parameter.count; i++)
{
if (handle->bind_parameter.param[i].type != SQL_PARAM_OUTPUT &&
handle->bind_parameter.param[i].type != SQL_PARAM_INPUT_OUTPUT) continue;
len_to_user( handle->bind_parameter.param[i].ptr, handle->bind_parameter.param[i].len, handle->row_count, width );
}
break;
case SQL_PARAM_INPUT:
for (i = 0; i < handle->bind_col.count; i++)
{
len_from_user( handle->bind_col.param[i].len, handle->bind_col.param[i].ptr, handle->row_count, width );
}
/* FIXME: handle bind_param */
for (i = 0; i < handle->bind_parameter.count; i++)
{
if (handle->bind_parameter.param[i].type != SQL_PARAM_INPUT &&
handle->bind_parameter.param[i].type != SQL_PARAM_INPUT_OUTPUT) continue;
len_from_user( handle->bind_parameter.param[i].len, handle->bind_parameter.param[i].ptr, handle->row_count, width );
}
default: break;
}
}
/*************************************************************************
* SQLExecute [ODBC32.012]
*/
@ -600,50 +669,12 @@ SQLRETURN WINAPI SQLExecute(SQLHSTMT StatementHandle)
if (!handle) return SQL_INVALID_HANDLE;
params.StatementHandle = handle->unix_handle;
ret = ODBC_CALL( SQLExecute, &params );
update_result_lengths( handle, SQL_PARAM_INPUT );
if (SUCCESS(( ret = ODBC_CALL( SQLExecute, &params )))) update_result_lengths( handle, SQL_PARAM_OUTPUT );
TRACE("Returning %d\n", ret);
return ret;
}
static void update_result_lengths( struct handle *handle )
{
UINT i, j, width = sizeof(void *) == 8 ? 8 : is_wow64 ? 8 : 4;
for (i = 0; i < handle->bind_col.count; i++)
{
SQLLEN *ptr = handle->bind_col.param[i].ptr;
if (ptr)
{
for (j = 0; j < handle->row_count; j++)
{
*ptr++ = *(SQLLEN *)(handle->bind_col.param[i].len + j * width);
}
}
}
for (i = 0; i < handle->bind_param.count; i++)
{
SQLLEN *ptr = handle->bind_param.param[i].ptr;
if (ptr)
{
for (j = 0; j < handle->row_count; j++)
{
*ptr++ = *(SQLLEN *)(handle->bind_param.param[i].len + j * width);
}
}
}
for (i = 0; i < handle->bind_parameter.count; i++)
{
SQLLEN *ptr = handle->bind_parameter.param[i].ptr;
if (ptr)
{
for (j = 0; j < handle->row_count; j++)
{
*ptr++ = *(SQLLEN *)(handle->bind_parameter.param[i].len + j * width);
}
}
}
}
/*************************************************************************
* SQLFetch [ODBC32.013]
*/
@ -658,7 +689,7 @@ SQLRETURN WINAPI SQLFetch(SQLHSTMT StatementHandle)
if (!handle) return SQL_INVALID_HANDLE;
params.StatementHandle = handle->unix_handle;
if (SUCCESS(( ret = ODBC_CALL( SQLFetch, &params )))) update_result_lengths( handle );
if (SUCCESS(( ret = ODBC_CALL( SQLFetch, &params )))) update_result_lengths( handle, SQL_PARAM_OUTPUT );
TRACE("Returning %d\n", ret);
return ret;
}
@ -678,7 +709,7 @@ SQLRETURN WINAPI SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrien
if (!handle) return SQL_INVALID_HANDLE;
params.StatementHandle = handle->unix_handle;
if (SUCCESS(( ret = ODBC_CALL( SQLFetchScroll, &params )))) update_result_lengths( handle );
if (SUCCESS(( ret = ODBC_CALL( SQLFetchScroll, &params )))) update_result_lengths( handle, SQL_PARAM_OUTPUT );
TRACE("Returning %d\n", ret);
return ret;
}
@ -1354,20 +1385,76 @@ static BOOL resize_result_lengths( struct handle *handle, UINT size )
UINT i;
for (i = 0; i < handle->bind_col.count; i++)
{
UINT8 *tmp = realloc( handle->bind_col.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!handle->bind_col.param[i].ptr) continue;
if (!(tmp = realloc( handle->bind_col.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_col.param[i].len)
{
struct SQLBindCol_params params;
params.StatementHandle = handle->unix_handle;
params.ColumnNumber = i + 1;
params.TargetType = handle->bind_col.param[i].col.target_type;
params.TargetValue = handle->bind_col.param[i].col.target_value;
params.BufferLength = handle->bind_col.param[i].col.buffer_length;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindCol, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_col.param[i].len = tmp;
}
for (i = 0; i < handle->bind_param.count; i++)
{
UINT8 *tmp = realloc( handle->bind_param.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!handle->bind_param.param[i].ptr) continue;
if (!(tmp = realloc( handle->bind_param.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_param.param[i].len)
{
struct SQLBindParam_params params;
params.StatementHandle = handle->unix_handle;
params.ParameterNumber = i + 1;
params.ValueType = handle->bind_param.param[i].param.value_type;
params.ParameterType = handle->bind_param.param[i].param.parameter_type;
params.LengthPrecision = handle->bind_param.param[i].param.length_precision;
params.ParameterScale = handle->bind_param.param[i].param.parameter_scale;
params.ParameterValue = handle->bind_param.param[i].param.parameter_value;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindParam, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_param.param[i].len = tmp;
}
for (i = 0; i < handle->bind_parameter.count; i++)
{
UINT8 *tmp = realloc( handle->bind_parameter.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!(tmp = realloc( handle->bind_parameter.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_parameter.param[i].len)
{
struct SQLBindParameter_params params;
params.StatementHandle = handle->unix_handle;
params.ParameterNumber = i + 1;
params.InputOutputType = handle->bind_parameter.param[i].parameter.input_output_type;
params.ValueType = handle->bind_parameter.param[i].parameter.value_type;
params.ParameterType = handle->bind_parameter.param[i].parameter.parameter_type;
params.ColumnSize = handle->bind_parameter.param[i].parameter.column_size;
params.DecimalDigits = handle->bind_parameter.param[i].parameter.decimal_digits;
params.ParameterValue = handle->bind_parameter.param[i].parameter.parameter_value;
params.BufferLength = handle->bind_parameter.param[i].parameter.buffer_length;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindParameter, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_parameter.param[i].len = tmp;
}
return TRUE;
@ -1560,7 +1647,7 @@ SQLRETURN WINAPI SQLBulkOperations(SQLHSTMT StatementHandle, SQLSMALLINT Operati
if (!handle) return SQL_INVALID_HANDLE;
params.StatementHandle = handle->unix_handle;
if (SUCCESS(( ret = ODBC_CALL( SQLBulkOperations, &params )))) update_result_lengths( handle );
if (SUCCESS(( ret = ODBC_CALL( SQLBulkOperations, &params )))) update_result_lengths( handle, SQL_PARAM_OUTPUT );
TRACE("Returning %d\n", ret);
return ret;
}
@ -1876,7 +1963,7 @@ SQLRETURN WINAPI SQLSetPos(SQLHSTMT StatementHandle, SQLSETPOSIROW RowNumber, SQ
params.StatementHandle = handle->unix_handle;
if (SUCCESS(( ret = ODBC_CALL( SQLSetPos, &params ))) && Operation == SQL_REFRESH)
update_result_lengths( handle );
update_result_lengths( handle, SQL_PARAM_OUTPUT );
TRACE("Returning %d\n", ret);
return ret;
}
@ -1961,7 +2048,14 @@ SQLRETURN WINAPI SQLBindParameter(SQLHSTMT StatementHandle, SQLUSMALLINT Paramet
FIXME( "parameter 0 not handled\n" );
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_parameter, ParameterNumber, handle->row_count )) return SQL_ERROR;
if (!alloc_binding( &handle->bind_parameter, InputOutputType, ParameterNumber, handle->row_count )) return SQL_ERROR;
handle->bind_parameter.param[i].parameter.input_output_type = InputOutputType;
handle->bind_parameter.param[i].parameter.value_type = ValueType;
handle->bind_parameter.param[i].parameter.parameter_type = ParameterType;
handle->bind_parameter.param[i].parameter.column_size = ColumnSize;
handle->bind_parameter.param[i].parameter.decimal_digits = DecimalDigits;
handle->bind_parameter.param[i].parameter.parameter_value = ParameterValue;
handle->bind_parameter.param[i].parameter.buffer_length = BufferLength;
params.StatementHandle = handle->unix_handle;
params.StrLen_or_Ind = handle->bind_parameter.param[i].len;
@ -2277,7 +2371,7 @@ SQLRETURN WINAPI SQLColAttributeW(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnN
params.StatementHandle = handle->unix_handle;
params.NumericAttribute = &attr;
if (SUCCESS((ret = ODBC_CALL( SQLColAttributeW, &params )))) *NumericAttribute = attr;
if (SUCCESS((ret = ODBC_CALL( SQLColAttributeW, &params ))) && NumericAttribute) *NumericAttribute = attr;
if (ret == SQL_SUCCESS && CharacterAttribute != NULL && SQLColAttributes_KnownStringAttribute(FieldIdentifier) &&
StringLength && *StringLength != wcslen(CharacterAttribute) * 2)

View File

@ -152,8 +152,42 @@ enum sql_funcs
unix_funcs_count
};
struct bind_col_args
{
INT16 target_type;
void *target_value;
INT64 buffer_length;
};
struct bind_param_args
{
INT16 value_type;
INT16 parameter_type;
UINT64 length_precision;
INT16 parameter_scale;
void *parameter_value;
};
struct bind_parameter_args
{
INT16 input_output_type;
INT16 value_type;
INT16 parameter_type;
UINT64 column_size;
INT16 decimal_digits;
void *parameter_value;
INT64 buffer_length;
};
struct param
{
INT16 type;
union
{
struct bind_col_args col;
struct bind_param_args param;
struct bind_parameter_args parameter;
};
UINT8 *len; /* result length array stored in Unix lib */
void *ptr; /* result length ptr passed by client */
};

View File

@ -335,16 +335,44 @@ static HRESULT convert_dbproperty_mode(const WCHAR *src, VARIANT *dest)
{ L"Write", DB_MODE_WRITE },
};
struct mode_propval *prop;
WCHAR mode[64];
WCHAR *pos = NULL;
const WCHAR *lastpos = src;
if ((prop = bsearch(src, mode_propvals, ARRAY_SIZE(mode_propvals),
sizeof(struct mode_propval), dbmodeprop_compare)))
V_VT(dest) = VT_I4;
V_I4(dest) = 0;
pos = wcschr(src, '|');
while (pos != NULL)
{
V_VT(dest) = VT_I4;
V_I4(dest) = prop->value;
TRACE("%s = %#lx\n", debugstr_w(src), prop->value);
return S_OK;
lstrcpynW(mode, lastpos, pos - lastpos + 1);
if (!(prop = bsearch(mode, mode_propvals, ARRAY_SIZE(mode_propvals),
sizeof(struct mode_propval), dbmodeprop_compare)))
goto done;
V_I4(dest) |= prop->value;
lastpos = pos + 1;
pos = wcschr(lastpos, '|');
}
if (lastpos)
{
lstrcpyW(mode, lastpos);
if (!(prop = bsearch(mode, mode_propvals, ARRAY_SIZE(mode_propvals),
sizeof(struct mode_propval), dbmodeprop_compare)))
goto done;
V_I4(dest) |= prop->value;
}
TRACE("%s = %#lx\n", debugstr_w(src), V_I4(dest));
return S_OK;
done:
FIXME("Failed to parse Mode (%s)\n", debugstr_w(src));
return E_FAIL;
}
@ -755,6 +783,11 @@ HRESULT get_data_source(IUnknown *outer, DWORD clsctx, LPCOLESTR initstring, REF
}
hr = IDBProperties_SetProperties(dbprops, 1, propset);
/* Return S_OK for any successful code. */
if (SUCCEEDED(hr))
{
hr = S_OK;
}
IDBProperties_Release(dbprops);
free_dbpropset(1, propset);
if (FAILED(hr))

View File

@ -557,6 +557,8 @@ static void test_initializationstring(void)
static const WCHAR *initstring_mode = L"Provider=MSDASQL.1;Data Source=dummy;Mode=invalid";
static const WCHAR *initstring_mode2 = L"Provider=MSDASQL.1;Data Source=dummy;Mode=WriteRead";
static const WCHAR *initstring_mode3 = L"Provider=MSDASQL.1;Data Source=dummy;Mode=ReadWRITE";
static const WCHAR *initstring_mode4 = L"Provider=MSDASQL.1;Data Source=dummy;Mode=ReadWrite|Share Deny None";
static const WCHAR *initstring_mode5 = L"Provider=MSDASQL.1;Data Source=dummy;Mode=ReadWrite|Share Deny None|Share Exclusive";
static const WCHAR *initstring_quote_semicolon = L"Provider=MSDASQL.1;"
"Data Source=dummy;"
"Extended Properties=\"ConnectTo=11.0;Cell Error Mode=TextValue;Optimize Response=3;\"";
@ -625,6 +627,18 @@ static void test_initializationstring(void)
&IID_IDBInitialize, (IUnknown **)&dbinit);
ok(hr == S_OK, "got 0x%08lx\n", hr);
IDBInitialize_Release(dbinit);
dbinit = NULL;
hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, (WCHAR *)initstring_mode4,
&IID_IDBInitialize, (IUnknown **)&dbinit);
ok(hr == S_OK, "got 0x%08lx\n", hr);
IDBInitialize_Release(dbinit);
dbinit = NULL;
hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, (WCHAR *)initstring_mode5,
&IID_IDBInitialize, (IUnknown **)&dbinit);
ok(hr == S_OK, "got 0x%08lx\n", hr);
IDBInitialize_Release(dbinit);
}
else
ok(dbinit == NULL, "got %p\n", dbinit);

View File

@ -181,6 +181,8 @@ my %manual_win_thunks =
"wglGetExtensionsStringARB" => 1,
"wglGetExtensionsStringEXT" => 1,
"wglGetPixelFormat" => 1,
"wglGetPixelFormatAttribfvARB" => 1,
"wglGetPixelFormatAttribivARB" => 1,
"wglGetProcAddress" => 1,
"wglQueryCurrentRendererStringWINE" => 1,
"wglQueryRendererStringWINE" => 1,
@ -884,6 +886,31 @@ print HEADER "struct wgl_pbuffer;\n\n";
print HEADER "struct wgl_pixel_format\n";
print HEADER "{\n";
print HEADER " PIXELFORMATDESCRIPTOR pfd;\n";
print HEADER " int swap_method;\n";
print HEADER " int transparent;\n";
print HEADER " int pixel_type;\n";
print HEADER " int draw_to_pbuffer;\n";
print HEADER " int max_pbuffer_pixels;\n";
print HEADER " int max_pbuffer_width;\n";
print HEADER " int max_pbuffer_height;\n";
print HEADER " int transparent_red_value;\n";
print HEADER " int transparent_red_value_valid;\n";
print HEADER " int transparent_green_value;\n";
print HEADER " int transparent_green_value_valid;\n";
print HEADER " int transparent_blue_value;\n";
print HEADER " int transparent_blue_value_valid;\n";
print HEADER " int transparent_alpha_value;\n";
print HEADER " int transparent_alpha_value_valid;\n";
print HEADER " int transparent_index_value;\n";
print HEADER " int transparent_index_value_valid;\n";
print HEADER " int sample_buffers;\n";
print HEADER " int samples;\n";
print HEADER " int bind_to_texture_rgb;\n";
print HEADER " int bind_to_texture_rgba;\n";
print HEADER " int bind_to_texture_rectangle_rgb;\n";
print HEADER " int bind_to_texture_rectangle_rgba;\n";
print HEADER " int framebuffer_srgb_capable;\n";
print HEADER " int float_components;\n";
print HEADER "};\n\n";
print HEADER "struct opengl_funcs\n{\n";

View File

@ -24217,24 +24217,6 @@ static HDC WINAPI wglGetPbufferDCARB( HPBUFFERARB hPbuffer )
return args.ret;
}
static BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues )
{
struct wglGetPixelFormatAttribfvARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .iPixelFormat = iPixelFormat, .iLayerPlane = iLayerPlane, .nAttributes = nAttributes, .piAttributes = piAttributes, .pfValues = pfValues };
NTSTATUS status;
TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, pfValues %p\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues );
if ((status = UNIX_CALL( wglGetPixelFormatAttribfvARB, &args ))) WARN( "wglGetPixelFormatAttribfvARB returned %#lx\n", status );
return args.ret;
}
static BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues )
{
struct wglGetPixelFormatAttribivARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .iPixelFormat = iPixelFormat, .iLayerPlane = iLayerPlane, .nAttributes = nAttributes, .piAttributes = piAttributes, .piValues = piValues };
NTSTATUS status;
TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, piValues %p\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues );
if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args ))) WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status );
return args.ret;
}
static int WINAPI wglGetSwapIntervalEXT(void)
{
struct wglGetSwapIntervalEXT_params args = { .teb = NtCurrentTeb() };
@ -24340,6 +24322,8 @@ extern GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer );
extern HDC WINAPI wglGetCurrentReadDCARB(void);
extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc );
extern const char * WINAPI wglGetExtensionsStringEXT(void);
extern BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues );
extern BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues );
extern const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute );
extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute );
const void *extension_procs[] =

View File

@ -322,7 +322,9 @@ static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats,
}
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
if (!(args.formats = malloc( sizeof(*args.formats) * args.num_formats ))) goto error;
/* Clear formats memory since not all drivers deal with all wgl_pixel_format
* fields at the moment. */
if (!(args.formats = calloc( args.num_formats, sizeof(*args.formats) ))) goto error;
args.max_formats = args.num_formats;
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
@ -343,6 +345,153 @@ error:
return NULL;
}
static BOOL wgl_attrib_uses_layer( int attrib )
{
switch (attrib)
{
case WGL_ACCELERATION_ARB:
case WGL_TRANSPARENT_ARB:
case WGL_SHARE_DEPTH_ARB:
case WGL_SHARE_STENCIL_ARB:
case WGL_SHARE_ACCUM_ARB:
case WGL_TRANSPARENT_RED_VALUE_ARB:
case WGL_TRANSPARENT_GREEN_VALUE_ARB:
case WGL_TRANSPARENT_BLUE_VALUE_ARB:
case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
case WGL_TRANSPARENT_INDEX_VALUE_ARB:
case WGL_SUPPORT_GDI_ARB:
case WGL_SUPPORT_OPENGL_ARB:
case WGL_DOUBLE_BUFFER_ARB:
case WGL_STEREO_ARB:
case WGL_PIXEL_TYPE_ARB:
case WGL_COLOR_BITS_ARB:
case WGL_RED_BITS_ARB:
case WGL_RED_SHIFT_ARB:
case WGL_GREEN_BITS_ARB:
case WGL_GREEN_SHIFT_ARB:
case WGL_BLUE_BITS_ARB:
case WGL_BLUE_SHIFT_ARB:
case WGL_ALPHA_BITS_ARB:
case WGL_ALPHA_SHIFT_ARB:
case WGL_ACCUM_BITS_ARB:
case WGL_ACCUM_RED_BITS_ARB:
case WGL_ACCUM_GREEN_BITS_ARB:
case WGL_ACCUM_BLUE_BITS_ARB:
case WGL_ACCUM_ALPHA_BITS_ARB:
case WGL_DEPTH_BITS_ARB:
case WGL_STENCIL_BITS_ARB:
case WGL_AUX_BUFFERS_ARB:
case WGL_SAMPLE_BUFFERS_ARB:
case WGL_SAMPLES_ARB:
case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB:
case WGL_FLOAT_COMPONENTS_NV:
return TRUE;
default:
return FALSE;
}
}
static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int attrib, int *value )
{
int val = 0;
int valid = -1;
switch (attrib)
{
case WGL_DRAW_TO_WINDOW_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_WINDOW); break;
case WGL_DRAW_TO_BITMAP_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_BITMAP); break;
case WGL_ACCELERATION_ARB:
if (fmt->pfd.dwFlags & PFD_GENERIC_ACCELERATED)
val = WGL_GENERIC_ACCELERATION_ARB;
else if (fmt->pfd.dwFlags & PFD_GENERIC_FORMAT)
val = WGL_NO_ACCELERATION_ARB;
else
val = WGL_FULL_ACCELERATION_ARB;
break;
case WGL_NEED_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_PALETTE); break;
case WGL_NEED_SYSTEM_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE); break;
case WGL_SWAP_LAYER_BUFFERS_ARB: val = !!(fmt->pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS); break;
case WGL_SWAP_METHOD_ARB: val = fmt->swap_method; break;
case WGL_NUMBER_OVERLAYS_ARB:
case WGL_NUMBER_UNDERLAYS_ARB:
/* We don't support any overlays/underlays. */
val = 0;
break;
case WGL_TRANSPARENT_ARB: val = fmt->transparent; break;
case WGL_SHARE_DEPTH_ARB:
case WGL_SHARE_STENCIL_ARB:
case WGL_SHARE_ACCUM_ARB:
/* We support only a main plane at the moment which by definition
* shares the depth/stencil/accum buffers with itself. */
val = GL_TRUE;
break;
case WGL_SUPPORT_GDI_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_GDI); break;
case WGL_SUPPORT_OPENGL_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_OPENGL); break;
case WGL_DOUBLE_BUFFER_ARB: val = !!(fmt->pfd.dwFlags & PFD_DOUBLEBUFFER); break;
case WGL_STEREO_ARB: val = !!(fmt->pfd.dwFlags & PFD_STEREO); break;
case WGL_PIXEL_TYPE_ARB: val = fmt->pixel_type; break;
case WGL_COLOR_BITS_ARB: val = fmt->pfd.cColorBits; break;
case WGL_RED_BITS_ARB: val = fmt->pfd.cRedBits; break;
case WGL_RED_SHIFT_ARB: val = fmt->pfd.cRedShift; break;
case WGL_GREEN_BITS_ARB: val = fmt->pfd.cGreenBits; break;
case WGL_GREEN_SHIFT_ARB: val = fmt->pfd.cGreenShift; break;
case WGL_BLUE_BITS_ARB: val = fmt->pfd.cBlueBits; break;
case WGL_BLUE_SHIFT_ARB: val = fmt->pfd.cBlueShift; break;
case WGL_ALPHA_BITS_ARB: val = fmt->pfd.cAlphaBits; break;
case WGL_ALPHA_SHIFT_ARB: val = fmt->pfd.cAlphaShift; break;
case WGL_ACCUM_BITS_ARB: val = fmt->pfd.cAccumBits; break;
case WGL_ACCUM_RED_BITS_ARB: val = fmt->pfd.cAccumRedBits; break;
case WGL_ACCUM_GREEN_BITS_ARB: val = fmt->pfd.cAccumGreenBits; break;
case WGL_ACCUM_BLUE_BITS_ARB: val = fmt->pfd.cAccumBlueBits; break;
case WGL_ACCUM_ALPHA_BITS_ARB: val = fmt->pfd.cAccumAlphaBits; break;
case WGL_DEPTH_BITS_ARB: val = fmt->pfd.cDepthBits; break;
case WGL_STENCIL_BITS_ARB: val = fmt->pfd.cStencilBits; break;
case WGL_AUX_BUFFERS_ARB: val = fmt->pfd.cAuxBuffers; break;
case WGL_DRAW_TO_PBUFFER_ARB: val = fmt->draw_to_pbuffer; break;
case WGL_MAX_PBUFFER_PIXELS_ARB: val = fmt->max_pbuffer_pixels; break;
case WGL_MAX_PBUFFER_WIDTH_ARB: val = fmt->max_pbuffer_width; break;
case WGL_MAX_PBUFFER_HEIGHT_ARB: val = fmt->max_pbuffer_height; break;
case WGL_TRANSPARENT_RED_VALUE_ARB:
val = fmt->transparent_red_value;
valid = !!fmt->transparent_red_value_valid;
break;
case WGL_TRANSPARENT_GREEN_VALUE_ARB:
val = fmt->transparent_green_value;
valid = !!fmt->transparent_green_value_valid;
break;
case WGL_TRANSPARENT_BLUE_VALUE_ARB:
val = fmt->transparent_blue_value;
valid = !!fmt->transparent_blue_value_valid;
break;
case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
val = fmt->transparent_alpha_value;
valid = !!fmt->transparent_alpha_value_valid;
break;
case WGL_TRANSPARENT_INDEX_VALUE_ARB:
val = fmt->transparent_index_value;
valid = !!fmt->transparent_index_value_valid;
break;
case WGL_SAMPLE_BUFFERS_ARB: val = fmt->sample_buffers; break;
case WGL_SAMPLES_ARB: val = fmt->samples; break;
case WGL_BIND_TO_TEXTURE_RGB_ARB: val = fmt->bind_to_texture_rgb; break;
case WGL_BIND_TO_TEXTURE_RGBA_ARB: val = fmt->bind_to_texture_rgba; break;
case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV: val = fmt->bind_to_texture_rectangle_rgb; break;
case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV: val = fmt->bind_to_texture_rectangle_rgba; break;
case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: val = fmt->framebuffer_srgb_capable; break;
case WGL_FLOAT_COMPONENTS_NV: val = fmt->float_components; break;
default:
FIXME( "unsupported 0x%x WGL attribute\n", attrib );
valid = 0;
break;
}
/* If we haven't already determined validity, use the default check */
if (valid == -1) valid = val != -1;
if (valid) *value = val;
return valid;
}
INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd )
{
struct wgl_pixel_format *formats;
@ -360,6 +509,102 @@ INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDES
return num_onscreen_formats;
}
/***********************************************************************
* wglGetPixelFormatAttribivARB (OPENGL32.@)
*/
BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int index, int plane, UINT count,
const int *attributes, int *values )
{
static const DWORD invalid_data_error = 0xC007000D;
struct wgl_pixel_format *formats;
UINT i, num_formats, num_onscreen_formats;
TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
hdc, index, plane, count, attributes, values );
formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats );
/* If the driver doesn't yet provide ARB attrib information in
* wgl_pixel_format, fall back to an explicit call. */
if (num_formats && !formats[0].pixel_type)
{
struct wglGetPixelFormatAttribivARB_params args =
{
.teb = NtCurrentTeb(),
.hdc = hdc,
.iPixelFormat = index,
.iLayerPlane = plane,
.nAttributes = count,
.piAttributes = attributes,
.piValues = values
};
NTSTATUS status;
if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args )))
WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status );
return args.ret;
}
if (!count) return TRUE;
if (count == 1 && attributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
{
values[0] = num_formats;
return TRUE;
}
if (index <= 0 || index > num_formats)
{
SetLastError( invalid_data_error );
return FALSE;
}
for (i = 0; i < count; ++i)
{
int attrib = attributes[i];
if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB)
{
values[i] = num_formats;
}
else if ((plane != 0 && wgl_attrib_uses_layer( attrib )) ||
!wgl_pixel_format_get_attrib( &formats[index - 1], attrib, &values[i] ))
{
SetLastError( invalid_data_error );
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* wglGetPixelFormatAttribfvARB (OPENGL32.@)
*/
BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int index, int plane, UINT count,
const int *attributes, FLOAT *values )
{
int *ivalues;
BOOL ret;
UINT i;
TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
hdc, index, plane, count, attributes, values );
if (!(ivalues = malloc( count * sizeof(int) ))) return FALSE;
/* For now we can piggy-back on wglGetPixelFormatAttribivARB, since we don't support
* any non-integer attributes. */
ret = wglGetPixelFormatAttribivARB( hdc, index, plane, count, attributes, ivalues );
if (ret)
{
for (i = 0; i < count; i++)
values[i] = ivalues[i];
}
free( ivalues );
return ret;
}
/***********************************************************************
* wglGetPixelFormat (OPENGL32.@)
*/

View File

@ -48,6 +48,8 @@ struct avi_decompressor
HIC hvid;
BITMAPINFOHEADER* pBihIn;
CRITICAL_SECTION late_cs;
REFERENCE_TIME late;
};
@ -77,7 +79,9 @@ static HRESULT avi_decompressor_sink_query_accept(struct strmbase_pin *iface, co
static HRESULT avi_decompressor_sink_end_flush(struct strmbase_sink *iface)
{
struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter);
EnterCriticalSection(&filter->late_cs);
filter->late = -1;
LeaveCriticalSection(&filter->late_cs);
if (filter->source.pin.peer)
return IPin_EndFlush(filter->source.pin.peer);
return S_OK;
@ -167,8 +171,10 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface,
if (IMediaSample_IsSyncPoint(pSample) != S_OK)
flags |= ICDECOMPRESS_NOTKEYFRAME;
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
EnterCriticalSection(&This->late_cs);
if (hr == S_OK && AVIDec_DropSample(This, tStart))
flags |= ICDECOMPRESS_HURRYUP;
LeaveCriticalSection(&This->late_cs);
res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, &source_format->bmiHeader, pbDstStream);
if (res != ICERR_OK)
@ -482,12 +488,13 @@ static HRESULT WINAPI avi_decompressor_source_qc_Notify(IQualityControl *iface,
TRACE("filter %p, sender %p, type %#x, proportion %ld, late %s, timestamp %s.\n",
filter, sender, q.Type, q.Proportion, debugstr_time(q.Late), debugstr_time(q.TimeStamp));
EnterCriticalSection(&filter->filter.stream_cs);
/* can't take the stream CS here, Submarine Titans calls this function from a foreign thread while inside sink_Receive */
EnterCriticalSection(&filter->late_cs);
if (q.Late > 0)
filter->late = q.Late + q.TimeStamp;
else
filter->late = -1;
LeaveCriticalSection(&filter->filter.stream_cs);
LeaveCriticalSection(&filter->late_cs);
return S_OK;
}
@ -532,6 +539,9 @@ static void avi_decompressor_destroy(struct strmbase_filter *iface)
IPin_Disconnect(filter->source.pin.peer);
IPin_Disconnect(&filter->source.pin.IPin_iface);
filter->late_cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&filter->late_cs);
strmbase_sink_cleanup(&filter->sink);
strmbase_source_cleanup(&filter->source);
strmbase_passthrough_cleanup(&filter->passthrough);
@ -550,7 +560,9 @@ static HRESULT avi_decompressor_init_stream(struct strmbase_filter *iface)
if (!filter->source.pin.peer)
return S_OK;
EnterCriticalSection(&filter->late_cs);
filter->late = -1;
LeaveCriticalSection(&filter->late_cs);
source_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat;
if ((res = ICDecompressBegin(filter->hvid, filter->pBihIn, &source_format->bmiHeader)))
@ -618,6 +630,9 @@ HRESULT avi_dec_create(IUnknown *outer, IUnknown **out)
ISeekingPassThru_Init(&object->passthrough.ISeekingPassThru_iface, FALSE,
&object->sink.pin.IPin_iface);
InitializeCriticalSectionEx(&object->late_cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
object->late_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": object.late_cs");
TRACE("Created AVI decompressor %p.\n", object);
*out = &object->filter.IUnknown_inner;

View File

@ -873,6 +873,20 @@ static HRESULT testsink_connect(struct strmbase_sink *iface, IPin *peer, const A
return S_OK;
}
static DWORD WINAPI call_qc_notify(void *ptr)
{
struct testfilter *filter = ptr;
IQualityControl *qc;
Quality q = { Famine, 2000, -10000000, 10000000 };
IPin_QueryInterface(filter->sink.pin.peer, &IID_IQualityControl, (void**)&qc);
/* don't worry too much about what it returns, just check that it doesn't deadlock */
IQualityControl_Notify(qc, &filter->filter.IBaseFilter_iface, q);
IQualityControl_Release(qc);
return 0;
}
static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample *sample)
{
struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter);
@ -920,6 +934,13 @@ static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample
hr = IMediaSample_IsSyncPoint(sample);
todo_wine_if (testmode == 5 || testmode == 6) ok(hr == S_OK, "Got hr %#lx.\n", hr);
if (testmode == 7)
{
HANDLE h = CreateThread(NULL, 0, call_qc_notify, filter, 0, NULL);
ok(WaitForSingleObject(h, 1000) == WAIT_OBJECT_0, "Didn't expect deadlock.\n");
CloseHandle(h);
}
return S_OK;
}
@ -1129,6 +1150,15 @@ static void test_sample_processing(IMediaControl *control, IMemInputPin *input,
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(!sink->got_sample, "Got %u calls to Receive().\n", sink->got_sample);
testmode = 7;
hr = IMediaSample_SetSyncPoint(sample, TRUE);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
sink->got_sample = 0;
hr = IMemInputPin_Receive(input, sample);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
ok(sink->got_sample == 1, "Got %u calls to Receive().\n", sink->got_sample);
sink->got_sample = 0;
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
@ -1174,7 +1204,7 @@ static void test_streaming_events(IMediaControl *control, IPin *sink,
ok(!testsink->got_eos, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
hr = IPin_EndOfStream(sink);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(!testsink->got_sample, "Got %u calls to Receive().\n", testsink->got_sample);
ok(!testsink->got_sample, "Got %u calls to Receive().\n", testsink->got_sample);
ok(testsink->got_eos == 1, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
testsink->got_eos = 0;
@ -1185,7 +1215,7 @@ static void test_streaming_events(IMediaControl *control, IPin *sink,
testmode = 0;
hr = IMemInputPin_Receive(input, sample);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(testsink->got_sample == 1, "Got %u calls to Receive().\n", testsink->got_sample);
ok(testsink->got_sample == 1, "Got %u calls to Receive().\n", testsink->got_sample);
testsink->got_sample = 0;
ok(!testsink->got_begin_flush, "Got %u calls to IPin::BeginFlush().\n", testsink->got_begin_flush);

View File

@ -1677,9 +1677,9 @@ static void test_seeking(void)
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
}
static void test_streaming(void)
static void test_streaming(const WCHAR *resname)
{
const WCHAR *filename = load_resource(L"test.avi");
const WCHAR *filename = load_resource(resname);
IBaseFilter *filter = create_avi_splitter();
IFilterGraph2 *graph = connect_input(filter, filename);
struct testfilter testsink;
@ -1691,6 +1691,8 @@ static void test_streaming(void)
ULONG ref;
DWORD ret;
winetest_push_context("File %ls", resname);
testfilter_init(&testsink);
IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
@ -1761,6 +1763,8 @@ static void test_streaming(void)
ok(!ref, "Got outstanding refcount %ld.\n", ref);
ret = DeleteFileW(filename);
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
winetest_pop_context();
}
START_TEST(avisplit)
@ -1787,7 +1791,8 @@ START_TEST(avisplit)
test_unconnected_filter_state();
test_connect_pin();
test_seeking();
test_streaming();
test_streaming(L"test.avi");
test_streaming(L"test_cinepak.avi");
CoUninitialize();
}

View File

@ -39,3 +39,7 @@ test.wav RCDATA "test.wav"
/* ffmpeg -f lavfi -i smptebars -f lavfi -i "sine=frequency=1000" -t 2.04 -r 25 -f mpeg -vcodec mpeg1video -vf scale=64x48 -acodec mp2 -ar 32k -ab 96k test2.mpg */
/* @makedep: test2.mpg */
test2.mpg RCDATA "test2.mpg"
/* ffmpeg -f lavfi -i smptebars -t 5 -r 1 -f avi -vcodec cinepak -pix_fmt rgb24 -vf scale=32x24 test_cinepak.avi */
/* @makedep: test_cinepak.avi */
test_cinepak.avi RCDATA "test_cinepak.avi"

Binary file not shown.

View File

@ -28,6 +28,7 @@
#define WIN32_NO_STATUS
#include "ntgdi_private.h"
#include "win32u_private.h"
#include "ntuser_private.h"
#include "wine/vulkan.h"
#include "wine/vulkan_driver.h"
@ -83,13 +84,13 @@ static void d3dkmt_init_vulkan(void)
PFN_vkCreateInstance p_vkCreateInstance;
VkResult vr;
if (!(vulkan_funcs = __wine_get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION )))
if (!vulkan_init())
{
WARN( "Failed to open the Vulkan driver\n" );
return;
}
p_vkCreateInstance = vulkan_funcs->p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" );
p_vkCreateInstance = p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" );
if ((vr = p_vkCreateInstance( &create_info, NULL, &d3dkmt_vk_instance )))
{
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
@ -97,9 +98,9 @@ static void d3dkmt_init_vulkan(void)
return;
}
p_vkDestroyInstance = vulkan_funcs->p_vkGetInstanceProcAddr( d3dkmt_vk_instance, "vkDestroyInstance" );
p_vkDestroyInstance = p_vkGetInstanceProcAddr( d3dkmt_vk_instance, "vkDestroyInstance" );
#define LOAD_VK_FUNC( f ) \
if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr( d3dkmt_vk_instance, #f ))) \
if (!(p##f = (void *)p_vkGetInstanceProcAddr( d3dkmt_vk_instance, #f ))) \
{ \
WARN( "Failed to load " #f ".\n" ); \
p_vkDestroyInstance( d3dkmt_vk_instance, NULL ); \

View File

@ -25,6 +25,7 @@
#include "ntuser.h"
#include "shellapi.h"
#include "wine/list.h"
#include "wine/vulkan.h"
#define WM_POPUPSYSTEMMENU 0x0313
@ -250,6 +251,10 @@ extern int peek_message( MSG *msg, const struct peek_message_filter *filter );
extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data );
/* vulkan.c */
extern void *(*p_vkGetDeviceProcAddr)(VkDevice, const char *);
extern void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
extern BOOL vulkan_init(void);
extern void vulkan_detach_surfaces( struct list *surfaces );
/* window.c */

View File

@ -39,16 +39,18 @@
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
#ifdef SONAME_LIBVULKAN
void *(*p_vkGetDeviceProcAddr)(VkDevice, const char *) = NULL;
void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *) = NULL;
static void *vulkan_handle;
static const struct vulkan_driver_funcs *driver_funcs;
static struct vulkan_funcs vulkan_funcs;
#ifdef SONAME_LIBVULKAN
static const struct vulkan_driver_funcs *driver_funcs;
static void (*p_vkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *);
static VkResult (*p_vkQueuePresentKHR)(VkQueue, const VkPresentInfoKHR *);
static void *(*p_vkGetDeviceProcAddr)(VkDevice, const char *);
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
struct surface
{
@ -283,7 +285,7 @@ static const struct vulkan_driver_funcs lazydrv_funcs =
.p_vulkan_surface_presented = lazydrv_vulkan_surface_presented,
};
static void vulkan_init(void)
static void vulkan_init_once(void)
{
if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW )))
{
@ -323,36 +325,37 @@ void vulkan_detach_surfaces( struct list *surfaces )
}
}
/***********************************************************************
* __wine_get_vulkan_driver (win32u.so)
*/
const struct vulkan_funcs *__wine_get_vulkan_driver( UINT version )
{
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
if (version != WINE_VULKAN_DRIVER_VERSION)
{
ERR( "version mismatch, vulkan wants %u but win32u has %u\n", version, WINE_VULKAN_DRIVER_VERSION );
return NULL;
}
pthread_once( &init_once, vulkan_init );
return vulkan_handle ? &vulkan_funcs : NULL;
}
#else /* SONAME_LIBVULKAN */
void vulkan_detach_surfaces( struct list *surfaces )
{
}
static void vulkan_init_once(void)
{
ERR( "Wine was built without Vulkan support.\n" );
}
#endif /* SONAME_LIBVULKAN */
BOOL vulkan_init(void)
{
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
pthread_once( &init_once, vulkan_init_once );
return !!vulkan_handle;
}
/***********************************************************************
* __wine_get_vulkan_driver (win32u.so)
*/
const struct vulkan_funcs *__wine_get_vulkan_driver( UINT version )
{
ERR("Wine was built without Vulkan support.\n");
return NULL;
}
if (version != WINE_VULKAN_DRIVER_VERSION)
{
ERR( "version mismatch, vulkan wants %u but win32u has %u\n", version, WINE_VULKAN_DRIVER_VERSION );
return NULL;
}
#endif /* SONAME_LIBVULKAN */
if (!vulkan_init()) return NULL;
return &vulkan_funcs;
}

View File

@ -100,6 +100,9 @@ struct parser_source
bool need_segment;
bool eos;
bool interpolate_timestamps;
UINT64 prev_end_pts;
};
static inline struct parser *impl_from_strmbase_filter(struct strmbase_filter *iface)
@ -630,7 +633,7 @@ static bool amt_from_wg_format_video_cinepak(AM_MEDIA_TYPE *mt, const struct wg_
return true;
}
static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format)
static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm)
{
VIDEOINFOHEADER *video_format;
uint32_t frame_time;
@ -671,7 +674,8 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format));
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
if (wm)
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
video_format->rcTarget = video_format->rcSource;
if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1)
video_format->AvgTimePerFrame = frame_time;
@ -681,6 +685,8 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
video_format->bmiHeader.biPlanes = 1;
video_format->bmiHeader.biCompression = mt->subtype.Data1;
video_format->bmiHeader.biBitCount = 24;
if (!wm)
video_format->bmiHeader.biSizeImage = 3 * format->u.video.width * format->u.video.height;
video_format->dwBitRate = 0;
memcpy(video_format+1, format->u.video.codec_data, format->u.video.codec_data_len);
@ -747,7 +753,7 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
return amt_from_wg_format_video_cinepak(mt, format);
case WG_MAJOR_TYPE_VIDEO_WMV:
return amt_from_wg_format_video_wmv(mt, format);
return amt_from_wg_format_video_wmv(mt, format, wm);
case WG_MAJOR_TYPE_VIDEO_MPEG1:
return amt_from_wg_format_video_mpeg1(mt, format);
@ -977,6 +983,30 @@ static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *fo
return false;
}
static bool amt_to_wg_format_video_cinepak(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
const VIDEOINFOHEADER *video_format = (const VIDEOINFOHEADER *)mt->pbFormat;
if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
{
FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype));
return false;
}
if (mt->cbFormat < sizeof(VIDEOINFOHEADER) || !mt->pbFormat)
{
ERR("Unexpected format size %lu.\n", mt->cbFormat);
return false;
}
format->major_type = WG_MAJOR_TYPE_VIDEO_CINEPAK;
format->u.video.width = video_format->bmiHeader.biWidth;
format->u.video.height = video_format->bmiHeader.biHeight;
format->u.video.fps_n = 10000000;
format->u.video.fps_d = video_format->AvgTimePerFrame;
return true;
}
static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
const VIDEOINFOHEADER *video_format = (const VIDEOINFOHEADER *)mt->pbFormat;
@ -1051,6 +1081,8 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Video))
{
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_CVID))
return amt_to_wg_format_video_cinepak(mt, format);
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)
@ -1153,30 +1185,34 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
return S_OK;
}
if (buffer->has_pts)
if (buffer->has_pts || (pin->interpolate_timestamps && pin->prev_end_pts != 0))
{
REFERENCE_TIME start_pts = buffer->pts;
UINT64 start_pts = (buffer->has_pts ? buffer->pts : pin->prev_end_pts);
REFERENCE_TIME start_reftime = start_pts;
if (offset)
start_pts += scale_uint64(offset, 10000000, bytes_per_second);
start_pts -= pin->seek.llCurrent;
start_pts *= pin->seek.dRate;
start_reftime += scale_uint64(offset, 10000000, bytes_per_second);
start_reftime -= pin->seek.llCurrent;
start_reftime *= pin->seek.dRate;
if (buffer->has_duration)
{
REFERENCE_TIME end_pts = buffer->pts + buffer->duration;
UINT64 end_pts = start_pts + buffer->duration;
REFERENCE_TIME end_reftime = end_pts;
pin->prev_end_pts = end_pts;
if (offset + size < buffer->size)
end_pts = buffer->pts + scale_uint64(offset + size, 10000000, bytes_per_second);
end_pts -= pin->seek.llCurrent;
end_pts *= pin->seek.dRate;
end_reftime = end_reftime + scale_uint64(offset + size, 10000000, bytes_per_second);
end_reftime -= pin->seek.llCurrent;
end_reftime *= pin->seek.dRate;
IMediaSample_SetTime(sample, &start_pts, &end_pts);
IMediaSample_SetMediaTime(sample, &start_pts, &end_pts);
IMediaSample_SetTime(sample, &start_reftime, &end_reftime);
IMediaSample_SetMediaTime(sample, &start_reftime, &end_reftime);
}
else
{
IMediaSample_SetTime(sample, &start_pts, NULL);
pin->prev_end_pts = 0;
IMediaSample_SetTime(sample, &start_reftime, NULL);
IMediaSample_SetMediaTime(sample, NULL, NULL);
}
}
@ -2291,6 +2327,7 @@ static const struct strmbase_sink_ops avi_splitter_sink_ops =
static BOOL avi_splitter_filter_init_gst(struct parser *filter)
{
wg_parser_t parser = filter->wg_parser;
struct parser_source *src;
uint32_t i, stream_count;
WCHAR source_name[20];
@ -2298,8 +2335,10 @@ static BOOL avi_splitter_filter_init_gst(struct parser *filter)
for (i = 0; i < stream_count; ++i)
{
swprintf(source_name, ARRAY_SIZE(source_name), L"Stream %02u", i);
if (!create_pin(filter, wg_parser_get_stream(parser, i), source_name))
src = create_pin(filter, wg_parser_get_stream(parser, i), source_name);
if (!src)
return FALSE;
src->interpolate_timestamps = TRUE;
}
return TRUE;

View File

@ -661,8 +661,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde
DMO_MEDIA_TYPE *type)
{
struct wma_decoder *decoder = impl_from_IMediaObject(iface);
UINT32 depth, channels, rate;
IMFMediaType *media_type;
UINT32 depth;
HRESULT hr;
TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type);
@ -686,6 +686,16 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde
else
hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
if (SUCCEEDED(hr))
hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
if (SUCCEEDED(hr))
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, depth * channels / 8);
if (SUCCEEDED(hr))
hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
if (SUCCEEDED(hr))
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, depth * channels / 8 * rate);
if (SUCCEEDED(hr))
hr = IMFMediaType_DeleteItem(media_type, &MF_MT_USER_DATA);
if (SUCCEEDED(hr))

View File

@ -3391,45 +3391,6 @@ invalid_layer:
}
/**********************************************************************
* macdrv_wglGetPixelFormatAttribfvARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
*/
static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
{
int *attr;
int ret;
TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
/* Allocate a temporary array to store integer values */
attr = malloc(nAttributes * sizeof(int));
if (!attr)
{
ERR("couldn't allocate %d array\n", nAttributes);
return GL_FALSE;
}
/* Piggy-back on wglGetPixelFormatAttribivARB */
ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
if (ret)
{
UINT i;
/* Convert integer values to float. Should also check for attributes
that can give decimal values here */
for (i = 0; i < nAttributes; i++)
pfValues[i] = attr[i];
}
free(attr);
return ret;
}
/**********************************************************************
* macdrv_wglGetSwapIntervalEXT
*
@ -4136,7 +4097,7 @@ static void load_extensions(void)
register_extension("WGL_ARB_pixel_format");
opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))

View File

@ -1553,132 +1553,208 @@ void destroy_gl_drawable( HWND hwnd )
/**
* glxdrv_DescribePixelFormat
* describe_pixel_format
*
* Get the pixel-format descriptor associated to the given id
* Get the wgl_pixel_format description for the given id
*/
static int describe_pixel_format( int iPixelFormat, PIXELFORMATDESCRIPTOR *ppfd )
static int describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf )
{
/*XVisualInfo *vis;*/
int value;
int rb,gb,bb,ab;
const struct glx_pixel_format *fmt;
int value, drawable_type = 0, render_type = 0;
int rb, gb, bb, ab;
const struct glx_pixel_format *fmt;
if (!has_opengl()) return 0;
if (!has_opengl()) return 0;
/* Look for the iPixelFormat in our list of supported formats. If it is supported we get the index in the FBConfig table and the number of supported formats back */
fmt = get_pixel_format(gdi_display, iPixelFormat, TRUE /* Offscreen */);
if (!fmt) {
WARN("unexpected format %d\n", iPixelFormat);
return 0;
}
/* Look for the iPixelFormat in our list of supported formats. If it is
* supported we get the index in the FBConfig table and the number of
* supported formats back */
fmt = get_pixel_format( gdi_display, iPixelFormat, TRUE /* Offscreen */);
if (!fmt)
{
WARN( "unexpected format %d\n", iPixelFormat );
return 0;
}
memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
/* If we can't get basic information, there is no point continuing */
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &drawable_type )) return 0;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &render_type )) return 0;
/* These flags are always the same... */
ppfd->dwFlags = PFD_SUPPORT_OPENGL;
/* Now the flags extracted from the Visual */
memset( pf, 0, sizeof(*pf) );
pf->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pf->pfd.nVersion = 1;
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
if(value & GLX_WINDOW_BIT)
ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
/* These flags are always the same... */
pf->pfd.dwFlags = PFD_SUPPORT_OPENGL;
/* Now the flags extracted from the Visual */
/* On Windows bitmap rendering is only offered using the GDI Software renderer. We reserve some formats (see get_formats for more info)
* for bitmap rendering since we require indirect rendering for this. Further pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
* Radeon 9000 indicated that all bitmap formats have PFD_SUPPORT_GDI. Except for 2 formats on the Radeon 9000 none of the hw accelerated formats
* offered the GDI bit either. */
ppfd->dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
if (drawable_type & GLX_WINDOW_BIT) pf->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
/* PFD_GENERIC_FORMAT - gdi software rendering
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver (MCD e.g. 3dfx minigl)
* none set - full hardware accelerated by a ICD
*
* We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as that's what ATI and Nvidia Windows drivers do */
ppfd->dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
/* On Windows bitmap rendering is only offered using the GDI Software
* renderer. We reserve some formats (see get_formats for more info) for
* bitmap rendering since we require indirect rendering for this. Further
* pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
* Radeon 9000 indicated that all bitmap formats have PFD_SUPPORT_GDI.
* Except for 2 formats on the Radeon 9000 none of the hw accelerated
* formats offered the GDI bit either. */
pf->pfd.dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
if (!(ppfd->dwFlags & PFD_GENERIC_FORMAT))
ppfd->dwFlags |= PFD_SUPPORT_COMPOSITION;
/* PFD_GENERIC_FORMAT - gdi software rendering
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver
* (MCD e.g. 3dfx minigl) none set - full hardware accelerated by a ICD
*
* We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as
* that's what ATI and Nvidia Windows drivers do */
pf->pfd.dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
if (value) {
ppfd->dwFlags |= PFD_DOUBLEBUFFER;
ppfd->dwFlags &= ~PFD_SUPPORT_GDI;
}
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
if (!(pf->pfd.dwFlags & PFD_GENERIC_FORMAT)) pf->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
/* Pixel type */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
if (value & GLX_RGBA_BIT)
ppfd->iPixelType = PFD_TYPE_RGBA;
else
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value );
if (value)
{
pf->pfd.dwFlags |= PFD_DOUBLEBUFFER;
pf->pfd.dwFlags &= ~PFD_SUPPORT_GDI;
}
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STEREO, &value );
if (value) pf->pfd.dwFlags |= PFD_STEREO;
/* Color bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value);
ppfd->cColorBits = value;
/* Pixel type */
if (render_type & GLX_RGBA_BIT) pf->pfd.iPixelType = PFD_TYPE_RGBA;
else pf->pfd.iPixelType = PFD_TYPE_COLORINDEX;
/* Red, green, blue and alpha bits / shifts */
if (ppfd->iPixelType == PFD_TYPE_RGBA) {
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab);
/* Color bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value );
pf->pfd.cColorBits = value;
ppfd->cBlueBits = bb;
ppfd->cBlueShift = 0;
ppfd->cGreenBits = gb;
ppfd->cGreenShift = bb;
ppfd->cRedBits = rb;
ppfd->cRedShift = gb + bb;
ppfd->cAlphaBits = ab;
if (ab)
ppfd->cAlphaShift = rb + gb + bb;
/* Red, green, blue and alpha bits / shifts */
if (pf->pfd.iPixelType == PFD_TYPE_RGBA)
{
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab );
pf->pfd.cBlueBits = bb;
pf->pfd.cBlueShift = 0;
pf->pfd.cGreenBits = gb;
pf->pfd.cGreenShift = bb;
pf->pfd.cRedBits = rb;
pf->pfd.cRedShift = gb + bb;
pf->pfd.cAlphaBits = ab;
if (ab) pf->pfd.cAlphaShift = rb + gb + bb;
else pf->pfd.cAlphaShift = 0;
}
else
ppfd->cAlphaShift = 0;
} else {
ppfd->cRedBits = 0;
ppfd->cRedShift = 0;
ppfd->cBlueBits = 0;
ppfd->cBlueShift = 0;
ppfd->cGreenBits = 0;
ppfd->cGreenShift = 0;
ppfd->cAlphaBits = 0;
ppfd->cAlphaShift = 0;
}
{
pf->pfd.cRedBits = 0;
pf->pfd.cRedShift = 0;
pf->pfd.cBlueBits = 0;
pf->pfd.cBlueShift = 0;
pf->pfd.cGreenBits = 0;
pf->pfd.cGreenShift = 0;
pf->pfd.cAlphaBits = 0;
pf->pfd.cAlphaShift = 0;
}
/* Accum RGBA bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab);
/* Accum RGBA bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab );
ppfd->cAccumBits = rb+gb+bb+ab;
ppfd->cAccumRedBits = rb;
ppfd->cAccumGreenBits = gb;
ppfd->cAccumBlueBits = bb;
ppfd->cAccumAlphaBits = ab;
pf->pfd.cAccumBits = rb + gb + bb + ab;
pf->pfd.cAccumRedBits = rb;
pf->pfd.cAccumGreenBits = gb;
pf->pfd.cAccumBlueBits = bb;
pf->pfd.cAccumAlphaBits = ab;
/* Aux bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value);
ppfd->cAuxBuffers = value;
/* Aux bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value );
pf->pfd.cAuxBuffers = value;
/* Depth bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value);
ppfd->cDepthBits = value;
/* Depth bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value );
pf->pfd.cDepthBits = value;
/* stencil bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value);
ppfd->cStencilBits = value;
/* stencil bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value );
pf->pfd.cStencilBits = value;
ppfd->iLayerType = PFD_MAIN_PLANE;
pf->pfd.iLayerType = PFD_MAIN_PLANE;
if (TRACE_ON(wgl)) {
dump_PIXELFORMATDESCRIPTOR(ppfd);
}
if (!has_swap_method) pf->swap_method = WGL_SWAP_EXCHANGE_ARB;
else if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SWAP_METHOD_OML, &value ))
{
switch (value) {
case GLX_SWAP_EXCHANGE_OML: pf->swap_method = WGL_SWAP_EXCHANGE_ARB; break;
case GLX_SWAP_COPY_OML: pf->swap_method = WGL_SWAP_COPY_ARB; break;
case GLX_SWAP_UNDEFINED_OML: pf->swap_method = WGL_SWAP_UNDEFINED_ARB; break;
default: { ERR( "Unexpected swap method %x.\n", value ); pf->swap_method = -1; break; }
}
}
else pf->swap_method = -1;
return nb_onscreen_formats;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_TYPE, &value) ) pf->transparent = -1;
else pf->transparent = value != GLX_NONE;
if (render_type & GLX_RGBA_BIT) pf->pixel_type = WGL_TYPE_RGBA_ARB;
else if (render_type & GLX_COLOR_INDEX_BIT) pf->pixel_type = WGL_TYPE_COLORINDEX_ARB;
else if (render_type & GLX_RGBA_FLOAT_BIT) pf->pixel_type = WGL_TYPE_RGBA_FLOAT_ATI;
else if (render_type & GLX_RGBA_FLOAT_ATI_BIT) pf->pixel_type = WGL_TYPE_RGBA_FLOAT_ATI;
else if (render_type & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) pf->pixel_type = WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT;
else { ERR( "unexpected RenderType(%x)\n", render_type ); pf->pixel_type = -1; }
pf->draw_to_pbuffer = (drawable_type & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_PIXELS, &value )) value = -1;
pf->max_pbuffer_pixels = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_WIDTH, &value )) value = -1;
pf->max_pbuffer_width = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_HEIGHT, &value )) value = -1;
pf->max_pbuffer_height = value;
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_RED_VALUE, &value ))
{
pf->transparent_red_value_valid = GL_TRUE;
pf->transparent_red_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &value ))
{
pf->transparent_green_value_valid = GL_TRUE;
pf->transparent_green_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &value ))
{
pf->transparent_blue_value_valid = GL_TRUE;
pf->transparent_blue_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &value ))
{
pf->transparent_alpha_value_valid = GL_TRUE;
pf->transparent_alpha_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &value ))
{
pf->transparent_index_value_valid = GL_TRUE;
pf->transparent_index_value = value;
}
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SAMPLE_BUFFERS_ARB, &value )) value = -1;
pf->sample_buffers = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SAMPLES_ARB, &value )) value = -1;
pf->samples = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &value )) value = -1;
pf->framebuffer_srgb_capable = value;
pf->bind_to_texture_rgb = pf->bind_to_texture_rgba =
use_render_texture_emulation && render_type != GLX_COLOR_INDEX_BIT && (render_type & GLX_PBUFFER_BIT);
pf->bind_to_texture_rectangle_rgb = pf->bind_to_texture_rectangle_rgba = GL_FALSE;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_FLOAT_COMPONENTS_NV, &value )) value = -1;
pf->float_components = value;
if (TRACE_ON(wgl)) dump_PIXELFORMATDESCRIPTOR( &pf->pfd );
return nb_onscreen_formats;
}
@ -2520,7 +2596,7 @@ struct choose_pixel_format_arb_format
{
int format;
int original_index;
PIXELFORMATDESCRIPTOR pfd;
struct wgl_pixel_format pf;
int depth, stencil;
};
@ -2537,7 +2613,7 @@ static int compare_formats(const void *a, const void *b)
if (offscreen_a != offscreen_b)
return offscreen_a - offscreen_b;
if (memcmp(&fmt_a->pfd, &fmt_b->pfd, sizeof(fmt_a->pfd)))
if (memcmp(&fmt_a->pf.pfd, &fmt_b->pf.pfd, sizeof(fmt_a->pf.pfd)))
return fmt_a->original_index - fmt_b->original_index;
if (fmt_a->depth != fmt_b->depth)
return fmt_a->depth - fmt_b->depth;
@ -2652,16 +2728,16 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
format->format = i + 1;
format->original_index = it;
memset(&format->pfd, 0, sizeof(format->pfd));
if (!describe_pixel_format(format->format, &format->pfd))
memset(&format->pf, 0, sizeof(format->pf));
if (!describe_pixel_format(format->format, &format->pf))
ERR("describe_pixel_format failed, format %d.\n", format->format);
format->depth = format->pfd.cDepthBits;
format->stencil = format->pfd.cStencilBits;
if (!depth_bits && !(format->pfd.dwFlags & PFD_GENERIC_FORMAT))
format->depth = format->pf.pfd.cDepthBits;
format->stencil = format->pf.pfd.cStencilBits;
if (!depth_bits && !(format->pf.pfd.dwFlags & PFD_GENERIC_FORMAT))
{
format->pfd.cDepthBits = 0;
format->pfd.cStencilBits = 0;
format->pf.pfd.cDepthBits = 0;
format->pf.pfd.cStencilBits = 0;
}
++format_count;
@ -2678,329 +2754,6 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
return GL_TRUE;
}
/**
* X11DRV_wglGetPixelFormatAttribivARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
*/
static BOOL X11DRV_wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, int *piValues )
{
UINT i;
const struct glx_pixel_format *fmt;
int hTest;
int tmp;
int curGLXAttr = 0;
PIXELFORMATDESCRIPTOR pfd;
TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
if (0 < iLayerPlane) {
FIXME("unsupported iLayerPlane(%d) > 0, returns FALSE\n", iLayerPlane);
return GL_FALSE;
}
/* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supported.
* We don't have to fail yet as a program can specify an invalid iPixelFormat (lets say 0) if it wants to query
* the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */
fmt = get_pixel_format(gdi_display, iPixelFormat, TRUE /* Offscreen */);
if(!fmt) {
WARN("Unable to convert iPixelFormat %d to a GLX one!\n", iPixelFormat);
}
if (!describe_pixel_format(iPixelFormat, &pfd))
{
WARN("describe_pixel_format failed.\n");
memset(&pfd, 0, sizeof(pfd));
}
for (i = 0; i < nAttributes; ++i) {
const int curWGLAttr = piAttributes[i];
TRACE("pAttr[%d] = %x\n", i, curWGLAttr);
switch (curWGLAttr) {
case WGL_NUMBER_PIXEL_FORMATS_ARB:
piValues[i] = nb_pixel_formats;
continue;
case WGL_SUPPORT_OPENGL_ARB:
piValues[i] = GL_TRUE;
continue;
case WGL_ACCELERATION_ARB:
curGLXAttr = GLX_CONFIG_CAVEAT;
if (!fmt) goto pix_error;
if(fmt->dwFlags & PFD_GENERIC_FORMAT)
piValues[i] = WGL_NO_ACCELERATION_ARB;
else if(fmt->dwFlags & PFD_GENERIC_ACCELERATED)
piValues[i] = WGL_GENERIC_ACCELERATION_ARB;
else
piValues[i] = WGL_FULL_ACCELERATION_ARB;
continue;
case WGL_TRANSPARENT_ARB:
curGLXAttr = GLX_TRANSPARENT_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
piValues[i] = GL_FALSE;
if (GLX_NONE != tmp) piValues[i] = GL_TRUE;
continue;
case WGL_PIXEL_TYPE_ARB:
curGLXAttr = GLX_RENDER_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp);
if (tmp & GLX_RGBA_BIT) { piValues[i] = WGL_TYPE_RGBA_ARB; }
else if (tmp & GLX_COLOR_INDEX_BIT) { piValues[i] = WGL_TYPE_COLORINDEX_ARB; }
else if (tmp & GLX_RGBA_FLOAT_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
else if (tmp & GLX_RGBA_FLOAT_ATI_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
else if (tmp & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { piValues[i] = WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT; }
else {
ERR("unexpected RenderType(%x)\n", tmp);
piValues[i] = WGL_TYPE_RGBA_ARB;
}
continue;
case WGL_COLOR_BITS_ARB:
curGLXAttr = GLX_BUFFER_SIZE;
break;
case WGL_BIND_TO_TEXTURE_RGB_ARB:
case WGL_BIND_TO_TEXTURE_RGBA_ARB:
if (!use_render_texture_emulation) {
piValues[i] = GL_FALSE;
continue;
}
curGLXAttr = GLX_RENDER_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
if (GLX_COLOR_INDEX_BIT == tmp) {
piValues[i] = GL_FALSE;
continue;
}
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
if (hTest) goto get_error;
piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
continue;
case WGL_BLUE_BITS_ARB:
curGLXAttr = GLX_BLUE_SIZE;
break;
case WGL_RED_BITS_ARB:
curGLXAttr = GLX_RED_SIZE;
break;
case WGL_GREEN_BITS_ARB:
curGLXAttr = GLX_GREEN_SIZE;
break;
case WGL_ALPHA_BITS_ARB:
curGLXAttr = GLX_ALPHA_SIZE;
break;
case WGL_DEPTH_BITS_ARB:
curGLXAttr = GLX_DEPTH_SIZE;
break;
case WGL_STENCIL_BITS_ARB:
curGLXAttr = GLX_STENCIL_SIZE;
break;
case WGL_DOUBLE_BUFFER_ARB:
curGLXAttr = GLX_DOUBLEBUFFER;
break;
case WGL_STEREO_ARB:
curGLXAttr = GLX_STEREO;
break;
case WGL_AUX_BUFFERS_ARB:
curGLXAttr = GLX_AUX_BUFFERS;
break;
case WGL_RED_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cRedShift;
continue;
case WGL_GREEN_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cGreenShift;
continue;
case WGL_BLUE_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cBlueShift;
continue;
case WGL_ALPHA_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cAlphaShift;
continue;
case WGL_SUPPORT_GDI_ARB:
if (!fmt) goto pix_error;
piValues[i] = (fmt->dwFlags & PFD_SUPPORT_GDI) != 0;
continue;
case WGL_DRAW_TO_BITMAP_ARB:
if (!fmt) goto pix_error;
piValues[i] = (fmt->dwFlags & PFD_DRAW_TO_BITMAP) != 0;
continue;
case WGL_DRAW_TO_WINDOW_ARB:
case WGL_DRAW_TO_PBUFFER_ARB:
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
if (hTest) goto get_error;
if((curWGLAttr == WGL_DRAW_TO_WINDOW_ARB && (tmp&GLX_WINDOW_BIT)) ||
(curWGLAttr == WGL_DRAW_TO_PBUFFER_ARB && (tmp&GLX_PBUFFER_BIT)))
piValues[i] = GL_TRUE;
else
piValues[i] = GL_FALSE;
continue;
case WGL_SWAP_METHOD_ARB:
if (has_swap_method)
{
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_SWAP_METHOD_OML, &tmp);
if (hTest) goto get_error;
switch (tmp)
{
case GLX_SWAP_EXCHANGE_OML:
piValues[i] = WGL_SWAP_EXCHANGE_ARB;
break;
case GLX_SWAP_COPY_OML:
piValues[i] = WGL_SWAP_COPY_ARB;
break;
case GLX_SWAP_UNDEFINED_OML:
piValues[i] = WGL_SWAP_UNDEFINED_ARB;
break;
default:
ERR("Unexpected swap method %x.\n", tmp);
}
}
else
{
WARN("GLX_OML_swap_method not supported, returning WGL_SWAP_EXCHANGE_ARB.\n");
piValues[i] = WGL_SWAP_EXCHANGE_ARB;
}
continue;
case WGL_PBUFFER_LARGEST_ARB:
curGLXAttr = GLX_LARGEST_PBUFFER;
break;
case WGL_SAMPLE_BUFFERS_ARB:
curGLXAttr = GLX_SAMPLE_BUFFERS_ARB;
break;
case WGL_SAMPLES_ARB:
curGLXAttr = GLX_SAMPLES_ARB;
break;
case WGL_FLOAT_COMPONENTS_NV:
curGLXAttr = GLX_FLOAT_COMPONENTS_NV;
break;
case WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT:
curGLXAttr = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT;
break;
case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
curGLXAttr = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
break;
case WGL_ACCUM_RED_BITS_ARB:
curGLXAttr = GLX_ACCUM_RED_SIZE;
break;
case WGL_ACCUM_GREEN_BITS_ARB:
curGLXAttr = GLX_ACCUM_GREEN_SIZE;
break;
case WGL_ACCUM_BLUE_BITS_ARB:
curGLXAttr = GLX_ACCUM_BLUE_SIZE;
break;
case WGL_ACCUM_ALPHA_BITS_ARB:
curGLXAttr = GLX_ACCUM_ALPHA_SIZE;
break;
case WGL_ACCUM_BITS_ARB:
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] = tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
continue;
default:
FIXME("unsupported %x WGL Attribute\n", curWGLAttr);
}
/* Retrieve a GLX FBConfigAttrib when the attribute to query is valid and
* iPixelFormat != 0. When iPixelFormat is 0 the only value which makes
* sense to query is WGL_NUMBER_PIXEL_FORMATS_ARB.
*
* TODO: properly test the behavior of wglGetPixelFormatAttrib*v on Windows
* and check which options can work using iPixelFormat=0 and which not.
* A problem would be that this function is an extension. This would
* mean that the behavior could differ between different vendors (ATI, Nvidia, ..).
*/
if (0 != curGLXAttr && iPixelFormat != 0) {
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, piValues + i);
if (hTest) goto get_error;
curGLXAttr = 0;
} else {
piValues[i] = GL_FALSE;
}
}
return GL_TRUE;
get_error:
ERR("(%p): unexpected failure on GetFBConfigAttrib(%x) returns FALSE\n", hdc, curGLXAttr);
return GL_FALSE;
pix_error:
ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nb_pixel_formats);
return GL_FALSE;
}
/**
* X11DRV_wglGetPixelFormatAttribfvARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
*/
static BOOL X11DRV_wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, FLOAT *pfValues )
{
int *attr;
int ret;
UINT i;
TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
/* Allocate a temporary array to store integer values */
attr = malloc( nAttributes * sizeof(int) );
if (!attr) {
ERR("couldn't allocate %d array\n", nAttributes);
return GL_FALSE;
}
/* Piggy-back on wglGetPixelFormatAttribivARB */
ret = X11DRV_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
if (ret) {
/* Convert integer values to float. Should also check for attributes
that can give decimal values here */
for (i=0; i<nAttributes;i++) {
pfValues[i] = attr[i];
}
}
free( attr );
return ret;
}
/**
* X11DRV_wglBindTexImageARB
*
@ -3260,8 +3013,8 @@ static void X11DRV_WineGL_LoadExtensions(void)
register_extension( "WGL_ARB_pixel_format" );
opengl_funcs.ext.p_wglChoosePixelFormatARB = X11DRV_wglChoosePixelFormatARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = X11DRV_wglGetPixelFormatAttribfvARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = X11DRV_wglGetPixelFormatAttribivARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
if (has_extension( glxExtensions, "GLX_ARB_fbconfig_float"))
{
@ -3445,7 +3198,7 @@ static void glxdrv_get_pixel_formats( struct wgl_pixel_format *formats,
if (formats)
{
for (i = 0; i < min( max_formats, nb_pixel_formats ); ++i)
describe_pixel_format( i + 1, &formats[i].pfd );
describe_pixel_format( i + 1, &formats[i] );
}
*num_formats = nb_pixel_formats;
*num_onscreen_formats = nb_onscreen_formats;

View File

@ -49,6 +49,8 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#include "wine/vulkan_driver.h"
static void *xrandr_handle;
static void *vulkan_handle;
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
MAKE_FUNCPTR(XRRConfigCurrentConfiguration)
@ -136,6 +138,45 @@ sym_not_found:
return r;
}
#ifdef SONAME_LIBVULKAN
static void vulkan_init_once(void)
{
if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW )))
{
ERR( "Failed to load %s\n", SONAME_LIBVULKAN );
return;
}
#define LOAD_FUNCPTR( f ) \
if (!(p_##f = dlsym( vulkan_handle, #f ))) \
{ \
ERR( "Failed to find " #f "\n" ); \
dlclose( vulkan_handle ); \
vulkan_handle = NULL; \
return; \
}
LOAD_FUNCPTR( vkGetInstanceProcAddr );
#undef LOAD_FUNCPTR
}
#else /* SONAME_LIBVULKAN */
static void vulkan_init_once(void)
{
ERR( "Wine was built without Vulkan support.\n" );
}
#endif /* SONAME_LIBVULKAN */
static BOOL vulkan_init(void)
{
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
pthread_once( &init_once, vulkan_init_once );
return !!vulkan_handle;
}
static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
{
return 1;
@ -641,11 +682,11 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
"VK_KHR_display",
VK_KHR_SURFACE_EXTENSION_NAME,
};
const struct vulkan_funcs *vulkan_funcs = __wine_get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION );
VkResult (*pvkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
uint32_t device_count, device_idx, output_idx, i;
PFN_vkDestroyInstance pvkDestroyInstance = NULL;
VkPhysicalDevice *vk_physical_devices = NULL;
VkPhysicalDeviceProperties2 properties2;
PFN_vkCreateInstance pvkCreateInstance;
@ -656,8 +697,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
BOOL ret = FALSE;
VkResult vr;
if (!vulkan_funcs)
goto done;
if (!vulkan_init()) goto done;
memset( &create_info, 0, sizeof(create_info) );
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -665,7 +705,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
create_info.ppEnabledExtensionNames = extensions;
#define LOAD_VK_FUNC(f) \
if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr( vk_instance, #f ))) \
if (!(p##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
{ \
WARN("Failed to load " #f ".\n"); \
goto done; \
@ -683,6 +723,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
LOAD_VK_FUNC(vkGetRandROutputDisplayEXT)
LOAD_VK_FUNC(vkDestroyInstance)
#undef LOAD_VK_FUNC
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, NULL );
@ -747,12 +788,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
done:
free( vk_physical_devices );
if (vk_instance)
{
PFN_vkDestroyInstance p_vkDestroyInstance;
p_vkDestroyInstance = vulkan_funcs->p_vkGetInstanceProcAddr( vk_instance, "vkDestroyInstance" );
p_vkDestroyInstance( vk_instance, NULL );
}
if (vk_instance && pvkDestroyInstance) pvkDestroyInstance( vk_instance, NULL );
return ret;
}

View File

@ -3016,9 +3016,7 @@ struct get_serial_info_reply
{
struct reply_header __header;
unsigned int eventmask;
unsigned int cookie;
unsigned int pending_write;
char __pad_20[4];
};
@ -3035,7 +3033,6 @@ struct set_serial_info_reply
struct reply_header __header;
};
#define SERIALINFO_PENDING_WRITE 0x04
#define SERIALINFO_PENDING_WAIT 0x08
struct cancel_sync_request
@ -6534,7 +6531,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 806
#define SERVER_PROTOCOL_VERSION 808
/* ### protocol_version end ### */

View File

@ -7,7 +7,7 @@
#define WINE_GLAPI
#endif
#define WINE_WGL_DRIVER_VERSION 25
#define WINE_WGL_DRIVER_VERSION 26
struct wgl_context;
struct wgl_pbuffer;
@ -15,6 +15,31 @@ struct wgl_pbuffer;
struct wgl_pixel_format
{
PIXELFORMATDESCRIPTOR pfd;
int swap_method;
int transparent;
int pixel_type;
int draw_to_pbuffer;
int max_pbuffer_pixels;
int max_pbuffer_width;
int max_pbuffer_height;
int transparent_red_value;
int transparent_red_value_valid;
int transparent_green_value;
int transparent_green_value_valid;
int transparent_blue_value;
int transparent_blue_value_valid;
int transparent_alpha_value;
int transparent_alpha_value_valid;
int transparent_index_value;
int transparent_index_value_valid;
int sample_buffers;
int samples;
int bind_to_texture_rgb;
int bind_to_texture_rgba;
int bind_to_texture_rectangle_rgb;
int bind_to_texture_rectangle_rgba;
int framebuffer_srgb_capable;
int float_components;
};
struct opengl_funcs

View File

@ -815,17 +815,35 @@ typedef struct DECLSPEC_ALIGN(8) MEM_EXTENDED_PARAMETER {
#define MEM_EXTENDED_PARAMETER_EC_CODE 0x00000040
#define MEM_EXTENDED_PARAMETER_IMAGE_NO_HPAT 0x00000080
#define PAGE_NOACCESS 0x01
#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
#define PAGE_NOACCESS 0x00000001
#define PAGE_READONLY 0x00000002
#define PAGE_READWRITE 0x00000004
#define PAGE_WRITECOPY 0x00000008
#define PAGE_EXECUTE 0x00000010
#define PAGE_EXECUTE_READ 0x00000020
#define PAGE_EXECUTE_READWRITE 0x00000040
#define PAGE_EXECUTE_WRITECOPY 0x00000080
#define PAGE_GUARD 0x00000100
#define PAGE_NOCACHE 0x00000200
#define PAGE_WRITECOMBINE 0x00000400
#define PAGE_GRAPHICS_NOACCESS 0x00000800
#define PAGE_GRAPHICS_READONLY 0x00001000
#define PAGE_GRAPHICS_READWRITE 0x00002000
#define PAGE_GRAPHICS_EXECUTE 0x00004000
#define PAGE_GRAPHICS_EXECUTE_READ 0x00008000
#define PAGE_GRAPHICS_EXECUTE_READWRITE 0x00010000
#define PAGE_GRAPHICS_COHERENT 0x00020000
#define PAGE_GRAPHICS_NOCACHE 0x00040000
#define PAGE_ENCLAVE_MASK 0x10000000
#define PAGE_ENCLAVE_UNVALIDATED 0x20000000
#define PAGE_ENCLAVE_NO_CHANGE 0x20000000
#define PAGE_TARGETS_NO_UPDATE 0x40000000
#define PAGE_TARGETS_INVALID 0x40000000
#define PAGE_REVERT_TO_FILE_MAP 0x80000000
#define PAGE_ENCLAVE_THREAD_CONTROL 0x80000000
#define PAGE_ENCLAVE_DECOMMIT (PAGE_ENCLAVE_MASK | 0)
#define PAGE_ENCLAVE_SS_FIRST (PAGE_ENCLAVE_MASK | 1)
#define PAGE_ENCLAVE_SS_REST (PAGE_ENCLAVE_MASK | 2)
#define MEM_COMMIT 0x00001000
#define MEM_RESERVE 0x00002000

View File

@ -1546,8 +1546,8 @@ void WCMD_echo (const WCHAR *args)
* first command to be executed may not be at the front of the
* commands->thiscommand string (eg. it may point after a DO or ELSE)
*/
static void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds)
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds)
{
CMD_NODE *curPosition = *cmdList;
int myDepth = CMD_node_get_depth(*cmdList);
@ -1850,11 +1850,11 @@ static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk)
* are recursively passed. If any have duplicates, then the * token should
* not be honoured.
*/
static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates)
int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates)
{
WCHAR *pos = tokenstr;
const WCHAR *pos = tokenstr;
int nexttoken = -1;
if (totalfound) *totalfound = 0;
@ -2136,7 +2136,7 @@ static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
*
*/
void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
static void WCMD_for_OLD (WCHAR *p, CMD_NODE **cmdList) {
WIN32_FIND_DATAW fd;
HANDLE hff;
@ -2541,6 +2541,32 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
if (cmdEnd && CMD_node_get_command(cmdEnd)->command == NULL) *cmdList = CMD_node_next(cmdEnd);
}
void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
{
CMD_FOR_CONTROL *for_ctrl;
for_ctrl = for_control_parse(p);
if (!for_ctrl)
{
/* temporary code: use OLD code for non migrated FOR constructs */
WCMD_for_OLD(p, cmdList);
return;
}
for (*cmdList = CMD_node_next(*cmdList); /* swallow options */
*cmdList && CMD_node_get_command(*cmdList)->command != NULL;
*cmdList = CMD_node_next(*cmdList))
{
for_control_append_set(for_ctrl, CMD_node_get_command(*cmdList)->command);
}
/* step over terminating NULL CMD_NODE of set */
*cmdList = CMD_node_next(*cmdList);
for_control_execute(for_ctrl, cmdList);
for_control_dispose(for_ctrl);
}
/**************************************************************************
* WCMD_give_help
*

View File

@ -757,11 +757,6 @@ setlocal EnableDelayedExpansion
set WINE_FOO=foo bar
for %%i in ("!WINE_FOO!") do echo %%i
for %%i in (!WINE_FOO!) do echo %%i
rem tests disabled for now... wine's cmd loops endlessly here
rem set WINE_FOO=4 4 4
rem for /l %%i in (!WINE_FOO!) do echo %%i
rem set WINE_FOO=4
rem for /l %%i in (1 2 !WINE_FOO!) do echo %%i
setlocal DisableDelayedExpansion
echo --- in digit variables

View File

@ -1014,21 +1014,21 @@ A D
B C
B D
--- nested FORs and args tempering
@todo_wine@inner argument {-foo, bar}
@todo_wine@inner argument {-x, y}
inner argument {-foo, bar}
inner argument {-x, y}
--- nesting and delayed expansion
a 1 2
@todo_wine@1-A2
@todo_wine@1-B1
@todo_wine@2-A1
@todo_wine@2-B2
@todo_wine@b 1 3
@todo_wine@1-A2
@todo_wine@1-B1
@todo_wine@2-A2
@todo_wine@2-B2
@todo_wine@3-A1
@todo_wine@3-B2
1-A2
1-B1
2-A1
2-B2
b 1 3
1-A2
1-B1
2-A2
2-B2
3-A1
3-B2
--- nesting if/for
@todo_wine@"f"
@todo_wine@"g"
@ -1385,7 +1385,7 @@ h=%h i=b j=c k= l= m=%m n=%n o=%o@or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
h=%h i=b j=c k= l= m=%m n=%n o=%o@or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
1:3.14,%B
2:3.14,
@todo_wine@4:3,14
4:3,14
------ parameter splitting
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@

View File

@ -83,6 +83,27 @@ typedef struct _CMD_IF_CONDITION
};
} CMD_IF_CONDITION;
typedef struct _CMD_FOR_CONTROL
{
enum for_control_operator {
CMD_FOR_FILE_SET /* /F */,
CMD_FOR_NUMBERS /* /L */} operator;
unsigned flags; /* |-ed CMD_FOR_FLAG_* */
int variable_index;
const WCHAR *set;
union
{
struct /* for CMD_FOR_FILE_SET */
{
WCHAR eol;
BOOL use_backq;
int num_lines_to_skip;
const WCHAR *delims;
const WCHAR *tokens;
};
};
} CMD_FOR_CONTROL;
typedef struct _CMD_COMMAND
{
WCHAR *command; /* Command string to execute */
@ -129,6 +150,21 @@ void if_condition_dispose(CMD_IF_CONDITION *);
BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test);
const char *debugstr_if_condition(const CMD_IF_CONDITION *cond);
void for_control_create(enum for_control_operator for_op, unsigned flags, const WCHAR *options, int var_idx, CMD_FOR_CONTROL *for_ctrl);
void for_control_create_fileset(unsigned flags, int var_idx, WCHAR eol, int num_lines_to_skip, BOOL use_backq,
const WCHAR *delims, const WCHAR *tokens,
CMD_FOR_CONTROL *for_ctrl);
CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var);
void for_control_append_set(CMD_FOR_CONTROL *for_ctrl, const WCHAR *string);
void for_control_dump(const CMD_FOR_CONTROL *for_ctrl);
void for_control_dispose(CMD_FOR_CONTROL *for_ctrl);
void for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE **cmdList);
int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates);
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds);
void WCMD_assoc (const WCHAR *, BOOL);
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
void WCMD_call (WCHAR *command);

View File

@ -991,6 +991,94 @@ static void command_dispose(CMD_COMMAND *cmd)
}
}
void for_control_dispose(CMD_FOR_CONTROL *for_ctrl)
{
free((void*)for_ctrl->set);
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
free((void*)for_ctrl->delims);
free((void*)for_ctrl->tokens);
break;
default:
break;
}
}
const char *debugstr_for_control(const CMD_FOR_CONTROL *for_ctrl)
{
static const char* for_ctrl_strings[] = {"file", "numbers"};
const char *flags, *options;
if (for_ctrl->operator >= ARRAY_SIZE(for_ctrl_strings))
{
FIXME("Unexpected operator\n");
return wine_dbg_sprintf("<<%u>>", for_ctrl->operator);
}
flags = "";
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
{
WCHAR eol_buf[4] = {L'\'', for_ctrl->eol, L'\'', L'\0'};
const WCHAR *eol = for_ctrl->eol ? eol_buf : L"<nul>";
options = wine_dbg_sprintf("eol=%ls skip=%d use_backq=%c delims=%s tokens=%s ",
eol, for_ctrl->num_lines_to_skip, for_ctrl->use_backq ? 'Y' : 'N',
wine_dbgstr_w(for_ctrl->delims), wine_dbgstr_w(for_ctrl->tokens));
}
break;
default:
options = "";
break;
}
return wine_dbg_sprintf("[FOR] %s %s%s%%%c (%ls)",
for_ctrl_strings[for_ctrl->operator], flags, options,
for_var_index_to_char(for_ctrl->variable_index), for_ctrl->set);
}
void for_control_create(enum for_control_operator for_op, unsigned flags, const WCHAR *options, int var_idx, CMD_FOR_CONTROL *for_ctrl)
{
for_ctrl->operator = for_op;
for_ctrl->flags = flags;
for_ctrl->variable_index = var_idx;
for_ctrl->set = NULL;
switch (for_ctrl->operator)
{
default:
break;
}
}
void for_control_create_fileset(unsigned flags, int var_idx, WCHAR eol, int num_lines_to_skip, BOOL use_backq,
const WCHAR *delims, const WCHAR *tokens,
CMD_FOR_CONTROL *for_ctrl)
{
for_ctrl->operator = CMD_FOR_FILE_SET;
for_ctrl->flags = flags;
for_ctrl->variable_index = var_idx;
for_ctrl->set = NULL;
for_ctrl->eol = eol;
for_ctrl->use_backq = use_backq;
for_ctrl->num_lines_to_skip = num_lines_to_skip;
for_ctrl->delims = delims;
for_ctrl->tokens = tokens;
}
void for_control_append_set(CMD_FOR_CONTROL *for_ctrl, const WCHAR *set)
{
if (for_ctrl->set)
{
for_ctrl->set = xrealloc((void*)for_ctrl->set,
(wcslen(for_ctrl->set) + 1 + wcslen(set) + 1) * sizeof(WCHAR));
wcscat((WCHAR*)for_ctrl->set, L" ");
wcscat((WCHAR*)for_ctrl->set, set);
}
else
for_ctrl->set = xstrdupW(set);
}
/***************************************************************************
* node_dispose_tree
*
@ -2093,6 +2181,170 @@ static BOOL WCMD_IsEndQuote(const WCHAR *quote, int quoteIndex)
return FALSE;
}
static WCHAR *for_fileset_option_split(WCHAR *from, const WCHAR* key)
{
size_t len = wcslen(key);
if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
from, len, key, len) != CSTR_EQUAL)
return NULL;
from += len;
if (len && key[len - 1] == L'=')
while (*from && *from != L' ' && *from != L'\t') from++;
return from;
}
CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var)
{
CMD_FOR_CONTROL *for_ctrl;
enum for_control_operator for_op;
WCHAR mode = L' ', option;
WCHAR options[MAXSTRING];
WCHAR *arg;
unsigned flags = 0;
int arg_index;
int var_idx;
options[0] = L'\0';
/* native allows two options only in the /D /R case, a repetition of the option
* and prints an error otherwise
*/
for (arg_index = 0; ; arg_index++)
{
arg = WCMD_parameter(opts_var, arg_index, NULL, FALSE, FALSE);
if (!arg || *arg != L'/') break;
option = towupper(arg[1]);
if (mode != L' ' && (mode != L'D' || option != 'R') && mode != option)
break;
switch (option)
{
case L'R':
if (mode == L'D')
{
mode = L'X';
break;
}
/* fall thru */
case L'D':
case L'L':
case L'F':
mode = option;
break;
default:
/* error unexpected 'arg' at this time */
WARN("for qualifier '%c' unhandled\n", *arg);
goto syntax_error;
}
}
switch (mode)
{
case L'L':
for_op = CMD_FOR_NUMBERS;
break;
case L'F':
for_op = CMD_FOR_FILE_SET;
break;
default:
return NULL;
}
if (mode == L'F')
{
/* Retrieve next parameter to see if is root/options (raw form required
* with for /f, or unquoted in for /r)
*/
arg = WCMD_parameter(opts_var, arg_index, NULL, for_op == CMD_FOR_FILE_SET, FALSE);
/* Next parm is either qualifier, path/options or variable -
* only care about it if it is the path/options
*/
if (arg && *arg != L'/' && *arg != L'%')
{
arg_index++;
wcscpy(options, arg);
}
}
/* Ensure line continues with variable */
arg = WCMD_parameter(opts_var, arg_index++, NULL, FALSE, FALSE);
if (!arg || *arg != L'%' || (var_idx = for_var_char_to_index(arg[1])) == -1)
goto syntax_error; /* FIXME native prints the offending token "%<whatever>" was unexpected at this time */
for_ctrl = xalloc(sizeof(*for_ctrl));
if (for_op == CMD_FOR_FILE_SET)
{
size_t len = wcslen(options);
WCHAR *p = options, *end;
WCHAR eol = L'\0';
int num_lines_to_skip = 0;
BOOL use_backq = FALSE;
WCHAR *delims = NULL, *tokens = NULL;
/* strip enclosing double-quotes when present */
if (len >= 2 && p[0] == L'"' && p[len - 1] == L'"')
{
p[len - 1] = L'\0';
p++;
}
for ( ; *p; p = end)
{
p = WCMD_skip_leading_spaces(p);
/* Save End of line character (Ignore line if first token (based on delims) starts with it) */
if ((end = for_fileset_option_split(p, L"eol=")))
{
/* assuming one char for eol marker */
if (end != p + 5) goto syntax_error;
eol = p[4];
}
/* Save number of lines to skip (Can be in base 10, hex (0x...) or octal (0xx) */
else if ((end = for_fileset_option_split(p, L"skip=")))
{
WCHAR *nextchar;
num_lines_to_skip = wcstoul(p + 5, &nextchar, 0);
if (end != nextchar) goto syntax_error;
}
/* Save if usebackq semantics are in effect */
else if ((end = for_fileset_option_split(p, L"usebackq")))
use_backq = TRUE;
/* Save the supplied delims */
else if ((end = for_fileset_option_split(p, L"delims=")))
{
size_t copy_len;
/* interpret space when last character of whole options string as part of delims= */
if (end[0] && !end[1]) end++;
copy_len = end - (p + 7) /* delims= */;
delims = xalloc((copy_len + 1) * sizeof(WCHAR));
memcpy(delims, p + 7, copy_len * sizeof(WCHAR));
delims[copy_len] = L'\0';
}
/* Save the tokens being requested */
else if ((end = for_fileset_option_split(p, L"tokens=")))
{
size_t copy_len;
copy_len = end - (p + 7) /* tokens= */;
tokens = xalloc((copy_len + 1) * sizeof(WCHAR));
memcpy(tokens, p + 7, copy_len * sizeof(WCHAR));
tokens[copy_len] = L'\0';
}
else
{
WARN("FOR option not found %ls\n", p);
goto syntax_error;
}
}
for_control_create_fileset(flags, var_idx, eol, num_lines_to_skip, use_backq,
delims ? delims : xstrdupW(L" \t"),
tokens ? tokens : xstrdupW(L"1"), for_ctrl);
}
else
for_control_create(for_op, flags, options, var_idx, for_ctrl);
return for_ctrl;
syntax_error:
WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR));
return NULL;
}
/***************************************************************************
* WCMD_ReadAndParseLine
*
@ -2710,6 +2962,97 @@ BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test)
return TRUE;
}
static CMD_NODE *for_loop_fileset_parse_line(CMD_NODE *cmdList, int varidx, WCHAR *buffer,
WCHAR forf_eol, const WCHAR *forf_delims, const WCHAR *forf_tokens)
{
WCHAR *parm;
int varoffset;
int nexttoken, lasttoken = -1;
BOOL starfound = FALSE;
BOOL thisduplicate = FALSE;
BOOL anyduplicates = FALSE;
int totalfound;
static WCHAR emptyW[] = L"";
/* Extract the parameters based on the tokens= value (There will always
be some value, as if it is not supplied, it defaults to tokens=1).
Rough logic:
Count how many tokens are named in the line, identify the lowest
Empty (set to null terminated string) that number of named variables
While lasttoken != nextlowest
%letter = parameter number 'nextlowest'
letter++ (if >26 or >52 abort)
Go through token= string finding next lowest number
If token ends in * set %letter = raw position of token(nextnumber+1)
*/
lasttoken = -1;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound,
&starfound, &thisduplicate);
TRACE("Using var=%lc on %d max\n", for_var_index_to_char(varidx), totalfound);
/* Empty out variables */
for (varoffset = 0;
varoffset < totalfound && for_var_index_in_range(varidx, varoffset);
varoffset++)
WCMD_set_for_loop_variable(varidx + varoffset, emptyW);
/* Loop extracting the tokens
* Note: nexttoken of 0 means there were no tokens requested, to handle
* the special case of tokens=*
*/
varoffset = 0;
TRACE("Parsing buffer into tokens: '%s'\n", wine_dbgstr_w(buffer));
while (nexttoken > 0 && (nexttoken > lasttoken))
{
anyduplicates |= thisduplicate;
if (!for_var_index_in_range(varidx, varoffset))
{
WARN("Out of range offset\n");
break;
}
/* Extract the token number requested and set into the next variable context */
parm = WCMD_parameter_with_delims(buffer, (nexttoken-1), NULL, TRUE, FALSE, forf_delims);
TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken,
varidx + varoffset, wine_dbgstr_w(parm));
if (parm)
{
WCMD_set_for_loop_variable(varidx + varoffset, parm);
varoffset++;
}
/* Find the next token */
lasttoken = nexttoken;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, NULL,
&starfound, &thisduplicate);
}
/* If all the rest of the tokens were requested, and there is still space in
* the variable range, write them now
*/
if (!anyduplicates && starfound && for_var_index_in_range(varidx, varoffset))
{
nexttoken++;
WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims);
TRACE("Parsed all remaining tokens (%d) as parameter %s\n",
varidx + varoffset, wine_dbgstr_w(parm));
if (parm)
WCMD_set_for_loop_variable(varidx + varoffset, parm);
}
/* Execute the body of the for loop with these values */
if (forloopcontext->variable[varidx] && forloopcontext->variable[varidx][0] != forf_eol)
{
/* +3 for "do " */
WCMD_part_execute(&cmdList, CMD_node_get_command(cmdList)->command + 3, FALSE, TRUE);
}
else
{
TRACE("Skipping line because of eol\n");
cmdList = NULL;
}
return cmdList;
}
void WCMD_save_for_loop_context(BOOL reset)
{
FOR_CONTEXT *new = xalloc(sizeof(*new));
@ -2748,6 +3091,179 @@ void WCMD_set_for_loop_variable(int var_idx, const WCHAR *value)
forloopcontext->variable[var_idx] = xstrdupW(value);
}
static BOOL match_ending_delim(WCHAR *string)
{
WCHAR *to = string + wcslen(string);
/* strip trailing delim */
if (to > string) to--;
if (to > string && *to == string[0])
{
*to = L'\0';
return TRUE;
}
WARN("Can't find ending delimiter (%ls)\n", string);
return FALSE;
}
static CMD_NODE *for_control_execute_from_FILE(CMD_FOR_CONTROL *for_ctrl, FILE *input, CMD_NODE *cmdList)
{
WCHAR buffer[MAXSTRING];
int skip_count = for_ctrl->num_lines_to_skip;
CMD_NODE *body = NULL;
/* Read line by line until end of file */
while (fgetws(buffer, ARRAY_SIZE(buffer), input))
{
size_t len;
if (skip_count)
{
TRACE("skipping %d\n", skip_count);
skip_count--;
continue;
}
len = wcslen(buffer);
/* Either our buffer isn't large enough to fit a full line, or there's a stray
* '\0' in the buffer.
*/
if (!feof(input) && (len == 0 || (buffer[len - 1] != '\n' && buffer[len - 1] != '\r')))
break;
while (len && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r'))
buffer[--len] = L'\0';
body = for_loop_fileset_parse_line(cmdList, for_ctrl->variable_index, buffer,
for_ctrl->eol, for_ctrl->delims, for_ctrl->tokens);
buffer[0] = 0;
}
return body;
}
static CMD_NODE *for_control_execute_fileset(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
{
WCHAR set[MAXSTRING];
WCHAR *args;
size_t len;
CMD_NODE *body = NULL;
FILE *input;
int i;
wcscpy(set, for_ctrl->set);
handleExpansion(set, context != NULL, delayedsubst);
args = WCMD_skip_leading_spaces(set);
for (len = wcslen(args); len && (args[len - 1] == L' ' || args[len - 1] == L'\t'); len--)
args[len - 1] = L'\0';
if (args[0] == (for_ctrl->use_backq ? L'\'' : L'"') && match_ending_delim(args))
{
args++;
if (!for_ctrl->num_lines_to_skip)
{
body = for_loop_fileset_parse_line(cmdList, for_ctrl->variable_index, args,
for_ctrl->eol, for_ctrl->delims, for_ctrl->tokens);
}
}
else if (args[0] == (for_ctrl->use_backq ? L'`' : L'\'') && match_ending_delim(args))
{
WCHAR temp_cmd[MAX_PATH];
args++;
wsprintfW(temp_cmd, L"CMD.EXE /C %s", args);
TRACE("Reading output of '%s'\n", wine_dbgstr_w(temp_cmd));
input = _wpopen(temp_cmd, L"rt,ccs=unicode");
if (!input)
{
WCMD_print_error();
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), args);
errorlevel = 1;
return NULL; /* FOR loop aborts at first failure here */
}
body = for_control_execute_from_FILE(for_ctrl, input, cmdList);
fclose(input);
}
else
{
for (i = 0; ; i++)
{
WCHAR *element = WCMD_parameter(args, i, NULL, TRUE, FALSE);
if (!element || !*element) break;
if (element[0] == L'"' && match_ending_delim(element)) element++;
/* Open the file, read line by line and process */
TRACE("Reading input to parse from '%s'\n", wine_dbgstr_w(element));
input = _wfopen(element, L"rt,ccs=unicode");
if (!input)
{
WCMD_print_error();
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), element);
errorlevel = 1;
return NULL; /* FOR loop aborts at first failure here */
}
body = for_control_execute_from_FILE(for_ctrl, input, cmdList);
fclose(input);
}
}
return body;
}
static CMD_NODE *for_control_execute_numbers(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
{
WCHAR set[MAXSTRING];
CMD_NODE *body = NULL;
int numbers[3] = {0, 0, 0}, var;
int i;
wcscpy(set, for_ctrl->set);
handleExpansion(set, context != NULL, delayedsubst);
/* Note: native doesn't check the actual number of parameters, and set
* them by default to 0.
* so (-10 1) is interpreted as (-10 1 0)
* and (10) loops for ever !!!
*/
for (i = 0; i < ARRAY_SIZE(numbers); i++)
{
WCHAR *element = WCMD_parameter(set, i, NULL, FALSE, FALSE);
if (!element || !*element) break;
/* native doesn't no error handling */
numbers[i] = wcstol(element, NULL, 0);
}
for (var = numbers[0];
(numbers[1] < 0) ? var >= numbers[2] : var <= numbers[2];
var += numbers[1])
{
WCHAR tmp[32];
body = cmdList;
swprintf(tmp, ARRAY_SIZE(tmp), L"%d", var);
WCMD_set_for_loop_variable(for_ctrl->variable_index, tmp);
TRACE("Processing FOR number %s\n", wine_dbgstr_w(tmp));
WCMD_part_execute(&body, CMD_node_get_command(cmdList)->command + 3, FALSE, TRUE);
}
return body;
}
void for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE **cmdList)
{
CMD_NODE *last;
WCMD_save_for_loop_context(FALSE);
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
last = for_control_execute_fileset(for_ctrl, *cmdList);
break;
case CMD_FOR_NUMBERS:
last = for_control_execute_numbers(for_ctrl, *cmdList);
break;
default:
last = NULL;
break;
}
WCMD_restore_for_loop_context();
*cmdList = last;
}
/***************************************************************************
* WCMD_process_commands
*

View File

@ -2245,7 +2245,6 @@ enum message_type
int flags;
@REPLY
unsigned int eventmask;
unsigned int cookie;
unsigned int pending_write;
@END
@ -2256,7 +2255,6 @@ enum message_type
int flags; /* bitmask to set values (see below) */
@END
#define SERIALINFO_PENDING_WRITE 0x04
#define SERIALINFO_PENDING_WAIT 0x08
/* Cancel all sync io on a thread */
@REQ(cancel_sync)

View File

@ -1455,9 +1455,8 @@ C_ASSERT( FIELD_OFFSET(struct get_serial_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_serial_info_request, flags) == 16 );
C_ASSERT( sizeof(struct get_serial_info_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, eventmask) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, cookie) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, pending_write) == 16 );
C_ASSERT( sizeof(struct get_serial_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, pending_write) == 12 );
C_ASSERT( sizeof(struct get_serial_info_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, flags) == 16 );
C_ASSERT( sizeof(struct set_serial_info_request) == 24 );

View File

@ -76,9 +76,7 @@ struct serial
struct timeout_user *read_timer;
SERIAL_TIMEOUTS timeouts;
unsigned int eventmask;
unsigned int generation; /* event mask change counter */
unsigned int pending_write : 1;
unsigned int pending_wait : 1;
struct termios original;
@ -142,9 +140,7 @@ struct object *create_serial( struct fd *fd )
serial->read_timer = NULL;
serial->eventmask = 0;
serial->generation = 0;
serial->pending_write = 0;
serial->pending_wait = 0;
memset( &serial->timeouts, 0, sizeof(serial->timeouts) );
init_async_queue( &serial->wait_q );
serial->fd = (struct fd *)grab_object( fd );
@ -242,14 +238,19 @@ static void serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async
return;
}
serial->eventmask = *(unsigned int *)get_req_data();
serial->generation++;
fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
async_wake_up( &serial->wait_q, STATUS_CANCELLED );
return;
case IOCTL_SERIAL_WAIT_ON_MASK:
{
struct wait_req *req;
if (async_queued( &serial->wait_q ))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (!(req = mem_alloc(sizeof(*req))))
return;
@ -329,20 +330,8 @@ DECL_HANDLER(get_serial_info)
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
{
if (req->flags & SERIALINFO_PENDING_WAIT)
{
if (serial->pending_wait)
{
release_object( serial );
set_error( STATUS_INVALID_PARAMETER );
return;
}
serial->pending_wait = 1;
}
/* event mask */
reply->eventmask = serial->eventmask;
reply->cookie = serial->generation;
/* pending write */
reply->pending_write = serial->pending_write;
@ -359,18 +348,6 @@ DECL_HANDLER(set_serial_info)
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
{
if (req->flags & SERIALINFO_PENDING_WAIT)
{
if (!serial->pending_wait)
{
release_object( serial );
set_error( STATUS_INVALID_PARAMETER );
return;
}
serial->pending_wait = 0;
}
/* pending write */
if (req->flags & SERIALINFO_PENDING_WRITE)
serial->pending_write = 1;

View File

@ -2856,7 +2856,6 @@ static void dump_get_serial_info_request( const struct get_serial_info_request *
static void dump_get_serial_info_reply( const struct get_serial_info_reply *req )
{
fprintf( stderr, " eventmask=%08x", req->eventmask );
fprintf( stderr, ", cookie=%08x", req->cookie );
fprintf( stderr, ", pending_write=%08x", req->pending_write );
}