[PATCH 1/5] wmvcore/tests: Add some basic tests for streaming with the synchronous reader.

Zebediah Figura zfigura at codeweavers.com
Mon Oct 25 10:54:57 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/wmvcore/tests/Makefile.in |   3 +
 dlls/wmvcore/tests/rsrc.rc     |  25 +++
 dlls/wmvcore/tests/test.wmv    | Bin 0 -> 45663 bytes
 dlls/wmvcore/tests/wmvcore.c   | 392 +++++++++++++++++++++++++++++++++
 4 files changed, 420 insertions(+)
 create mode 100644 dlls/wmvcore/tests/rsrc.rc
 create mode 100644 dlls/wmvcore/tests/test.wmv

diff --git a/dlls/wmvcore/tests/Makefile.in b/dlls/wmvcore/tests/Makefile.in
index 8054ddd0a2e..856e02d45d5 100644
--- a/dlls/wmvcore/tests/Makefile.in
+++ b/dlls/wmvcore/tests/Makefile.in
@@ -3,3 +3,6 @@ IMPORTS   = ole32 wmvcore
 
 C_SRCS = \
 	wmvcore.c
+
+RC_SRCS = \
+	rsrc.rc
diff --git a/dlls/wmvcore/tests/rsrc.rc b/dlls/wmvcore/tests/rsrc.rc
new file mode 100644
index 00000000000..cd642ceb1d0
--- /dev/null
+++ b/dlls/wmvcore/tests/rsrc.rc
@@ -0,0 +1,25 @@
+/*
+ * Resource file for wmvcore tests
+ *
+ * Copyright 2021 Zebediah Figura for CodeWeavers
+ *
+ * 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
+ */
+
+#include "windef.h"
+
+/* ffmpeg -f lavfi -i smptebars -f lavfi -i "sine=frequency=700" -t 2.0 -f asf -vcodec wmv1 -vf scale=64x48 -acodec wmav1 test.wmv */
+/* @makedep: test.wmv */
+test.wmv RCDATA "test.wmv"
diff --git a/dlls/wmvcore/tests/test.wmv b/dlls/wmvcore/tests/test.wmv
new file mode 100644
index 0000000000000000000000000000000000000000..fa953771cd31213ec24bef9000127125047e0623
GIT binary patch
literal 45663
zcmeI5dsq|47Qkn+KuCBb#DJ(M0TB=sL9IrL5KuHwMMUwzqsF&b at C7O=)lEPJA4pY1
zxr$LiQBlzg1<`8a3yZfx at lm9xDHgHTT55fu7P&LKB<Ab=`dz)f{iDeauq0<EyL(Q~
zFEeN6WY*jD#Ny0Z)i(QYfkR;0)%YtcKov8zg{(adhc}EoSZ$N}Jy2PS#?72V at BEML
zloK5y(*MSt<GY}B$5Z8C8v;Mn_=q9??_i0y0N|65=rR72KvPgkoSou@&vTDH&rYfq
z05-MP4p(6LeOhh?=Ak_gue4q~7QIxOHv7<q;jczjVHqy?s1S4o1TaC50zo2J0A_;e
zAPGc(sc0Jq=7UL89kltcH79q}l;qdcvhUT}<g at _gmme2~&%iH61p;?45sU`?Krp(h
z>FC%q&>7}|*<c(xYZ7%n{49~G?EprhYghtife(Nfc!9xS5Zd|xZ}bDeXY7WuGCe)z
z)N24x{oLjB=;&&j!Ztuoi5cz*CcYL$>Ob$OH=yG`Wn>^h&+t)M?&uPcfjgc;U=Jpa
zp5Oyqkl=Ua_ZJY~v0suG*Q$R3;a{CUyJ>2*&H59_T}m27+QZnP2j=JxzXbruAOypU
z(A(<|Kr at R^y&Vw1W>zx`U7;l6>owhdYHar9BZCss=lCtbCGdB0`t39YOF;rMoDWsU
zgwlWo%qS@~C at p89a}N5QEB8M}z2rYOTIYmNfjlhsHD$C3APrv|(xMri7yD^5YezT$
z#DS_Go+Z8V{j|IP(cKfr>`Sj}98|vXXwTVCJYU*13S)v&)2}xQ7sS4>IXrZ3byQ32
z?x8b_Z^VCab7#Bwe8zn1UZ=~qeIvLP6Fkvo<?{BtFEpY|(1T^JAvB_Gz at Nn-p+>Y9
zNw^{;If^6}07*_Gi6uai8YHojA;|+I;h{QCW=LYAgc_&*NMeg63y`EMmeeANi;~bd
zry+?SI*yAgk`&7b&Ct2PpSYtTG<}3<mzac_o=?#(ClXbjfFzyq%l9LR0H6a7M-ppP
z2b~LDh6r6oJ(6%`9T&zybwv5V-)fvHPz3z$eQ at Dpi!WkE`hJ at 7th{IS_Y>2OTx+UU
zRLf=mXm at +#Rjo+cs2;5LX+8DwmFmTqThRlWjtoeh{p-!jid743E(}gfY*M>gW#)W7
zwDzj=?6YZ~q?%-(S43S(DxKbZHn)2I;21Ht+`IeqH<24(zC3&7tC{}u-Bpvrh&EZj
zyUnkDJG*MvsV8MkgC6a at yY<@>nE`h@|G4SJ#aH**eu>`p(~lFHPA$K2a^9WN3uTu|
zFSKub(do_LhB2*o`vyd(l(Z#0x%RBW?qKwux!LI7s$mbO)V#`h>R-^tqn_+}GKKn$
z3+5CEUAKnkjt%;QhvvQC^T&lH`GenS|F<$#6ZURJPWyeV2>_wU?_*6&Q#Sa1e`#5z
zC at x&QP_r<x(8_~t?Pu+^Wa)=eOTqZg&$If3a&GS67d@#z{MjeN*18H^Q^D#q<voo$
ze3*0ig4gi;E_P>MGibpHtW+zMYh)dw4;{UNqa?x~rFL$nZTYrc#>Tm-k3Y(Jo at KuL
z+R2DoQ>(xkB?|fBMRoh!z0G6ALq3Ol>crA)c4K&=<hwkR;<v&OqA=8Yj>7;|j^hzg
zmm~Qwv_u}bE<vPxc3{Msp<60yVQIaj(+a7b)7(Y1Tu%LBj$D+!)4{yIrO>2RI!hHN
z7V~G=yK`DLSFV?uT at Fjg=XO8oDfO@~st-{{)I!gO?0k!^Yoev at orjmaoVQrgVTv>C
zm8Pq<uAcH`wq2`jp7k%%`c6a~5Gc<|>Lp{{-DK|jX3pMr at p9>&^IN!bGU#0R!WLPf
z({=}c)q>{0i&vFq)~C2<GLtNJv^dR{c`kN%aO?8CUimN#zg*m}r9{5ZqpwSy_lmHL
zxQ2t@{Uj1yw;SG?WO`uHmFc0~YzeUXTIxS!UAw2IW%;Hl at 5|5oabz-nMRIx5>Kv9k
zyinIYFnNe_K{X4hkc%vRSSqyNU(4l1CC%|JA^T3qGHDnNLcS^$%lWXI)ZA^Mw{Vn#
z2vMt2MQX{Iw5?`aQsriW3NlwPf9(|0C57DE`NVX$fuSYjurim)6S7=<CYNlH976Vq
z*)}N4a&8x7 at mRsNrgG3DZgyJw)UOwKu9I&jWrqn68%XwEtx=gABhn>J<lgSEMP^?~
zzFMOeeldALinW+8AG40Qe<mvWhV7UkSIcYsZV{ka9%RYw2UM~`<u=P)^U4zwI_-%2
zHpk8Msc@{NBA{?z>#BwqzVepJ)v<|NXVxrQx9P)#%YDlD-+a_1ac5;;Xa3r*DH4~l
zc?-PF9ATxh(Sc2n`-yX6v($7x|D{rMh{*UzRnyHJK4)uwn_5cbZA&iOHSS+M*|{+{
zSX)$kN!b^rvIE;IcF*2wP2AWT`D!?CkenPL)AX?9_F?x(HD!|z`p<Dc6jxzeYPY?9
zzs0?nb!(#c#eRD>EutVa*Zt_p?}8I|xb>HW%PfC+l$&;cY{IyOqP<n>A$t<a5AohK
zM=XB)(*eHiRS%B0lq<C7PY!f0_mw0mlO6c#i2 at hFM{+gaDyU{~WKd0Tyj768@>cMj
zJ1yxFdyr at CZ))#n1~;ZEijugp$ka?&C9kUOA0>9oTxmUM{zLJ;f)ra;AQ^Q2UVQ4X
zI%|O&-+zwlf%aj&1l%Iwq?zTrH_bb`^`Pzb<V9H^@>2YY*P|z&^c<HH(;As=azEPZ
zv9r6P$UVaGaRl48-C=w~#mMWu#W8ctL~Lho_j6$L5Vomzpdif$6gw0-NCdUK^GzR&
zOydvycILYAg%|xE<^_2#D=4;y&fQZLX||fQ{4O5u%E$*ELB-1oEW*YJT9xrXczdoP
zS-4rJTUq>R)6Cj~T3Pna%be(=Ja`YaF+(ST0k`8!$d-5e^kQl;7Wg|@0MdSsJIRZX
z-<yNrPb)Vp at o6V94ooph3n&2K#14x=y61v)78NN|;Yae at 55`});iWPDM1zX0T3QS$
zCeO>_B>x at Uow-KF0`F!4Nc%nB<|4l*KyW}i3&kQGorD8=ECdP4Cfy-^Q4y-7EZ`ga
zjOir2n~9lPe-jHp+V3$7=X5NX>R7lzu~3MIrShFDRuWf99$6<MUWLGSjrIQ~c3>`(
zu>hJDz-<6#;h~NNJS{;7k0w?)c%)e{%RUBwmJq5q0NRuSCU9h&$G|KAX}`xT2$0`X
zeI!i6pDa}T(a#Qz{}zG_78 at Upia+}6vE{t_EPMgjs+k(t=5k(TV1{MXF?tI?+V3%2
zzFM|ec$kJ}VX7VrW;u6=-vFDuD1on89~-^p7y}rZ1t9JBn1yLt79fXW0n65DWh`2T
zr^+``d>o`>5 at 9P(f~Jb^lDr4onPDnJ^A1KI$knlMLdOCv!z`T9W5F!fk6j9QaJq_k
zZgQG29b*9lvjDWvu~4sN0ZZPap!mZk7O-ki0OF7Gujm6}kRIuQ<jGB8R{}>kQNn&Y
z%Fn=z$f(0u0HV>Yj)5)~%1xvvKxi3ep(~O#v*-?%g)o^{gp%^IN%kXV9*}VzgR_7f
zeefd|a4w<;@_Qy1k;z45auJza#J?yP5r5V&#ds}%;tx)&M_<&*I*8^!=%xpExkB{1
zT%IPayvt}zD+MrPS_aqMU=#`qqra?Yjz at kYkl(*eOvS-S$0W#7Js at xl(tu)+X-o{l
zxQ`)P0P-lm#}gjQk>6ACIOOYOd$lqaT at N=H`}O$nBs2l#pq1kc0uHVv4bec1PDX73
zXrp7HO2-1t2WH{A9t##Wng9(*HZKQ`<v9!sM(s8RsXP?uSa_mk0ZZPkC~*AI4?|Oi
z;tv`t{ER>?OEaq&&8eGl?hs#s0P`~pJqGDNj8b8+6NZJ#^X-cKo}T`ovBE6)=&|qy
zvEVhhg-P&b+{Q310EIdhf^;m<d|(!)=&^v?g~8IwS_THgbOoc=3fk&en5$!f<^!{k
zNwLr|E#65JP=msZM<9R+GmPGG4A1}&udhY-kv3~tfSq-+3at!F-lHh!{3|6I>Iy^o
zS2S=KuG4yOc|uLVb~K(f9yl`NSqA7^Mz0dI$H-6tNTU`c77ZL`;YU3dEKq_wUS(}Q
z;62J<65Ng6bqvk`@-7q$IRA=^hIE<yD<=Pn$-iRqubBL+_vlqKRo~SDDE>hCS8XW#
zIEm&z=y(Qqxw at dHN1O8QX_CyVK>1f0fc?Op>2eudkHhE{f?cUD7tX)xkNjRQ|B8-F
zFc4BbAaD$lhhmVuOblZ5zGILEfZZq{aQ;;k at _Twhkd8|*3rqA^@Z|cj&!F!H#*)NS
zOXj<Q2I&q)trT?7v7pegKsOkeg#tYm;J{Yi1k^5EBbl)&qxKm?RUUTNv2aMs0_>ra
z)oNu}@@_>zt-o7_2D^5n^>^uJ2V-?j5363h)9h^2#4JWlj0Lm&m7zM9@#+N~F)Y;d
z$15#DEV|jjEZ}Tk?K+FBoHxWXz$Pz~#A_*&k!ZX=W2l-#k&Xpt<o9&wK{q>?1#dkT
zTvs21ze?Du*$Y6Mh*=lWP(8wU^@2`17D9C_(A_P}!pC|nK+l!LO_ELC0H|Fs)flhM
z7|jjS0?=8<!XhmTSn?-}0_R^nf(y|~*RfzVi|&YFxHeL7QFliAl@(EX|1|prTI#(?
z1JpeqGJqMTj~T62uqVcd3P5tTaIr*`46|@bkA+Zv*`zl_GfAkHh(JZ`JW|Tc2pX;5
z7^33PMaRN9EerBqlnm!&Jw!4lCyU9+Vsf&WoGd0M3x6y!<xf}u#UGql|EnncP@?${
zI^M@!F5Jv$Z_KLd9ffYp`UAS>x8HU!;MUyDkm+(6V$Z{9b%L&#AZq<90s7jxUjCIc
zwF3iTk9KH*$S{wtUIlL}p~jyN5^pD%yD*6-M(aF=s5o?^{2u3D`69okCqd{K9kVb}
zj|J7hGu89q*DAE+RTA)&$Mt4zL}-W}VZ1s)cO47UbS%&@I%Z)p#R7d3LO7@$7NeUG
zF3*DZq&#4}He)n5Obfu?Iu_PxS-_J2y(p;luhycQ8y-X7|DcDtFjo8CVwI7$_qJvr
z`u;g at JFpnf+}qPIUCWrYf*u$kYWm}Z7AqDVlVBEV^;jt0eV6<fiPmF~fg`m9lZ<H0
zZex(TLr)zG^*R>la0Ige&{A0R_X16iPrI$@SBRR0fq<9w5rcw3x`R<G1^eh&U?IP!
z!f at DEC-czCSagVj`RJ#|$B4TcF9}HI%>w<HroyNl$v~BdUOE;cv at BrBdlUsqZ;uT`
z_kT_RYglx2gE5NLVMJtX?t6#z72uICMKGATji-USk}<0V`(a?H at MF0aBNiQ!U=}v$
zu~58fC94#$$=6C^v^TTvs4;tuVd at UObu8@Fu|S6;n1u>G7B&Zb%-V(8g*FuoW=5q9
z(;bXjE4dHF0?s<DLViDvFiqLu`~9V5m7=(C at j}hQ#6l|%wzZ$N*OH|lN-YKBJ3r6r
z6Uw={gJ1Nd{_tm?3|s3ebWH`T)0Fo#>hNLC;R{~F^Sjucea)Z+C$LhjP_B`6h(2`m
z3XYNpf0Wv}nYQKIb{QMzsy_ZG=XsX-@@pp}YE7*IXOt-9hZoiDbN4on6%Y9w?x_<?
zv)PT|iIVT~Op4zMLx{pq>p2bsR5^}EL|u;L!_X3W;JO5n^4WnAYld#AsD-8Vl1?k6
zc208_)p9xYi#c*p`c4P){+2?MR_QENoLJ1CVeigq*<86^YIZp+A)nj*q^H!wzNkJ#
z$z&ZeS%?4UtV0xk*u;)7KZ+s{caSRg8HeWFse9jI;<#{6Lir)yo92kckAFJAx4r7Y
z at s@Ih_Wa3#&gH(6BxSM#Up-OaBKSzI=352T42}${368f4QdiyzzH_G~U1AUNto=>x
z{mkITR7Ft|R~DI?39IB)wf&>Sj+ra12hD#d-dB)f%L*ie&fkkq9ad*8aO3;WaXrvJ
zte1dWB%Cy}eD|h#N4Fldy`H=%3q)RuU-5eM<ddG`a$;H|vrX<tdp&k`R}{HNI6jVG
z+qOH5Z>ac-k`h_;SO{)}A5e|3G8}z6Ro!~&yGmVJTj%O{ll`V;lsLW7i?jQi#->B6
z-vs4r)IRrHMqlOpv*5(%O$ln(6hTU_Wj|*xoaE5x=<&~aZ-OTh2fq2m(chwa(hn)m
zs()>nJ3tfGt4tLn1?_Ih=Cc70@<_AB=xQ=u0$OZb(b5{-RBTnqcJQs$N+KMfnO;6<
zweUmrdH|?#egINTqDbq=>8j!0Kz2*xGzTQ!Jl%PP`j9N=s%h1#&n8FPO>5usN$R=C
z5s_C4+VhgyVunPIjhgQM`Ow;D8{-pSPrum`LKgQ}aVF`6=h_!9mlaf0`hT*%ch!Vq
z8`b<L>zDS3*s#a3wDj<zRkIpi&d*%Gbaib>>6mUxr-U|(ksFST4Xul^NUC}1IqzKW
z0^Y7I!JL(j+=z8nu4%5H1zp%<mQ99^MgKX{y$6H1b4~J{4@!C;9G at n<Zt7$!HT?iO
z*~&UaNKI5O9CB0$OV&vsadnY<b23DuLNc&q+Ne>S3?J{h?VSYErXKIJJ$}@nUR$g(
zCJ6IRF)4w6O<w`_ry60rHrNy7_iuC4u$U=~1sDr37GNyESb(trV}bX#K$bZeaJ;G7
nCgUkkeo2H}nf3>VAh&I&_CT~nvC1D7oHC43x~Q!s+CuPe!fZnO

literal 0
HcmV?d00001

diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 79bcfef0d52..dd1e3027d57 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -1,6 +1,7 @@
 /*
  * Copyright 2017 Alistair Leslie-Hughes
  * Copyright 2019 Vijay Kiran Kamuju
+ * Copyright 2021 Zebediah Figura for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,15 +17,43 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+
+#include <stdbool.h>
 #define COBJMACROS
 #define WIN32_LEAN_AND_MEAN
 #include "initguid.h"
 #include "wmsdk.h"
+#include "wmsecure.h"
 
 #include "wine/test.h"
 
 HRESULT WINAPI WMCreateWriterPriv(IWMWriter **writer);
 
+static WCHAR *load_resource(const WCHAR *name)
+{
+    static WCHAR pathW[MAX_PATH];
+    DWORD written;
+    HANDLE file;
+    HRSRC res;
+    void *ptr;
+
+    GetTempPathW(ARRAY_SIZE(pathW), pathW);
+    wcscat(pathW, name);
+
+    file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s, error %u.\n",
+            wine_dbgstr_w(pathW), GetLastError());
+
+    res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
+    ok(!!res, "Failed to load resource, error %u.\n", GetLastError());
+    ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
+    WriteFile(file, ptr, SizeofResource( GetModuleHandleA(NULL), res), &written, NULL);
+    ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource.\n");
+    CloseHandle(file);
+
+    return pathW;
+}
+
 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
 static HRESULT check_interface_(unsigned int line, void *iface, REFIID riid, BOOL supported)
 {
@@ -225,6 +254,368 @@ static void test_iscontentprotected(void)
     ok(drm == FALSE, "got %0dx\n", drm);
 }
 
+struct teststream
+{
+    IStream IStream_iface;
+    LONG refcount;
+    HANDLE file;
+};
+
+static struct teststream *impl_from_IStream(IStream *iface)
+{
+    return CONTAINING_RECORD(iface, struct teststream, IStream_iface);
+}
+
+static HRESULT WINAPI stream_QueryInterface(IStream *iface, REFIID iid, void **out)
+{
+    if (winetest_debug > 1)
+        trace("%04x: IStream::QueryInterface(%s)\n", GetCurrentThreadId(), debugstr_guid(iid));
+
+    if (!IsEqualGUID(iid, &IID_IWMGetSecureChannel) && !IsEqualGUID(iid, &IID_IWMIStreamProps))
+        ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI stream_AddRef(IStream *iface)
+{
+    struct teststream *stream = impl_from_IStream(iface);
+
+    return InterlockedIncrement(&stream->refcount);
+}
+
+static ULONG WINAPI stream_Release(IStream *iface)
+{
+    struct teststream *stream = impl_from_IStream(iface);
+
+    return InterlockedDecrement(&stream->refcount);
+}
+
+static HRESULT WINAPI stream_Read(IStream *iface, void *data, ULONG size, ULONG *ret_size)
+{
+    struct teststream *stream = impl_from_IStream(iface);
+
+    if (winetest_debug > 2)
+        trace("%04x: IStream::Read(size %u)\n", GetCurrentThreadId(), size);
+
+    ok(size > 0, "Got zero size.\n");
+    ok(!!ret_size, "Got NULL ret_size pointer.\n");
+    if (!ReadFile(stream->file, data, size, ret_size, NULL))
+        return HRESULT_FROM_WIN32(GetLastError());
+    return S_OK;
+}
+
+static HRESULT WINAPI stream_Write(IStream *iface, const void *data, ULONG size, ULONG *ret_size)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD method, ULARGE_INTEGER *ret_offset)
+{
+    struct teststream *stream = impl_from_IStream(iface);
+    LARGE_INTEGER size;
+
+    if (winetest_debug > 2)
+        trace("%04x: IStream::Seek(offset %I64u, method %#x)\n", GetCurrentThreadId(), offset.QuadPart, method);
+
+    GetFileSizeEx(stream->file, &size);
+    ok(offset.QuadPart < size.QuadPart, "Expected offset less than size %I64u, got %I64u.\n",
+            size.QuadPart, offset.QuadPart);
+
+    ok(method == STREAM_SEEK_SET, "Got method %#x.\n", method);
+    ok(!ret_offset, "Got unexpected ret_offset pointer %p\n", ret_offset);
+
+    if (!SetFilePointerEx(stream->file, offset, &offset, method))
+        return HRESULT_FROM_WIN32(GetLastError());
+    return S_OK;
+}
+
+static HRESULT WINAPI stream_SetSize(IStream *iface, ULARGE_INTEGER size)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
+        ULARGE_INTEGER *read_size, ULARGE_INTEGER *write_size)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Commit(IStream *iface, DWORD flags)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Revert(IStream *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *stat, DWORD flags)
+{
+    struct teststream *stream = impl_from_IStream(iface);
+    LARGE_INTEGER size;
+
+    if (winetest_debug > 1)
+        trace("%04x: IStream::Stat(flags %#x)\n", GetCurrentThreadId(), flags);
+
+    ok(flags == STATFLAG_NONAME, "Got flags %#x.\n", flags);
+
+    stat->type = 0xdeadbeef;
+    GetFileSizeEx(stream->file, &size);
+    stat->cbSize.QuadPart = size.QuadPart;
+    stat->grfMode = 0;
+    stat->grfLocksSupported = TRUE;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI stream_Clone(IStream *iface, IStream **out)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static const IStreamVtbl stream_vtbl =
+{
+    stream_QueryInterface,
+    stream_AddRef,
+    stream_Release,
+    stream_Read,
+    stream_Write,
+    stream_Seek,
+    stream_SetSize,
+    stream_CopyTo,
+    stream_Commit,
+    stream_Revert,
+    stream_LockRegion,
+    stream_UnlockRegion,
+    stream_Stat,
+    stream_Clone,
+};
+
+static void test_sync_reader_streaming(void)
+{
+    DWORD size, flags, output_number, expect_output_number;
+    const WCHAR *filename = load_resource(L"test.wmv");
+    WORD stream_numbers[2], stream_number;
+    IWMStreamConfig *config, *config2;
+    bool eos[2] = {0}, first = true;
+    struct teststream stream = {0};
+    ULONG i, j, count, ref;
+    IWMSyncReader *reader;
+    IWMProfile *profile;
+    QWORD pts, duration;
+    INSSBuffer *sample;
+    HANDLE file;
+    HRESULT hr;
+    BYTE *data;
+    BOOL ret;
+
+    file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u.\n", debugstr_w(file), GetLastError());
+
+    stream.IStream_iface.lpVtbl = &stream_vtbl;
+    stream.refcount = 1;
+    stream.file = file;
+
+    hr = WMCreateSyncReader(NULL, 0, &reader);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
+
+    hr = IWMSyncReader_OpenStream(reader, &stream.IStream_iface);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
+
+    hr = IWMProfile_GetStreamCount(profile, NULL);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+    count = 0xdeadbeef;
+    hr = IWMProfile_GetStreamCount(profile, &count);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine ok(count == 2, "Got count %u.\n", count);
+
+    count = 0xdeadbeef;
+    hr = IWMSyncReader_GetOutputCount(reader, &count);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine ok(count == 2, "Got count %u.\n", count);
+
+    for (i = 0; i < 2; ++i)
+    {
+        hr = IWMProfile_GetStream(profile, i, &config);
+        todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+        if (hr == S_OK)
+        {
+            hr = IWMProfile_GetStream(profile, i, &config2);
+            ok(hr == S_OK, "Got hr %#x.\n", hr);
+            ok(config2 != config, "Expected different objects.\n");
+            ref = IWMStreamConfig_Release(config2);
+            ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+            stream_numbers[i] = 0xdead;
+            hr = IWMStreamConfig_GetStreamNumber(config, &stream_numbers[i]);
+            ok(hr == S_OK, "Got hr %#x.\n", hr);
+            ok(stream_numbers[i] == i + 1, "Got stream number %u.\n", stream_numbers[i]);
+
+            ref = IWMStreamConfig_Release(config);
+            ok(!ref, "Got outstanding refcount %d.\n", ref);
+        }
+
+        hr = IWMSyncReader_SetReadStreamSamples(reader, stream_numbers[i], FALSE);
+        todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    }
+
+    hr = IWMProfile_GetStream(profile, 2, &config);
+    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+    while (!eos[0] || !eos[1])
+    {
+        for (j = 0; j < 2; ++j)
+        {
+            stream_number = pts = duration = flags = output_number = 0xdeadbeef;
+            hr = IWMSyncReader_GetNextSample(reader, stream_numbers[j], &sample,
+                    &pts, &duration, &flags, &output_number, &stream_number);
+            if (first)
+                todo_wine ok(hr == S_OK, "Expected at least one valid sample; got hr %#x.\n", hr);
+            else if (eos[j])
+                ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+            else
+                ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+            if (hr == S_OK)
+            {
+                hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
+                todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+                ref = INSSBuffer_Release(sample);
+                ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+                hr = IWMSyncReader_GetOutputNumberForStream(reader, stream_number, &expect_output_number);
+                ok(hr == S_OK, "Got hr %#x.\n", hr);
+                ok(output_number == expect_output_number, "Expected output number %u, got %u.\n",
+                        expect_output_number, output_number);
+            }
+            else
+            {
+                ok(pts == 0xdeadbeef, "Got PTS %I64u.\n", pts);
+                ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
+                ok(flags == 0xdeadbeef, "Got flags %#x.\n", flags);
+                ok(output_number == 0xdeadbeef, "Got output number %u.\n", output_number);
+                eos[j] = true;
+            }
+
+            todo_wine ok(stream_number == stream_numbers[j], "Expected stream number %u, got %u.\n",
+                    stream_numbers[j], stream_number);
+        }
+        first = false;
+    }
+
+    hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
+            &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
+            &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_SetRange(reader, 0, 0);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample, &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    if (hr == S_OK)
+        INSSBuffer_Release(sample);
+
+    hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, &output_number, NULL);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    if (hr == S_OK)
+        INSSBuffer_Release(sample);
+
+    hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, &stream_number);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    if (hr == S_OK)
+        INSSBuffer_Release(sample);
+
+    for (;;)
+    {
+        stream_number = pts = duration = flags = output_number = 0xdeadbeef;
+        hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
+                &pts, &duration, &flags, &output_number, &stream_number);
+        todo_wine ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+        if (hr == S_OK)
+        {
+            hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
+            ok(hr == S_OK, "Got hr %#x.\n", hr);
+            ref = INSSBuffer_Release(sample);
+            ok(!ref, "Got outstanding refcount %d.\n", ref);
+        }
+        else
+        {
+            ok(pts == 0xdeadbeef, "Got PTS %I64u.\n", pts);
+            ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
+            ok(flags == 0xdeadbeef, "Got flags %#x.\n", flags);
+            ok(output_number == 0xdeadbeef, "Got output number %u.\n", output_number);
+            ok(stream_number == 0xbeef, "Got stream number %u.\n", stream_number);
+            break;
+        }
+    }
+
+    hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
+            &pts, &duration, &flags, NULL, &stream_number);
+    todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
+            &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
+            &pts, &duration, &flags, NULL, NULL);
+    todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_Close(reader);
+    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IWMSyncReader_Close(reader);
+    todo_wine ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
+
+    ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
+
+    SetFilePointer(stream.file, 0, NULL, FILE_BEGIN);
+    hr = IWMSyncReader_OpenStream(reader, &stream.IStream_iface);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    todo_wine ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
+
+    IWMProfile_Release(profile);
+    ref = IWMSyncReader_Release(reader);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
+    CloseHandle(stream.file);
+    ret = DeleteFileW(filename);
+    ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
+}
+
 START_TEST(wmvcore)
 {
     HRESULT hr;
@@ -241,6 +632,7 @@ START_TEST(wmvcore)
     test_WMCreateWriterPriv();
     test_urlextension();
     test_iscontentprotected();
+    test_sync_reader_streaming();
 
     CoUninitialize();
 }
-- 
2.33.0




More information about the wine-devel mailing list