mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-01 19:52:48 +00:00
Compare commits
29 commits
96d294aa12
...
1953d1e774
Author | SHA1 | Date | |
---|---|---|---|
1953d1e774 | |||
1b702aea3c | |||
73f2e64fd4 | |||
c4a162a8fe | |||
1543fc8d1b | |||
640698e432 | |||
66ceeed861 | |||
fb523ed66f | |||
ed819cc973 | |||
427e848d0d | |||
02ca366b5a | |||
af565ce846 | |||
bb46d4a621 | |||
2ac86fb8c3 | |||
0a83c4f287 | |||
2e5b4ff32a | |||
8934fbcdbd | |||
35801043df | |||
3ecd3ff853 | |||
5b126f7806 | |||
6d6fee9dda | |||
2e2a3f4539 | |||
53f7a59992 | |||
9ba05f5e5b | |||
4a3365daff | |||
1200a80d76 | |||
898253af36 | |||
d72567c626 | |||
e4e5d22145 |
|
@ -153,6 +153,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
|
||||||
|
|
||||||
#define MACHO_CPU_TYPE_X86 0x00000007
|
#define MACHO_CPU_TYPE_X86 0x00000007
|
||||||
#define MACHO_CPU_TYPE_X86_64 0x01000007
|
#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_EXECUTE 0x2
|
||||||
#define MACHO_MH_DYLIB 0x6
|
#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: return IMAGE_FILE_MACHINE_I386;
|
||||||
case MACHO_CPU_TYPE_X86_64: return IMAGE_FILE_MACHINE_AMD64;
|
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:
|
default:
|
||||||
FIXME("Untranslated Mach-O CPU %x\n", cpu);
|
FIXME("Untranslated Mach-O CPU %x\n", cpu);
|
||||||
return IMAGE_FILE_MACHINE_UNKNOWN;
|
return IMAGE_FILE_MACHINE_UNKNOWN;
|
||||||
|
|
|
@ -797,26 +797,21 @@ static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBIT
|
||||||
if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
|
if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
|
||||||
return ICERR_BADFORMAT;
|
return ICERR_BADFORMAT;
|
||||||
|
|
||||||
switch( out->bmiHeader.biBitCount )
|
switch( out->bmiHeader.biCompression )
|
||||||
{
|
{
|
||||||
case 16:
|
case BI_RGB:
|
||||||
if ( out->bmiHeader.biCompression == BI_BITFIELDS )
|
if ( out->bmiHeader.biBitCount == 16 || out->bmiHeader.biBitCount == 24 || out->bmiHeader.biBitCount == 32 )
|
||||||
{
|
return ICERR_OK;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 24:
|
case BI_BITFIELDS:
|
||||||
case 32:
|
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;
|
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;
|
return ICERR_OK;
|
||||||
|
|
|
@ -604,7 +604,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
|
||||||
SIZE_T size, SIZE_T *bytes_written )
|
SIZE_T size, SIZE_T *bytes_written )
|
||||||
{
|
{
|
||||||
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
|
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
|
||||||
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | PAGE_EXECUTE_WRITECOPY;
|
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE;
|
||||||
MEMORY_BASIC_INFORMATION info;
|
MEMORY_BASIC_INFORMATION info;
|
||||||
void *base_addr;
|
void *base_addr;
|
||||||
SIZE_T region_size;
|
SIZE_T region_size;
|
||||||
|
@ -634,6 +634,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
|
||||||
base_addr = ROUND_ADDR( addr );
|
base_addr = ROUND_ADDR( addr );
|
||||||
region_size = ROUND_SIZE( addr, size );
|
region_size = ROUND_SIZE( addr, size );
|
||||||
region_size = min( region_size, (char *)info.BaseAddress + info.RegionSize - (char *)base_addr );
|
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,
|
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
|
||||||
base_addr, region_size, 1, prot );
|
base_addr, region_size, 1, prot );
|
||||||
|
|
|
@ -1274,6 +1274,7 @@ static void session_close(struct media_session *session)
|
||||||
switch (session->state)
|
switch (session->state)
|
||||||
{
|
{
|
||||||
case SESSION_STATE_STOPPED:
|
case SESSION_STATE_STOPPED:
|
||||||
|
case SESSION_STATE_RESTARTING_SOURCES:
|
||||||
hr = session_finalize_sinks(session);
|
hr = session_finalize_sinks(session);
|
||||||
break;
|
break;
|
||||||
case SESSION_STATE_STARTED:
|
case SESSION_STATE_STARTED:
|
||||||
|
@ -3192,8 +3193,15 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
|
||||||
break;
|
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);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -6249,6 +6249,8 @@ static void test_media_session_Start(void)
|
||||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
hr = IMFMediaSession_Close(session);
|
hr = IMFMediaSession_Close(session);
|
||||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
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 */
|
/* Media session is shut down */
|
||||||
hr = IMFMediaSource_Shutdown(source);
|
hr = IMFMediaSource_Shutdown(source);
|
||||||
|
@ -6331,6 +6333,8 @@ static void test_media_session_Start(void)
|
||||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
hr = IMFMediaSession_Close(session);
|
hr = IMFMediaSession_Close(session);
|
||||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
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);
|
hr = IMFMediaSession_Shutdown(session);
|
||||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
hr = IMFMediaSource_Shutdown(source);
|
hr = IMFMediaSource_Shutdown(source);
|
||||||
|
@ -6534,6 +6538,88 @@ static void test_MFEnumDeviceSources(void)
|
||||||
CoUninitialize();
|
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)
|
START_TEST(mf)
|
||||||
{
|
{
|
||||||
init_functions();
|
init_functions();
|
||||||
|
@ -6568,4 +6654,5 @@ START_TEST(mf)
|
||||||
test_MFCreateSequencerSegmentOffset();
|
test_MFCreateSequencerSegmentOffset();
|
||||||
test_media_session_Start();
|
test_media_session_Start();
|
||||||
test_MFEnumDeviceSources();
|
test_MFEnumDeviceSources();
|
||||||
|
test_media_session_Close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3585,6 +3585,8 @@ static void test_wma_decoder_dmo_output_type(void)
|
||||||
good_output_type = (void *)buffer_good_output;
|
good_output_type = (void *)buffer_good_output;
|
||||||
bad_output_type = (void *)buffer_bad_output;
|
bad_output_type = (void *)buffer_bad_output;
|
||||||
init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate, 16);
|
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);
|
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));
|
memset(bad_output_type, 0, sizeof(buffer_bad_output));
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ static HRESULT load_typelib(void)
|
||||||
if(typelib)
|
if(typelib)
|
||||||
return S_OK;
|
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)) {
|
if(FAILED(hres)) {
|
||||||
ERR("LoadRegTypeLib failed: %08lx\n", hres);
|
ERR("LoadRegTypeLib failed: %08lx\n", hres);
|
||||||
return hres;
|
return hres;
|
||||||
|
|
|
@ -190,6 +190,13 @@ static void test_Locate(void)
|
||||||
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
|
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
|
||||||
bo.biHeight = - bo.biHeight;
|
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;
|
bo.biBitCount = bi.biBitCount = 32;
|
||||||
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
|
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
|
||||||
ok(h != 0, "cvid->RGB32 failed\n");
|
ok(h != 0, "cvid->RGB32 failed\n");
|
||||||
|
|
|
@ -2125,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 void test_iosb(void)
|
||||||
{
|
{
|
||||||
static const char pipe_name[] = "\\\\.\\pipe\\wow64iosbnamedpipe";
|
static const char pipe_name[] = "\\\\.\\pipe\\wow64iosbnamedpipe";
|
||||||
HANDLE client, server;
|
HANDLE client, server, thread;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
ULONG64 func;
|
ULONG64 read_func, flush_func;
|
||||||
DWORD id;
|
|
||||||
IO_STATUS_BLOCK iosb32;
|
IO_STATUS_BLOCK iosb32;
|
||||||
|
char buffer[6];
|
||||||
|
DWORD size;
|
||||||
|
BOOL ret;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
|
@ -2142,66 +2159,89 @@ static void test_iosb(void)
|
||||||
};
|
};
|
||||||
ULONG64 Information;
|
ULONG64 Information;
|
||||||
} iosb64;
|
} 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 (!is_wow64) return;
|
||||||
if (!code_mem) return;
|
if (!code_mem) return;
|
||||||
if (!ntdll_module) 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 */
|
/* 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,
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||||
4, 1024, 1024, 1000, NULL );
|
4, 1024, 1024, 1000, NULL );
|
||||||
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
|
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) );
|
memset( &iosb32, 0x55, sizeof(iosb32) );
|
||||||
iosb64.Pointer = PtrToUlong( &iosb32 );
|
iosb64.Pointer = PtrToUlong( &iosb32 );
|
||||||
iosb64.Information = 0xdeadbeef;
|
iosb64.Information = 0xdeadbeef;
|
||||||
|
|
||||||
args[0] = (LONG_PTR)server;
|
args[0] = (LONG_PTR)server;
|
||||||
status = call_func64( func, ARRAY_SIZE(args), args );
|
status = call_func64( read_func, ARRAY_SIZE(args), args );
|
||||||
ok( status == STATUS_PENDING, "NtFsControlFile returned %lx\n", status );
|
ok( status == STATUS_PENDING, "NtReadFile returned %lx\n", status );
|
||||||
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.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 );
|
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
|
||||||
|
|
||||||
client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
|
||||||
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
|
ok( ret == TRUE, "got error %lu\n", GetLastError() );
|
||||||
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
|
|
||||||
|
|
||||||
ok( iosb32.Status == 0, "Wrong iostatus %lx\n", iosb32.Status );
|
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( 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) );
|
memset( &iosb32, 0x55, sizeof(iosb32) );
|
||||||
iosb64.Pointer = PtrToUlong( &iosb32 );
|
iosb64.Pointer = PtrToUlong( &iosb32 );
|
||||||
iosb64.Information = 0xdeadbeef;
|
iosb64.Information = 0xdeadbeef;
|
||||||
id = 0xdeadbeef;
|
|
||||||
|
|
||||||
args[5] = FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE;
|
flush_args[0] = (LONG_PTR)server;
|
||||||
args[6] = (ULONG_PTR)"ClientProcessId";
|
status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
|
||||||
args[7] = sizeof("ClientProcessId");
|
ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
|
||||||
args[8] = (ULONG_PTR)&id;
|
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
|
||||||
args[9] = sizeof(id);
|
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( client );
|
||||||
CloseHandle( server );
|
CloseHandle( server );
|
||||||
|
|
||||||
/* synchronous calls set iosb64 but not iosb32 */
|
/* 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,
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||||
4, 1024, 1024, 1000, NULL );
|
4, 1024, 1024, 1000, NULL );
|
||||||
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
|
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
|
||||||
|
@ -2210,19 +2250,60 @@ static void test_iosb(void)
|
||||||
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
|
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
|
||||||
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
|
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) );
|
memset( &iosb32, 0x55, sizeof(iosb32) );
|
||||||
iosb64.Pointer = PtrToUlong( &iosb32 );
|
iosb64.Pointer = PtrToUlong( &iosb32 );
|
||||||
iosb64.Information = 0xdeadbeef;
|
iosb64.Information = 0xdeadbeef;
|
||||||
id = 0xdeadbeef;
|
|
||||||
|
|
||||||
args[0] = (LONG_PTR)server;
|
args[0] = (LONG_PTR)server;
|
||||||
status = call_func64( func, ARRAY_SIZE(args), args );
|
status = call_func64( read_func, ARRAY_SIZE(args), args );
|
||||||
ok( status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status );
|
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
|
||||||
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
|
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
|
||||||
ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
|
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
|
||||||
ok( iosb64.Pointer == STATUS_SUCCESS, "status changed to %lx\n", iosb64.Status );
|
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
|
||||||
ok( iosb64.Information == sizeof(id), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
|
ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
|
||||||
ok( id == GetCurrentProcessId(), "wrong id %lx / %lx\n", id, GetCurrentProcessId() );
|
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( client );
|
||||||
CloseHandle( server );
|
CloseHandle( server );
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,10 @@ SQLRETURN WINAPI SQLBindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber,
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
if (!alloc_binding( &handle->bind_col, SQL_PARAM_INPUT_OUTPUT, 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.StatementHandle = handle->unix_handle;
|
||||||
if (StrLen_or_Ind) params.StrLen_or_Ind = handle->bind_col.param[i].len;
|
if (StrLen_or_Ind) params.StrLen_or_Ind = handle->bind_col.param[i].len;
|
||||||
if (SUCCESS(( ret = ODBC_CALL( SQLBindCol, ¶ms )))) handle->bind_col.param[i].ptr = StrLen_or_Ind;
|
if (SUCCESS(( ret = ODBC_CALL( SQLBindCol, ¶ms )))) handle->bind_col.param[i].ptr = StrLen_or_Ind;
|
||||||
|
@ -274,6 +278,11 @@ SQLRETURN WINAPI SQLBindParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNu
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
if (!alloc_binding( &handle->bind_param, SQL_PARAM_INPUT, 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.StatementHandle = handle->unix_handle;
|
||||||
params.StrLen_or_Ind = handle->bind_param.param[i].len;
|
params.StrLen_or_Ind = handle->bind_param.param[i].len;
|
||||||
|
@ -1376,20 +1385,76 @@ static BOOL resize_result_lengths( struct handle *handle, UINT size )
|
||||||
UINT i;
|
UINT i;
|
||||||
for (i = 0; i < handle->bind_col.count; i++)
|
for (i = 0; i < handle->bind_col.count; i++)
|
||||||
{
|
{
|
||||||
UINT8 *tmp = realloc( handle->bind_col.param[i].len, size * sizeof(UINT64) );
|
UINT8 *tmp;
|
||||||
if (!tmp) return FALSE;
|
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, ¶ms )))
|
||||||
|
{
|
||||||
|
free( tmp );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
handle->bind_col.param[i].len = tmp;
|
handle->bind_col.param[i].len = tmp;
|
||||||
}
|
}
|
||||||
for (i = 0; i < handle->bind_param.count; i++)
|
for (i = 0; i < handle->bind_param.count; i++)
|
||||||
{
|
{
|
||||||
UINT8 *tmp = realloc( handle->bind_param.param[i].len, size * sizeof(UINT64) );
|
UINT8 *tmp;
|
||||||
if (!tmp) return FALSE;
|
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, ¶ms )))
|
||||||
|
{
|
||||||
|
free( tmp );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
handle->bind_param.param[i].len = tmp;
|
handle->bind_param.param[i].len = tmp;
|
||||||
}
|
}
|
||||||
for (i = 0; i < handle->bind_parameter.count; i++)
|
for (i = 0; i < handle->bind_parameter.count; i++)
|
||||||
{
|
{
|
||||||
UINT8 *tmp = realloc( handle->bind_parameter.param[i].len, size * sizeof(UINT64) );
|
UINT8 *tmp;
|
||||||
if (!tmp) return FALSE;
|
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, ¶ms )))
|
||||||
|
{
|
||||||
|
free( tmp );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
handle->bind_parameter.param[i].len = tmp;
|
handle->bind_parameter.param[i].len = tmp;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1984,6 +2049,13 @@ SQLRETURN WINAPI SQLBindParameter(SQLHSTMT StatementHandle, SQLUSMALLINT Paramet
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
if (!alloc_binding( &handle->bind_parameter, InputOutputType, 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.StatementHandle = handle->unix_handle;
|
||||||
params.StrLen_or_Ind = handle->bind_parameter.param[i].len;
|
params.StrLen_or_Ind = handle->bind_parameter.param[i].len;
|
||||||
|
|
|
@ -152,9 +152,42 @@ enum sql_funcs
|
||||||
unix_funcs_count
|
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
|
struct param
|
||||||
{
|
{
|
||||||
INT16 type;
|
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 */
|
UINT8 *len; /* result length array stored in Unix lib */
|
||||||
void *ptr; /* result length ptr passed by client */
|
void *ptr; /* result length ptr passed by client */
|
||||||
};
|
};
|
||||||
|
|
|
@ -181,6 +181,8 @@ my %manual_win_thunks =
|
||||||
"wglGetExtensionsStringARB" => 1,
|
"wglGetExtensionsStringARB" => 1,
|
||||||
"wglGetExtensionsStringEXT" => 1,
|
"wglGetExtensionsStringEXT" => 1,
|
||||||
"wglGetPixelFormat" => 1,
|
"wglGetPixelFormat" => 1,
|
||||||
|
"wglGetPixelFormatAttribfvARB" => 1,
|
||||||
|
"wglGetPixelFormatAttribivARB" => 1,
|
||||||
"wglGetProcAddress" => 1,
|
"wglGetProcAddress" => 1,
|
||||||
"wglQueryCurrentRendererStringWINE" => 1,
|
"wglQueryCurrentRendererStringWINE" => 1,
|
||||||
"wglQueryRendererStringWINE" => 1,
|
"wglQueryRendererStringWINE" => 1,
|
||||||
|
@ -884,6 +886,31 @@ print HEADER "struct wgl_pbuffer;\n\n";
|
||||||
print HEADER "struct wgl_pixel_format\n";
|
print HEADER "struct wgl_pixel_format\n";
|
||||||
print HEADER "{\n";
|
print HEADER "{\n";
|
||||||
print HEADER " PIXELFORMATDESCRIPTOR pfd;\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 "};\n\n";
|
||||||
|
|
||||||
print HEADER "struct opengl_funcs\n{\n";
|
print HEADER "struct opengl_funcs\n{\n";
|
||||||
|
|
|
@ -24217,24 +24217,6 @@ static HDC WINAPI wglGetPbufferDCARB( HPBUFFERARB hPbuffer )
|
||||||
return args.ret;
|
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)
|
static int WINAPI wglGetSwapIntervalEXT(void)
|
||||||
{
|
{
|
||||||
struct wglGetSwapIntervalEXT_params args = { .teb = NtCurrentTeb() };
|
struct wglGetSwapIntervalEXT_params args = { .teb = NtCurrentTeb() };
|
||||||
|
@ -24340,6 +24322,8 @@ extern GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer );
|
||||||
extern HDC WINAPI wglGetCurrentReadDCARB(void);
|
extern HDC WINAPI wglGetCurrentReadDCARB(void);
|
||||||
extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc );
|
extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc );
|
||||||
extern const char * WINAPI wglGetExtensionsStringEXT(void);
|
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 wglQueryCurrentRendererStringWINE( GLenum attribute );
|
||||||
extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute );
|
extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute );
|
||||||
const void *extension_procs[] =
|
const void *extension_procs[] =
|
||||||
|
|
|
@ -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 ((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;
|
args.max_formats = args.num_formats;
|
||||||
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
|
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
|
||||||
|
|
||||||
|
@ -343,6 +345,153 @@ error:
|
||||||
return NULL;
|
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 )
|
INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd )
|
||||||
{
|
{
|
||||||
struct wgl_pixel_format *formats;
|
struct wgl_pixel_format *formats;
|
||||||
|
@ -360,6 +509,102 @@ INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDES
|
||||||
return num_onscreen_formats;
|
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.@)
|
* wglGetPixelFormat (OPENGL32.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -48,6 +48,8 @@ struct avi_decompressor
|
||||||
|
|
||||||
HIC hvid;
|
HIC hvid;
|
||||||
BITMAPINFOHEADER* pBihIn;
|
BITMAPINFOHEADER* pBihIn;
|
||||||
|
|
||||||
|
CRITICAL_SECTION late_cs;
|
||||||
REFERENCE_TIME late;
|
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)
|
static HRESULT avi_decompressor_sink_end_flush(struct strmbase_sink *iface)
|
||||||
{
|
{
|
||||||
struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter);
|
struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter);
|
||||||
|
EnterCriticalSection(&filter->late_cs);
|
||||||
filter->late = -1;
|
filter->late = -1;
|
||||||
|
LeaveCriticalSection(&filter->late_cs);
|
||||||
if (filter->source.pin.peer)
|
if (filter->source.pin.peer)
|
||||||
return IPin_EndFlush(filter->source.pin.peer);
|
return IPin_EndFlush(filter->source.pin.peer);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -167,8 +171,10 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface,
|
||||||
if (IMediaSample_IsSyncPoint(pSample) != S_OK)
|
if (IMediaSample_IsSyncPoint(pSample) != S_OK)
|
||||||
flags |= ICDECOMPRESS_NOTKEYFRAME;
|
flags |= ICDECOMPRESS_NOTKEYFRAME;
|
||||||
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
|
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
|
||||||
|
EnterCriticalSection(&This->late_cs);
|
||||||
if (hr == S_OK && AVIDec_DropSample(This, tStart))
|
if (hr == S_OK && AVIDec_DropSample(This, tStart))
|
||||||
flags |= ICDECOMPRESS_HURRYUP;
|
flags |= ICDECOMPRESS_HURRYUP;
|
||||||
|
LeaveCriticalSection(&This->late_cs);
|
||||||
|
|
||||||
res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, &source_format->bmiHeader, pbDstStream);
|
res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, &source_format->bmiHeader, pbDstStream);
|
||||||
if (res != ICERR_OK)
|
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",
|
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));
|
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)
|
if (q.Late > 0)
|
||||||
filter->late = q.Late + q.TimeStamp;
|
filter->late = q.Late + q.TimeStamp;
|
||||||
else
|
else
|
||||||
filter->late = -1;
|
filter->late = -1;
|
||||||
LeaveCriticalSection(&filter->filter.stream_cs);
|
LeaveCriticalSection(&filter->late_cs);
|
||||||
return S_OK;
|
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.peer);
|
||||||
IPin_Disconnect(&filter->source.pin.IPin_iface);
|
IPin_Disconnect(&filter->source.pin.IPin_iface);
|
||||||
|
|
||||||
|
filter->late_cs.DebugInfo->Spare[0] = 0;
|
||||||
|
DeleteCriticalSection(&filter->late_cs);
|
||||||
|
|
||||||
strmbase_sink_cleanup(&filter->sink);
|
strmbase_sink_cleanup(&filter->sink);
|
||||||
strmbase_source_cleanup(&filter->source);
|
strmbase_source_cleanup(&filter->source);
|
||||||
strmbase_passthrough_cleanup(&filter->passthrough);
|
strmbase_passthrough_cleanup(&filter->passthrough);
|
||||||
|
@ -550,7 +560,9 @@ static HRESULT avi_decompressor_init_stream(struct strmbase_filter *iface)
|
||||||
if (!filter->source.pin.peer)
|
if (!filter->source.pin.peer)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
EnterCriticalSection(&filter->late_cs);
|
||||||
filter->late = -1;
|
filter->late = -1;
|
||||||
|
LeaveCriticalSection(&filter->late_cs);
|
||||||
|
|
||||||
source_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat;
|
source_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat;
|
||||||
if ((res = ICDecompressBegin(filter->hvid, filter->pBihIn, &source_format->bmiHeader)))
|
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,
|
ISeekingPassThru_Init(&object->passthrough.ISeekingPassThru_iface, FALSE,
|
||||||
&object->sink.pin.IPin_iface);
|
&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);
|
TRACE("Created AVI decompressor %p.\n", object);
|
||||||
*out = &object->filter.IUnknown_inner;
|
*out = &object->filter.IUnknown_inner;
|
||||||
|
|
||||||
|
|
|
@ -873,6 +873,20 @@ static HRESULT testsink_connect(struct strmbase_sink *iface, IPin *peer, const A
|
||||||
return S_OK;
|
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)
|
static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample *sample)
|
||||||
{
|
{
|
||||||
struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter);
|
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);
|
hr = IMediaSample_IsSyncPoint(sample);
|
||||||
todo_wine_if (testmode == 5 || testmode == 6) ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
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;
|
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);
|
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||||
todo_wine ok(!sink->got_sample, "Got %u calls to Receive().\n", sink->got_sample);
|
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);
|
hr = IMediaControl_Stop(control);
|
||||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
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);
|
ok(!testsink->got_eos, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
|
||||||
hr = IPin_EndOfStream(sink);
|
hr = IPin_EndOfStream(sink);
|
||||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
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);
|
ok(testsink->got_eos == 1, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
|
||||||
testsink->got_eos = 0;
|
testsink->got_eos = 0;
|
||||||
|
|
||||||
|
@ -1185,7 +1215,7 @@ static void test_streaming_events(IMediaControl *control, IPin *sink,
|
||||||
testmode = 0;
|
testmode = 0;
|
||||||
hr = IMemInputPin_Receive(input, sample);
|
hr = IMemInputPin_Receive(input, sample);
|
||||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
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;
|
testsink->got_sample = 0;
|
||||||
|
|
||||||
ok(!testsink->got_begin_flush, "Got %u calls to IPin::BeginFlush().\n", testsink->got_begin_flush);
|
ok(!testsink->got_begin_flush, "Got %u calls to IPin::BeginFlush().\n", testsink->got_begin_flush);
|
||||||
|
|
|
@ -1677,9 +1677,9 @@ static void test_seeking(void)
|
||||||
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
|
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();
|
IBaseFilter *filter = create_avi_splitter();
|
||||||
IFilterGraph2 *graph = connect_input(filter, filename);
|
IFilterGraph2 *graph = connect_input(filter, filename);
|
||||||
struct testfilter testsink;
|
struct testfilter testsink;
|
||||||
|
@ -1691,6 +1691,8 @@ static void test_streaming(void)
|
||||||
ULONG ref;
|
ULONG ref;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
winetest_push_context("File %ls", resname);
|
||||||
|
|
||||||
testfilter_init(&testsink);
|
testfilter_init(&testsink);
|
||||||
IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
|
IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
|
||||||
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
|
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
|
||||||
|
@ -1761,6 +1763,8 @@ static void test_streaming(void)
|
||||||
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
||||||
ret = DeleteFileW(filename);
|
ret = DeleteFileW(filename);
|
||||||
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
|
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
|
||||||
|
|
||||||
|
winetest_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(avisplit)
|
START_TEST(avisplit)
|
||||||
|
@ -1787,7 +1791,8 @@ START_TEST(avisplit)
|
||||||
test_unconnected_filter_state();
|
test_unconnected_filter_state();
|
||||||
test_connect_pin();
|
test_connect_pin();
|
||||||
test_seeking();
|
test_seeking();
|
||||||
test_streaming();
|
test_streaming(L"test.avi");
|
||||||
|
test_streaming(L"test_cinepak.avi");
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
/* 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 */
|
/* @makedep: test2.mpg */
|
||||||
test2.mpg RCDATA "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"
|
||||||
|
|
BIN
dlls/quartz/tests/test_cinepak.avi
Normal file
BIN
dlls/quartz/tests/test_cinepak.avi
Normal file
Binary file not shown.
|
@ -100,6 +100,9 @@ struct parser_source
|
||||||
bool need_segment;
|
bool need_segment;
|
||||||
|
|
||||||
bool eos;
|
bool eos;
|
||||||
|
|
||||||
|
bool interpolate_timestamps;
|
||||||
|
UINT64 prev_end_pts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct parser *impl_from_strmbase_filter(struct strmbase_filter *iface)
|
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;
|
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;
|
VIDEOINFOHEADER *video_format;
|
||||||
uint32_t frame_time;
|
uint32_t frame_time;
|
||||||
|
@ -671,6 +674,7 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
|
||||||
mt->pbFormat = (BYTE *)video_format;
|
mt->pbFormat = (BYTE *)video_format;
|
||||||
|
|
||||||
memset(video_format, 0, sizeof(*video_format));
|
memset(video_format, 0, sizeof(*video_format));
|
||||||
|
if (wm)
|
||||||
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
|
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
|
||||||
video_format->rcTarget = video_format->rcSource;
|
video_format->rcTarget = video_format->rcSource;
|
||||||
if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1)
|
if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1)
|
||||||
|
@ -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.biPlanes = 1;
|
||||||
video_format->bmiHeader.biCompression = mt->subtype.Data1;
|
video_format->bmiHeader.biCompression = mt->subtype.Data1;
|
||||||
video_format->bmiHeader.biBitCount = 24;
|
video_format->bmiHeader.biBitCount = 24;
|
||||||
|
if (!wm)
|
||||||
|
video_format->bmiHeader.biSizeImage = 3 * format->u.video.width * format->u.video.height;
|
||||||
video_format->dwBitRate = 0;
|
video_format->dwBitRate = 0;
|
||||||
memcpy(video_format+1, format->u.video.codec_data, format->u.video.codec_data_len);
|
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);
|
return amt_from_wg_format_video_cinepak(mt, format);
|
||||||
|
|
||||||
case WG_MAJOR_TYPE_VIDEO_WMV:
|
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:
|
case WG_MAJOR_TYPE_VIDEO_MPEG1:
|
||||||
return amt_from_wg_format_video_mpeg1(mt, format);
|
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;
|
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)
|
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;
|
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->majortype, &MEDIATYPE_Video))
|
||||||
{
|
{
|
||||||
|
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_CVID))
|
||||||
|
return amt_to_wg_format_video_cinepak(mt, format);
|
||||||
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)
|
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)
|
||||||
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)
|
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)
|
||||||
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)
|
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)
|
||||||
|
@ -1153,30 +1185,34 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
|
||||||
return S_OK;
|
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)
|
if (offset)
|
||||||
start_pts += scale_uint64(offset, 10000000, bytes_per_second);
|
start_reftime += scale_uint64(offset, 10000000, bytes_per_second);
|
||||||
start_pts -= pin->seek.llCurrent;
|
start_reftime -= pin->seek.llCurrent;
|
||||||
start_pts *= pin->seek.dRate;
|
start_reftime *= pin->seek.dRate;
|
||||||
|
|
||||||
if (buffer->has_duration)
|
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)
|
if (offset + size < buffer->size)
|
||||||
end_pts = buffer->pts + scale_uint64(offset + size, 10000000, bytes_per_second);
|
end_reftime = end_reftime + scale_uint64(offset + size, 10000000, bytes_per_second);
|
||||||
end_pts -= pin->seek.llCurrent;
|
end_reftime -= pin->seek.llCurrent;
|
||||||
end_pts *= pin->seek.dRate;
|
end_reftime *= pin->seek.dRate;
|
||||||
|
|
||||||
IMediaSample_SetTime(sample, &start_pts, &end_pts);
|
IMediaSample_SetTime(sample, &start_reftime, &end_reftime);
|
||||||
IMediaSample_SetMediaTime(sample, &start_pts, &end_pts);
|
IMediaSample_SetMediaTime(sample, &start_reftime, &end_reftime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IMediaSample_SetTime(sample, &start_pts, NULL);
|
pin->prev_end_pts = 0;
|
||||||
|
IMediaSample_SetTime(sample, &start_reftime, NULL);
|
||||||
IMediaSample_SetMediaTime(sample, NULL, 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)
|
static BOOL avi_splitter_filter_init_gst(struct parser *filter)
|
||||||
{
|
{
|
||||||
wg_parser_t parser = filter->wg_parser;
|
wg_parser_t parser = filter->wg_parser;
|
||||||
|
struct parser_source *src;
|
||||||
uint32_t i, stream_count;
|
uint32_t i, stream_count;
|
||||||
WCHAR source_name[20];
|
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)
|
for (i = 0; i < stream_count; ++i)
|
||||||
{
|
{
|
||||||
swprintf(source_name, ARRAY_SIZE(source_name), L"Stream %02u", 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;
|
return FALSE;
|
||||||
|
src->interpolate_timestamps = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -661,8 +661,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde
|
||||||
DMO_MEDIA_TYPE *type)
|
DMO_MEDIA_TYPE *type)
|
||||||
{
|
{
|
||||||
struct wma_decoder *decoder = impl_from_IMediaObject(iface);
|
struct wma_decoder *decoder = impl_from_IMediaObject(iface);
|
||||||
|
UINT32 depth, channels, rate;
|
||||||
IMFMediaType *media_type;
|
IMFMediaType *media_type;
|
||||||
UINT32 depth;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type);
|
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
|
else
|
||||||
hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
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))
|
if (SUCCEEDED(hr))
|
||||||
hr = IMFMediaType_DeleteItem(media_type, &MF_MT_USER_DATA);
|
hr = IMFMediaType_DeleteItem(media_type, &MF_MT_USER_DATA);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
|
|
@ -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
|
* macdrv_wglGetSwapIntervalEXT
|
||||||
*
|
*
|
||||||
|
@ -4136,7 +4097,7 @@ static void load_extensions(void)
|
||||||
|
|
||||||
register_extension("WGL_ARB_pixel_format");
|
register_extension("WGL_ARB_pixel_format");
|
||||||
opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
|
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;
|
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
|
||||||
|
|
||||||
if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
|
if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
|
||||||
|
|
|
@ -1553,99 +1553,106 @@ 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, drawable_type = 0, render_type = 0;
|
||||||
int value;
|
|
||||||
int rb, gb, bb, ab;
|
int rb, gb, bb, ab;
|
||||||
const struct glx_pixel_format *fmt;
|
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 */
|
/* 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 */);
|
fmt = get_pixel_format( gdi_display, iPixelFormat, TRUE /* Offscreen */);
|
||||||
if (!fmt) {
|
if (!fmt)
|
||||||
|
{
|
||||||
WARN( "unexpected format %d\n", iPixelFormat );
|
WARN( "unexpected format %d\n", iPixelFormat );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
/* If we can't get basic information, there is no point continuing */
|
||||||
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &drawable_type )) return 0;
|
||||||
ppfd->nVersion = 1;
|
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &render_type )) return 0;
|
||||||
|
|
||||||
|
memset( pf, 0, sizeof(*pf) );
|
||||||
|
pf->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||||
|
pf->pfd.nVersion = 1;
|
||||||
|
|
||||||
/* These flags are always the same... */
|
/* These flags are always the same... */
|
||||||
ppfd->dwFlags = PFD_SUPPORT_OPENGL;
|
pf->pfd.dwFlags = PFD_SUPPORT_OPENGL;
|
||||||
/* Now the flags extracted from the Visual */
|
/* Now the flags extracted from the Visual */
|
||||||
|
|
||||||
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
|
if (drawable_type & GLX_WINDOW_BIT) pf->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
|
||||||
if(value & GLX_WINDOW_BIT)
|
|
||||||
ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
|
|
||||||
|
|
||||||
/* On Windows bitmap rendering is only offered using the GDI Software renderer. We reserve some formats (see get_formats for more info)
|
/* On Windows bitmap rendering is only offered using the GDI Software
|
||||||
* for bitmap rendering since we require indirect rendering for this. Further pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
|
* renderer. We reserve some formats (see get_formats for more info) for
|
||||||
* 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
|
* bitmap rendering since we require indirect rendering for this. Further
|
||||||
* offered the GDI bit either. */
|
* pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
|
||||||
ppfd->dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
|
* 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);
|
||||||
|
|
||||||
/* PFD_GENERIC_FORMAT - gdi software rendering
|
/* PFD_GENERIC_FORMAT - gdi software rendering
|
||||||
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver (MCD e.g. 3dfx minigl)
|
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver
|
||||||
* none set - full hardware accelerated by a ICD
|
* (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 */
|
* We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as
|
||||||
ppfd->dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
|
* that's what ATI and Nvidia Windows drivers do */
|
||||||
|
pf->pfd.dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
|
||||||
|
|
||||||
if (!(ppfd->dwFlags & PFD_GENERIC_FORMAT))
|
if (!(pf->pfd.dwFlags & PFD_GENERIC_FORMAT)) pf->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
|
||||||
ppfd->dwFlags |= PFD_SUPPORT_COMPOSITION;
|
|
||||||
|
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value );
|
||||||
if (value) {
|
if (value)
|
||||||
ppfd->dwFlags |= PFD_DOUBLEBUFFER;
|
{
|
||||||
ppfd->dwFlags &= ~PFD_SUPPORT_GDI;
|
pf->pfd.dwFlags |= PFD_DOUBLEBUFFER;
|
||||||
|
pf->pfd.dwFlags &= ~PFD_SUPPORT_GDI;
|
||||||
}
|
}
|
||||||
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STEREO, &value );
|
||||||
|
if (value) pf->pfd.dwFlags |= PFD_STEREO;
|
||||||
|
|
||||||
/* Pixel type */
|
/* Pixel type */
|
||||||
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
|
if (render_type & GLX_RGBA_BIT) pf->pfd.iPixelType = PFD_TYPE_RGBA;
|
||||||
if (value & GLX_RGBA_BIT)
|
else pf->pfd.iPixelType = PFD_TYPE_COLORINDEX;
|
||||||
ppfd->iPixelType = PFD_TYPE_RGBA;
|
|
||||||
else
|
|
||||||
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
|
|
||||||
|
|
||||||
/* Color bits */
|
/* Color bits */
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value );
|
||||||
ppfd->cColorBits = value;
|
pf->pfd.cColorBits = value;
|
||||||
|
|
||||||
/* Red, green, blue and alpha bits / shifts */
|
/* Red, green, blue and alpha bits / shifts */
|
||||||
if (ppfd->iPixelType == PFD_TYPE_RGBA) {
|
if (pf->pfd.iPixelType == PFD_TYPE_RGBA)
|
||||||
|
{
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb );
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb );
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb );
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab );
|
||||||
|
|
||||||
ppfd->cBlueBits = bb;
|
pf->pfd.cBlueBits = bb;
|
||||||
ppfd->cBlueShift = 0;
|
pf->pfd.cBlueShift = 0;
|
||||||
ppfd->cGreenBits = gb;
|
pf->pfd.cGreenBits = gb;
|
||||||
ppfd->cGreenShift = bb;
|
pf->pfd.cGreenShift = bb;
|
||||||
ppfd->cRedBits = rb;
|
pf->pfd.cRedBits = rb;
|
||||||
ppfd->cRedShift = gb + bb;
|
pf->pfd.cRedShift = gb + bb;
|
||||||
ppfd->cAlphaBits = ab;
|
pf->pfd.cAlphaBits = ab;
|
||||||
if (ab)
|
if (ab) pf->pfd.cAlphaShift = rb + gb + bb;
|
||||||
ppfd->cAlphaShift = rb + gb + bb;
|
else pf->pfd.cAlphaShift = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ppfd->cAlphaShift = 0;
|
{
|
||||||
} else {
|
pf->pfd.cRedBits = 0;
|
||||||
ppfd->cRedBits = 0;
|
pf->pfd.cRedShift = 0;
|
||||||
ppfd->cRedShift = 0;
|
pf->pfd.cBlueBits = 0;
|
||||||
ppfd->cBlueBits = 0;
|
pf->pfd.cBlueShift = 0;
|
||||||
ppfd->cBlueShift = 0;
|
pf->pfd.cGreenBits = 0;
|
||||||
ppfd->cGreenBits = 0;
|
pf->pfd.cGreenShift = 0;
|
||||||
ppfd->cGreenShift = 0;
|
pf->pfd.cAlphaBits = 0;
|
||||||
ppfd->cAlphaBits = 0;
|
pf->pfd.cAlphaShift = 0;
|
||||||
ppfd->cAlphaShift = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accum RGBA bits */
|
/* Accum RGBA bits */
|
||||||
|
@ -1654,29 +1661,98 @@ static int describe_pixel_format( int iPixelFormat, PIXELFORMATDESCRIPTOR *ppfd
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb );
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab );
|
||||||
|
|
||||||
ppfd->cAccumBits = rb+gb+bb+ab;
|
pf->pfd.cAccumBits = rb + gb + bb + ab;
|
||||||
ppfd->cAccumRedBits = rb;
|
pf->pfd.cAccumRedBits = rb;
|
||||||
ppfd->cAccumGreenBits = gb;
|
pf->pfd.cAccumGreenBits = gb;
|
||||||
ppfd->cAccumBlueBits = bb;
|
pf->pfd.cAccumBlueBits = bb;
|
||||||
ppfd->cAccumAlphaBits = ab;
|
pf->pfd.cAccumAlphaBits = ab;
|
||||||
|
|
||||||
/* Aux bits */
|
/* Aux bits */
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value );
|
||||||
ppfd->cAuxBuffers = value;
|
pf->pfd.cAuxBuffers = value;
|
||||||
|
|
||||||
/* Depth bits */
|
/* Depth bits */
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value );
|
||||||
ppfd->cDepthBits = value;
|
pf->pfd.cDepthBits = value;
|
||||||
|
|
||||||
/* stencil bits */
|
/* stencil bits */
|
||||||
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value );
|
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value );
|
||||||
ppfd->cStencilBits = value;
|
pf->pfd.cStencilBits = value;
|
||||||
|
|
||||||
ppfd->iLayerType = PFD_MAIN_PLANE;
|
pf->pfd.iLayerType = PFD_MAIN_PLANE;
|
||||||
|
|
||||||
if (TRACE_ON(wgl)) {
|
if (!has_swap_method) pf->swap_method = WGL_SWAP_EXCHANGE_ARB;
|
||||||
dump_PIXELFORMATDESCRIPTOR(ppfd);
|
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;
|
||||||
|
|
||||||
|
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;
|
return nb_onscreen_formats;
|
||||||
}
|
}
|
||||||
|
@ -2520,7 +2596,7 @@ struct choose_pixel_format_arb_format
|
||||||
{
|
{
|
||||||
int format;
|
int format;
|
||||||
int original_index;
|
int original_index;
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
struct wgl_pixel_format pf;
|
||||||
int depth, stencil;
|
int depth, stencil;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2537,7 +2613,7 @@ static int compare_formats(const void *a, const void *b)
|
||||||
|
|
||||||
if (offscreen_a != offscreen_b)
|
if (offscreen_a != offscreen_b)
|
||||||
return 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;
|
return fmt_a->original_index - fmt_b->original_index;
|
||||||
if (fmt_a->depth != fmt_b->depth)
|
if (fmt_a->depth != fmt_b->depth)
|
||||||
return 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->format = i + 1;
|
||||||
format->original_index = it;
|
format->original_index = it;
|
||||||
|
|
||||||
memset(&format->pfd, 0, sizeof(format->pfd));
|
memset(&format->pf, 0, sizeof(format->pf));
|
||||||
if (!describe_pixel_format(format->format, &format->pfd))
|
if (!describe_pixel_format(format->format, &format->pf))
|
||||||
ERR("describe_pixel_format failed, format %d.\n", format->format);
|
ERR("describe_pixel_format failed, format %d.\n", format->format);
|
||||||
|
|
||||||
format->depth = format->pfd.cDepthBits;
|
format->depth = format->pf.pfd.cDepthBits;
|
||||||
format->stencil = format->pfd.cStencilBits;
|
format->stencil = format->pf.pfd.cStencilBits;
|
||||||
if (!depth_bits && !(format->pfd.dwFlags & PFD_GENERIC_FORMAT))
|
if (!depth_bits && !(format->pf.pfd.dwFlags & PFD_GENERIC_FORMAT))
|
||||||
{
|
{
|
||||||
format->pfd.cDepthBits = 0;
|
format->pf.pfd.cDepthBits = 0;
|
||||||
format->pfd.cStencilBits = 0;
|
format->pf.pfd.cStencilBits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
++format_count;
|
++format_count;
|
||||||
|
@ -2678,329 +2754,6 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
|
||||||
return GL_TRUE;
|
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
|
* X11DRV_wglBindTexImageARB
|
||||||
*
|
*
|
||||||
|
@ -3260,8 +3013,8 @@ static void X11DRV_WineGL_LoadExtensions(void)
|
||||||
|
|
||||||
register_extension( "WGL_ARB_pixel_format" );
|
register_extension( "WGL_ARB_pixel_format" );
|
||||||
opengl_funcs.ext.p_wglChoosePixelFormatARB = X11DRV_wglChoosePixelFormatARB;
|
opengl_funcs.ext.p_wglChoosePixelFormatARB = X11DRV_wglChoosePixelFormatARB;
|
||||||
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = X11DRV_wglGetPixelFormatAttribfvARB;
|
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */
|
||||||
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = X11DRV_wglGetPixelFormatAttribivARB;
|
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
|
||||||
|
|
||||||
if (has_extension( glxExtensions, "GLX_ARB_fbconfig_float"))
|
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)
|
if (formats)
|
||||||
{
|
{
|
||||||
for (i = 0; i < min( max_formats, nb_pixel_formats ); ++i)
|
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_formats = nb_pixel_formats;
|
||||||
*num_onscreen_formats = nb_onscreen_formats;
|
*num_onscreen_formats = nb_onscreen_formats;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#define WINE_GLAPI
|
#define WINE_GLAPI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WINE_WGL_DRIVER_VERSION 25
|
#define WINE_WGL_DRIVER_VERSION 26
|
||||||
|
|
||||||
struct wgl_context;
|
struct wgl_context;
|
||||||
struct wgl_pbuffer;
|
struct wgl_pbuffer;
|
||||||
|
@ -15,6 +15,31 @@ struct wgl_pbuffer;
|
||||||
struct wgl_pixel_format
|
struct wgl_pixel_format
|
||||||
{
|
{
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
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
|
struct opengl_funcs
|
||||||
|
|
|
@ -1546,7 +1546,7 @@ void WCMD_echo (const WCHAR *args)
|
||||||
* first command to be executed may not be at the front of the
|
* 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)
|
* commands->thiscommand string (eg. it may point after a DO or ELSE)
|
||||||
*/
|
*/
|
||||||
static void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
|
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
|
||||||
BOOL isIF, BOOL executecmds)
|
BOOL isIF, BOOL executecmds)
|
||||||
{
|
{
|
||||||
CMD_NODE *curPosition = *cmdList;
|
CMD_NODE *curPosition = *cmdList;
|
||||||
|
@ -1850,11 +1850,11 @@ static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk)
|
||||||
* are recursively passed. If any have duplicates, then the * token should
|
* are recursively passed. If any have duplicates, then the * token should
|
||||||
* not be honoured.
|
* not be honoured.
|
||||||
*/
|
*/
|
||||||
static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
|
int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
|
||||||
int *totalfound, BOOL *doall,
|
int *totalfound, BOOL *doall,
|
||||||
BOOL *duplicates)
|
BOOL *duplicates)
|
||||||
{
|
{
|
||||||
WCHAR *pos = tokenstr;
|
const WCHAR *pos = tokenstr;
|
||||||
int nexttoken = -1;
|
int nexttoken = -1;
|
||||||
|
|
||||||
if (totalfound) *totalfound = 0;
|
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;
|
WIN32_FIND_DATAW fd;
|
||||||
HANDLE hff;
|
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);
|
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
|
* WCMD_give_help
|
||||||
*
|
*
|
||||||
|
|
|
@ -757,11 +757,6 @@ setlocal EnableDelayedExpansion
|
||||||
set WINE_FOO=foo bar
|
set WINE_FOO=foo bar
|
||||||
for %%i in ("!WINE_FOO!") do echo %%i
|
for %%i in ("!WINE_FOO!") do echo %%i
|
||||||
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
|
setlocal DisableDelayedExpansion
|
||||||
|
|
||||||
echo --- in digit variables
|
echo --- in digit variables
|
||||||
|
|
|
@ -1014,21 +1014,21 @@ A D
|
||||||
B C
|
B C
|
||||||
B D
|
B D
|
||||||
--- nested FORs and args tempering
|
--- nested FORs and args tempering
|
||||||
@todo_wine@inner argument {-foo, bar}
|
inner argument {-foo, bar}
|
||||||
@todo_wine@inner argument {-x, y}
|
inner argument {-x, y}
|
||||||
--- nesting and delayed expansion
|
--- nesting and delayed expansion
|
||||||
a 1 2
|
a 1 2
|
||||||
@todo_wine@1-A2
|
1-A2
|
||||||
@todo_wine@1-B1
|
1-B1
|
||||||
@todo_wine@2-A1
|
2-A1
|
||||||
@todo_wine@2-B2
|
2-B2
|
||||||
@todo_wine@b 1 3
|
b 1 3
|
||||||
@todo_wine@1-A2
|
1-A2
|
||||||
@todo_wine@1-B1
|
1-B1
|
||||||
@todo_wine@2-A2
|
2-A2
|
||||||
@todo_wine@2-B2
|
2-B2
|
||||||
@todo_wine@3-A1
|
3-A1
|
||||||
@todo_wine@3-B2
|
3-B2
|
||||||
--- nesting if/for
|
--- nesting if/for
|
||||||
@todo_wine@"f"
|
@todo_wine@"f"
|
||||||
@todo_wine@"g"
|
@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
|
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
|
1:3.14,%B
|
||||||
2:3.14,
|
2:3.14,
|
||||||
@todo_wine@4:3,14
|
4:3,14
|
||||||
------ parameter splitting
|
------ parameter splitting
|
||||||
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
|
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
|
||||||
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
|
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
|
||||||
|
|
|
@ -83,6 +83,27 @@ typedef struct _CMD_IF_CONDITION
|
||||||
};
|
};
|
||||||
} 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
|
typedef struct _CMD_COMMAND
|
||||||
{
|
{
|
||||||
WCHAR *command; /* Command string to execute */
|
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);
|
BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test);
|
||||||
const char *debugstr_if_condition(const CMD_IF_CONDITION *cond);
|
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_assoc (const WCHAR *, BOOL);
|
||||||
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
|
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
|
||||||
void WCMD_call (WCHAR *command);
|
void WCMD_call (WCHAR *command);
|
||||||
|
|
|
@ -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
|
* node_dispose_tree
|
||||||
*
|
*
|
||||||
|
@ -2093,6 +2181,170 @@ static BOOL WCMD_IsEndQuote(const WCHAR *quote, int quoteIndex)
|
||||||
return FALSE;
|
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
|
* WCMD_ReadAndParseLine
|
||||||
*
|
*
|
||||||
|
@ -2710,6 +2962,97 @@ BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test)
|
||||||
return TRUE;
|
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)
|
void WCMD_save_for_loop_context(BOOL reset)
|
||||||
{
|
{
|
||||||
FOR_CONTEXT *new = xalloc(sizeof(*new));
|
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);
|
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
|
* WCMD_process_commands
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue