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