1 /*
2  * Copyright (C) 2008 Stefan Dösinger
3  * Copyright (C) 2009 Matteo Bruni
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 #define COBJMACROS
20 #define CONST_VTABLE
21 #include "wine/test.h"
22 
23 #include <d3dx9.h>
24 
25 #include "resources.h"
26 
27 static char temp_path[MAX_PATH];
28 
29 static BOOL create_file(const char *filename, const char *data, const unsigned int size, char *out_path)
30 {
31     DWORD written;
32     HANDLE hfile;
33     char path[MAX_PATH];
34 
35     if (!*temp_path)
36         GetTempPathA(sizeof(temp_path), temp_path);
37 
38     strcpy(path, temp_path);
39     strcat(path, filename);
40     hfile = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
41     if (hfile == INVALID_HANDLE_VALUE)
42         return FALSE;
43 
44     if (WriteFile(hfile, data, size, &written, NULL))
45     {
46         CloseHandle(hfile);
47 
48         if (out_path)
49             strcpy(out_path, path);
50         return TRUE;
51     }
52 
53     CloseHandle(hfile);
54     return FALSE;
55 }
56 
57 static void delete_file(const char *filename)
58 {
59     char path[MAX_PATH];
60 
61     strcpy(path, temp_path);
62     strcat(path, filename);
63     DeleteFileA(path);
64 }
65 
66 static BOOL create_directory(const char *name)
67 {
68     char path[MAX_PATH];
69 
70     strcpy(path, temp_path);
71     strcat(path, name);
72     return CreateDirectoryA(path, NULL);
73 }
74 
75 static void delete_directory(const char *name)
76 {
77     char path[MAX_PATH];
78 
79     strcpy(path, temp_path);
80     strcat(path, name);
81     RemoveDirectoryA(path);
82 }
83 
84 static HRESULT WINAPI testD3DXInclude_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type,
85         const char *filename, const void *parent_data, const void **data, UINT *bytes)
86 {
87     char *buffer;
88     static const char shader[] =
89             "#include \"incl.vsh\"\n"
90             "mov REGISTER, v0\n";
91     static const char include[] = "#define REGISTER r0\nvs.1.1\n";
92     static const char include2[] = "#include \"incl3.vsh\"\n";
93     static const char include3[] = "vs.1.1\n";
94 
95     trace("filename %s.\n", filename);
96     trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)");
97 
98     if (!strcmp(filename, "shader.vsh"))
99     {
100         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(shader));
101         memcpy(buffer, shader, sizeof(shader));
102         *bytes = sizeof(shader);
103     }
104     else if (!strcmp(filename, "incl.vsh"))
105     {
106         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include));
107         memcpy(buffer, include, sizeof(include));
108         *bytes = sizeof(include);
109         /* This is included from the first D3DXAssembleShader with non-null ID3DXInclude test
110          * (parent_data == NULL) and from shader.vsh / shader[] (with matching parent_data).
111          * Allow both cases. */
112         ok(parent_data == NULL || !strncmp(shader, parent_data, strlen(shader)), "wrong parent_data value\n");
113     }
114     else if (!strcmp(filename, "incl2.vsh"))
115     {
116         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include2));
117         memcpy(buffer, include2, sizeof(include2));
118         *bytes = sizeof(include2);
119     }
120     else if (!strcmp(filename, "incl3.vsh"))
121     {
122         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include3));
123         memcpy(buffer, include3, sizeof(include3));
124         *bytes = sizeof(include3);
125         /* Also check for the correct parent_data content */
126         ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)), "wrong parent_data value\n");
127     }
128     else if (!strcmp(filename, "include/incl3.vsh"))
129     {
130         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include));
131         memcpy(buffer, include, sizeof(include));
132         *bytes = sizeof(include);
133         ok(!parent_data, "wrong parent_data value\n");
134     }
135     else
136     {
137         ok(0, "Unexpected #include for file %s.\n", filename);
138         return D3DERR_INVALIDCALL;
139     }
140     *data = buffer;
141     return S_OK;
142 }
143 
144 static HRESULT WINAPI testD3DXInclude_close(ID3DXInclude *iface, const void *data)
145 {
146     HeapFree(GetProcessHeap(), 0, (void *)data);
147     return S_OK;
148 }
149 
150 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
151     testD3DXInclude_open,
152     testD3DXInclude_close
153 };
154 
155 struct D3DXIncludeImpl {
156     ID3DXInclude ID3DXInclude_iface;
157 };
158 
159 static void assembleshader_test(void)
160 {
161     static const char test1[] =
162         "vs.1.1\n"
163         "mov DEF2, v0\n";
164     static const char testincl[] =
165         "#define REGISTER r0\n"
166         "vs.1.1\n";
167     static const char testshader[] =
168         "#include \"incl.vsh\"\n"
169         "mov REGISTER, v0\n";
170     static const char testshader2[] =
171         "#include \"incl2.vsh\"\n"
172         "mov REGISTER, v0\n";
173     static const char testshader3[] =
174         "#include \"include/incl3.vsh\"\n"
175         "mov REGISTER, v0\n";
176     static const char testincl3[] =
177         "#include \"incl4.vsh\"\n";
178     static const char testincl4_ok[] =
179         "#define REGISTER r0\n"
180         "vs.1.1\n";
181     static const char testincl4_wrong[] =
182         "#error \"wrong include\"\n";
183     HRESULT hr;
184     ID3DXBuffer *shader, *messages;
185     static const D3DXMACRO defines[] = {
186         {
187             "DEF1", "10 + 15"
188         },
189         {
190             "DEF2", "r0"
191         },
192         {
193             NULL, NULL
194         }
195     };
196     struct D3DXIncludeImpl include;
197     char shader_vsh_path[MAX_PATH], shader3_vsh_path[MAX_PATH];
198 
199     /* pDefines test */
200     shader = NULL;
201     messages = NULL;
202     hr = D3DXAssembleShader(test1, strlen(test1),
203                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
204                             &shader, &messages);
205     ok(hr == D3D_OK, "pDefines test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
206     if(messages) {
207         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
208         ID3DXBuffer_Release(messages);
209     }
210     if(shader) ID3DXBuffer_Release(shader);
211 
212     /* NULL messages test */
213     shader = NULL;
214     hr = D3DXAssembleShader(test1, strlen(test1),
215                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
216                             &shader, NULL);
217     ok(hr == D3D_OK, "NULL messages test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
218     if(shader) ID3DXBuffer_Release(shader);
219 
220     /* NULL shader test */
221     messages = NULL;
222     hr = D3DXAssembleShader(test1, strlen(test1),
223                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
224                             NULL, &messages);
225     ok(hr == D3D_OK, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
226     if(messages) {
227         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
228         ID3DXBuffer_Release(messages);
229     }
230 
231     /* pInclude test */
232     shader = NULL;
233     messages = NULL;
234     include.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
235     hr = D3DXAssembleShader(testshader, strlen(testshader), NULL, &include.ID3DXInclude_iface,
236                             D3DXSHADER_SKIPVALIDATION, &shader, &messages);
237     ok(hr == D3D_OK, "pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
238     if(messages) {
239         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
240         ID3DXBuffer_Release(messages);
241     }
242     if(shader) ID3DXBuffer_Release(shader);
243 
244     /* "unexpected #include file from memory" test */
245     shader = NULL;
246     messages = NULL;
247     hr = D3DXAssembleShader(testshader, strlen(testshader),
248                             NULL, NULL, D3DXSHADER_SKIPVALIDATION,
249                             &shader, &messages);
250     ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
251     if(messages) {
252         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
253         ID3DXBuffer_Release(messages);
254     }
255     if(shader) ID3DXBuffer_Release(shader);
256 
257     /* recursive #include test */
258     shader = NULL;
259     messages = NULL;
260     hr = D3DXAssembleShader(testshader2, strlen(testshader2), NULL, &include.ID3DXInclude_iface,
261                             D3DXSHADER_SKIPVALIDATION, &shader, &messages);
262     ok(hr == D3D_OK, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
263     if(messages) {
264         trace("recursive D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
265         ID3DXBuffer_Release(messages);
266     }
267     if(shader) ID3DXBuffer_Release(shader);
268 
269     /* #include with a path. */
270     shader = NULL;
271     messages = NULL;
272     hr = D3DXAssembleShader(testshader3, strlen(testshader3), NULL, &include.ID3DXInclude_iface,
273             D3DXSHADER_SKIPVALIDATION, &shader, &messages);
274     ok(hr == D3D_OK, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000ffff);
275     if (messages)
276     {
277         trace("Path search D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
278         ID3DXBuffer_Release(messages);
279     }
280     if (shader)
281         ID3DXBuffer_Release(shader);
282 
283     if (create_file("shader.vsh", testshader, sizeof(testshader) - 1, shader_vsh_path))
284     {
285         create_file("incl.vsh", testincl, sizeof(testincl) - 1, NULL);
286 
287         /* D3DXAssembleShaderFromFile + #include test */
288         shader = NULL;
289         messages = NULL;
290         hr = D3DXAssembleShaderFromFileA(shader_vsh_path,
291                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
292                                          &shader, &messages);
293         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
294         if(messages) {
295             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
296             ID3DXBuffer_Release(messages);
297         }
298         if(shader) ID3DXBuffer_Release(shader);
299 
300         /* D3DXAssembleShaderFromFile + pInclude test */
301         shader = NULL;
302         messages = NULL;
303         hr = D3DXAssembleShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
304                                          D3DXSHADER_SKIPVALIDATION, &shader, &messages);
305         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
306         if(messages) {
307             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
308             ID3DXBuffer_Release(messages);
309         }
310         if(shader) ID3DXBuffer_Release(shader);
311 
312         create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1, shader3_vsh_path);
313         create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1, NULL);
314         if (create_directory("include"))
315         {
316             create_file("include\\incl3.vsh", testincl3, sizeof(testincl3) - 1, NULL);
317             create_file("include\\incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1, NULL);
318 
319             /* path search #include test */
320             shader = NULL;
321             messages = NULL;
322             hr = D3DXAssembleShaderFromFileA(shader3_vsh_path, NULL, NULL,
323                                              D3DXSHADER_SKIPVALIDATION,
324                                              &shader, &messages);
325             ok(hr == D3D_OK, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
326             if(messages) {
327                 trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
328                 ID3DXBuffer_Release(messages);
329             }
330             if(shader) ID3DXBuffer_Release(shader);
331         } else skip("Couldn't create \"include\" directory\n");
332 
333         delete_file("shader.vsh");
334         delete_file("incl.vsh");
335         delete_file("shader3.vsh");
336         delete_file("incl4.vsh");
337         delete_file("include\\incl3.vsh");
338         delete_file("include\\incl4.vsh");
339         delete_directory("include");
340 
341         /* The main shader is also to be loaded through the ID3DXInclude object. */
342         shader = NULL;
343         messages = NULL;
344         hr = D3DXAssembleShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
345                 D3DXSHADER_SKIPVALIDATION, &shader, &messages);
346         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
347                 hr, hr & 0x0000ffff);
348         if (messages)
349         {
350             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
351             ID3DXBuffer_Release(messages);
352         }
353         if (shader)
354             ID3DXBuffer_Release(shader);
355 
356         shader = NULL;
357         messages = NULL;
358         hr = D3DXAssembleShaderFromFileW(L"shader.vsh", NULL, &include.ID3DXInclude_iface,
359                 D3DXSHADER_SKIPVALIDATION, &shader, &messages);
360         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
361                 hr, hr & 0x0000ffff);
362         if (messages)
363         {
364             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
365             ID3DXBuffer_Release(messages);
366         }
367         if (shader)
368             ID3DXBuffer_Release(shader);
369     } else skip("Couldn't create \"shader.vsh\"\n");
370 
371     /* NULL shader tests */
372     shader = NULL;
373     messages = NULL;
374     hr = D3DXAssembleShader(NULL, 0,
375                             NULL, NULL, D3DXSHADER_SKIPVALIDATION,
376                             &shader, &messages);
377     ok(hr == D3DXERR_INVALIDDATA, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
378     if(messages) {
379         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
380         ID3DXBuffer_Release(messages);
381     }
382     if(shader) ID3DXBuffer_Release(shader);
383 
384     shader = NULL;
385     messages = NULL;
386     hr = D3DXAssembleShaderFromFileA("nonexistent.vsh",
387                                      NULL, NULL, D3DXSHADER_SKIPVALIDATION,
388                                      &shader, &messages);
389     ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
390         "D3DXAssembleShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
391         hr, hr & 0x0000FFFF);
392     if(messages) {
393         trace("D3DXAssembleShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
394         ID3DXBuffer_Release(messages);
395     }
396     if(shader) ID3DXBuffer_Release(shader);
397 
398     /* D3DXAssembleShaderFromResource test */
399     shader = NULL;
400     messages = NULL;
401     hr = D3DXAssembleShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
402                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
403                                          &shader, &messages);
404     ok(hr == D3D_OK, "D3DXAssembleShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
405     if(messages) {
406         trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
407         ID3DXBuffer_Release(messages);
408     }
409     if(shader) ID3DXBuffer_Release(shader);
410 
411     /* D3DXAssembleShaderFromResource with missing shader resource test */
412     shader = NULL;
413     messages = NULL;
414     hr = D3DXAssembleShaderFromResourceA(NULL, "notexisting",
415                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
416                                          &shader, &messages);
417     ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
418     if(messages) {
419         trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
420         ID3DXBuffer_Release(messages);
421     }
422     if(shader) ID3DXBuffer_Release(shader);
423 }
424 
425 static void d3dxpreprocess_test(void)
426 {
427     static const char testincl[] =
428             "#define REGISTER r0\n"
429             "vs.1.1\n";
430     static const char testshader[] =
431             "#include \"incl.vsh\"\n"
432             "mov REGISTER, v0\n";
433     static const char testshader3[] =
434             "#include \"include/incl3.vsh\"\n"
435             "mov REGISTER, v0\n";
436     static const char testincl3[] =
437             "#include \"incl4.vsh\"\n";
438     static const char testincl4_ok[] =
439             "#define REGISTER r0\n"
440             "vs.1.1\n";
441     static const char testincl4_wrong[] =
442             "#error \"wrong include\"\n";
443     HRESULT hr;
444     ID3DXBuffer *shader, *messages;
445     char shader_vsh_path[MAX_PATH], shader3_vsh_path[MAX_PATH];
446     static struct D3DXIncludeImpl include = {{&D3DXInclude_Vtbl}};
447 
448     if (create_file("shader.vsh", testshader, sizeof(testshader) - 1, shader_vsh_path))
449     {
450         create_file("incl.vsh", testincl, sizeof(testincl) - 1, NULL);
451         create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1, shader3_vsh_path);
452         create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1, NULL);
453         if (create_directory("include"))
454         {
455             create_file("include\\incl3.vsh", testincl3, sizeof(testincl3) - 1, NULL);
456             create_file("include\\incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1, NULL);
457 
458             /* path search #include test */
459             shader = NULL;
460             messages = NULL;
461             hr = D3DXPreprocessShaderFromFileA(shader3_vsh_path, NULL, NULL,
462                                                &shader, &messages);
463             ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
464             if(messages) {
465                 trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
466                 ID3DXBuffer_Release(messages);
467             }
468             if(shader) ID3DXBuffer_Release(shader);
469         } else skip("Couldn't create \"include\" directory\n");
470 
471         /* D3DXPreprocessShaderFromFile + #include test */
472         shader = NULL;
473         messages = NULL;
474         hr = D3DXPreprocessShaderFromFileA(shader_vsh_path,
475                                            NULL, NULL,
476                                            &shader, &messages);
477         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
478         if(messages) {
479             trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
480             ID3DXBuffer_Release(messages);
481         }
482         if(shader) ID3DXBuffer_Release(shader);
483 
484         /* D3DXPreprocessShaderFromFile + pInclude test */
485         shader = NULL;
486         messages = NULL;
487         hr = D3DXPreprocessShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
488                                            &shader, &messages);
489         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
490         if(messages) {
491             trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
492             ID3DXBuffer_Release(messages);
493         }
494         if(shader) ID3DXBuffer_Release(shader);
495 
496         delete_file("shader.vsh");
497         delete_file("incl.vsh");
498         delete_file("shader3.vsh");
499         delete_file("incl4.vsh");
500         delete_file("include\\incl3.vsh");
501         delete_file("include\\incl4.vsh");
502         delete_directory("include");
503 
504         /* The main shader is also to be loaded through the ID3DXInclude object. */
505         shader = NULL;
506         messages = NULL;
507         hr = D3DXPreprocessShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
508                 &shader, &messages);
509         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
510                 hr, hr & 0x0000ffff);
511         if (messages)
512         {
513             trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
514             ID3DXBuffer_Release(messages);
515         }
516         if (shader)
517             ID3DXBuffer_Release(shader);
518 
519         shader = NULL;
520         messages = NULL;
521         hr = D3DXPreprocessShaderFromFileW(L"shader.vsh", NULL, &include.ID3DXInclude_iface,
522                 &shader, &messages);
523         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
524                 hr, hr & 0x0000ffff);
525         if (messages)
526         {
527             trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
528             ID3DXBuffer_Release(messages);
529         }
530         if (shader)
531             ID3DXBuffer_Release(shader);
532     } else skip("Couldn't create \"shader.vsh\"\n");
533 
534     /* NULL shader tests */
535     shader = NULL;
536     messages = NULL;
537     hr = D3DXPreprocessShaderFromFileA("nonexistent.vsh",
538                                        NULL, NULL,
539                                        &shader, &messages);
540     ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
541         "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
542         hr, hr & 0x0000FFFF);
543     if(messages) {
544         trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
545         ID3DXBuffer_Release(messages);
546     }
547     if(shader) ID3DXBuffer_Release(shader);
548 
549     /* D3DXPreprocessShaderFromResource test */
550     shader = NULL;
551     messages = NULL;
552     hr = D3DXPreprocessShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
553                                            NULL, NULL,
554                                            &shader, &messages);
555     ok(hr == D3D_OK, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
556     if(messages) {
557         trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
558         ID3DXBuffer_Release(messages);
559     }
560     if(shader) ID3DXBuffer_Release(shader);
561 
562     /* D3DXPreprocessShaderFromResource with missing shader resource test */
563     shader = NULL;
564     messages = NULL;
565     hr = D3DXPreprocessShaderFromResourceA(NULL, "notexisting",
566                                            NULL, NULL,
567                                            &shader, &messages);
568     ok(hr == D3DXERR_INVALIDDATA, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
569     if(messages) {
570         trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
571         ID3DXBuffer_Release(messages);
572     }
573     if(shader) ID3DXBuffer_Release(shader);
574 }
575 
576 START_TEST(asm)
577 {
578     assembleshader_test();
579 
580     d3dxpreprocess_test();
581 }
582