baf20ffa118289346dab093463cf325bf902578e
[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", NULL, 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, HINTERNET hConnect)
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, "HELO" },
726 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE " },
727 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, " SIZE" },
728 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE " },
729 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg /welcome.msg" },
730 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg" },
731 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg " },
732 { TRUE, ERROR_SUCCESS, "SIZE\t/welcome.msg" },
733 { TRUE, ERROR_SUCCESS, "SIZE /welcome.msg" },
734 { FALSE, ERROR_INTERNET_EXTENDED_ERROR, "PWD /welcome.msg" },
735 { TRUE, ERROR_SUCCESS, "PWD" }
736 };
737
738 if (!pFtpCommandA)
739 {
740 win_skip("FtpCommandA() is not available. Skipping the Ftp command tests\n");
741 return;
742 }
743
744 for (i = 0; i < sizeof(command_test) / sizeof(command_test[0]); i++)
745 {
746 SetLastError(0xdeadbeef);
747 ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
748 error = GetLastError();
749
750 ok(ret == command_test[i].ret, "%d: expected FtpCommandA to %s\n", i, command_test[i].ret ? "succeed" : "fail");
751 ok(error == command_test[i].error, "%d: expected error %u, got %u\n", i, command_test[i].error, error);
752 }
753 }
754
755 static void test_find_first_file(HINTERNET hFtp, HINTERNET hConnect)
756 {
757 WIN32_FIND_DATAA findData;
758 HINTERNET hSearch;
759 HINTERNET hSearch2;
760 HINTERNET hOpenFile;
761 DWORD error;
762 BOOL success;
763
764 /* NULL as the search file ought to return the first file in the directory */
765 SetLastError(0xdeadbeef);
766 hSearch = FtpFindFirstFileA(hFtp, NULL, &findData, 0, 0);
767 ok ( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
768
769 /* This should fail as the previous handle wasn't closed */
770 SetLastError(0xdeadbeef);
771 hSearch2 = FtpFindFirstFileA(hFtp, "welcome.msg", &findData, 0, 0);
772 todo_wine ok ( hSearch2 == NULL, "Expected FtpFindFirstFileA to fail\n" );
773 todo_wine ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
774 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError() );
775 InternetCloseHandle(hSearch2); /* Just in case */
776
777 InternetCloseHandle(hSearch);
778
779 /* Try a valid filename in a subdirectory search */
780 SetLastError(0xdeadbeef);
781 hSearch = FtpFindFirstFileA(hFtp, "pub/wine", &findData, 0, 0);
782 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
783 InternetCloseHandle(hSearch);
784
785 /* Try a valid filename in a subdirectory wildcard search */
786 SetLastError(0xdeadbeef);
787 hSearch = FtpFindFirstFileA(hFtp, "pub/w*", &findData, 0, 0);
788 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
789 InternetCloseHandle(hSearch);
790
791 /* Try an invalid wildcard search */
792 SetLastError(0xdeadbeef);
793 hSearch = FtpFindFirstFileA(hFtp, "*/w*", &findData, 0, 0);
794 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
795 InternetCloseHandle(hSearch); /* Just in case */
796
797 /* change current directory, and repeat those tests - this shows
798 * that the search string is interpreted as relative directory. */
799 success = FtpSetCurrentDirectoryA(hFtp, "pub");
800 ok( success, "Expected FtpSetCurrentDirectory to succeed\n" );
801
802 SetLastError(0xdeadbeef);
803 hSearch = FtpFindFirstFileA(hFtp, "wine", &findData, 0, 0);
804 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
805 InternetCloseHandle(hSearch);
806
807 SetLastError(0xdeadbeef);
808 hSearch = FtpFindFirstFileA(hFtp, "w*", &findData, 0, 0);
809 ok( hSearch != NULL, "Expected FtpFindFirstFileA to pass\n" );
810 InternetCloseHandle(hSearch);
811
812 success = FtpSetCurrentDirectoryA(hFtp, "..");
813 ok( success, "Expected FtpSetCurrentDirectory to succeed\n" );
814
815 /* Try FindFirstFile between FtpOpenFile and InternetCloseHandle */
816 SetLastError(0xdeadbeef);
817 hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
818 ok ( hOpenFile != NULL, "Expected FtpOpenFileA to succeed\n" );
819 ok ( GetLastError() == ERROR_SUCCESS ||
820 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
821 "Expected ERROR_SUCCESS, got %u\n", GetLastError() );
822
823 /* This should fail as the OpenFile handle wasn't closed */
824 SetLastError(0xdeadbeef);
825 hSearch = FtpFindFirstFileA(hFtp, "welcome.msg", &findData, 0, 0);
826 error = GetLastError();
827 ok ( hSearch == NULL || broken(hSearch != NULL), /* win2k */
828 "Expected FtpFindFirstFileA to fail\n" );
829 if (!hSearch)
830 ok ( error == ERROR_FTP_TRANSFER_IN_PROGRESS || broken(error == ERROR_INTERNET_EXTENDED_ERROR),
831 "Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", error );
832 else
833 {
834 ok( error == ERROR_SUCCESS, "wrong error %u on success\n", GetLastError() );
835 InternetCloseHandle(hSearch);
836 }
837
838 InternetCloseHandle(hOpenFile);
839
840 /* Test using a nonexistent filename */
841 SetLastError(0xdeadbeef);
842 hSearch = FtpFindFirstFileA(hFtp, "this_file_should_not_exist", &findData, 0, 0);
843 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
844 todo_wine ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
845 "Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError() );
846 InternetCloseHandle(hSearch); /* Just in case */
847
848 /* Test using a nonexistent filename and a wildcard */
849 SetLastError(0xdeadbeef);
850 hSearch = FtpFindFirstFileA(hFtp, "this_file_should_not_exist*", &findData, 0, 0);
851 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
852 todo_wine ok ( GetLastError() == ERROR_NO_MORE_FILES,
853 "Expected ERROR_NO_MORE_FILES, got %d\n", GetLastError() );
854 InternetCloseHandle(hSearch); /* Just in case */
855
856 /* Test using an invalid handle type */
857 SetLastError(0xdeadbeef);
858 hSearch = FtpFindFirstFileA(hConnect, "welcome.msg", &findData, 0, 0);
859 ok ( hSearch == NULL, "Expected FtpFindFirstFileA to fail\n" );
860 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
861 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError() );
862 InternetCloseHandle(hSearch); /* Just in case */
863 }
864
865 static void test_get_current_dir(HINTERNET hFtp, HINTERNET hConnect)
866 {
867 BOOL bRet;
868 DWORD dwCurrentDirectoryLen = MAX_PATH;
869 CHAR lpszCurrentDirectory[MAX_PATH];
870
871 if (!pFtpCommandA)
872 {
873 win_skip("FtpCommandA() is not available. Skipping the Ftp get_current_dir tests\n");
874 return;
875 }
876
877 /* change directories to get a more interesting pwd */
878 bRet = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, "CWD pub/", 0, NULL);
879 if(bRet == FALSE)
880 {
881 skip("Failed to change directories in test_get_current_dir(HINTERNET hFtp).\n");
882 return;
883 }
884
885 /* test with all NULL arguments */
886 SetLastError(0xdeadbeef);
887 bRet = FtpGetCurrentDirectoryA( NULL, NULL, 0 );
888 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
889 ok ( GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got: %d\n", GetLastError());
890
891 /* test with NULL parameters instead of expected LPSTR/LPDWORD */
892 SetLastError(0xdeadbeef);
893 bRet = FtpGetCurrentDirectoryA( hFtp, NULL, 0 );
894 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
895 ok ( GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got: %d\n", GetLastError());
896
897 /* test with no valid handle and valid parameters */
898 SetLastError(0xdeadbeef);
899 bRet = FtpGetCurrentDirectoryA( NULL, lpszCurrentDirectory, &dwCurrentDirectoryLen );
900 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
901 ok ( GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got: %d\n", GetLastError());
902
903 /* test with invalid dwCurrentDirectory and all other parameters correct */
904 SetLastError(0xdeadbeef);
905 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, 0 );
906 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
907 ok ( GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got: %d\n", GetLastError());
908
909 /* test with invalid lpszCurrentDirectory and all other parameters correct */
910 SetLastError(0xdeadbeef);
911 bRet = FtpGetCurrentDirectoryA( hFtp, NULL, &dwCurrentDirectoryLen );
912 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
913 ok ( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got: %d\n", GetLastError());
914
915 /* test to show it checks the handle type */
916 SetLastError(0xdeadbeef);
917 bRet = FtpGetCurrentDirectoryA( hConnect, lpszCurrentDirectory, &dwCurrentDirectoryLen );
918 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n" );
919 ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
920 "Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got: %d\n", GetLastError());
921
922 /* test for the current directory with legitimate values */
923 SetLastError(0xdeadbeef);
924 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
925 ok ( bRet == TRUE, "Expected FtpGetCurrentDirectoryA to pass\n" );
926 ok ( !strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to match \"/pub\"\n", lpszCurrentDirectory);
927 ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got: %d\n", GetLastError());
928
929 /* test for the current directory with a size only large enough to
930 * fit the string and not the null terminating character */
931 SetLastError(0xdeadbeef);
932 dwCurrentDirectoryLen = 4;
933 lpszCurrentDirectory[4] = 'a'; /* set position 4 of the array to something else to make sure a leftover \0 isn't fooling the test */
934 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
935 ok ( bRet == FALSE, "Expected FtpGetCurrentDirectoryA to fail\n");
936 ok ( strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to not match \"/pub\"\n", lpszCurrentDirectory);
937 ok ( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got: %d\n", GetLastError());
938
939 /* test for the current directory with a size large enough to store
940 * the expected string as well as the null terminating character */
941 SetLastError(0xdeadbeef);
942 dwCurrentDirectoryLen = 5;
943 bRet = FtpGetCurrentDirectoryA( hFtp, lpszCurrentDirectory, &dwCurrentDirectoryLen );
944 ok ( bRet == TRUE, "Expected FtpGetCurrentDirectoryA to pass\n");
945 ok ( !strcmp(lpszCurrentDirectory, "/pub"), "Expected returned value \"%s\" to match \"/pub\"\n", lpszCurrentDirectory);
946 ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got: %d\n", GetLastError());
947 }
948
949 static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
950 {
951 switch (status)
952 {
953 case INTERNET_STATUS_RESOLVING_NAME:
954 case INTERNET_STATUS_NAME_RESOLVED:
955 case INTERNET_STATUS_CONNECTING_TO_SERVER:
956 case INTERNET_STATUS_CONNECTED_TO_SERVER:
957 trace("%p %lx %u %s %u\n", handle, ctx, status, (char *)info, info_len);
958 break;
959 default:
960 break;
961 }
962 }
963
964 static void test_status_callbacks(HINTERNET hInternet)
965 {
966 INTERNET_STATUS_CALLBACK cb;
967 HINTERNET hFtp;
968 BOOL ret;
969
970 cb = pInternetSetStatusCallbackA(hInternet, status_callback);
971 ok(cb == NULL, "expected NULL got %p\n", cb);
972
973 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", NULL,
974 INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 1);
975 if (!hFtp)
976 {
977 skip("No ftp connection could be made to ftp.winehq.org %u\n", GetLastError());
978 return;
979 }
980
981 ret = InternetCloseHandle(hFtp);
982 ok(ret, "InternetCloseHandle failed %u\n", GetLastError());
983
984 cb = pInternetSetStatusCallbackA(hInternet, NULL);
985 ok(cb == status_callback, "expected check_status got %p\n", cb);
986 }
987
988 START_TEST(ftp)
989 {
990 HMODULE hWininet;
991 HANDLE hInternet, hFtp, hHttp;
992
993 hWininet = GetModuleHandleA("wininet.dll");
994
995 if(!GetProcAddress(hWininet, "InternetGetCookieExW")) {
996 win_skip("Too old IE (older than 6.0)\n");
997 return;
998 }
999
1000 pFtpCommandA = (void*)GetProcAddress(hWininet, "FtpCommandA");
1001 pInternetSetStatusCallbackA = (void*)GetProcAddress(hWininet, "InternetSetStatusCallbackA");
1002
1003 SetLastError(0xdeadbeef);
1004 hInternet = InternetOpenA("winetest", 0, NULL, NULL, 0);
1005 ok(hInternet != NULL, "InternetOpen failed: %u\n", GetLastError());
1006
1007 hFtp = InternetConnectA(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", NULL, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
1008 if (!hFtp)
1009 {
1010 InternetCloseHandle(hInternet);
1011 skip("No ftp connection could be made to ftp.winehq.org\n");
1012 return;
1013 }
1014 hHttp = InternetConnectA(hInternet, "www.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
1015 if (!hHttp)
1016 {
1017 InternetCloseHandle(hFtp);
1018 InternetCloseHandle(hInternet);
1019 skip("No http connection could be made to www.winehq.org\n");
1020 return;
1021 }
1022
1023 /* The first call should always be a proper InternetOpen, if not
1024 * several calls will return ERROR_INTERNET_NOT_INITIALIZED when
1025 * all parameters are correct but no session handle is given. Whereas
1026 * the same call will return ERROR_INVALID_HANDLE if an InternetOpen
1027 * is done before.
1028 * The following test will show that behaviour, where the tests inside
1029 * the other sub-tests will show the other situation.
1030 */
1031 test_getfile_no_open();
1032 test_connect(hInternet);
1033 test_createdir(hFtp, hHttp);
1034 test_deletefile(hFtp, hHttp);
1035 test_getfile(hFtp, hHttp);
1036 test_openfile(hFtp, hHttp);
1037 test_putfile(hFtp, hHttp);
1038 test_removedir(hFtp, hHttp);
1039 test_renamefile(hFtp, hHttp);
1040 test_command(hFtp, hHttp);
1041 test_find_first_file(hFtp, hHttp);
1042 test_get_current_dir(hFtp, hHttp);
1043 test_status_callbacks(hInternet);
1044
1045 InternetCloseHandle(hHttp);
1046 InternetCloseHandle(hFtp);
1047 InternetCloseHandle(hInternet);
1048 }