1 /*
2  * Unit tests for MCIWnd
3  *
4  * Copyright 2019 Sven Baars
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define WIN32_LEAN_AND_MEAN
22 
23 #include <windows.h>
24 #include <vfw.h>
25 
26 #include "wine/heap.h"
27 #include "wine/test.h"
28 
29 static const DWORD file_header[] = /* file_header */
30 {
31     FOURCC_RIFF, 0x8c0 /* file size */,
32     formtypeAVI,
33     FOURCC_LIST, 0xc0 /* list length */,
34     listtypeAVIHEADER, ckidAVIMAINHDR, sizeof(MainAVIHeader),
35 };
36 
37 static const MainAVIHeader main_avi_header =
38 {
39     0x0001046b,    /* dwMicroSecPerFrame   */
40     0x00000000,    /* dwMaxBytesPerSec     */
41     0x00000000,    /* dwPaddingGranularity */
42     0x00000810,    /* dwFlags              */
43     2,             /* dwTotalFrames        */
44     0,             /* dwInitialFrames      */
45     1,             /* dwStreams            */
46     0x48,          /* dwSuggestedBufferSize*/
47     5,             /* dwWidth              */
48     5,             /* dwHeight             */
49     { 0, 0, 0, 0 } /* dwReserved[4]        */
50 };
51 
52 static const DWORD stream_list[] =
53 {
54     FOURCC_LIST, 0x74 /* length */,
55     listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */,
56 };
57 
58 static const AVIStreamHeader avi_stream_header =
59 {
60     streamtypeVIDEO, /* fccType              */
61     0,               /* fccHandler           */
62     0,               /* dwFlags              */
63     0,               /* wPriority            */
64     0,               /* wLanguage            */
65     0,               /* dwInitialFrames      */
66     1,               /* dwScale              */
67     0xf,             /* dwRate               */
68     0,               /* dwStart              */
69     2,               /* dwLength             */
70     0x48,            /* dwSuggestedBufferSize*/
71     0,               /* dwQuality            */
72     0,               /* dwSampleSize         */
73     { 0, 0, 0, 0 }   /* short left right top bottom */
74 };
75 
76 static const DWORD video_stream_format[] =
77 {
78     ckidSTREAMFORMAT,
79     0x28 /* length */,
80     0x28 /* length */,
81     5    /* width */,
82     5    /* height */,
83     0x00180001 ,
84     mmioFOURCC('c', 'v', 'i', 'd'),
85     0x245a,
86     0, 0, 0, 0,
87 };
88 
89 static const DWORD padding[] =
90 {
91     ckidAVIPADDING, 0x718 /* length */,
92 };
93 
94 static const DWORD data[] =
95 {
96     FOURCC_LIST, 0xa4 /* length */, listtypeAVIMOVIE,
97     mmioFOURCC('0', '0', 'd', 'b'), 0x48, 0x48000000, 0x08000800,
98     0x00100100, 0x00003e00, 0x08000000, 0x00200800,
99     0x00001600, 0x00000000, 0x00003a00, 0x22e306f9,
100     0xfc120000, 0x0a000022, 0x00000000, 0x00300000,
101     0x00c01200, 0x00000000, 0x02010000, 0x00000000,
102     mmioFOURCC('0', '0', 'd', 'b'), 0x48, 0x48000000, 0x08000800,
103     0x00100100, 0x00003e00, 0x08000000, 0x00200800,
104     0x00001600, 0x00000000, 0x00003a00, 0x22e306f9,
105     0xfc120000, 0x0a000022, 0x00000000, 0x00300000,
106     0x00c01200, 0x00000000, 0x02010000, 0x00000000,
107     mmioFOURCC('i', 'd', 'x', '1'), 0x20, mmioFOURCC('0', '0', 'd', 'b'), 0x10,
108     0x04, 0x48, mmioFOURCC('0', '0', 'd', 'b'), 0x10,
109     0x54, 0x48,
110 };
111 
112 static BOOL create_avi_file(char *fname)
113 {
114     HANDLE hFile;
115     DWORD written;
116     char temp_path[MAX_PATH];
117     BOOL ret;
118     BYTE *buffer;
119     ULONG buffer_length;
120 
121     ret = GetTempPathA(sizeof(temp_path), temp_path);
122     ok(ret, "Failed to get a temp path, err %d\n", GetLastError());
123     if (!ret)
124         return FALSE;
125 
126     ret = GetTempFileNameA(temp_path, "mci", 0, fname);
127     ok(ret, "Failed to get a temp name, err %d\n", GetLastError());
128     if (!ret)
129         return FALSE;
130     DeleteFileA(fname);
131 
132     lstrcatA(fname, ".avi");
133 
134     hFile = CreateFileA(fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
135     ok(hFile != INVALID_HANDLE_VALUE, "Failed to create a file, err %d\n", GetLastError());
136     if (hFile == INVALID_HANDLE_VALUE) return FALSE;
137 
138     buffer_length = padding[1];
139     buffer = heap_alloc_zero(buffer_length);
140 
141     WriteFile(hFile, file_header, sizeof(file_header), &written, NULL);
142     WriteFile(hFile, &main_avi_header, sizeof(MainAVIHeader), &written, NULL);
143     WriteFile(hFile, stream_list, sizeof(stream_list), &written, NULL);
144     WriteFile(hFile, &avi_stream_header, sizeof(AVIStreamHeader), &written, NULL);
145     WriteFile(hFile, video_stream_format, sizeof(video_stream_format), &written, NULL);
146     WriteFile(hFile, padding, sizeof(padding), &written, NULL);
147     WriteFile(hFile, buffer, buffer_length, &written, NULL);
148     WriteFile(hFile, data, sizeof(data), &written, NULL);
149 
150     heap_free(buffer);
151 
152     CloseHandle(hFile);
153     return ret;
154 }
155 
156 static void test_MCIWndCreate(void)
157 {
158     HWND parent, window;
159     HMODULE hinst = GetModuleHandleA(NULL);
160     char fname[MAX_PATH];
161     char invalid_fname[] = "invalid.avi";
162     char error[200];
163     LRESULT ret;
164 
165     create_avi_file(fname);
166 
167     window = MCIWndCreateA(NULL, hinst, MCIWNDF_NOERRORDLG, fname);
168     ok(window != NULL, "Failed to create an MCIWnd window without parent\n");
169 
170     ret = SendMessageA(window, MCIWNDM_GETERRORA, sizeof(error), (LPARAM)error);
171     ok(!ret || broken(ret == ERROR_INVALID_HANDLE) /* w2003std, w2008s64 */,
172        "Unexpected error %ld\n", ret);
173 
174     DestroyWindow(window);
175 
176     parent = CreateWindowExA(0, "static", "msvfw32 test",
177                              WS_POPUP, 0, 0, 100, 100,
178                              0, 0, 0, NULL);
179     ok(parent != NULL, "Failed to create a window\n");
180     window = MCIWndCreateA(parent, hinst, MCIWNDF_NOERRORDLG, fname);
181     ok(window != NULL, "Failed to create an MCIWnd window\n");
182 
183     ret = SendMessageA(window, MCIWNDM_GETERRORA, sizeof(error), (LPARAM)error);
184     ok(!ret || broken(ret == ERROR_INVALID_HANDLE) /* w2003std, w2008s64 */,
185        "Unexpected error %ld\n", ret);
186 
187     DestroyWindow(parent);
188 
189     window = MCIWndCreateA(NULL, hinst, MCIWNDF_NOERRORDLG, invalid_fname);
190     ok(window != NULL, "Failed to create an MCIWnd window\n");
191 
192     ret = SendMessageA(window, MCIWNDM_GETERRORA, sizeof(error), (LPARAM)error);
193     todo_wine ok(ret == MCIERR_FILE_NOT_FOUND, "Unexpected error %ld\n", ret);
194 
195     DestroyWindow(window);
196 
197     DeleteFileA(fname);
198 }
199 
200 START_TEST(mciwnd)
201 {
202     test_MCIWndCreate();
203 }
204