[WININET_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / wininet / ftp.c
1 /*
2 * Wininet - ftp tests
3 *
4 * Copyright 2007 Paul Vriens
5 * Copyright 2007 Hans Leidekker
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 /*
23 * FIXME:
24 * Use InternetGetLastResponseInfo when the last error is set to ERROR_INTERNET_EXTENDED_ERROR.
25 * TODO:
26 * Add W-function tests.
27 * Add missing function tests:
28 * FtpGetFileSize
29 * FtpSetCurrentDirectory
30 */
31
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "windef.h"
37 #include "winbase.h"
38 #include "wininet.h"
39 #include "winsock2.h"
40
41 #include "wine/test.h"
42
43
44 static BOOL (WINAPI *pFtpCommandA)(HINTERNET,BOOL,DWORD,LPCSTR,DWORD_PTR,HINTERNET*);
45 static INTERNET_STATUS_CALLBACK (WINAPI *pInternetSetStatusCallbackA)(HINTERNET,INTERNET_STATUS_CALLBACK);
46
47
48 static void test_getfile_no_open(void)
49 {
50 BOOL bRet;
51
52 /* Invalid internet handle, the others are valid parameters */
53 SetLastError(0xdeadbeef);
54 bRet = FtpGetFileA(NULL, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
55 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
56 ok ( GetLastError() == ERROR_INTERNET_NOT_INITIALIZED ||
57 GetLastError() == ERROR_INVALID_HANDLE,
58 "Expected ERROR_INTERNET_NOT_INITIALIZED or ERROR_INVALID_HANDLE (win98), got %d\n", GetLastError());
59 }
60
61 static void test_connect(HINTERNET hInternet)
62 {
63 HINTERNET hFtp;
64
65 /* Try a few username/password combinations:
66 * anonymous : NULL
67 * NULL : IEUser@
68 * NULL : NULL
69 * "" : IEUser@
70 * "" : NULL
71 */
72
73 SetLastError(0xdeadbeef);
74 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
75 if (hFtp) /* some servers accept an empty password */
76 {
77 ros_skip_flaky
78 ok ( GetLastError() == ERROR_SUCCESS, "ERROR_SUCCESS, got %d\n", GetLastError());
79 InternetCloseHandle(hFtp);
80 }
81 else
82 ros_skip_flaky
83 ok ( GetLastError() == ERROR_INTERNET_LOGIN_FAILURE,
84 "Expected ERROR_INTERNET_LOGIN_FAILURE, got %d\n", GetLastError());
85
86 SetLastError(0xdeadbeef);
87 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, NULL, "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
88 ok ( hFtp == NULL, "Expected InternetConnect to fail\n");
89 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
90 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
91
92 SetLastError(0xdeadbeef);
93 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "", "IEUser@",
94 INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
95 ok(!hFtp, "Expected InternetConnect to fail\n");
96 ok(GetLastError() == ERROR_INVALID_PARAMETER,
97 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
98
99 /* Using a NULL username and password will be interpreted as anonymous ftp. The username will be 'anonymous' the password
100 * is created via some simple heuristics (see dlls/wininet/ftp.c).
101 * On Wine this registry key is not set by default so (NULL, NULL) will result in anonymous ftp with an (most likely) not
102 * accepted password (the username).
103 * If the first call fails because we get an ERROR_INTERNET_LOGIN_FAILURE, we try again with a (more) correct password.
104 */
105
106 SetLastError(0xdeadbeef);
107 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, NULL, NULL, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
108 if (!hFtp && (GetLastError() == ERROR_INTERNET_LOGIN_FAILURE))
109 {
110 /* We are most likely running on a clean Wine install or a Windows install where the registry key is removed */
111 SetLastError(0xdeadbeef);
112 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
113 }
114 ros_skip_flaky
115 ok ( hFtp != NULL, "InternetConnect failed : %d\n", GetLastError());
116 ros_skip_flaky
117 ok ( GetLastError() == ERROR_SUCCESS,
118 "ERROR_SUCCESS, got %d\n", GetLastError());
119 InternetCloseHandle(hFtp);
120
121 SetLastError(0xdeadbeef);
122 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "", NULL,
123 INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
124 if (!hFtp)
125 {
126 ros_skip_flaky
127 ok(GetLastError() == ERROR_INTERNET_LOGIN_FAILURE,
128 "Expected ERROR_INTERNET_LOGIN_FAILURE, got %d\n", GetLastError());
129 }
130 else
131 {
132 ros_skip_flaky
133 ok(GetLastError() == ERROR_SUCCESS,
134 "Expected ERROR_SUCCESS, got %d\n", GetLastError());
135 InternetCloseHandle(hFtp);
136 }
137 }
138
139 static void test_createdir(HINTERNET hFtp, HINTERNET hConnect)
140 {
141 BOOL bRet;
142
143 /* Invalid internet handle, the other is a valid parameter */
144 SetLastError(0xdeadbeef);
145 bRet = FtpCreateDirectoryA(NULL, "new_directory_deadbeef");
146 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
147 ok ( GetLastError() == ERROR_INVALID_HANDLE,
148 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
149
150 /* No directory-name */
151 SetLastError(0xdeadbeef);
152 bRet = FtpCreateDirectoryA(hFtp, NULL);
153 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
154 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
155 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
156
157 /* Parameters are OK, but we shouldn't be allowed to create the directory */
158 SetLastError(0xdeadbeef);
159 bRet = FtpCreateDirectoryA(hFtp, "new_directory_deadbeef");
160 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
161 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
162 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
163
164 /* One small test to show that handle type is checked before parameters */
165 SetLastError(0xdeadbeef);
166 bRet = FtpCreateDirectoryA(hConnect, NULL);
167 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
168 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
169 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
170
171 SetLastError(0xdeadbeef);
172 bRet = FtpCreateDirectoryA(hConnect, "new_directory_deadbeef");
173 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
174 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
175 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
176 }
177
178 static void test_deletefile(HINTERNET hFtp, HINTERNET hConnect)
179 {
180 BOOL bRet;
181
182 /* Invalid internet handle, the other is a valid parameter */
183 SetLastError(0xdeadbeef);
184 bRet = FtpDeleteFileA(NULL, "non_existent_file_deadbeef");
185 ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
186 ok ( GetLastError() == ERROR_INVALID_HANDLE,
187 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
188
189 /* No filename */
190 SetLastError(0xdeadbeef);
191 bRet = FtpDeleteFileA(hFtp, NULL);
192 ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
193 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
194 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
195
196 /* Parameters are OK but remote file should not be there */
197 SetLastError(0xdeadbeef);
198 bRet = FtpDeleteFileA(hFtp, "non_existent_file_deadbeef");
199 ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
200 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
201 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
202
203 /* One small test to show that handle type is checked before parameters */
204 SetLastError(0xdeadbeef);
205 bRet = FtpDeleteFileA(hConnect, NULL);
206 ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
207 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
208 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
209
210 SetLastError(0xdeadbeef);
211 bRet = FtpDeleteFileA(hConnect, "non_existent_file_deadbeef");
212 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
213 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
214 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
215 }
216
217 static void test_getfile(HINTERNET hFtp, HINTERNET hConnect)
218 {
219 BOOL bRet;
220 HANDLE hFile;
221
222 /* The order of checking is:
223 *
224 * All parameters except 'session handle' and 'condition flags'
225 * Session handle
226 * Session handle type
227 * Condition flags
228 */
229
230 /* Test to show the parameter checking order depends on the Windows version */
231 SetLastError(0xdeadbeef);
232 bRet = FtpGetFileA(NULL, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
233 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
234 ok ( GetLastError() == ERROR_INVALID_HANDLE ||
235 GetLastError() == ERROR_INVALID_PARAMETER,
236 "Expected ERROR_INVALID_HANDLE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
237
238 /* Test to show session handle is checked before 'condition flags' */
239 SetLastError(0xdeadbeef);
240 bRet = FtpGetFileA(NULL, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 5, 0);
241 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
242 ok ( GetLastError() == ERROR_INVALID_HANDLE,
243 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
244
245 /* Make sure we start clean */
246
247 DeleteFileA("should_be_non_existing_deadbeef");
248 DeleteFileA("should_also_be_non_existing_deadbeef");
249
250 /* No remote file */
251 SetLastError(0xdeadbeef);
252 bRet = FtpGetFileA(hFtp, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
253 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
254 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
255 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
256 ok (GetFileAttributesA("should_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
257 "Local file should not have been created\n");
258 DeleteFileA("should_be_non_existing_deadbeef");
259
260 /* No local file */
261 SetLastError(0xdeadbeef);
262 bRet = FtpGetFileA(hFtp, "welcome.msg", NULL, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
263 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
264 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
265 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
266
267 /* Zero attributes */
268 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_existing_non_deadbeef", FALSE, 0, FTP_TRANSFER_TYPE_UNKNOWN, 0);
269 ok ( bRet == TRUE, "Expected FtpGetFileA to succeed\n");
270 ok (GetFileAttributesA("should_be_existing_non_deadbeef") != INVALID_FILE_ATTRIBUTES,
271 "Local file should have been created\n");
272 DeleteFileA("should_be_existing_non_deadbeef");
273
274 /* Illegal condition flags */
275 SetLastError(0xdeadbeef);
276 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 0xffffffff, 0);
277 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
278 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR || GetLastError() == ERROR_INVALID_PARAMETER,
279 "Expected ERROR_INTERNET_EXTENDED_ERROR or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
280 ok (GetFileAttributesA("should_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
281 "Local file should not have been created\n");
282 DeleteFileA("should_be_non_existing_deadbeef");
283
284 /* Remote file doesn't exist (and local doesn't exist as well) */
285 SetLastError(0xdeadbeef);
286 bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_also_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
287 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
288 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
289 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
290 /* Currently Wine always creates the local file (even on failure) which is not correct, hence the test */
291 ok (GetFileAttributesA("should_also_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
292 "Local file should not have been created\n");
293
294 DeleteFileA("should_also_be_non_existing_deadbeef");
295
296 /* Same call as the previous but now the local file does exists. Windows just removes the file if the call fails
297 * even if the local existed before!
298 */
299
300 /* Create a temporary local file */
301 SetLastError(0xdeadbeef);
302 hFile = CreateFileA("should_also_be_non_existing_deadbeef", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
303 ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
304 CloseHandle(hFile);
305 SetLastError(0xdeadbeef);
306 bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_also_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
307 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
308 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
309 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
310 /* Currently Wine always creates the local file (even on failure) which is not correct, hence the test */
311 ok (GetFileAttributesA("should_also_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
312 "Local file should not have been created\n");
313
314 DeleteFileA("should_also_be_non_existing_deadbeef");
315
316 /* This one should succeed */
317 SetLastError(0xdeadbeef);
318 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_existing_non_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
319 ok ( bRet == TRUE, "Expected FtpGetFileA to fail\n");
320 ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
321
322 if (GetFileAttributesA("should_be_existing_non_deadbeef") != INVALID_FILE_ATTRIBUTES)
323 {
324 /* Should succeed as fFailIfExists is set to FALSE (meaning don't fail if local file exists) */
325 SetLastError(0xdeadbeef);
326 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
327 ok ( bRet == TRUE, "Expected FtpGetFileA to succeed\n");
328 ok ( GetLastError() == ERROR_SUCCESS,
329 "Expected ERROR_SUCCESS, got %d\n", GetLastError());
330
331 /* Should fail as fFailIfExists is set to TRUE */
332 SetLastError(0xdeadbeef);
333 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
334 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
335 ok ( GetLastError() == ERROR_FILE_EXISTS,
336 "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
337
338 /* Prove that the existence of the local file is checked first (or at least reported last) */
339 SetLastError(0xdeadbeef);
340 bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
341 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
342 ok ( GetLastError() == ERROR_FILE_EXISTS,
343 "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
344
345 DeleteFileA("should_be_existing_non_deadbeef");
346 }
347
348 /* Test to show the parameter checking order depends on the Windows version */
349 SetLastError(0xdeadbeef);
350 bRet = FtpGetFileA(hConnect, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
351 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
352 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE ||
353 GetLastError() == ERROR_INVALID_PARAMETER,
354 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
355
356 /* Test to show that 'session handle type' is checked before 'condition flags' */
357 SetLastError(0xdeadbeef);
358 bRet = FtpGetFileA(hConnect, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 5, 0);
359 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
360 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
361 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
362
363 SetLastError(0xdeadbeef);
364 bRet = FtpGetFileA(hConnect, "should_be_non_existing_deadbeef", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
365 ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
366 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
367 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
368 }
369
370 static void trace_extended_error(DWORD error)
371 {
372 DWORD code, buflen = 0;
373
374 if (error != ERROR_INTERNET_EXTENDED_ERROR) return;
375 if (!InternetGetLastResponseInfoA(&code, NULL, &buflen) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
376 {
377 char *text = HeapAlloc(GetProcessHeap(), 0, ++buflen);
378 InternetGetLastResponseInfoA(&code, text, &buflen);
379 trace("%u %s\n", code, text);
380 HeapFree(GetProcessHeap(), 0, text);
381 }
382 }
383
384 static void test_openfile(HINTERNET hFtp, HINTERNET hConnect)
385 {
386 HINTERNET hOpenFile;
387
388 /* Invalid internet handle, the rest are valid parameters */
389 SetLastError(0xdeadbeef);
390 hOpenFile = FtpOpenFileA(NULL, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
391 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
392 ok ( GetLastError() == ERROR_INVALID_HANDLE,
393 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
394 InternetCloseHandle(hOpenFile); /* Just in case */
395
396 /* No filename */
397 SetLastError(0xdeadbeef);
398 hOpenFile = FtpOpenFileA(hFtp, NULL, GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
399 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
400 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
401 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
402 InternetCloseHandle(hOpenFile); /* Just in case */
403
404 /* Illegal access flags */
405 SetLastError(0xdeadbeef);
406 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", 0, FTP_TRANSFER_TYPE_ASCII, 0);
407 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
408 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
409 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
410 InternetCloseHandle(hOpenFile); /* Just in case */
411
412 /* Illegal combination of access flags */
413 SetLastError(0xdeadbeef);
414 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ|GENERIC_WRITE, FTP_TRANSFER_TYPE_ASCII, 0);
415 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
416 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
417 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
418 InternetCloseHandle(hOpenFile); /* Just in case */
419
420 /* Illegal condition flags */
421 SetLastError(0xdeadbeef);
422 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, 0xffffffff, 0);
423 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
424 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR || GetLastError() == ERROR_INVALID_PARAMETER,
425 "Expected ERROR_INTERNET_EXTENDED_ERROR or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
426 InternetCloseHandle(hOpenFile); /* Just in case */
427
428 SetLastError(0xdeadbeef);
429 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
430 ok ( hOpenFile != NULL, "Expected FtpOpenFileA to succeed\n");
431 ok ( GetLastError() == ERROR_SUCCESS ||
432 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
433 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
434
435 if (hOpenFile)
436 {
437 BOOL bRet;
438 DWORD error;
439 HINTERNET hOpenFile2;
440 HANDLE hFile;
441
442 /* We have a handle so all ftp calls should fail (TODO: Put all ftp-calls in here) */
443 SetLastError(0xdeadbeef);
444 bRet = FtpCreateDirectoryA(hFtp, "new_directory_deadbeef");
445 error = GetLastError();
446 ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
447 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
448 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
449 trace_extended_error(error);
450
451 SetLastError(0xdeadbeef);
452 bRet = FtpDeleteFileA(hFtp, "non_existent_file_deadbeef");
453 error = GetLastError();
454 ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
455 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
456 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
457 trace_extended_error(error);
458
459 SetLastError(0xdeadbeef);
460 bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
461 error = GetLastError();
462 ok ( bRet == FALSE || broken(bRet == TRUE), "Expected FtpGetFileA to fail\n");
463 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_SUCCESS),
464 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
465 DeleteFileA("should_be_non_existing_deadbeef"); /* Just in case */
466
467 SetLastError(0xdeadbeef);
468 hOpenFile2 = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
469 error = GetLastError();
470 ok ( bRet == FALSE || broken(bRet == TRUE), "Expected FtpOpenFileA to fail\n");
471 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_SUCCESS),
472 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
473 InternetCloseHandle(hOpenFile2); /* Just in case */
474
475 /* Create a temporary local file */
476 SetLastError(0xdeadbeef);
477 hFile = CreateFileA("now_existing_local", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
478 ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
479 CloseHandle(hFile);
480 SetLastError(0xdeadbeef);
481 bRet = FtpPutFileA(hFtp, "now_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
482 error = GetLastError();
483 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
484 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
485 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
486 DeleteFileA("now_existing_local");
487
488 SetLastError(0xdeadbeef);
489 bRet = FtpRemoveDirectoryA(hFtp, "should_be_non_existing_deadbeef_dir");
490 error = GetLastError();
491 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
492 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
493 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
494
495 SetLastError(0xdeadbeef);
496 bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", "new");
497 error = GetLastError();
498 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
499 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
500 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error);
501 }
502
503 InternetCloseHandle(hOpenFile);
504
505 /* One small test to show that handle type is checked before parameters */
506 SetLastError(0xdeadbeef);
507 hOpenFile = FtpOpenFileA(hConnect, "welcome.msg", GENERIC_READ, 5, 0);
508 ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
509 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
510 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
511 InternetCloseHandle(hOpenFile); /* Just in case */
512
513 SetLastError(0xdeadbeef);
514 hOpenFile = FtpOpenFileA(hConnect, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
515 ok ( hOpenFile == NULL, "Expected FtpOpenFileA to fail\n");
516 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
517 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
518
519 InternetCloseHandle(hOpenFile); /* Just in case */
520 }
521
522 static void test_putfile(HINTERNET hFtp, HINTERNET hConnect)
523 {
524 BOOL bRet;
525 HANDLE hFile;
526
527 /* The order of checking is:
528 *
529 * All parameters except 'session handle' and 'condition flags'
530 * Session handle
531 * Session handle type
532 * Condition flags
533 */
534
535 /* Test to show the parameter checking order depends on the Windows version */
536 SetLastError(0xdeadbeef);
537 bRet = FtpPutFileA(NULL, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
538 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
539 ok ( GetLastError() == ERROR_INVALID_HANDLE ||
540 GetLastError() == ERROR_INVALID_PARAMETER,
541 "Expected ERROR_INVALID_HANDLE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
542
543 /* Test to show session handle is checked before 'condition flags' */
544 SetLastError(0xdeadbeef);
545 bRet = FtpPutFileA(NULL, "non_existing_local", "non_existing_remote", 5, 0);
546 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
547 ok ( GetLastError() == ERROR_INVALID_HANDLE,
548 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
549
550 /* Start clean */
551 DeleteFileA("non_existing_local");
552
553 /* No local file given */
554 SetLastError(0xdeadbeef);
555 bRet = FtpPutFileA(hFtp, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
556 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
557 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
558 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
559
560 /* No remote file given */
561 SetLastError(0xdeadbeef);
562 bRet = FtpPutFileA(hFtp, "non_existing_local", NULL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
563 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
564 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
565 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
566
567 /* Illegal condition flags */
568 SetLastError(0xdeadbeef);
569 bRet = FtpPutFileA(hFtp, "non_existing_local", "non_existing_remote", 5, 0);
570 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
571 ok ( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER,
572 "Expected ERROR_FILE_NOT_FOUND or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
573
574 /* Parameters are OK but local file doesn't exist */
575 SetLastError(0xdeadbeef);
576 bRet = FtpPutFileA(hFtp, "non_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
577 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
578 ok ( GetLastError() == ERROR_FILE_NOT_FOUND,
579 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
580
581 /* Create a temporary local file */
582 SetLastError(0xdeadbeef);
583 hFile = CreateFileA("now_existing_local", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
584 ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
585 CloseHandle(hFile);
586
587 /* Local file exists but we shouldn't be allowed to 'put' the file */
588 SetLastError(0xdeadbeef);
589 bRet = FtpPutFileA(hFtp, "now_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
590 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
591 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
592 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
593
594 DeleteFileA("now_existing_local");
595
596 /* Test to show the parameter checking order depends on the Windows version */
597 SetLastError(0xdeadbeef);
598 bRet = FtpPutFileA(hConnect, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
599 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
600 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE ||
601 GetLastError() == ERROR_INVALID_PARAMETER,
602 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
603
604 /* Test to show that 'session handle type' is checked before 'condition flags' */
605 SetLastError(0xdeadbeef);
606 bRet = FtpPutFileA(hConnect, "non_existing_local", "non_existing_remote", 5, 0);
607 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
608 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
609 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
610
611 SetLastError(0xdeadbeef);
612 bRet = FtpPutFileA(hConnect, "non_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
613 ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
614 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
615 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
616 }
617
618 static void test_removedir(HINTERNET hFtp, HINTERNET hConnect)
619 {
620 BOOL bRet;
621
622 /* Invalid internet handle, the other is a valid parameter */
623 SetLastError(0xdeadbeef);
624 bRet = FtpRemoveDirectoryA(NULL, "should_be_non_existing_deadbeef_dir");
625 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
626 ok ( GetLastError() == ERROR_INVALID_HANDLE,
627 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
628
629 /* No remote directory given */
630 SetLastError(0xdeadbeef);
631 bRet = FtpRemoveDirectoryA(hFtp, NULL);
632 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
633 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
634 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
635
636 /* Remote directory doesn't exist */
637 SetLastError(0xdeadbeef);
638 bRet = FtpRemoveDirectoryA(hFtp, "should_be_non_existing_deadbeef_dir");
639 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
640 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
641 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
642
643 /* We shouldn't be allowed to remove that directory */
644 SetLastError(0xdeadbeef);
645 bRet = FtpRemoveDirectoryA(hFtp, "pub");
646 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
647 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
648 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
649
650 /* One small test to show that handle type is checked before parameters */
651 SetLastError(0xdeadbeef);
652 bRet = FtpRemoveDirectoryA(hConnect, NULL);
653 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
654 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
655 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
656
657 SetLastError(0xdeadbeef);
658 bRet = FtpRemoveDirectoryA(hConnect, "should_be_non_existing_deadbeef_dir");
659 ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
660 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
661 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
662 }
663
664 static void test_renamefile(HINTERNET hFtp, HINTERNET hConnect)
665 {
666 BOOL bRet;
667
668 /* Invalid internet handle, the rest are valid parameters */
669 SetLastError(0xdeadbeef);
670 bRet = FtpRenameFileA(NULL , "should_be_non_existing_deadbeef", "new");
671 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
672 ok ( GetLastError() == ERROR_INVALID_HANDLE,
673 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
674
675 /* No 'existing' file */
676 SetLastError(0xdeadbeef);
677 bRet = FtpRenameFileA(hFtp , NULL, "new");
678 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
679 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
680 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
681
682 /* No new file */
683 SetLastError(0xdeadbeef);
684 bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", NULL);
685 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
686 ok ( GetLastError() == ERROR_INVALID_PARAMETER,
687 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
688
689 /* Existing file shouldn't be there */
690 SetLastError(0xdeadbeef);
691 bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", "new");
692 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
693 ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
694 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
695
696 /* One small test to show that handle type is checked before parameters */
697 SetLastError(0xdeadbeef);
698 bRet = FtpRenameFileA(hConnect , "should_be_non_existing_deadbeef", NULL);
699 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
700 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
701 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
702
703 SetLastError(0xdeadbeef);
704 bRet = FtpRenameFileA(hConnect , "should_be_non_existing_deadbeef", "new");
705 ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
706 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
707 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
708 }
709
710 static void test_command(HINTERNET hFtp)
711 {
712 BOOL ret;
713 DWORD error;
714 unsigned int i;
715 static const struct
716 {
717 BOOL ret;
718 DWORD error;
719 const char *cmd;
720 }
721 command_test[] =
722 {
723 { FALSE, ERROR_INVALID_PARAMETER, NULL },
724 { FALSE, ERROR_INVALID_PARAMETER, "" },
725 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "invalid" },
726 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size" },
727 { TRUE, ERROR_SUCCESS, "type i" },
728 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size " },
729 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, " size" },
730 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size " },
731 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size welcome.msg welcome.msg" },
732 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size welcome.msg" },
733 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "size welcome.msg " },
734 { TRUE, ERROR_SUCCESS, "size welcome.msg" },
735 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "pwd welcome.msg" },
736 { TRUE, ERROR_SUCCESS, "pwd" }
737 };
738
739 if (!pFtpCommandA)
740 {
741 win_skip("FtpCommandA() is not available. Skipping the Ftp command tests\n");
742 return;
743 }
744
745 for (i = 0; i < ARRAY_SIZE(command_test); i++)
746 {
747 SetLastError(0xdeadbeef);
748 ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
749 error = GetLastError();
750
751 ok(ret == command_test[i].ret, "%d: expected FtpCommandA to %s\n", i, command_test[i].ret ? "succeed" : "fail");
752 ok(error == command_test[i].error, "%d: expected error %u, got %u\n", i, command_test[i].error, error);
753 }
754 }
755
756 static void test_find_first_file(HINTERNET hFtp, HINTERNET hConnect)
757 {
758 WIN32_FIND_DATAA findData;
759 HINTERNET hSearch;
760 HINTERNET hSearch2;
761 HINTERNET hOpenFile;
762 DWORD error;
763 BOOL success;
764
765 /* NULL as the search file ought to return the first file in the directory */
766 SetLastError(0xdeadbeef);
767 hSearch = FtpFindFirstFileA(hFtp, NULL, &findData, 0, 0);
768 ok ( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
769
770 /* This should fail as the previous handle wasn't closed */
771 SetLastError(0xdeadbeef);
772 hSearch2 = FtpFindFirstFileA(hFtp, "welcome.msg", &findData, 0, 0);
773 todo_wine ok ( hSearch2 == NULL, "Expected FtpFindFirstFileA to fail\n" );
774 todo_wine ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
775 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError() );
776 InternetCloseHandle(hSearch2); /* Just in case */
777
778 InternetCloseHandle(hSearch);
779
780 /* Try a valid filename in a subdirectory search */
781 SetLastError(0xdeadbeef);
782 hSearch = FtpFindFirstFileA(hFtp, "pub/wine", &findData, 0, 0);
783 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
784 InternetCloseHandle(hSearch);
785
786 /* Try a valid filename in a subdirectory wildcard search */
787 SetLastError(0xdeadbeef);
788 hSearch = FtpFindFirstFileA(hFtp, "pub/w*", &findData, 0, 0);
789 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
790 InternetCloseHandle(hSearch);
791
792 /* Try an invalid wildcard search */
793 SetLastError(0xdeadbeef);
794 hSearch = FtpFindFirstFileA(hFtp, "*/w*", &findData, 0, 0);
795 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
796 InternetCloseHandle(hSearch); /* Just in case */
797
798 /* change current directory, and repeat those tests - this shows
799 * that the search string is interpreted as relative directory. */
800 success = FtpSetCurrentDirectoryA(hFtp, "pub");
801 ok( success, "Expected FtpSetCurrentDirectory to succeed\n" );
802
803 SetLastError(0xdeadbeef);
804 hSearch = FtpFindFirstFileA(hFtp, "wine", &findData, 0, 0);
805 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
806 InternetCloseHandle(hSearch);
807
808 SetLastError(0xdeadbeef);
809 hSearch = FtpFindFirstFileA(hFtp, "w*", &findData, 0, 0);
810 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
811 InternetCloseHandle(hSearch);
812
813 success = FtpSetCurrentDirectoryA(hFtp, "..");
814 ok( success, "Expected FtpSetCurrentDirectory to succeed\n" );
815
816 /* Try FindFirstFile between FtpOpenFile and InternetCloseHandle */
817 SetLastError(0xdeadbeef);
818 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
819 ok ( hOpenFile != NULL, "Expected FtpOpenFileA to succeed\n" );
820 ok ( GetLastError() == ERROR_SUCCESS ||
821 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
822 "Expected ERROR_SUCCESS, got %u\n", GetLastError() );
823
824 /* This should fail as the OpenFile handle wasn't closed */
825 SetLastError(0xdeadbeef);
826 hSearch = FtpFindFirstFileA(hFtp, "welcome.msg", &findData, 0, 0);
827 error = GetLastError();
828 ok ( hSearch == NULL || broken(hSearch != NULL), /* win2k */
829 "Expected FtpFindFirstFileA to fail\n" );
830 if (!hSearch)
831 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
832 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error );
833 else
834 {
835 ok( error == ERROR_SUCCESS, "wrong error %u on success\n", GetLastError() );
836 InternetCloseHandle(hSearch);
837 }
838
839 InternetCloseHandle(hOpenFile);
840
841 /* Test using a nonexistent filename */
842 SetLastError(0xdeadbeef);
843 hSearch = FtpFindFirstFileA(hFtp, "this_file_should_not_exist", &findData, 0, 0);
844 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
845 todo_wine ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
846 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError() );
847 InternetCloseHandle(hSearch); /* Just in case */
848
849 /* Test using a nonexistent filename and a wildcard */
850 SetLastError(0xdeadbeef);
851 hSearch = FtpFindFirstFileA(hFtp, "this_file_should_not_exist*", &findData, 0, 0);
852 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
853 todo_wine ok ( GetLastError() == ERROR_NO_MORE_FILES,
854 "Expected ERROR_NO_MORE_FILES, got %d\n", GetLastError() );
855 InternetCloseHandle(hSearch); /* Just in case */
856
857 /* Test using an invalid handle type */
858 SetLastError(0xdeadbeef);
859 hSearch = FtpFindFirstFileA(hConnect, "welcome.msg", &findData, 0, 0);
860 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
861 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
862 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError() );
863 InternetCloseHandle(hSearch); /* Just in case */
864 }
865
866 static void test_get_current_dir(HINTERNET hFtp, HINTERNET hConnect)
867 {
868 BOOL bRet;
869 DWORD dwCurrentDirectoryLen = MAX_PATH;
870 CHAR lpszCurrentDirectory[MAX_PATH];
871
872 if (!pFtpCommandA)
873 {
874 win_skip("FtpCommandA() is not available. Skipping the Ftp get_current_dir tests\n");
875 return;
876 }
877
878 /* change directories to get a more interesting pwd */
879 bRet = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, "CWD pub/", 0, NULL);
880 if(bRet == FALSE)
881 {
882 skip("Failed to change directories in test_get_current_dir(HINTERNET hFtp).\n");
883 return;
884 }
885
886 /* test with all NULL arguments */
887 SetLastError(0xdeadbeef);
888 bRet = FtpGetCurrentDirectoryA( NULL, NULL, 0 );
889 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
890 ok ( GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got: %d\n", GetLastError());
891
892 /* test with NULL parameters instead of expected LPSTR/LPDWORD */
893 SetLastError(0xdeadbeef);
894 bRet = FtpGetCurrentDirectoryA( hFtp, NULL, 0 );
895 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
896 ok ( GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got: %d\n", GetLastError());
897
898 /* test with no valid handle and valid parameters */
899 SetLastError(0xdeadbeef);
900 bRet = FtpGetCurrentDirectoryA( NULL, lpszCurrentDirectory, &dwCurrentDirectoryLen );
901 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
902 ok ( GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got: %d\n", GetLastError());
903
904 /* test with invalid dwCurrentDirectory and all other parameters correct */
905 SetLastError(0xdeadbeef);
906 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, 0 );
907 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
908 ok ( GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got: %d\n", GetLastError());
909
910 /* test with invalid lpszCurrentDirectory and all other parameters correct */
911 SetLastError(0xdeadbeef);
912 bRet = FtpGetCurrentDirectoryA( hFtp, NULL, &dwCurrentDirectoryLen );
913 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
914 ok ( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got: %d\n", GetLastError());
915
916 /* test to show it checks the handle type */
917 SetLastError(0xdeadbeef);
918 bRet = FtpGetCurrentDirectoryA( hConnect, lpszCurrentDirectory, &dwCurrentDirectoryLen );
919 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
920 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
921 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got: %d\n", GetLastError());
922
923 /* test for the current directory with legitimate values */
924 SetLastError(0xdeadbeef);
925 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
926 ok ( bRet == TRUE, "Expected FtpGetCurrentDirectoryA to pass\n" );
927 ok ( !strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to match \"/pub\"\n", lpszCurrentDirectory);
928 ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got: %d\n", GetLastError());
929
930 /* test for the current directory with a size only large enough to
931 * fit the string and not the null terminating character */
932 SetLastError(0xdeadbeef);
933 dwCurrentDirectoryLen = 4;
934 lpszCurrentDirectory[4] = 'a'; /* set position 4 of the array to something else to make sure a leftover \0 isn't fooling the test */
935 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
936 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n");
937 ok ( strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to not match \"/pub\"\n", lpszCurrentDirectory);
938 ok ( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got: %d\n", GetLastError());
939
940 /* test for the current directory with a size large enough to store
941 * the expected string as well as the null terminating character */
942 SetLastError(0xdeadbeef);
943 dwCurrentDirectoryLen = 5;
944 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
945 ok ( bRet == TRUE, "Expected FtpGetCurrentDirectoryA to pass\n");
946 ok ( !strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to match \"/pub\"\n", lpszCurrentDirectory);
947 ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got: %d\n", GetLastError());
948 }
949
950 static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
951 {
952 switch (status)
953 {
954 case INTERNET_STATUS_RESOLVING_NAME:
955 case INTERNET_STATUS_NAME_RESOLVED:
956 case INTERNET_STATUS_CONNECTING_TO_SERVER:
957 case INTERNET_STATUS_CONNECTED_TO_SERVER:
958 trace("%p %lx %u %s %u\n", handle, ctx, status, (char *)info, info_len);
959 break;
960 default:
961 break;
962 }
963 }
964
965 static void test_status_callbacks(HINTERNET hInternet)
966 {
967 INTERNET_STATUS_CALLBACK cb;
968 HINTERNET hFtp;
969 BOOL ret;
970
971 cb = pInternetSetStatusCallbackA(hInternet, status_callback);
972 ok(cb == NULL, "expected NULL got %p\n", cb);
973
974 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", "IEUser@",
975 INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 1);
976 if (!hFtp)
977 {
978 skip("No ftp connection could be made to ftp.winehq.org %u\n", GetLastError());
979 return;
980 }
981
982 ret = InternetCloseHandle(hFtp);
983 ok(ret, "InternetCloseHandle failed %u\n", GetLastError());
984
985 cb = pInternetSetStatusCallbackA(hInternet, NULL);
986 ok(cb == status_callback, "expected check_status got %p\n", cb);
987 }
988
989 START_TEST(ftp)
990 {
991 HMODULE hWininet;
992 HANDLE hInternet, hFtp, hHttp;
993
994 hWininet = GetModuleHandleA("wininet.dll");
995
996 if(!GetProcAddress(hWininet, "InternetGetCookieExW")) {
997 win_skip("Too old IE (older than 6.0)\n");
998 return;
999 }
1000
1001 pFtpCommandA = (void*)GetProcAddress(hWininet, "FtpCommandA");
1002 pInternetSetStatusCallbackA = (void*)GetProcAddress(hWininet, "InternetSetStatusCallbackA");
1003
1004 SetLastError(0xdeadbeef);
1005 hInternet = InternetOpenA("winetest", 0, NULL, NULL, 0);
1006 ok(hInternet != NULL, "InternetOpen failed: %u\n", GetLastError());
1007
1008 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
1009 if (!hFtp)
1010 {
1011 InternetCloseHandle(hInternet);
1012 skip("No ftp connection could be made to ftp.winehq.org\n");
1013 return;
1014 }
1015 hHttp = InternetConnectA(hInternet, "www.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
1016 if (!hHttp)
1017 {
1018 InternetCloseHandle(hFtp);
1019 InternetCloseHandle(hInternet);
1020 skip("No http connection could be made to www.winehq.org\n");
1021 return;
1022 }
1023
1024 /* The first call should always be a proper InternetOpen, if not
1025 * several calls will return ERROR_INTERNET_NOT_INITIALIZED when
1026 * all parameters are correct but no session handle is given. Whereas
1027 * the same call will return ERROR_INVALID_HANDLE if an InternetOpen
1028 * is done before.
1029 * The following test will show that behaviour, where the tests inside
1030 * the other sub-tests will show the other situation.
1031 */
1032 test_getfile_no_open();
1033 test_connect(hInternet);
1034 test_createdir(hFtp, hHttp);
1035 test_deletefile(hFtp, hHttp);
1036 test_getfile(hFtp, hHttp);
1037 test_openfile(hFtp, hHttp);
1038 test_putfile(hFtp, hHttp);
1039 test_removedir(hFtp, hHttp);
1040 test_renamefile(hFtp, hHttp);
1041 test_command(hFtp);
1042 test_find_first_file(hFtp, hHttp);
1043 test_get_current_dir(hFtp, hHttp);
1044 test_status_callbacks(hInternet);
1045
1046 InternetCloseHandle(hHttp);
1047 InternetCloseHandle(hFtp);
1048 InternetCloseHandle(hInternet);
1049 }