2 * Copyright 2010 Louis Lenders
3 * Copyright 2011 André Hentschel
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.
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.
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
25 #include "wine/test.h"
27 static HMODULE hmscoree
;
29 static HRESULT (WINAPI
*pGetCORVersion
)(LPWSTR
, DWORD
, DWORD
*);
30 static HRESULT (WINAPI
*pGetCORSystemDirectory
)(LPWSTR
, DWORD
, DWORD
*);
31 static HRESULT (WINAPI
*pGetRequestedRuntimeInfo
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, DWORD
, DWORD
, LPWSTR
, DWORD
, DWORD
*, LPWSTR
, DWORD
, DWORD
*);
32 static HRESULT (WINAPI
*pLoadLibraryShim
)(LPCWSTR
, LPCWSTR
, LPVOID
, HMODULE
*);
33 static HRESULT (WINAPI
*pCreateConfigStream
)(LPCWSTR
, IStream
**);
35 static BOOL
init_functionpointers(void)
37 hmscoree
= LoadLibraryA("mscoree.dll");
41 win_skip("mscoree.dll not available\n");
45 pGetCORVersion
= (void *)GetProcAddress(hmscoree
, "GetCORVersion");
46 pGetCORSystemDirectory
= (void *)GetProcAddress(hmscoree
, "GetCORSystemDirectory");
47 pGetRequestedRuntimeInfo
= (void *)GetProcAddress(hmscoree
, "GetRequestedRuntimeInfo");
48 pLoadLibraryShim
= (void *)GetProcAddress(hmscoree
, "LoadLibraryShim");
49 pCreateConfigStream
= (void *)GetProcAddress(hmscoree
, "CreateConfigStream");
51 if (!pGetCORVersion
|| !pGetCORSystemDirectory
|| !pGetRequestedRuntimeInfo
|| !pLoadLibraryShim
)
53 win_skip("functions not available\n");
54 FreeLibrary(hmscoree
);
61 static void test_versioninfo(void)
63 const WCHAR v9_0
[] = {'v','9','.','0','.','3','0','3','1','9',0};
64 const WCHAR v2_0cap
[] = {'V','2','.','0','.','5','0','7','2','7',0};
65 const WCHAR v2_0
[] = {'v','2','.','0','.','5','0','7','2','7',0};
66 const WCHAR v2_0_0
[] = {'v','2','.','0','.','0',0};
67 const WCHAR v1_1
[] = {'v','1','.','1','.','4','3','2','2',0};
68 const WCHAR v1_1_0
[] = {'v','1','.','1','.','0',0};
70 WCHAR version
[MAX_PATH
];
75 if (0) /* crashes on <= w2k3 */
77 hr
= pGetCORVersion(NULL
, MAX_PATH
, &size
);
78 ok(hr
== E_POINTER
,"GetCORVersion returned %08x\n", hr
);
81 hr
= pGetCORVersion(version
, 1, &size
);
82 if (hr
== CLR_E_SHIM_RUNTIME
)
84 /* FIXME: Get Mono packaged properly so we can fail here. */
85 todo_wine
ok(hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
),"GetCORVersion returned %08x\n", hr
);
86 skip("No .NET runtimes are installed\n");
90 ok(hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
),"GetCORVersion returned %08x\n", hr
);
92 hr
= pGetCORVersion(version
, MAX_PATH
, &size
);
93 ok(hr
== S_OK
,"GetCORVersion returned %08x\n", hr
);
95 trace("latest installed .net runtime: %s\n", wine_dbgstr_w(version
));
97 hr
= pGetCORSystemDirectory(path
, MAX_PATH
, &size
);
98 ok(hr
== S_OK
, "GetCORSystemDirectory returned %08x\n", hr
);
99 /* size includes terminating null-character */
100 ok(size
== (lstrlenW(path
) + 1),"size is %d instead of %d\n", size
, (lstrlenW(path
) + 1));
104 hr
= pGetCORSystemDirectory(path
, path_len
-1 , &size
);
105 ok(hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
), "GetCORSystemDirectory returned %08x\n", hr
);
107 if (0) /* crashes on <= w2k3 */
109 hr
= pGetCORSystemDirectory(NULL
, MAX_PATH
, &size
);
110 ok(hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
), "GetCORSystemDirectory returned %08x\n", hr
);
113 hr
= pGetCORSystemDirectory(path
, MAX_PATH
, NULL
);
114 ok(hr
== E_POINTER
,"GetCORSystemDirectory returned %08x\n", hr
);
116 trace("latest installed .net installed in directory: %s\n", wine_dbgstr_w(path
));
118 /* test GetRequestedRuntimeInfo, first get info about different versions of runtime */
119 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, &size
);
121 if(hr
== CLR_E_SHIM_RUNTIME
) return; /* skipping rest of tests on win2k as .net 2.0 not installed */
123 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
124 trace(" installed in directory %s is .net version %s\n", wine_dbgstr_w(path
), wine_dbgstr_w(version
));
126 hr
= pGetRequestedRuntimeInfo( NULL
, v1_1
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, &size
);
127 ok(hr
== S_OK
|| hr
== CLR_E_SHIM_RUNTIME
/*v1_1 not installed*/, "GetRequestedRuntimeInfo returned %08x\n", hr
);
129 trace(" installed in directory %s is .net version %s\n", wine_dbgstr_w(path
), wine_dbgstr_w(version
));
130 /* version number NULL not allowed without RUNTIME_INFO_UPGRADE_VERSION flag */
131 hr
= pGetRequestedRuntimeInfo( NULL
, NULL
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, &size
);
132 ok(hr
== CLR_E_SHIM_RUNTIME
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
133 /* with RUNTIME_INFO_UPGRADE_VERSION flag and version number NULL, latest installed version is returned */
134 hr
= pGetRequestedRuntimeInfo( NULL
, NULL
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, &size
);
135 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
137 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0
, NULL
, 0, 0, path
, 1, &path_len
, version
, MAX_PATH
, &size
);
138 ok(hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
), "GetRequestedRuntimeInfo returned %08x\n", hr
);
140 /* if one of the buffers is NULL, the other one is still happily filled */
141 memset(version
, 0, sizeof(version
));
142 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0
, NULL
, 0, 0, NULL
, MAX_PATH
, &path_len
, version
, MAX_PATH
, &size
);
143 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
144 ok(!winetest_strcmpW(version
, v2_0
), "version is %s , expected %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v2_0
));
145 /* With NULL-pointer for bufferlength, the buffer itself still gets filled with correct string */
146 memset(version
, 0, sizeof(version
));
147 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
148 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
149 ok(!winetest_strcmpW(version
, v2_0
), "version is %s , expected %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v2_0
));
151 memset(version
, 0, sizeof(version
));
152 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0cap
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
153 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
154 ok(!winetest_strcmpW(version
, v2_0cap
), "version is %s , expected %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v2_0cap
));
156 /* Invalid Version and RUNTIME_INFO_UPGRADE_VERSION flag*/
157 memset(version
, 0, sizeof(version
));
158 hr
= pGetRequestedRuntimeInfo( NULL
, v1_1
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
159 ok(hr
== S_OK
|| hr
== CLR_E_SHIM_RUNTIME
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
162 /* .NET 1.1 may not be installed. */
163 ok(!winetest_strcmpW(version
, v1_1
) || !winetest_strcmpW(version
, v2_0
),
164 "version is %s , expected %s or %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v1_1
), wine_dbgstr_w(v2_0
));
168 memset(version
, 0, sizeof(version
));
169 hr
= pGetRequestedRuntimeInfo( NULL
, v9_0
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
170 ok(hr
== CLR_E_SHIM_RUNTIME
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
172 memset(version
, 0, sizeof(version
));
173 hr
= pGetRequestedRuntimeInfo( NULL
, v1_1_0
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
174 ok(hr
== CLR_E_SHIM_RUNTIME
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
176 memset(version
, 0, sizeof(version
));
177 hr
= pGetRequestedRuntimeInfo( NULL
, v1_1_0
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
178 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
179 ok(!winetest_strcmpW(version
, v2_0
), "version is %s , expected %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v2_0
));
181 memset(version
, 0, sizeof(version
));
182 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0_0
, NULL
, 0, 0, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
183 ok(hr
== CLR_E_SHIM_RUNTIME
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
185 memset(version
, 0, sizeof(version
));
186 hr
= pGetRequestedRuntimeInfo( NULL
, v2_0_0
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, path
, MAX_PATH
, &path_len
, version
, MAX_PATH
, NULL
);
187 ok(hr
== S_OK
, "GetRequestedRuntimeInfo returned %08x\n", hr
);
188 ok(!winetest_strcmpW(version
, v2_0
), "version is %s , expected %s\n", wine_dbgstr_w(version
), wine_dbgstr_w(v2_0
));
191 static void test_loadlibraryshim(void)
193 const WCHAR v4_0
[] = {'v','4','.','0','.','3','0','3','1','9',0};
194 const WCHAR v2_0
[] = {'v','2','.','0','.','5','0','7','2','7',0};
195 const WCHAR v1_1
[] = {'v','1','.','1','.','4','3','2','2',0};
196 const WCHAR vbogus
[] = {'v','b','o','g','u','s',0};
197 const WCHAR fusion
[] = {'f','u','s','i','o','n',0};
198 const WCHAR fusiondll
[] = {'f','u','s','i','o','n','.','d','l','l',0};
199 const WCHAR nosuchdll
[] = {'j','n','v','n','l','.','d','l','l',0};
200 const WCHAR gdidll
[] = {'g','d','i','3','2','.','d','l','l',0};
202 const WCHAR
*latest
= NULL
;
203 CHAR latestA
[MAX_PATH
];
205 CHAR dllpath
[MAX_PATH
];
207 hr
= pLoadLibraryShim(fusion
, v1_1
, NULL
, &hdll
);
208 ok(hr
== S_OK
|| hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
213 GetModuleFileNameA(hdll
, dllpath
, MAX_PATH
);
215 todo_wine
ok(StrStrIA(dllpath
, "v1.1.4322") != 0, "incorrect fusion.dll path %s\n", dllpath
);
216 ok(StrStrIA(dllpath
, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath
);
221 hr
= pLoadLibraryShim(fusion
, v2_0
, NULL
, &hdll
);
222 ok(hr
== S_OK
|| hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
227 GetModuleFileNameA(hdll
, dllpath
, MAX_PATH
);
229 todo_wine
ok(StrStrIA(dllpath
, "v2.0.50727") != 0, "incorrect fusion.dll path %s\n", dllpath
);
230 ok(StrStrIA(dllpath
, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath
);
235 hr
= pLoadLibraryShim(fusion
, v4_0
, NULL
, &hdll
);
236 ok(hr
== S_OK
|| hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
239 /* LoadLibraryShim with a NULL version prefers 2.0 and earlier */
243 GetModuleFileNameA(hdll
, dllpath
, MAX_PATH
);
245 todo_wine
ok(StrStrIA(dllpath
, "v4.0.30319") != 0, "incorrect fusion.dll path %s\n", dllpath
);
246 ok(StrStrIA(dllpath
, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath
);
251 hr
= pLoadLibraryShim(fusion
, vbogus
, NULL
, &hdll
);
252 todo_wine
ok(hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
256 WideCharToMultiByte(CP_ACP
, 0, latest
, -1, latestA
, MAX_PATH
, NULL
, NULL
);
258 hr
= pLoadLibraryShim(fusion
, NULL
, NULL
, &hdll
);
259 ok(hr
== S_OK
, "LoadLibraryShim failed, hr=%x\n", hr
);
262 GetModuleFileNameA(hdll
, dllpath
, MAX_PATH
);
265 todo_wine
ok(StrStrIA(dllpath
, latestA
) != 0, "incorrect fusion.dll path %s\n", dllpath
);
266 ok(StrStrIA(dllpath
, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath
);
271 hr
= pLoadLibraryShim(fusiondll
, NULL
, NULL
, &hdll
);
272 ok(hr
== S_OK
, "LoadLibraryShim failed, hr=%x\n", hr
);
275 GetModuleFileNameA(hdll
, dllpath
, MAX_PATH
);
278 todo_wine
ok(StrStrIA(dllpath
, latestA
) != 0, "incorrect fusion.dll path %s\n", dllpath
);
279 ok(StrStrIA(dllpath
, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath
);
284 hr
= pLoadLibraryShim(nosuchdll
, latest
, NULL
, &hdll
);
285 ok(hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
289 hr
= pLoadLibraryShim(gdidll
, latest
, NULL
, &hdll
);
290 todo_wine
ok(hr
== E_HANDLE
, "LoadLibraryShim failed, hr=%x\n", hr
);
295 static const char xmldata
[] =
296 "<?xml version=\"1.0\" ?>\n"
297 "<!DOCTYPE Config>\n"
299 " <Name>Test</Name>\n"
300 " <Value>1234</Value>\n"
303 static void create_xml_file(LPCWSTR filename
)
305 DWORD dwNumberOfBytesWritten
;
306 HANDLE hfile
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
,
307 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
308 ok(hfile
!= INVALID_HANDLE_VALUE
, "File creation failed\n");
309 WriteFile(hfile
, xmldata
, sizeof(xmldata
) - 1, &dwNumberOfBytesWritten
, NULL
);
313 static void test_createconfigstream(void)
315 IStream
*stream
= NULL
;
316 WCHAR file
[] = {'c', 'o', 'n', 'f', '.', 'x', 'm', 'l', 0};
317 WCHAR nonexistent
[] = {'n', 'o', 'n', 'e', 'x', 'i', 's', 't', '.', 'x', 'm', 'l', 0};
318 WCHAR path
[MAX_PATH
];
320 char buffer
[256] = {0};
322 if (!pCreateConfigStream
)
324 win_skip("CreateConfigStream not available\n");
328 create_xml_file(file
);
329 GetFullPathNameW(file
, MAX_PATH
, path
, NULL
);
331 hr
= pCreateConfigStream(NULL
, &stream
);
332 todo_wine
ok(hr
== E_FAIL
||
333 broken(hr
== HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND
)) || /* some WinXP, Win2K3 and Win7 */
334 broken(hr
== S_OK
&& !stream
), /* some Win2K3 */
335 "CreateConfigStream returned %x\n", hr
);
337 hr
= pCreateConfigStream(path
, NULL
);
338 todo_wine
ok(hr
== COR_E_NULLREFERENCE
, "CreateConfigStream returned %x\n", hr
);
340 hr
= pCreateConfigStream(NULL
, NULL
);
341 todo_wine
ok(hr
== COR_E_NULLREFERENCE
, "CreateConfigStream returned %x\n", hr
);
343 hr
= pCreateConfigStream(nonexistent
, &stream
);
344 todo_wine
ok(hr
== COR_E_FILENOTFOUND
, "CreateConfigStream returned %x\n", hr
);
345 ok(stream
== NULL
, "Expected stream to be NULL\n");
347 hr
= pCreateConfigStream(path
, &stream
);
348 todo_wine
ok(hr
== S_OK
, "CreateConfigStream failed, hr=%x\n", hr
);
349 todo_wine
ok(stream
!= NULL
, "Expected non-NULL stream\n");
356 IStream
*stream2
= NULL
;
358 hr
= IStream_Read(stream
, buffer
, strlen(xmldata
), &count
);
359 ok(hr
== S_OK
, "IStream_Read failed, hr=%x\n", hr
);
360 ok(count
== strlen(xmldata
), "wrong count: %u\n", count
);
361 ok(!strcmp(buffer
, xmldata
), "Strings do not match\n");
363 hr
= IStream_Write(stream
, xmldata
, strlen(xmldata
), &count
);
364 ok(hr
== E_FAIL
, "IStream_Write returned hr=%x\n", hr
);
366 pos
.QuadPart
= strlen(xmldata
);
367 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
368 ok(hr
== E_NOTIMPL
, "IStream_Seek returned hr=%x\n", hr
);
370 size
.QuadPart
= strlen(xmldata
);
371 hr
= IStream_SetSize(stream
, size
);
372 ok(hr
== E_NOTIMPL
, "IStream_SetSize returned hr=%x\n", hr
);
374 hr
= IStream_Clone(stream
, &stream2
);
375 ok(hr
== E_NOTIMPL
, "IStream_Clone returned hr=%x\n", hr
);
377 hr
= IStream_Commit(stream
, STGC_DEFAULT
);
378 ok(hr
== E_NOTIMPL
, "IStream_Commit returned hr=%x\n", hr
);
380 hr
= IStream_Revert(stream
);
381 ok(hr
== E_NOTIMPL
, "IStream_Revert returned hr=%x\n", hr
);
383 hr
= IStream_Release(stream
);
384 ok(hr
== S_OK
, "IStream_Release returned hr=%x\n", hr
);
391 if (!init_functionpointers())
395 test_loadlibraryshim();
396 test_createconfigstream();
398 FreeLibrary(hmscoree
);