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