Wine-Devel
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 22 participants
- 84527 discussions
June 15, 2021
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
v2:
- don't allow 'const' variable declaration in compat mode.
dlls/jscript/compile.c | 5 +++++
dlls/jscript/lex.c | 2 ++
dlls/jscript/parser.h | 1 +
dlls/jscript/parser.y | 37 ++++++++++++++++++++++++++++++++-----
dlls/jscript/tests/lang.js | 34 ++++++++++++++++++++++++++++++++++
dlls/mshtml/tests/es5.js | 17 +++++++++++++++++
6 files changed, 91 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index 9bb9ff13d14..2a17639641f 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -1138,6 +1138,11 @@ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t
if(!iter->expr)
continue;
+ if (iter->block_scope)
+ FIXME("Block scope variables are not supported.\n");
+ if (iter->constant)
+ FIXME("Constant variables are not supported.\n");
+
hres = emit_identifier_ref(ctx, iter->identifier, 0);
if(FAILED(hres))
return hres;
diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c
index efed1038a95..695615721a7 100644
--- a/dlls/jscript/lex.c
+++ b/dlls/jscript/lex.c
@@ -41,6 +41,7 @@ static const struct {
{L"break", kBREAK, TRUE},
{L"case", kCASE},
{L"catch", kCATCH},
+ {L"const", kCONST},
{L"continue", kCONTINUE, TRUE},
{L"default", kDEFAULT},
{L"delete", kDELETE},
@@ -54,6 +55,7 @@ static const struct {
{L"if", kIF},
{L"in", kIN},
{L"instanceof", kINSTANCEOF},
+ {L"let", kLET, FALSE, SCRIPTLANGUAGEVERSION_ES5},
{L"new", kNEW},
{L"null", kNULL},
{L"return", kRETURN, TRUE},
diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h
index b88a52af242..c4dd0752ee9 100644
--- a/dlls/jscript/parser.h
+++ b/dlls/jscript/parser.h
@@ -95,6 +95,7 @@ literal_t *new_boolean_literal(parser_ctx_t*,BOOL) DECLSPEC_HIDDEN;
typedef struct _variable_declaration_t {
const WCHAR *identifier;
+ BOOL block_scope, constant;
expression_t *expr;
struct _variable_declaration_t *next;
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index f11119143b8..fd8ea7e7aa7 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -87,7 +87,7 @@ static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variabl
static void *new_statement(parser_ctx_t*,statement_type_t,size_t,unsigned);
static statement_t *new_block_statement(parser_ctx_t*,unsigned,statement_list_t*);
-static statement_t *new_var_statement(parser_ctx_t*,unsigned,variable_list_t*);
+static statement_t *new_var_statement(parser_ctx_t*,BOOL,BOOL,unsigned,variable_list_t*);
static statement_t *new_expression_statement(parser_ctx_t*,unsigned,expression_t*);
static statement_t *new_if_statement(parser_ctx_t*,unsigned,expression_t*,statement_t*,statement_t*);
static statement_t *new_while_statement(parser_ctx_t*,unsigned,BOOL,expression_t*,statement_t*);
@@ -168,8 +168,9 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
}
/* keywords */
-%token <identifier> kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kFUNCTION kIF kFINALLY kFOR kGET kIN kSET
-%token <identifier> kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
+%token <identifier> kBREAK kCASE kCATCH kCONST kCONTINUE kDEFAULT kDELETE kDO kELSE kFUNCTION kIF kFINALLY kFOR
+%token <identifier> kGET kIN kLET kSET kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE
+%token <identifier> kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ kDCOL
/* tokens */
@@ -182,6 +183,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%type <source_elements> FunctionBody
%type <statement> Statement
%type <statement> Block
+%type <statement> LexicalDeclaration
%type <statement> VariableStatement
%type <statement> EmptyStatement
%type <statement> ExpressionStatement
@@ -291,6 +293,7 @@ FormalParameterList_opt
/* ECMA-262 3rd Edition 12 */
Statement
: Block { $$ = $1; }
+ | LexicalDeclaration { $$ = $1; }
| VariableStatement { $$ = $1; }
| EmptyStatement { $$ = $1; }
| FunctionExpression { $$ = new_expression_statement(ctx, @$, $1); }
@@ -322,10 +325,25 @@ Block
: '{' StatementList '}' { $$ = new_block_statement(ctx, @2, $2); }
| '{' '}' { $$ = new_block_statement(ctx, @$, NULL); }
+/* ECMA-262 10th Edition 13.3.1, TODO: BindingList*/
+LexicalDeclaration
+ : kLET VariableDeclarationList semicolon_opt
+ { $$ = new_var_statement(ctx, TRUE, FALSE, @$, $2); }
+ | kCONST VariableDeclarationList semicolon_opt
+ {
+ if(ctx->script->version < SCRIPTLANGUAGEVERSION_ES5) {
+ WARN("const var declaration in legacy mode.\n",
+ debugstr_w($1));
+ set_error(ctx, @$, JS_E_SYNTAX);
+ YYABORT;
+ }
+ $$ = new_var_statement(ctx, TRUE, TRUE, @$, $2);
+ }
+
/* ECMA-262 3rd Edition 12.2 */
VariableStatement
: kVAR VariableDeclarationList semicolon_opt
- { $$ = new_var_statement(ctx, @$, $2); }
+ { $$ = new_var_statement(ctx, FALSE, FALSE, @$, $2); }
/* ECMA-262 3rd Edition 12.2 */
VariableDeclarationList
@@ -834,6 +852,7 @@ ReservedAsIdentifier
: kBREAK { $$ = $1; }
| kCASE { $$ = $1; }
| kCATCH { $$ = $1; }
+ | kCONST { $$ = $1; }
| kCONTINUE { $$ = $1; }
| kDEFAULT { $$ = $1; }
| kDELETE { $$ = $1; }
@@ -847,6 +866,7 @@ ReservedAsIdentifier
| kIF { $$ = $1; }
| kIN { $$ = $1; }
| kINSTANCEOF { $$ = $1; }
+ | kLET { $$ = $1; }
| kNEW { $$ = $1; }
| kNULL { $$ = $1; }
| kRETURN { $$ = $1; }
@@ -1144,8 +1164,10 @@ static variable_list_t *variable_list_add(parser_ctx_t *ctx, variable_list_t *li
return list;
}
-static statement_t *new_var_statement(parser_ctx_t *ctx, unsigned loc, variable_list_t *variable_list)
+static statement_t *new_var_statement(parser_ctx_t *ctx, BOOL block_scope, BOOL constant, unsigned loc,
+ variable_list_t *variable_list)
{
+ variable_declaration_t *var;
var_statement_t *ret;
ret = new_statement(ctx, STAT_VAR, sizeof(*ret), loc);
@@ -1153,6 +1175,11 @@ static statement_t *new_var_statement(parser_ctx_t *ctx, unsigned loc, variable_
return NULL;
ret->variable_list = variable_list->head;
+ for (var = ret->variable_list; var; var = var->next)
+ {
+ var->block_scope = block_scope;
+ var->constant = constant;
+ }
return &ret->stat;
}
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 9e6e6ad239f..0db86c89985 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -2030,3 +2030,37 @@ Math = 6;
ok(Math === 6, "NaN !== 6");
reportSuccess();
+
+function test_es5_keywords() {
+ var let = 1
+ var tmp
+ ok(let == 1, "let != 1");
+
+ tmp = false
+ try {
+ eval('var var = 1;');
+ }
+ catch(e) {
+ tmp = true
+ }
+ ok(tmp === true, "Expected exception for 'var var = 1;'");
+
+ tmp = false
+ try {
+ eval('var const = 1;');
+ }
+ catch(e) {
+ tmp = true
+ }
+ ok(tmp === true, "Expected exception for 'var const = 1;'");
+
+ tmp = false
+ try {
+ eval('const c1 = 1;');
+ }
+ catch(e) {
+ tmp = true
+ }
+ ok(tmp === true, "Expected exception for 'const c1 = 1;'");
+}
+test_es5_keywords();
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 7e46848d40e..24906de5231 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -1207,3 +1207,20 @@ sync_test("head_setter", function() {
document.head = "";
ok(typeof(document.head) === "object", "typeof(document.head) = " + typeof(document.head));
});
+
+
+sync_test("declaration_let", function() {
+ ok(a === undefined, "a is not undefined");
+ var a = 3;
+
+ {
+ let a = 2;
+
+ ok(a == 2, "a != 2");
+
+ a = 4;
+ ok(a == 4, "a != 4");
+ }
+
+ todo_wine.ok(a == 3, "a != 3");
+});
--
2.31.1
3
9
[PATCH resend 1/4] iphlpapi: Implement asynchronous events for IcmpSendEcho2(Ex).
by Gabriel Ivăncescu June 15, 2021
by Gabriel Ivăncescu June 15, 2021
June 15, 2021
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/iphlpapi/icmp.c | 108 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 100 insertions(+), 8 deletions(-)
diff --git a/dlls/iphlpapi/icmp.c b/dlls/iphlpapi/icmp.c
index 8ef0321..ceeab69 100644
--- a/dlls/iphlpapi/icmp.c
+++ b/dlls/iphlpapi/icmp.c
@@ -106,9 +106,42 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
typedef struct {
int sid;
+ LONG lock_count;
+ HANDLE lock_event;
IP_OPTION_INFORMATION default_opts;
} icmp_t;
+static void icmp_lock(icmp_t *icp)
+{
+ InterlockedIncrement(&icp->lock_count);
+}
+
+static void icmp_unlock(icmp_t *icp)
+{
+ if (InterlockedDecrement(&icp->lock_count) == 0x80000000)
+ {
+ if (icp->lock_event)
+ SetEvent(icp->lock_event);
+ }
+}
+
+static void icmp_wait_for_released_locks(icmp_t *icp)
+{
+ HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ icp->lock_event = event;
+ if (InterlockedExchangeAdd(&icp->lock_count, 0x80000000) != 0)
+ {
+ do
+ {
+ if (event) WaitForSingleObjectEx(event, INFINITE, TRUE);
+ else SleepEx(1, TRUE);
+ }
+ while (icp->lock_count != 0x80000000);
+ }
+ if (event) CloseHandle(event);
+}
+
#define IP_OPTS_UNKNOWN 0
#define IP_OPTS_DEFAULT 1
#define IP_OPTS_CUSTOM 2
@@ -347,6 +380,30 @@ done:
return res;
}
+struct icmp_get_reply_async_ctx
+{
+ icmp_t *icp;
+ HANDLE event;
+ unsigned char *buffer;
+ void *reply_buf;
+ DWORD reply_size;
+ DWORD send_time;
+ DWORD timeout;
+};
+
+static DWORD WINAPI icmp_get_reply_async_func(VOID *parameter)
+{
+ struct icmp_get_reply_async_ctx *ctx = parameter;
+
+ icmp_get_reply(ctx->icp->sid, ctx->buffer, ctx->send_time, ctx->reply_buf, ctx->reply_size, ctx->timeout);
+
+ SetEvent(ctx->event);
+
+ icmp_unlock(ctx->icp);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ return 0;
+}
+
/*
@@ -381,6 +438,7 @@ HANDLE WINAPI Icmp6CreateFile(VOID)
}
icp->sid=sid;
icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN;
+ icp->lock_count=0;
return (HANDLE)icp;
}
@@ -439,6 +497,7 @@ HANDLE WINAPI IcmpCreateFile(VOID)
}
icp->sid=sid;
icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN;
+ icp->lock_count=0;
return (HANDLE)icp;
}
@@ -455,6 +514,9 @@ BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle)
return FALSE;
}
+ /* Windows waits until all outstanding async requests are complete or timed out */
+ icmp_wait_for_released_locks(icp);
+
close( icp->sid );
HeapFree(GetProcessHeap (), 0, icp);
return TRUE;
@@ -526,6 +588,7 @@ DWORD WINAPI IcmpSendEcho2Ex(
unsigned char *buffer;
int reqsize, repsize;
DWORD send_time;
+ DWORD res = 0;
TRACE("(%p, %p, %p, %p, %08x, %08x, %p, %d, %p, %p, %d, %d)\n", IcmpHandle,
Event, ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData,
@@ -553,11 +616,6 @@ DWORD WINAPI IcmpSendEcho2Ex(
return 0;
}
- if (Event)
- {
- FIXME("unsupported for events\n");
- return 0;
- }
if (ApcRoutine)
{
FIXME("unsupported for APCs\n");
@@ -569,6 +627,8 @@ DWORD WINAPI IcmpSendEcho2Ex(
return 0;
}
+ icmp_lock(icp);
+
/* Prepare the request */
id=getpid() & 0xFFFF;
seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF;
@@ -580,7 +640,7 @@ DWORD WINAPI IcmpSendEcho2Ex(
buffer = HeapAlloc(GetProcessHeap(), 0, max( repsize, reqsize ));
if (buffer == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
- return 0;
+ goto done;
}
icmp_header=(struct icmp*)buffer;
@@ -661,10 +721,42 @@ DWORD WINAPI IcmpSendEcho2Ex(
}
}
HeapFree(GetProcessHeap(), 0, buffer);
- return 0;
+ goto done;
}
- return icmp_get_reply(icp->sid, buffer, send_time, ReplyBuffer, ReplySize, Timeout);
+ if (Event)
+ {
+ struct icmp_get_reply_async_ctx *ctx = HeapAlloc(GetProcessHeap(), 0, sizeof(*ctx));
+
+ if (ctx)
+ {
+ ctx->icp = icp;
+ ctx->event = Event;
+ ctx->buffer = buffer;
+ ctx->reply_buf = ReplyBuffer;
+ ctx->reply_size = ReplySize;
+ ctx->send_time = send_time;
+ ctx->timeout = Timeout;
+ if (QueueUserWorkItem(icmp_get_reply_async_func, ctx, WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION))
+ {
+ SetLastError(ERROR_IO_PENDING);
+ return 0;
+ }
+
+ HeapFree(GetProcessHeap(), 0, ctx);
+ }
+ else
+ SetLastError(ERROR_OUTOFMEMORY);
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+ goto done;
+ }
+
+ res = icmp_get_reply(icp->sid, buffer, send_time, ReplyBuffer, ReplySize, Timeout);
+
+done:
+ icmp_unlock(icp);
+ return res;
}
/*
--
2.31.1
1
3
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/win32u/Makefile.in | 1 +
dlls/win32u/win32u.spec | 1317 +++++++++++++++++++++++++++++++++++++++
2 files changed, 1318 insertions(+)
create mode 100644 dlls/win32u/Makefile.in
create mode 100644 dlls/win32u/win32u.spec
1
0
June 15, 2021
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/jscript/compile.c | 5 +++++
dlls/jscript/lex.c | 2 ++
dlls/jscript/parser.h | 1 +
dlls/jscript/parser.y | 29 ++++++++++++++++++++++++-----
dlls/jscript/tests/lang.js | 25 +++++++++++++++++++++++++
dlls/mshtml/tests/es5.js | 17 +++++++++++++++++
6 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index 9bb9ff13d14..2a17639641f 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -1138,6 +1138,11 @@ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t
if(!iter->expr)
continue;
+ if (iter->block_scope)
+ FIXME("Block scope variables are not supported.\n");
+ if (iter->constant)
+ FIXME("Constant variables are not supported.\n");
+
hres = emit_identifier_ref(ctx, iter->identifier, 0);
if(FAILED(hres))
return hres;
diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c
index efed1038a95..3dd609885e6 100644
--- a/dlls/jscript/lex.c
+++ b/dlls/jscript/lex.c
@@ -41,6 +41,7 @@ static const struct {
{L"break", kBREAK, TRUE},
{L"case", kCASE},
{L"catch", kCATCH},
+ {L"const", kCONST, FALSE},
{L"continue", kCONTINUE, TRUE},
{L"default", kDEFAULT},
{L"delete", kDELETE},
@@ -54,6 +55,7 @@ static const struct {
{L"if", kIF},
{L"in", kIN},
{L"instanceof", kINSTANCEOF},
+ {L"let", kLET, FALSE, SCRIPTLANGUAGEVERSION_ES5},
{L"new", kNEW},
{L"null", kNULL},
{L"return", kRETURN, TRUE},
diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h
index b88a52af242..c4dd0752ee9 100644
--- a/dlls/jscript/parser.h
+++ b/dlls/jscript/parser.h
@@ -95,6 +95,7 @@ literal_t *new_boolean_literal(parser_ctx_t*,BOOL) DECLSPEC_HIDDEN;
typedef struct _variable_declaration_t {
const WCHAR *identifier;
+ BOOL block_scope, constant;
expression_t *expr;
struct _variable_declaration_t *next;
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index f11119143b8..7d0630582e0 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -87,7 +87,7 @@ static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variabl
static void *new_statement(parser_ctx_t*,statement_type_t,size_t,unsigned);
static statement_t *new_block_statement(parser_ctx_t*,unsigned,statement_list_t*);
-static statement_t *new_var_statement(parser_ctx_t*,unsigned,variable_list_t*);
+static statement_t *new_var_statement(parser_ctx_t*,BOOL,BOOL,unsigned,variable_list_t*);
static statement_t *new_expression_statement(parser_ctx_t*,unsigned,expression_t*);
static statement_t *new_if_statement(parser_ctx_t*,unsigned,expression_t*,statement_t*,statement_t*);
static statement_t *new_while_statement(parser_ctx_t*,unsigned,BOOL,expression_t*,statement_t*);
@@ -168,8 +168,9 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
}
/* keywords */
-%token <identifier> kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kFUNCTION kIF kFINALLY kFOR kGET kIN kSET
-%token <identifier> kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
+%token <identifier> kBREAK kCASE kCATCH kCONST kCONTINUE kDEFAULT kDELETE kDO kELSE kFUNCTION kIF kFINALLY kFOR
+%token <identifier> kGET kIN kLET kSET kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE
+%token <identifier> kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ kDCOL
/* tokens */
@@ -182,6 +183,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%type <source_elements> FunctionBody
%type <statement> Statement
%type <statement> Block
+%type <statement> LexicalDeclaration
%type <statement> VariableStatement
%type <statement> EmptyStatement
%type <statement> ExpressionStatement
@@ -291,6 +293,7 @@ FormalParameterList_opt
/* ECMA-262 3rd Edition 12 */
Statement
: Block { $$ = $1; }
+ | LexicalDeclaration { $$ = $1; }
| VariableStatement { $$ = $1; }
| EmptyStatement { $$ = $1; }
| FunctionExpression { $$ = new_expression_statement(ctx, @$, $1); }
@@ -322,10 +325,17 @@ Block
: '{' StatementList '}' { $$ = new_block_statement(ctx, @2, $2); }
| '{' '}' { $$ = new_block_statement(ctx, @$, NULL); }
+/* ECMA-262 10th Edition 13.3.1, TODO: BindingList*/
+LexicalDeclaration
+ : kLET VariableDeclarationList semicolon_opt
+ { $$ = new_var_statement(ctx, TRUE, FALSE, @$, $2); }
+ | kCONST VariableDeclarationList semicolon_opt
+ { $$ = new_var_statement(ctx, TRUE, TRUE, @$, $2); }
+
/* ECMA-262 3rd Edition 12.2 */
VariableStatement
: kVAR VariableDeclarationList semicolon_opt
- { $$ = new_var_statement(ctx, @$, $2); }
+ { $$ = new_var_statement(ctx, FALSE, FALSE, @$, $2); }
/* ECMA-262 3rd Edition 12.2 */
VariableDeclarationList
@@ -834,6 +844,7 @@ ReservedAsIdentifier
: kBREAK { $$ = $1; }
| kCASE { $$ = $1; }
| kCATCH { $$ = $1; }
+ | kCONST { $$ = $1; }
| kCONTINUE { $$ = $1; }
| kDEFAULT { $$ = $1; }
| kDELETE { $$ = $1; }
@@ -847,6 +858,7 @@ ReservedAsIdentifier
| kIF { $$ = $1; }
| kIN { $$ = $1; }
| kINSTANCEOF { $$ = $1; }
+ | kLET { $$ = $1; }
| kNEW { $$ = $1; }
| kNULL { $$ = $1; }
| kRETURN { $$ = $1; }
@@ -1144,8 +1156,10 @@ static variable_list_t *variable_list_add(parser_ctx_t *ctx, variable_list_t *li
return list;
}
-static statement_t *new_var_statement(parser_ctx_t *ctx, unsigned loc, variable_list_t *variable_list)
+static statement_t *new_var_statement(parser_ctx_t *ctx, BOOL block_scope, BOOL constant, unsigned loc,
+ variable_list_t *variable_list)
{
+ variable_declaration_t *var;
var_statement_t *ret;
ret = new_statement(ctx, STAT_VAR, sizeof(*ret), loc);
@@ -1153,6 +1167,11 @@ static statement_t *new_var_statement(parser_ctx_t *ctx, unsigned loc, variable_
return NULL;
ret->variable_list = variable_list->head;
+ for (var = ret->variable_list; var; var = var->next)
+ {
+ var->block_scope = block_scope;
+ var->constant = constant;
+ }
return &ret->stat;
}
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 9e6e6ad239f..2028d233ccf 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -2030,3 +2030,28 @@ Math = 6;
ok(Math === 6, "NaN !== 6");
reportSuccess();
+
+function test_es5_keywords() {
+ var let = 1
+ var tmp
+ ok(let == 1, "let != 1");
+
+ tmp = false
+ try {
+ eval('var var = 1;');
+ }
+ catch(e) {
+ tmp = true
+ }
+ ok(tmp === true, "Expected exception for 'var var = 1;'");
+
+ tmp = false
+ try {
+ eval('var const = 1;');
+ }
+ catch(e) {
+ tmp = true
+ }
+ ok(tmp === true, "Expected exception for 'var const = 1;'");
+}
+test_es5_keywords();
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 7e46848d40e..24906de5231 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -1207,3 +1207,20 @@ sync_test("head_setter", function() {
document.head = "";
ok(typeof(document.head) === "object", "typeof(document.head) = " + typeof(document.head));
});
+
+
+sync_test("declaration_let", function() {
+ ok(a === undefined, "a is not undefined");
+ var a = 3;
+
+ {
+ let a = 2;
+
+ ok(a == 2, "a != 2");
+
+ a = 4;
+ ok(a == 4, "a != 4");
+ }
+
+ todo_wine.ok(a == 3, "a != 3");
+});
--
2.31.1
3
11
[PATCH 1/4] mf: Move presentation clock implementation to a separate file.
by Nikolay Sivov June 15, 2021
by Nikolay Sivov June 15, 2021
June 15, 2021
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/Makefile.in | 1 +
dlls/mf/clock.c | 1162 +++++++++++++++++++++++++++++++++++++++++++
dlls/mf/session.c | 1135 ------------------------------------------
3 files changed, 1163 insertions(+), 1135 deletions(-)
create mode 100644 dlls/mf/clock.c
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
index e56d4c04a84..e80883fb642 100644
--- a/dlls/mf/Makefile.in
+++ b/dlls/mf/Makefile.in
@@ -6,6 +6,7 @@ DELAYIMPORTS = evr user32
EXTRADLLFLAGS = -mno-cygwin -Wb,--prefer-native
C_SRCS = \
+ clock.c \
copier.c \
evr.c \
main.c \
diff --git a/dlls/mf/clock.c b/dlls/mf/clock.c
new file mode 100644
index 00000000000..a9ca9b4528b
--- /dev/null
+++ b/dlls/mf/clock.c
@@ -0,0 +1,1162 @@
+/*
+ * Copyright 2017 Nikolay Sivov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/list.h"
+
+#include "mf_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct clock_sink
+{
+ struct list entry;
+ IMFClockStateSink *state_sink;
+};
+
+enum clock_command
+{
+ CLOCK_CMD_START = 0,
+ CLOCK_CMD_STOP,
+ CLOCK_CMD_PAUSE,
+ CLOCK_CMD_SET_RATE,
+ CLOCK_CMD_MAX,
+};
+
+enum clock_notification
+{
+ CLOCK_NOTIFY_START,
+ CLOCK_NOTIFY_STOP,
+ CLOCK_NOTIFY_PAUSE,
+ CLOCK_NOTIFY_RESTART,
+ CLOCK_NOTIFY_SET_RATE,
+};
+
+struct clock_state_change_param
+{
+ union
+ {
+ LONGLONG offset;
+ float rate;
+ } u;
+};
+
+struct sink_notification
+{
+ IUnknown IUnknown_iface;
+ LONG refcount;
+ MFTIME system_time;
+ struct clock_state_change_param param;
+ enum clock_notification notification;
+ IMFClockStateSink *sink;
+};
+
+struct clock_timer
+{
+ IUnknown IUnknown_iface;
+ LONG refcount;
+ IMFAsyncResult *result;
+ IMFAsyncCallback *callback;
+ MFWORKITEM_KEY key;
+ struct list entry;
+};
+
+struct presentation_clock
+{
+ IMFPresentationClock IMFPresentationClock_iface;
+ IMFRateControl IMFRateControl_iface;
+ IMFTimer IMFTimer_iface;
+ IMFShutdown IMFShutdown_iface;
+ IMFAsyncCallback sink_callback;
+ IMFAsyncCallback timer_callback;
+ LONG refcount;
+ IMFPresentationTimeSource *time_source;
+ IMFClockStateSink *time_source_sink;
+ MFCLOCK_STATE state;
+ LONGLONG start_offset;
+ struct list sinks;
+ struct list timers;
+ float rate;
+ LONGLONG frequency;
+ CRITICAL_SECTION cs;
+ BOOL is_shut_down;
+};
+
+static struct presentation_clock *impl_from_IMFPresentationClock(IMFPresentationClock *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, IMFPresentationClock_iface);
+}
+
+static struct presentation_clock *impl_from_IMFRateControl(IMFRateControl *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, IMFRateControl_iface);
+}
+
+static struct presentation_clock *impl_from_IMFTimer(IMFTimer *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, IMFTimer_iface);
+}
+
+static struct presentation_clock *impl_from_IMFShutdown(IMFShutdown *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, IMFShutdown_iface);
+}
+
+static struct presentation_clock *impl_from_sink_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, sink_callback);
+}
+
+static struct presentation_clock *impl_from_timer_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct presentation_clock, timer_callback);
+}
+
+static struct clock_timer *impl_clock_timer_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct clock_timer, IUnknown_iface);
+}
+
+static struct sink_notification *impl_sink_notification_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct sink_notification, IUnknown_iface);
+}
+
+static HRESULT WINAPI sink_notification_QueryInterface(IUnknown *iface, REFIID riid, void **out)
+{
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *out = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI sink_notification_AddRef(IUnknown *iface)
+{
+ struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface);
+ ULONG refcount = InterlockedIncrement(¬ification->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI sink_notification_Release(IUnknown *iface)
+{
+ struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface);
+ ULONG refcount = InterlockedDecrement(¬ification->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ IMFClockStateSink_Release(notification->sink);
+ heap_free(notification);
+ }
+
+ return refcount;
+}
+
+static const IUnknownVtbl sinknotificationvtbl =
+{
+ sink_notification_QueryInterface,
+ sink_notification_AddRef,
+ sink_notification_Release,
+};
+
+static void clock_notify_async_sink(struct presentation_clock *clock, MFTIME system_time,
+ struct clock_state_change_param param, enum clock_notification notification, IMFClockStateSink *sink)
+{
+ struct sink_notification *object;
+ IMFAsyncResult *result;
+ HRESULT hr;
+
+ object = heap_alloc(sizeof(*object));
+ if (!object)
+ return;
+
+ object->IUnknown_iface.lpVtbl = &sinknotificationvtbl;
+ object->refcount = 1;
+ object->system_time = system_time;
+ object->param = param;
+ object->notification = notification;
+ object->sink = sink;
+ IMFClockStateSink_AddRef(object->sink);
+
+ hr = MFCreateAsyncResult(&object->IUnknown_iface, &clock->sink_callback, NULL, &result);
+ IUnknown_Release(&object->IUnknown_iface);
+ if (SUCCEEDED(hr))
+ {
+ MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, result);
+ IMFAsyncResult_Release(result);
+ }
+}
+
+static HRESULT WINAPI present_clock_QueryInterface(IMFPresentationClock *iface, REFIID riid, void **out)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualIID(riid, &IID_IMFPresentationClock) ||
+ IsEqualIID(riid, &IID_IMFClock) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *out = &clock->IMFPresentationClock_iface;
+ }
+ else if (IsEqualIID(riid, &IID_IMFRateControl))
+ {
+ *out = &clock->IMFRateControl_iface;
+ }
+ else if (IsEqualIID(riid, &IID_IMFTimer))
+ {
+ *out = &clock->IMFTimer_iface;
+ }
+ else if (IsEqualIID(riid, &IID_IMFShutdown))
+ {
+ *out = &clock->IMFShutdown_iface;
+ }
+ else
+ {
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static ULONG WINAPI present_clock_AddRef(IMFPresentationClock *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ ULONG refcount = InterlockedIncrement(&clock->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ ULONG refcount = InterlockedDecrement(&clock->refcount);
+ struct clock_timer *timer, *timer2;
+ struct clock_sink *sink, *sink2;
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ if (clock->time_source)
+ IMFPresentationTimeSource_Release(clock->time_source);
+ if (clock->time_source_sink)
+ IMFClockStateSink_Release(clock->time_source_sink);
+ LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &clock->sinks, struct clock_sink, entry)
+ {
+ list_remove(&sink->entry);
+ IMFClockStateSink_Release(sink->state_sink);
+ heap_free(sink);
+ }
+ LIST_FOR_EACH_ENTRY_SAFE(timer, timer2, &clock->timers, struct clock_timer, entry)
+ {
+ list_remove(&timer->entry);
+ IUnknown_Release(&timer->IUnknown_iface);
+ }
+ DeleteCriticalSection(&clock->cs);
+ heap_free(clock);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI present_clock_GetClockCharacteristics(IMFPresentationClock *iface, DWORD *flags)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
+
+ TRACE("%p, %p.\n", iface, flags);
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->time_source)
+ hr = IMFPresentationTimeSource_GetClockCharacteristics(clock->time_source, flags);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_GetCorrelatedTime(IMFPresentationClock *iface, DWORD reserved,
+ LONGLONG *clock_time, MFTIME *system_time)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
+
+ TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->time_source)
+ hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, reserved, clock_time, system_time);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_GetContinuityKey(IMFPresentationClock *iface, DWORD *key)
+{
+ TRACE("%p, %p.\n", iface, key);
+
+ *key = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI present_clock_GetState(IMFPresentationClock *iface, DWORD reserved, MFCLOCK_STATE *state)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+
+ TRACE("%p, %#x, %p.\n", iface, reserved, state);
+
+ EnterCriticalSection(&clock->cs);
+ *state = clock->state;
+ LeaveCriticalSection(&clock->cs);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI present_clock_GetProperties(IMFPresentationClock *iface, MFCLOCK_PROPERTIES *props)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
+
+ TRACE("%p, %p.\n", iface, props);
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->time_source)
+ hr = IMFPresentationTimeSource_GetProperties(clock->time_source, props);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_SetTimeSource(IMFPresentationClock *iface,
+ IMFPresentationTimeSource *time_source)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ MFCLOCK_PROPERTIES props;
+ IMFClock *source_clock;
+ HRESULT hr;
+
+ TRACE("%p, %p.\n", iface, time_source);
+
+ EnterCriticalSection(&clock->cs);
+
+ if (clock->time_source)
+ IMFPresentationTimeSource_Release(clock->time_source);
+ if (clock->time_source_sink)
+ IMFClockStateSink_Release(clock->time_source_sink);
+ clock->time_source = NULL;
+ clock->time_source_sink = NULL;
+
+ hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&clock->time_source_sink);
+ if (SUCCEEDED(hr))
+ {
+ clock->time_source = time_source;
+ IMFPresentationTimeSource_AddRef(clock->time_source);
+ }
+
+ if (SUCCEEDED(IMFPresentationTimeSource_GetUnderlyingClock(time_source, &source_clock)))
+ {
+ if (SUCCEEDED(IMFClock_GetProperties(source_clock, &props)))
+ clock->frequency = props.qwClockFrequency;
+ IMFClock_Release(source_clock);
+ }
+
+ if (!clock->frequency)
+ clock->frequency = MFCLOCK_FREQUENCY_HNS;
+
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_GetTimeSource(IMFPresentationClock *iface,
+ IMFPresentationTimeSource **time_source)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p.\n", iface, time_source);
+
+ if (!time_source)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->time_source)
+ {
+ *time_source = clock->time_source;
+ IMFPresentationTimeSource_AddRef(*time_source);
+ }
+ else
+ hr = MF_E_CLOCK_NO_TIME_SOURCE;
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_GetTime(IMFPresentationClock *iface, MFTIME *time)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
+ MFTIME systime;
+
+ TRACE("%p, %p.\n", iface, time);
+
+ if (!time)
+ return E_POINTER;
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->time_source)
+ hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, time, &systime);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_AddClockStateSink(IMFPresentationClock *iface, IMFClockStateSink *state_sink)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ struct clock_sink *sink, *cur;
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p.\n", iface, state_sink);
+
+ if (!state_sink)
+ return E_INVALIDARG;
+
+ sink = heap_alloc(sizeof(*sink));
+ if (!sink)
+ return E_OUTOFMEMORY;
+
+ sink->state_sink = state_sink;
+ IMFClockStateSink_AddRef(sink->state_sink);
+
+ EnterCriticalSection(&clock->cs);
+ LIST_FOR_EACH_ENTRY(cur, &clock->sinks, struct clock_sink, entry)
+ {
+ if (cur->state_sink == state_sink)
+ {
+ hr = E_INVALIDARG;
+ break;
+ }
+ }
+ if (SUCCEEDED(hr))
+ {
+ static const enum clock_notification notifications[MFCLOCK_STATE_PAUSED + 1] =
+ {
+ /* MFCLOCK_STATE_INVALID */ 0, /* Does not apply */
+ /* MFCLOCK_STATE_RUNNING */ CLOCK_NOTIFY_START,
+ /* MFCLOCK_STATE_STOPPED */ CLOCK_NOTIFY_STOP,
+ /* MFCLOCK_STATE_PAUSED */ CLOCK_NOTIFY_PAUSE,
+ };
+ struct clock_state_change_param param;
+
+ if (!clock->is_shut_down && clock->state != MFCLOCK_STATE_INVALID)
+ {
+ param.u.offset = clock->start_offset;
+ clock_notify_async_sink(clock, MFGetSystemTime(), param, notifications[clock->state], sink->state_sink);
+ }
+
+ list_add_tail(&clock->sinks, &sink->entry);
+ }
+ LeaveCriticalSection(&clock->cs);
+
+ if (FAILED(hr))
+ {
+ IMFClockStateSink_Release(sink->state_sink);
+ heap_free(sink);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *iface,
+ IMFClockStateSink *state_sink)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ struct clock_sink *sink;
+
+ TRACE("%p, %p.\n", iface, state_sink);
+
+ if (!state_sink)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&clock->cs);
+ LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry)
+ {
+ if (sink->state_sink == state_sink)
+ {
+ IMFClockStateSink_Release(sink->state_sink);
+ list_remove(&sink->entry);
+ heap_free(sink);
+ break;
+ }
+ }
+ LeaveCriticalSection(&clock->cs);
+
+ return S_OK;
+}
+
+static HRESULT clock_call_state_change(MFTIME system_time, struct clock_state_change_param param,
+ enum clock_notification notification, IMFClockStateSink *sink)
+{
+ HRESULT hr = S_OK;
+
+ switch (notification)
+ {
+ case CLOCK_NOTIFY_START:
+ hr = IMFClockStateSink_OnClockStart(sink, system_time, param.u.offset);
+ break;
+ case CLOCK_NOTIFY_STOP:
+ hr = IMFClockStateSink_OnClockStop(sink, system_time);
+ break;
+ case CLOCK_NOTIFY_PAUSE:
+ hr = IMFClockStateSink_OnClockPause(sink, system_time);
+ break;
+ case CLOCK_NOTIFY_RESTART:
+ hr = IMFClockStateSink_OnClockRestart(sink, system_time);
+ break;
+ case CLOCK_NOTIFY_SET_RATE:
+ /* System time source does not allow 0.0 rate, presentation clock allows it without raising errors. */
+ IMFClockStateSink_OnClockSetRate(sink, system_time, param.u.rate);
+ break;
+ default:
+ ;
+ }
+
+ return hr;
+}
+
+static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_command command,
+ struct clock_state_change_param param)
+{
+ static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
+ { /* S S* P, R */
+ /* INVALID */ { 1, 1, 1, 1 },
+ /* RUNNING */ { 1, 1, 1, 1 },
+ /* STOPPED */ { 1, 1, 0, 1 },
+ /* PAUSED */ { 1, 1, 0, 1 },
+ };
+ static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
+ {
+ /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
+ /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
+ /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
+ /* CLOCK_CMD_SET_RATE */ 0, /* Unused */
+ };
+ static const enum clock_notification notifications[CLOCK_CMD_MAX] =
+ {
+ /* CLOCK_CMD_START */ CLOCK_NOTIFY_START,
+ /* CLOCK_CMD_STOP */ CLOCK_NOTIFY_STOP,
+ /* CLOCK_CMD_PAUSE */ CLOCK_NOTIFY_PAUSE,
+ /* CLOCK_CMD_SET_RATE */ CLOCK_NOTIFY_SET_RATE,
+ };
+ enum clock_notification notification;
+ struct clock_sink *sink;
+ MFCLOCK_STATE old_state;
+ IMFAsyncResult *result;
+ MFTIME system_time;
+ HRESULT hr;
+
+ if (!clock->time_source)
+ return MF_E_CLOCK_NO_TIME_SOURCE;
+
+ if (command != CLOCK_CMD_SET_RATE && clock->state == states[command] && clock->state != MFCLOCK_STATE_RUNNING)
+ return MF_E_CLOCK_STATE_ALREADY_SET;
+
+ if (!state_change_is_allowed[clock->state][command])
+ return MF_E_INVALIDREQUEST;
+
+ system_time = MFGetSystemTime();
+
+ if (command == CLOCK_CMD_START && clock->state == MFCLOCK_STATE_PAUSED &&
+ param.u.offset == PRESENTATION_CURRENT_POSITION)
+ {
+ notification = CLOCK_NOTIFY_RESTART;
+ }
+ else
+ notification = notifications[command];
+
+ if (FAILED(hr = clock_call_state_change(system_time, param, notification, clock->time_source_sink)))
+ return hr;
+
+ old_state = clock->state;
+ if (command != CLOCK_CMD_SET_RATE)
+ clock->state = states[command];
+
+ /* Dump all pending timer requests immediately on start; otherwise try to cancel scheduled items when
+ transitioning from running state. */
+ if ((clock->state == MFCLOCK_STATE_RUNNING) ^ (old_state == MFCLOCK_STATE_RUNNING))
+ {
+ struct clock_timer *timer, *timer2;
+
+ if (clock->state == MFCLOCK_STATE_RUNNING)
+ {
+ LIST_FOR_EACH_ENTRY_SAFE(timer, timer2, &clock->timers, struct clock_timer, entry)
+ {
+ list_remove(&timer->entry);
+ hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result);
+ IUnknown_Release(&timer->IUnknown_iface);
+ if (SUCCEEDED(hr))
+ {
+ MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_TIMER, result);
+ IMFAsyncResult_Release(result);
+ }
+ }
+ }
+ else
+ {
+ LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry)
+ {
+ if (timer->key)
+ {
+ MFCancelWorkItem(timer->key);
+ timer->key = 0;
+ }
+ }
+ }
+ }
+
+ LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry)
+ {
+ clock_notify_async_sink(clock, system_time, param, notification, sink->state_sink);
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI present_clock_Start(IMFPresentationClock *iface, LONGLONG start_offset)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ struct clock_state_change_param param = {{0}};
+ HRESULT hr;
+
+ TRACE("%p, %s.\n", iface, debugstr_time(start_offset));
+
+ EnterCriticalSection(&clock->cs);
+ clock->start_offset = param.u.offset = start_offset;
+ hr = clock_change_state(clock, CLOCK_CMD_START, param);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_Stop(IMFPresentationClock *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ struct clock_state_change_param param = {{0}};
+ HRESULT hr;
+
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&clock->cs);
+ hr = clock_change_state(clock, CLOCK_CMD_STOP, param);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_Pause(IMFPresentationClock *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+ struct clock_state_change_param param = {{0}};
+ HRESULT hr;
+
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&clock->cs);
+ hr = clock_change_state(clock, CLOCK_CMD_PAUSE, param);
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static const IMFPresentationClockVtbl presentationclockvtbl =
+{
+ present_clock_QueryInterface,
+ present_clock_AddRef,
+ present_clock_Release,
+ present_clock_GetClockCharacteristics,
+ present_clock_GetCorrelatedTime,
+ present_clock_GetContinuityKey,
+ present_clock_GetState,
+ present_clock_GetProperties,
+ present_clock_SetTimeSource,
+ present_clock_GetTimeSource,
+ present_clock_GetTime,
+ present_clock_AddClockStateSink,
+ present_clock_RemoveClockStateSink,
+ present_clock_Start,
+ present_clock_Stop,
+ present_clock_Pause,
+};
+
+static HRESULT WINAPI present_clock_rate_control_QueryInterface(IMFRateControl *iface, REFIID riid, void **out)
+{
+ struct presentation_clock *clock = impl_from_IMFRateControl(iface);
+ return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
+}
+
+static ULONG WINAPI present_clock_rate_control_AddRef(IMFRateControl *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFRateControl(iface);
+ return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
+}
+
+static ULONG WINAPI present_clock_rate_control_Release(IMFRateControl *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFRateControl(iface);
+ return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
+}
+
+static HRESULT WINAPI present_clock_rate_SetRate(IMFRateControl *iface, BOOL thin, float rate)
+{
+ struct presentation_clock *clock = impl_from_IMFRateControl(iface);
+ struct clock_state_change_param param;
+ HRESULT hr;
+
+ TRACE("%p, %d, %f.\n", iface, thin, rate);
+
+ if (thin)
+ return MF_E_THINNING_UNSUPPORTED;
+
+ EnterCriticalSection(&clock->cs);
+ param.u.rate = rate;
+ if (SUCCEEDED(hr = clock_change_state(clock, CLOCK_CMD_SET_RATE, param)))
+ clock->rate = rate;
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_rate_GetRate(IMFRateControl *iface, BOOL *thin, float *rate)
+{
+ struct presentation_clock *clock = impl_from_IMFRateControl(iface);
+
+ TRACE("%p, %p, %p.\n", iface, thin, rate);
+
+ if (!rate)
+ return E_INVALIDARG;
+
+ if (thin)
+ *thin = FALSE;
+
+ EnterCriticalSection(&clock->cs);
+ *rate = clock->rate;
+ LeaveCriticalSection(&clock->cs);
+
+ return S_OK;
+}
+
+static const IMFRateControlVtbl presentclockratecontrolvtbl =
+{
+ present_clock_rate_control_QueryInterface,
+ present_clock_rate_control_AddRef,
+ present_clock_rate_control_Release,
+ present_clock_rate_SetRate,
+ present_clock_rate_GetRate,
+};
+
+static HRESULT WINAPI present_clock_timer_QueryInterface(IMFTimer *iface, REFIID riid, void **out)
+{
+ struct presentation_clock *clock = impl_from_IMFTimer(iface);
+ return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
+}
+
+static ULONG WINAPI present_clock_timer_AddRef(IMFTimer *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFTimer(iface);
+ return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
+}
+
+static ULONG WINAPI present_clock_timer_Release(IMFTimer *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFTimer(iface);
+ return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
+}
+
+static HRESULT present_clock_schedule_timer(struct presentation_clock *clock, DWORD flags, LONGLONG time,
+ struct clock_timer *timer)
+{
+ IMFAsyncResult *result;
+ MFTIME systime, clocktime;
+ LONGLONG frequency;
+ HRESULT hr;
+
+ if (!(flags & MFTIMER_RELATIVE))
+ {
+ if (FAILED(hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, &clocktime, &systime)))
+ {
+ WARN("Failed to get clock time, hr %#x.\n", hr);
+ return hr;
+ }
+ time -= clocktime;
+ }
+
+ frequency = clock->frequency / 1000;
+ time /= frequency;
+
+ /* Scheduled item is using clock instance callback, with timer instance as an object. Clock callback will
+ call user callback and cleanup timer list. */
+
+ if (FAILED(hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result)))
+ return hr;
+
+ hr = MFScheduleWorkItemEx(result, -time, &timer->key);
+ IMFAsyncResult_Release(result);
+
+ return hr;
+}
+
+static HRESULT WINAPI clock_timer_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI clock_timer_AddRef(IUnknown *iface)
+{
+ struct clock_timer *timer = impl_clock_timer_from_IUnknown(iface);
+ return InterlockedIncrement(&timer->refcount);
+}
+
+static ULONG WINAPI clock_timer_Release(IUnknown *iface)
+{
+ struct clock_timer *timer = impl_clock_timer_from_IUnknown(iface);
+ ULONG refcount = InterlockedDecrement(&timer->refcount);
+
+ if (!refcount)
+ {
+ IMFAsyncResult_Release(timer->result);
+ IMFAsyncCallback_Release(timer->callback);
+ heap_free(timer);
+ }
+
+ return refcount;
+}
+
+static const IUnknownVtbl clock_timer_vtbl =
+{
+ clock_timer_QueryInterface,
+ clock_timer_AddRef,
+ clock_timer_Release,
+};
+
+static HRESULT WINAPI present_clock_timer_SetTimer(IMFTimer *iface, DWORD flags, LONGLONG time,
+ IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_key)
+{
+ struct presentation_clock *clock = impl_from_IMFTimer(iface);
+ struct clock_timer *clock_timer;
+ HRESULT hr;
+
+ TRACE("%p, %#x, %s, %p, %p, %p.\n", iface, flags, debugstr_time(time), callback, state, cancel_key);
+
+ if (!(clock_timer = heap_alloc_zero(sizeof(*clock_timer))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = MFCreateAsyncResult(NULL, NULL, state, &clock_timer->result)))
+ {
+ heap_free(clock_timer);
+ return hr;
+ }
+
+ clock_timer->IUnknown_iface.lpVtbl = &clock_timer_vtbl;
+ clock_timer->refcount = 1;
+ clock_timer->callback = callback;
+ IMFAsyncCallback_AddRef(clock_timer->callback);
+
+ EnterCriticalSection(&clock->cs);
+
+ if (clock->state == MFCLOCK_STATE_RUNNING)
+ hr = present_clock_schedule_timer(clock, flags, time, clock_timer);
+ else if (clock->state == MFCLOCK_STATE_STOPPED)
+ hr = MF_S_CLOCK_STOPPED;
+
+ if (SUCCEEDED(hr))
+ {
+ list_add_tail(&clock->timers, &clock_timer->entry);
+ if (cancel_key)
+ {
+ *cancel_key = &clock_timer->IUnknown_iface;
+ IUnknown_AddRef(*cancel_key);
+ }
+ }
+
+ LeaveCriticalSection(&clock->cs);
+
+ if (FAILED(hr))
+ IUnknown_Release(&clock_timer->IUnknown_iface);
+
+ return hr;
+}
+
+static HRESULT WINAPI present_clock_timer_CancelTimer(IMFTimer *iface, IUnknown *cancel_key)
+{
+ struct presentation_clock *clock = impl_from_IMFTimer(iface);
+ struct clock_timer *timer;
+
+ TRACE("%p, %p.\n", iface, cancel_key);
+
+ EnterCriticalSection(&clock->cs);
+
+ LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry)
+ {
+ if (&timer->IUnknown_iface == cancel_key)
+ {
+ list_remove(&timer->entry);
+ if (timer->key)
+ {
+ MFCancelWorkItem(timer->key);
+ timer->key = 0;
+ }
+ IUnknown_Release(&timer->IUnknown_iface);
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&clock->cs);
+
+ return S_OK;
+}
+
+static const IMFTimerVtbl presentclocktimervtbl =
+{
+ present_clock_timer_QueryInterface,
+ present_clock_timer_AddRef,
+ present_clock_timer_Release,
+ present_clock_timer_SetTimer,
+ present_clock_timer_CancelTimer,
+};
+
+static HRESULT WINAPI present_clock_shutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **out)
+{
+ struct presentation_clock *clock = impl_from_IMFShutdown(iface);
+ return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
+}
+
+static ULONG WINAPI present_clock_shutdown_AddRef(IMFShutdown *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFShutdown(iface);
+ return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
+}
+
+static ULONG WINAPI present_clock_shutdown_Release(IMFShutdown *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFShutdown(iface);
+ return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
+}
+
+static HRESULT WINAPI present_clock_shutdown_Shutdown(IMFShutdown *iface)
+{
+ struct presentation_clock *clock = impl_from_IMFShutdown(iface);
+
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&clock->cs);
+ clock->is_shut_down = TRUE;
+ LeaveCriticalSection(&clock->cs);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI present_clock_shutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
+{
+ struct presentation_clock *clock = impl_from_IMFShutdown(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p.\n", iface, status);
+
+ if (!status)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&clock->cs);
+ if (clock->is_shut_down)
+ *status = MFSHUTDOWN_COMPLETED;
+ else
+ hr = MF_E_INVALIDREQUEST;
+ LeaveCriticalSection(&clock->cs);
+
+ return hr;
+}
+
+static const IMFShutdownVtbl presentclockshutdownvtbl =
+{
+ present_clock_shutdown_QueryInterface,
+ present_clock_shutdown_AddRef,
+ present_clock_shutdown_Release,
+ present_clock_shutdown_Shutdown,
+ present_clock_shutdown_GetShutdownStatus,
+};
+
+static HRESULT WINAPI present_clock_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **out)
+{
+ if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *out = iface;
+ IMFAsyncCallback_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", wine_dbgstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI present_clock_sink_callback_AddRef(IMFAsyncCallback *iface)
+{
+ struct presentation_clock *clock = impl_from_sink_callback_IMFAsyncCallback(iface);
+ return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
+}
+
+static ULONG WINAPI present_clock_sink_callback_Release(IMFAsyncCallback *iface)
+{
+ struct presentation_clock *clock = impl_from_sink_callback_IMFAsyncCallback(iface);
+ return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
+}
+
+static HRESULT WINAPI present_clock_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI present_clock_sink_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct sink_notification *data;
+ IUnknown *object;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFAsyncResult_GetObject(result, &object)))
+ return hr;
+
+ data = impl_sink_notification_from_IUnknown(object);
+
+ clock_call_state_change(data->system_time, data->param, data->notification, data->sink);
+
+ IUnknown_Release(object);
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl presentclocksinkcallbackvtbl =
+{
+ present_clock_callback_QueryInterface,
+ present_clock_sink_callback_AddRef,
+ present_clock_sink_callback_Release,
+ present_clock_callback_GetParameters,
+ present_clock_sink_callback_Invoke,
+};
+
+static ULONG WINAPI present_clock_timer_callback_AddRef(IMFAsyncCallback *iface)
+{
+ struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
+ return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
+}
+
+static ULONG WINAPI present_clock_timer_callback_Release(IMFAsyncCallback *iface)
+{
+ struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
+ return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
+}
+
+static HRESULT WINAPI present_clock_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
+ struct clock_timer *timer;
+ IUnknown *object;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFAsyncResult_GetObject(result, &object)))
+ return hr;
+
+ timer = impl_clock_timer_from_IUnknown(object);
+
+ EnterCriticalSection(&clock->cs);
+ list_remove(&timer->entry);
+ IUnknown_Release(&timer->IUnknown_iface);
+ LeaveCriticalSection(&clock->cs);
+
+ IMFAsyncCallback_Invoke(timer->callback, timer->result);
+
+ IUnknown_Release(object);
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl presentclocktimercallbackvtbl =
+{
+ present_clock_callback_QueryInterface,
+ present_clock_timer_callback_AddRef,
+ present_clock_timer_callback_Release,
+ present_clock_callback_GetParameters,
+ present_clock_timer_callback_Invoke,
+};
+
+/***********************************************************************
+ * MFCreatePresentationClock (mf.@)
+ */
+HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock)
+{
+ struct presentation_clock *object;
+
+ TRACE("%p.\n", clock);
+
+ object = heap_alloc_zero(sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->IMFPresentationClock_iface.lpVtbl = &presentationclockvtbl;
+ object->IMFRateControl_iface.lpVtbl = &presentclockratecontrolvtbl;
+ object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl;
+ object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl;
+ object->sink_callback.lpVtbl = &presentclocksinkcallbackvtbl;
+ object->timer_callback.lpVtbl = &presentclocktimercallbackvtbl;
+ object->refcount = 1;
+ list_init(&object->sinks);
+ list_init(&object->timers);
+ object->rate = 1.0f;
+ InitializeCriticalSection(&object->cs);
+
+ *clock = &object->IMFPresentationClock_iface;
+
+ return S_OK;
+}
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 9f233295773..a7f81e694c2 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -247,80 +247,6 @@ struct media_session
CRITICAL_SECTION cs;
};
-struct clock_sink
-{
- struct list entry;
- IMFClockStateSink *state_sink;
-};
-
-enum clock_command
-{
- CLOCK_CMD_START = 0,
- CLOCK_CMD_STOP,
- CLOCK_CMD_PAUSE,
- CLOCK_CMD_SET_RATE,
- CLOCK_CMD_MAX,
-};
-
-enum clock_notification
-{
- CLOCK_NOTIFY_START,
- CLOCK_NOTIFY_STOP,
- CLOCK_NOTIFY_PAUSE,
- CLOCK_NOTIFY_RESTART,
- CLOCK_NOTIFY_SET_RATE,
-};
-
-struct clock_state_change_param
-{
- union
- {
- LONGLONG offset;
- float rate;
- } u;
-};
-
-struct sink_notification
-{
- IUnknown IUnknown_iface;
- LONG refcount;
- MFTIME system_time;
- struct clock_state_change_param param;
- enum clock_notification notification;
- IMFClockStateSink *sink;
-};
-
-struct clock_timer
-{
- IUnknown IUnknown_iface;
- LONG refcount;
- IMFAsyncResult *result;
- IMFAsyncCallback *callback;
- MFWORKITEM_KEY key;
- struct list entry;
-};
-
-struct presentation_clock
-{
- IMFPresentationClock IMFPresentationClock_iface;
- IMFRateControl IMFRateControl_iface;
- IMFTimer IMFTimer_iface;
- IMFShutdown IMFShutdown_iface;
- IMFAsyncCallback sink_callback;
- IMFAsyncCallback timer_callback;
- LONG refcount;
- IMFPresentationTimeSource *time_source;
- IMFClockStateSink *time_source_sink;
- MFCLOCK_STATE state;
- LONGLONG start_offset;
- struct list sinks;
- struct list timers;
- float rate;
- LONGLONG frequency;
- CRITICAL_SECTION cs;
- BOOL is_shut_down;
-};
-
enum quality_manager_state
{
QUALITY_MANAGER_READY = 0,
@@ -384,46 +310,6 @@ static struct session_op *impl_op_from_IUnknown(IUnknown *iface)
return CONTAINING_RECORD(iface, struct session_op, IUnknown_iface);
}
-static struct presentation_clock *impl_from_IMFPresentationClock(IMFPresentationClock *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, IMFPresentationClock_iface);
-}
-
-static struct presentation_clock *impl_from_IMFRateControl(IMFRateControl *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, IMFRateControl_iface);
-}
-
-static struct presentation_clock *impl_from_IMFTimer(IMFTimer *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, IMFTimer_iface);
-}
-
-static struct presentation_clock *impl_from_IMFShutdown(IMFShutdown *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, IMFShutdown_iface);
-}
-
-static struct presentation_clock *impl_from_sink_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, sink_callback);
-}
-
-static struct presentation_clock *impl_from_timer_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
-{
- return CONTAINING_RECORD(iface, struct presentation_clock, timer_callback);
-}
-
-static struct clock_timer *impl_clock_timer_from_IUnknown(IUnknown *iface)
-{
- return CONTAINING_RECORD(iface, struct clock_timer, IUnknown_iface);
-}
-
-static struct sink_notification *impl_sink_notification_from_IUnknown(IUnknown *iface)
-{
- return CONTAINING_RECORD(iface, struct sink_notification, IUnknown_iface);
-}
-
static struct quality_manager *impl_from_IMFQualityManager(IMFQualityManager *iface)
{
return CONTAINING_RECORD(iface, struct quality_manager, IMFQualityManager_iface);
@@ -3795,1027 +3681,6 @@ failed:
return hr;
}
-static HRESULT WINAPI sink_notification_QueryInterface(IUnknown *iface, REFIID riid, void **out)
-{
- if (IsEqualIID(riid, &IID_IUnknown))
- {
- *out = iface;
- IUnknown_AddRef(iface);
- return S_OK;
- }
-
- WARN("Unsupported %s.\n", debugstr_guid(riid));
- *out = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI sink_notification_AddRef(IUnknown *iface)
-{
- struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface);
- ULONG refcount = InterlockedIncrement(¬ification->refcount);
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- return refcount;
-}
-
-static ULONG WINAPI sink_notification_Release(IUnknown *iface)
-{
- struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface);
- ULONG refcount = InterlockedDecrement(¬ification->refcount);
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- if (!refcount)
- {
- IMFClockStateSink_Release(notification->sink);
- heap_free(notification);
- }
-
- return refcount;
-}
-
-static const IUnknownVtbl sinknotificationvtbl =
-{
- sink_notification_QueryInterface,
- sink_notification_AddRef,
- sink_notification_Release,
-};
-
-static void clock_notify_async_sink(struct presentation_clock *clock, MFTIME system_time,
- struct clock_state_change_param param, enum clock_notification notification, IMFClockStateSink *sink)
-{
- struct sink_notification *object;
- IMFAsyncResult *result;
- HRESULT hr;
-
- object = heap_alloc(sizeof(*object));
- if (!object)
- return;
-
- object->IUnknown_iface.lpVtbl = &sinknotificationvtbl;
- object->refcount = 1;
- object->system_time = system_time;
- object->param = param;
- object->notification = notification;
- object->sink = sink;
- IMFClockStateSink_AddRef(object->sink);
-
- hr = MFCreateAsyncResult(&object->IUnknown_iface, &clock->sink_callback, NULL, &result);
- IUnknown_Release(&object->IUnknown_iface);
- if (SUCCEEDED(hr))
- {
- MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, result);
- IMFAsyncResult_Release(result);
- }
-}
-
-static HRESULT WINAPI present_clock_QueryInterface(IMFPresentationClock *iface, REFIID riid, void **out)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
-
- TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
-
- if (IsEqualIID(riid, &IID_IMFPresentationClock) ||
- IsEqualIID(riid, &IID_IMFClock) ||
- IsEqualIID(riid, &IID_IUnknown))
- {
- *out = &clock->IMFPresentationClock_iface;
- }
- else if (IsEqualIID(riid, &IID_IMFRateControl))
- {
- *out = &clock->IMFRateControl_iface;
- }
- else if (IsEqualIID(riid, &IID_IMFTimer))
- {
- *out = &clock->IMFTimer_iface;
- }
- else if (IsEqualIID(riid, &IID_IMFShutdown))
- {
- *out = &clock->IMFShutdown_iface;
- }
- else
- {
- WARN("Unsupported %s.\n", debugstr_guid(riid));
- *out = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown *)*out);
- return S_OK;
-}
-
-static ULONG WINAPI present_clock_AddRef(IMFPresentationClock *iface)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- ULONG refcount = InterlockedIncrement(&clock->refcount);
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- return refcount;
-}
-
-static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- ULONG refcount = InterlockedDecrement(&clock->refcount);
- struct clock_timer *timer, *timer2;
- struct clock_sink *sink, *sink2;
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- if (!refcount)
- {
- if (clock->time_source)
- IMFPresentationTimeSource_Release(clock->time_source);
- if (clock->time_source_sink)
- IMFClockStateSink_Release(clock->time_source_sink);
- LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &clock->sinks, struct clock_sink, entry)
- {
- list_remove(&sink->entry);
- IMFClockStateSink_Release(sink->state_sink);
- heap_free(sink);
- }
- LIST_FOR_EACH_ENTRY_SAFE(timer, timer2, &clock->timers, struct clock_timer, entry)
- {
- list_remove(&timer->entry);
- IUnknown_Release(&timer->IUnknown_iface);
- }
- DeleteCriticalSection(&clock->cs);
- heap_free(clock);
- }
-
- return refcount;
-}
-
-static HRESULT WINAPI present_clock_GetClockCharacteristics(IMFPresentationClock *iface, DWORD *flags)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
-
- TRACE("%p, %p.\n", iface, flags);
-
- EnterCriticalSection(&clock->cs);
- if (clock->time_source)
- hr = IMFPresentationTimeSource_GetClockCharacteristics(clock->time_source, flags);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_GetCorrelatedTime(IMFPresentationClock *iface, DWORD reserved,
- LONGLONG *clock_time, MFTIME *system_time)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
-
- TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
-
- EnterCriticalSection(&clock->cs);
- if (clock->time_source)
- hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, reserved, clock_time, system_time);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_GetContinuityKey(IMFPresentationClock *iface, DWORD *key)
-{
- TRACE("%p, %p.\n", iface, key);
-
- *key = 0;
-
- return S_OK;
-}
-
-static HRESULT WINAPI present_clock_GetState(IMFPresentationClock *iface, DWORD reserved, MFCLOCK_STATE *state)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
-
- TRACE("%p, %#x, %p.\n", iface, reserved, state);
-
- EnterCriticalSection(&clock->cs);
- *state = clock->state;
- LeaveCriticalSection(&clock->cs);
-
- return S_OK;
-}
-
-static HRESULT WINAPI present_clock_GetProperties(IMFPresentationClock *iface, MFCLOCK_PROPERTIES *props)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
-
- TRACE("%p, %p.\n", iface, props);
-
- EnterCriticalSection(&clock->cs);
- if (clock->time_source)
- hr = IMFPresentationTimeSource_GetProperties(clock->time_source, props);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_SetTimeSource(IMFPresentationClock *iface,
- IMFPresentationTimeSource *time_source)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- MFCLOCK_PROPERTIES props;
- IMFClock *source_clock;
- HRESULT hr;
-
- TRACE("%p, %p.\n", iface, time_source);
-
- EnterCriticalSection(&clock->cs);
-
- if (clock->time_source)
- IMFPresentationTimeSource_Release(clock->time_source);
- if (clock->time_source_sink)
- IMFClockStateSink_Release(clock->time_source_sink);
- clock->time_source = NULL;
- clock->time_source_sink = NULL;
-
- hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&clock->time_source_sink);
- if (SUCCEEDED(hr))
- {
- clock->time_source = time_source;
- IMFPresentationTimeSource_AddRef(clock->time_source);
- }
-
- if (SUCCEEDED(IMFPresentationTimeSource_GetUnderlyingClock(time_source, &source_clock)))
- {
- if (SUCCEEDED(IMFClock_GetProperties(source_clock, &props)))
- clock->frequency = props.qwClockFrequency;
- IMFClock_Release(source_clock);
- }
-
- if (!clock->frequency)
- clock->frequency = MFCLOCK_FREQUENCY_HNS;
-
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_GetTimeSource(IMFPresentationClock *iface,
- IMFPresentationTimeSource **time_source)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- HRESULT hr = S_OK;
-
- TRACE("%p, %p.\n", iface, time_source);
-
- if (!time_source)
- return E_INVALIDARG;
-
- EnterCriticalSection(&clock->cs);
- if (clock->time_source)
- {
- *time_source = clock->time_source;
- IMFPresentationTimeSource_AddRef(*time_source);
- }
- else
- hr = MF_E_CLOCK_NO_TIME_SOURCE;
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_GetTime(IMFPresentationClock *iface, MFTIME *time)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- HRESULT hr = MF_E_CLOCK_NO_TIME_SOURCE;
- MFTIME systime;
-
- TRACE("%p, %p.\n", iface, time);
-
- if (!time)
- return E_POINTER;
-
- EnterCriticalSection(&clock->cs);
- if (clock->time_source)
- hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, time, &systime);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_AddClockStateSink(IMFPresentationClock *iface, IMFClockStateSink *state_sink)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- struct clock_sink *sink, *cur;
- HRESULT hr = S_OK;
-
- TRACE("%p, %p.\n", iface, state_sink);
-
- if (!state_sink)
- return E_INVALIDARG;
-
- sink = heap_alloc(sizeof(*sink));
- if (!sink)
- return E_OUTOFMEMORY;
-
- sink->state_sink = state_sink;
- IMFClockStateSink_AddRef(sink->state_sink);
-
- EnterCriticalSection(&clock->cs);
- LIST_FOR_EACH_ENTRY(cur, &clock->sinks, struct clock_sink, entry)
- {
- if (cur->state_sink == state_sink)
- {
- hr = E_INVALIDARG;
- break;
- }
- }
- if (SUCCEEDED(hr))
- {
- static const enum clock_notification notifications[MFCLOCK_STATE_PAUSED + 1] =
- {
- /* MFCLOCK_STATE_INVALID */ 0, /* Does not apply */
- /* MFCLOCK_STATE_RUNNING */ CLOCK_NOTIFY_START,
- /* MFCLOCK_STATE_STOPPED */ CLOCK_NOTIFY_STOP,
- /* MFCLOCK_STATE_PAUSED */ CLOCK_NOTIFY_PAUSE,
- };
- struct clock_state_change_param param;
-
- if (!clock->is_shut_down && clock->state != MFCLOCK_STATE_INVALID)
- {
- param.u.offset = clock->start_offset;
- clock_notify_async_sink(clock, MFGetSystemTime(), param, notifications[clock->state], sink->state_sink);
- }
-
- list_add_tail(&clock->sinks, &sink->entry);
- }
- LeaveCriticalSection(&clock->cs);
-
- if (FAILED(hr))
- {
- IMFClockStateSink_Release(sink->state_sink);
- heap_free(sink);
- }
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *iface,
- IMFClockStateSink *state_sink)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- struct clock_sink *sink;
-
- TRACE("%p, %p.\n", iface, state_sink);
-
- if (!state_sink)
- return E_INVALIDARG;
-
- EnterCriticalSection(&clock->cs);
- LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry)
- {
- if (sink->state_sink == state_sink)
- {
- IMFClockStateSink_Release(sink->state_sink);
- list_remove(&sink->entry);
- heap_free(sink);
- break;
- }
- }
- LeaveCriticalSection(&clock->cs);
-
- return S_OK;
-}
-
-static HRESULT clock_call_state_change(MFTIME system_time, struct clock_state_change_param param,
- enum clock_notification notification, IMFClockStateSink *sink)
-{
- HRESULT hr = S_OK;
-
- switch (notification)
- {
- case CLOCK_NOTIFY_START:
- hr = IMFClockStateSink_OnClockStart(sink, system_time, param.u.offset);
- break;
- case CLOCK_NOTIFY_STOP:
- hr = IMFClockStateSink_OnClockStop(sink, system_time);
- break;
- case CLOCK_NOTIFY_PAUSE:
- hr = IMFClockStateSink_OnClockPause(sink, system_time);
- break;
- case CLOCK_NOTIFY_RESTART:
- hr = IMFClockStateSink_OnClockRestart(sink, system_time);
- break;
- case CLOCK_NOTIFY_SET_RATE:
- /* System time source does not allow 0.0 rate, presentation clock allows it without raising errors. */
- IMFClockStateSink_OnClockSetRate(sink, system_time, param.u.rate);
- break;
- default:
- ;
- }
-
- return hr;
-}
-
-static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_command command,
- struct clock_state_change_param param)
-{
- static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
- { /* S S* P, R */
- /* INVALID */ { 1, 1, 1, 1 },
- /* RUNNING */ { 1, 1, 1, 1 },
- /* STOPPED */ { 1, 1, 0, 1 },
- /* PAUSED */ { 1, 1, 0, 1 },
- };
- static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
- {
- /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
- /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
- /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
- /* CLOCK_CMD_SET_RATE */ 0, /* Unused */
- };
- static const enum clock_notification notifications[CLOCK_CMD_MAX] =
- {
- /* CLOCK_CMD_START */ CLOCK_NOTIFY_START,
- /* CLOCK_CMD_STOP */ CLOCK_NOTIFY_STOP,
- /* CLOCK_CMD_PAUSE */ CLOCK_NOTIFY_PAUSE,
- /* CLOCK_CMD_SET_RATE */ CLOCK_NOTIFY_SET_RATE,
- };
- enum clock_notification notification;
- struct clock_sink *sink;
- MFCLOCK_STATE old_state;
- IMFAsyncResult *result;
- MFTIME system_time;
- HRESULT hr;
-
- if (!clock->time_source)
- return MF_E_CLOCK_NO_TIME_SOURCE;
-
- if (command != CLOCK_CMD_SET_RATE && clock->state == states[command] && clock->state != MFCLOCK_STATE_RUNNING)
- return MF_E_CLOCK_STATE_ALREADY_SET;
-
- if (!state_change_is_allowed[clock->state][command])
- return MF_E_INVALIDREQUEST;
-
- system_time = MFGetSystemTime();
-
- if (command == CLOCK_CMD_START && clock->state == MFCLOCK_STATE_PAUSED &&
- param.u.offset == PRESENTATION_CURRENT_POSITION)
- {
- notification = CLOCK_NOTIFY_RESTART;
- }
- else
- notification = notifications[command];
-
- if (FAILED(hr = clock_call_state_change(system_time, param, notification, clock->time_source_sink)))
- return hr;
-
- old_state = clock->state;
- if (command != CLOCK_CMD_SET_RATE)
- clock->state = states[command];
-
- /* Dump all pending timer requests immediately on start; otherwise try to cancel scheduled items when
- transitioning from running state. */
- if ((clock->state == MFCLOCK_STATE_RUNNING) ^ (old_state == MFCLOCK_STATE_RUNNING))
- {
- struct clock_timer *timer, *timer2;
-
- if (clock->state == MFCLOCK_STATE_RUNNING)
- {
- LIST_FOR_EACH_ENTRY_SAFE(timer, timer2, &clock->timers, struct clock_timer, entry)
- {
- list_remove(&timer->entry);
- hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result);
- IUnknown_Release(&timer->IUnknown_iface);
- if (SUCCEEDED(hr))
- {
- MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_TIMER, result);
- IMFAsyncResult_Release(result);
- }
- }
- }
- else
- {
- LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry)
- {
- if (timer->key)
- {
- MFCancelWorkItem(timer->key);
- timer->key = 0;
- }
- }
- }
- }
-
- LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry)
- {
- clock_notify_async_sink(clock, system_time, param, notification, sink->state_sink);
- }
-
- return S_OK;
-}
-
-static HRESULT WINAPI present_clock_Start(IMFPresentationClock *iface, LONGLONG start_offset)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- struct clock_state_change_param param = {{0}};
- HRESULT hr;
-
- TRACE("%p, %s.\n", iface, debugstr_time(start_offset));
-
- EnterCriticalSection(&clock->cs);
- clock->start_offset = param.u.offset = start_offset;
- hr = clock_change_state(clock, CLOCK_CMD_START, param);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_Stop(IMFPresentationClock *iface)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- struct clock_state_change_param param = {{0}};
- HRESULT hr;
-
- TRACE("%p.\n", iface);
-
- EnterCriticalSection(&clock->cs);
- hr = clock_change_state(clock, CLOCK_CMD_STOP, param);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_Pause(IMFPresentationClock *iface)
-{
- struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
- struct clock_state_change_param param = {{0}};
- HRESULT hr;
-
- TRACE("%p.\n", iface);
-
- EnterCriticalSection(&clock->cs);
- hr = clock_change_state(clock, CLOCK_CMD_PAUSE, param);
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static const IMFPresentationClockVtbl presentationclockvtbl =
-{
- present_clock_QueryInterface,
- present_clock_AddRef,
- present_clock_Release,
- present_clock_GetClockCharacteristics,
- present_clock_GetCorrelatedTime,
- present_clock_GetContinuityKey,
- present_clock_GetState,
- present_clock_GetProperties,
- present_clock_SetTimeSource,
- present_clock_GetTimeSource,
- present_clock_GetTime,
- present_clock_AddClockStateSink,
- present_clock_RemoveClockStateSink,
- present_clock_Start,
- present_clock_Stop,
- present_clock_Pause,
-};
-
-static HRESULT WINAPI present_clock_rate_control_QueryInterface(IMFRateControl *iface, REFIID riid, void **out)
-{
- struct presentation_clock *clock = impl_from_IMFRateControl(iface);
- return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
-}
-
-static ULONG WINAPI present_clock_rate_control_AddRef(IMFRateControl *iface)
-{
- struct presentation_clock *clock = impl_from_IMFRateControl(iface);
- return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
-}
-
-static ULONG WINAPI present_clock_rate_control_Release(IMFRateControl *iface)
-{
- struct presentation_clock *clock = impl_from_IMFRateControl(iface);
- return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
-}
-
-static HRESULT WINAPI present_clock_rate_SetRate(IMFRateControl *iface, BOOL thin, float rate)
-{
- struct presentation_clock *clock = impl_from_IMFRateControl(iface);
- struct clock_state_change_param param;
- HRESULT hr;
-
- TRACE("%p, %d, %f.\n", iface, thin, rate);
-
- if (thin)
- return MF_E_THINNING_UNSUPPORTED;
-
- EnterCriticalSection(&clock->cs);
- param.u.rate = rate;
- if (SUCCEEDED(hr = clock_change_state(clock, CLOCK_CMD_SET_RATE, param)))
- clock->rate = rate;
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_rate_GetRate(IMFRateControl *iface, BOOL *thin, float *rate)
-{
- struct presentation_clock *clock = impl_from_IMFRateControl(iface);
-
- TRACE("%p, %p, %p.\n", iface, thin, rate);
-
- if (!rate)
- return E_INVALIDARG;
-
- if (thin)
- *thin = FALSE;
-
- EnterCriticalSection(&clock->cs);
- *rate = clock->rate;
- LeaveCriticalSection(&clock->cs);
-
- return S_OK;
-}
-
-static const IMFRateControlVtbl presentclockratecontrolvtbl =
-{
- present_clock_rate_control_QueryInterface,
- present_clock_rate_control_AddRef,
- present_clock_rate_control_Release,
- present_clock_rate_SetRate,
- present_clock_rate_GetRate,
-};
-
-static HRESULT WINAPI present_clock_timer_QueryInterface(IMFTimer *iface, REFIID riid, void **out)
-{
- struct presentation_clock *clock = impl_from_IMFTimer(iface);
- return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
-}
-
-static ULONG WINAPI present_clock_timer_AddRef(IMFTimer *iface)
-{
- struct presentation_clock *clock = impl_from_IMFTimer(iface);
- return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
-}
-
-static ULONG WINAPI present_clock_timer_Release(IMFTimer *iface)
-{
- struct presentation_clock *clock = impl_from_IMFTimer(iface);
- return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
-}
-
-static HRESULT present_clock_schedule_timer(struct presentation_clock *clock, DWORD flags, LONGLONG time,
- struct clock_timer *timer)
-{
- IMFAsyncResult *result;
- MFTIME systime, clocktime;
- LONGLONG frequency;
- HRESULT hr;
-
- if (!(flags & MFTIMER_RELATIVE))
- {
- if (FAILED(hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, &clocktime, &systime)))
- {
- WARN("Failed to get clock time, hr %#x.\n", hr);
- return hr;
- }
- time -= clocktime;
- }
-
- frequency = clock->frequency / 1000;
- time /= frequency;
-
- /* Scheduled item is using clock instance callback, with timer instance as an object. Clock callback will
- call user callback and cleanup timer list. */
-
- if (FAILED(hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result)))
- return hr;
-
- hr = MFScheduleWorkItemEx(result, -time, &timer->key);
- IMFAsyncResult_Release(result);
-
- return hr;
-}
-
-static HRESULT WINAPI clock_timer_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
-{
- if (IsEqualIID(riid, &IID_IUnknown))
- {
- *obj = iface;
- IUnknown_AddRef(iface);
- return S_OK;
- }
-
- *obj = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI clock_timer_AddRef(IUnknown *iface)
-{
- struct clock_timer *timer = impl_clock_timer_from_IUnknown(iface);
- return InterlockedIncrement(&timer->refcount);
-}
-
-static ULONG WINAPI clock_timer_Release(IUnknown *iface)
-{
- struct clock_timer *timer = impl_clock_timer_from_IUnknown(iface);
- ULONG refcount = InterlockedDecrement(&timer->refcount);
-
- if (!refcount)
- {
- IMFAsyncResult_Release(timer->result);
- IMFAsyncCallback_Release(timer->callback);
- heap_free(timer);
- }
-
- return refcount;
-}
-
-static const IUnknownVtbl clock_timer_vtbl =
-{
- clock_timer_QueryInterface,
- clock_timer_AddRef,
- clock_timer_Release,
-};
-
-static HRESULT WINAPI present_clock_timer_SetTimer(IMFTimer *iface, DWORD flags, LONGLONG time,
- IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_key)
-{
- struct presentation_clock *clock = impl_from_IMFTimer(iface);
- struct clock_timer *clock_timer;
- HRESULT hr;
-
- TRACE("%p, %#x, %s, %p, %p, %p.\n", iface, flags, debugstr_time(time), callback, state, cancel_key);
-
- if (!(clock_timer = heap_alloc_zero(sizeof(*clock_timer))))
- return E_OUTOFMEMORY;
-
- if (FAILED(hr = MFCreateAsyncResult(NULL, NULL, state, &clock_timer->result)))
- {
- heap_free(clock_timer);
- return hr;
- }
-
- clock_timer->IUnknown_iface.lpVtbl = &clock_timer_vtbl;
- clock_timer->refcount = 1;
- clock_timer->callback = callback;
- IMFAsyncCallback_AddRef(clock_timer->callback);
-
- EnterCriticalSection(&clock->cs);
-
- if (clock->state == MFCLOCK_STATE_RUNNING)
- hr = present_clock_schedule_timer(clock, flags, time, clock_timer);
- else if (clock->state == MFCLOCK_STATE_STOPPED)
- hr = MF_S_CLOCK_STOPPED;
-
- if (SUCCEEDED(hr))
- {
- list_add_tail(&clock->timers, &clock_timer->entry);
- if (cancel_key)
- {
- *cancel_key = &clock_timer->IUnknown_iface;
- IUnknown_AddRef(*cancel_key);
- }
- }
-
- LeaveCriticalSection(&clock->cs);
-
- if (FAILED(hr))
- IUnknown_Release(&clock_timer->IUnknown_iface);
-
- return hr;
-}
-
-static HRESULT WINAPI present_clock_timer_CancelTimer(IMFTimer *iface, IUnknown *cancel_key)
-{
- struct presentation_clock *clock = impl_from_IMFTimer(iface);
- struct clock_timer *timer;
-
- TRACE("%p, %p.\n", iface, cancel_key);
-
- EnterCriticalSection(&clock->cs);
-
- LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry)
- {
- if (&timer->IUnknown_iface == cancel_key)
- {
- list_remove(&timer->entry);
- if (timer->key)
- {
- MFCancelWorkItem(timer->key);
- timer->key = 0;
- }
- IUnknown_Release(&timer->IUnknown_iface);
- break;
- }
- }
-
- LeaveCriticalSection(&clock->cs);
-
- return S_OK;
-}
-
-static const IMFTimerVtbl presentclocktimervtbl =
-{
- present_clock_timer_QueryInterface,
- present_clock_timer_AddRef,
- present_clock_timer_Release,
- present_clock_timer_SetTimer,
- present_clock_timer_CancelTimer,
-};
-
-static HRESULT WINAPI present_clock_shutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **out)
-{
- struct presentation_clock *clock = impl_from_IMFShutdown(iface);
- return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out);
-}
-
-static ULONG WINAPI present_clock_shutdown_AddRef(IMFShutdown *iface)
-{
- struct presentation_clock *clock = impl_from_IMFShutdown(iface);
- return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
-}
-
-static ULONG WINAPI present_clock_shutdown_Release(IMFShutdown *iface)
-{
- struct presentation_clock *clock = impl_from_IMFShutdown(iface);
- return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
-}
-
-static HRESULT WINAPI present_clock_shutdown_Shutdown(IMFShutdown *iface)
-{
- struct presentation_clock *clock = impl_from_IMFShutdown(iface);
-
- TRACE("%p.\n", iface);
-
- EnterCriticalSection(&clock->cs);
- clock->is_shut_down = TRUE;
- LeaveCriticalSection(&clock->cs);
-
- return S_OK;
-}
-
-static HRESULT WINAPI present_clock_shutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
-{
- struct presentation_clock *clock = impl_from_IMFShutdown(iface);
- HRESULT hr = S_OK;
-
- TRACE("%p, %p.\n", iface, status);
-
- if (!status)
- return E_INVALIDARG;
-
- EnterCriticalSection(&clock->cs);
- if (clock->is_shut_down)
- *status = MFSHUTDOWN_COMPLETED;
- else
- hr = MF_E_INVALIDREQUEST;
- LeaveCriticalSection(&clock->cs);
-
- return hr;
-}
-
-static const IMFShutdownVtbl presentclockshutdownvtbl =
-{
- present_clock_shutdown_QueryInterface,
- present_clock_shutdown_AddRef,
- present_clock_shutdown_Release,
- present_clock_shutdown_Shutdown,
- present_clock_shutdown_GetShutdownStatus,
-};
-
-static HRESULT WINAPI present_clock_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **out)
-{
- if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
- IsEqualIID(riid, &IID_IUnknown))
- {
- *out = iface;
- IMFAsyncCallback_AddRef(iface);
- return S_OK;
- }
-
- WARN("Unsupported %s.\n", wine_dbgstr_guid(riid));
- *out = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI present_clock_sink_callback_AddRef(IMFAsyncCallback *iface)
-{
- struct presentation_clock *clock = impl_from_sink_callback_IMFAsyncCallback(iface);
- return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
-}
-
-static ULONG WINAPI present_clock_sink_callback_Release(IMFAsyncCallback *iface)
-{
- struct presentation_clock *clock = impl_from_sink_callback_IMFAsyncCallback(iface);
- return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
-}
-
-static HRESULT WINAPI present_clock_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI present_clock_sink_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
-{
- struct sink_notification *data;
- IUnknown *object;
- HRESULT hr;
-
- if (FAILED(hr = IMFAsyncResult_GetObject(result, &object)))
- return hr;
-
- data = impl_sink_notification_from_IUnknown(object);
-
- clock_call_state_change(data->system_time, data->param, data->notification, data->sink);
-
- IUnknown_Release(object);
-
- return S_OK;
-}
-
-static const IMFAsyncCallbackVtbl presentclocksinkcallbackvtbl =
-{
- present_clock_callback_QueryInterface,
- present_clock_sink_callback_AddRef,
- present_clock_sink_callback_Release,
- present_clock_callback_GetParameters,
- present_clock_sink_callback_Invoke,
-};
-
-static ULONG WINAPI present_clock_timer_callback_AddRef(IMFAsyncCallback *iface)
-{
- struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
- return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface);
-}
-
-static ULONG WINAPI present_clock_timer_callback_Release(IMFAsyncCallback *iface)
-{
- struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
- return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface);
-}
-
-static HRESULT WINAPI present_clock_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
-{
- struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface);
- struct clock_timer *timer;
- IUnknown *object;
- HRESULT hr;
-
- if (FAILED(hr = IMFAsyncResult_GetObject(result, &object)))
- return hr;
-
- timer = impl_clock_timer_from_IUnknown(object);
-
- EnterCriticalSection(&clock->cs);
- list_remove(&timer->entry);
- IUnknown_Release(&timer->IUnknown_iface);
- LeaveCriticalSection(&clock->cs);
-
- IMFAsyncCallback_Invoke(timer->callback, timer->result);
-
- IUnknown_Release(object);
-
- return S_OK;
-}
-
-static const IMFAsyncCallbackVtbl presentclocktimercallbackvtbl =
-{
- present_clock_callback_QueryInterface,
- present_clock_timer_callback_AddRef,
- present_clock_timer_callback_Release,
- present_clock_callback_GetParameters,
- present_clock_timer_callback_Invoke,
-};
-
-/***********************************************************************
- * MFCreatePresentationClock (mf.@)
- */
-HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock)
-{
- struct presentation_clock *object;
-
- TRACE("%p.\n", clock);
-
- object = heap_alloc_zero(sizeof(*object));
- if (!object)
- return E_OUTOFMEMORY;
-
- object->IMFPresentationClock_iface.lpVtbl = &presentationclockvtbl;
- object->IMFRateControl_iface.lpVtbl = &presentclockratecontrolvtbl;
- object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl;
- object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl;
- object->sink_callback.lpVtbl = &presentclocksinkcallbackvtbl;
- object->timer_callback.lpVtbl = &presentclocktimercallbackvtbl;
- object->refcount = 1;
- list_init(&object->sinks);
- list_init(&object->timers);
- object->rate = 1.0f;
- InitializeCriticalSection(&object->cs);
-
- *clock = &object->IMFPresentationClock_iface;
-
- return S_OK;
-}
-
static HRESULT WINAPI standard_quality_manager_QueryInterface(IMFQualityManager *iface, REFIID riid, void **out)
{
struct quality_manager *manager = impl_from_IMFQualityManager(iface);
--
2.30.2
1
3
June 15, 2021
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2:
* Merge 2 patches.
* Get rid of shift operation.
* Replace copy_texture with get_texuture_readback.
* Use winetest_push_context rather than "Test %u:".
* Release created texture.
* Only use D3D10_CPU_ACCESS_READ for readback.
v3: Fix test crash.
dlls/d3dx10_43/tests/d3dx10.c | 458 +++++++++++++++++++++++++++++-----
1 file changed, 394 insertions(+), 64 deletions(-)
2
1
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: This is a new patch in patch set.
v3: No changes.
dlls/d3dx10_43/tests/d3dx10.c | 205 ++++++++++++++++++----------------
1 file changed, 108 insertions(+), 97 deletions(-)
2
1
June 15, 2021
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/winegstreamer/media_source.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 3c87bbb2146..9c554c7c415 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -170,6 +170,11 @@ static ULONG WINAPI source_async_command_Release(IUnknown *iface)
{
if (command->op == SOURCE_ASYNC_START)
PropVariantClear(&command->u.start.position);
+ else if (command->op == SOURCE_ASYNC_REQUEST_SAMPLE)
+ {
+ if (command->u.request_sample.token)
+ IUnknown_Release(command->u.request_sample.token);
+ }
free(command);
}
@@ -467,8 +472,6 @@ static void wait_on_sample(struct media_stream *stream, IUnknown *token)
case WG_PARSER_EVENT_EOS:
stream->eos = TRUE;
- if (token)
- IUnknown_Release(token);
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var);
dispatch_end_of_presentation(stream->parent_source);
return;
--
2.30.2
1
0
[PATCH v4] iphlpapi: Fix the field 'AdapterName' of IP_ADAPTER_INFO returned by GetAdaptersInfo.
by Yeshun Ye June 15, 2021
by Yeshun Ye June 15, 2021
June 15, 2021
Signed-off-by: Yeshun Ye <yeyeshun(a)uniontech.com>
---
dlls/iphlpapi/iphlpapi_main.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 09414d26dde..21edd9ee128 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -706,9 +706,16 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
DWORD i;
PIP_ADDR_STRING currentIPAddr = &ptr->IpAddressList;
BOOL firstIPAddr = TRUE;
+ NET_LUID luid;
+ GUID guid;
/* on Win98 this is left empty, but whatever */
- getInterfaceNameByIndex(table->indexes[ndx], ptr->AdapterName);
+ ConvertInterfaceIndexToLuid(table->indexes[ndx], &luid);
+ ConvertInterfaceLuidToGuid(&luid, &guid);
+ sprintf(ptr->AdapterName, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
+ guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5],
+ guid.Data4[6], guid.Data4[7]);
getInterfaceNameByIndex(table->indexes[ndx], ptr->Description);
ptr->AddressLength = sizeof(ptr->Address);
getInterfacePhysicalByIndex(table->indexes[ndx],
--
2.20.1
2
1
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/ntdll/unix/socket.c | 6 ++++++
include/wine/afd.h | 7 +++++++
server/sock.c | 22 ++++++++++++++++++++++
3 files changed, 35 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 088f29f85ff..3b8206474f0 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -1181,6 +1181,12 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
break;
}
+ case IOCTL_AFD_GET_EVENTS:
+ if (in_size) FIXME( "unexpected input size %u\n", in_size );
+
+ status = STATUS_BAD_DEVICE_TYPE;
+ break;
+
case IOCTL_AFD_RECV:
{
const struct afd_recv_params *params = in_buffer;
diff --git a/include/wine/afd.h b/include/wine/afd.h
index 2eb3e6f12a9..46d242c7582 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -36,6 +36,7 @@
#define IOCTL_AFD_RECV CTL_CODE(FILE_DEVICE_BEEP, 0x805, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_AFD_POLL CTL_CODE(FILE_DEVICE_BEEP, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_EVENT_SELECT CTL_CODE(FILE_DEVICE_BEEP, 0x821, METHOD_NEITHER, FILE_ANY_ACCESS)
+#define IOCTL_AFD_GET_EVENTS CTL_CODE(FILE_DEVICE_BEEP, 0x822, METHOD_NEITHER, FILE_ANY_ACCESS)
enum afd_poll_bit
{
@@ -125,6 +126,12 @@ struct afd_event_select_params_32
int mask;
};
+struct afd_get_events_params
+{
+ int flags;
+ NTSTATUS status[13];
+};
+
#define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_ANY_ACCESS)
diff --git a/server/sock.c b/server/sock.c
index 3556ee21aa3..1d992d8f9e4 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -2011,6 +2011,28 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
}
return 1;
+ case IOCTL_AFD_GET_EVENTS:
+ {
+ struct afd_get_events_params params = {0};
+ unsigned int i;
+
+ if (get_reply_max_size() < sizeof(params))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return 0;
+ }
+
+ params.flags = sock->pending_events & sock->mask;
+ for (i = 0; i < ARRAY_SIZE( params.status ); ++i)
+ params.status[i] = sock_get_ntstatus( sock->errors[i] );
+
+ sock->pending_events = 0;
+ sock_reselect( sock );
+
+ set_reply_data( ¶ms, sizeof(params) );
+ return 0;
+ }
+
case IOCTL_AFD_EVENT_SELECT:
{
struct event *event = NULL;
--
2.30.2
2
7