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