Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

602 lines
14 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
ftpcat.c
Abstract:
Windows Internet API FTP test program
Provides the same functionality as a cut-down version of the venerable
(console-mode) ftp program
Author:
Richard L Firth (rfirth) 05-Jun-1995
Environment:
Win32 user-mode console app
Revision History:
05-Jun-1995 rfirth
Created
--*/
#include "ftpcatp.h"
#undef tolower
//
// macros
//
#define IS_ARG(c) (((c) == '-') || ((c) == '/'))
//
// manifests
//
#define MAX_COMMAND_LENGTH 100
//
// external data
//
extern BOOL fQuit;
extern DWORD CacheFlags;
//
// data
//
DWORD Verbose = 0;
INTERNET_STATUS_CALLBACK PreviousCallback;
HINTERNET hCancel = NULL;
BOOL AsyncMode = FALSE;
BOOL fOffline = FALSE;
DWORD Context = 0;
DWORD AsyncResult = 0;
DWORD AsyncError = 0;
HANDLE AsyncEvent = NULL;
BOOL UseQueryData = FALSE;
#if DBG
BOOL CheckHandleLeak = FALSE;
#endif
//
// external functions
//
extern BOOL DispatchCommand(LPCTSTR, HANDLE);
//
// prototypes
//
void __cdecl main(int, char**);
void __cdecl control_c_handler(int);
void usage(void);
BOOL Prompt(LPCTSTR, LPTSTR*);
//
// functions
//
void __cdecl main(int argc, char** argv) {
LPTSTR ptszSite = NULL;
LPTSTR ptszUser = NULL;
LPTSTR ptszPass = NULL;
HINTERNET hInternet;
HINTERNET hFtpSession;
DWORD dwLocalAccessFlags;
LPTSTR lpszCmd;
DWORD lastError;
DWORD bufLen;
BOOL enableCallbacks = FALSE;
DWORD flags = 0;
DWORD accessMethod = INTERNET_OPEN_TYPE_PRECONFIG;
BOOL expectingProxy = FALSE;
LPSTR proxyServer = NULL;
for (--argc, ++argv; argc; --argc, ++argv) {
if (IS_ARG(**argv)) {
switch (*++*argv) {
case '?':
usage();
break;
case 'a':
++*argv;
if ((**argv == 'l') || (**argv == 'd')) {
accessMethod = INTERNET_OPEN_TYPE_DIRECT;
} else if (**argv == 'p') {
accessMethod = INTERNET_OPEN_TYPE_PROXY;
if (*++*argv) {
proxyServer = *argv;
} else {
expectingProxy = TRUE;
}
} else {
printf("error: unrecognised access type: '%c'\n", **argv);
usage();
}
break;
case 'c':
enableCallbacks = TRUE;
break;
#if DBG
case 'l':
CheckHandleLeak = TRUE;
break;
#endif
case 'n':
CacheFlags |= INTERNET_FLAG_DONT_CACHE;
break;
case 'p':
flags |= INTERNET_FLAG_PASSIVE;
break;
case 'q':
UseQueryData = TRUE;
break;
case 'v':
if (*++*argv == '\0') {
Verbose = 1;
} else {
Verbose = atoi(*argv);
}
break;
case 'x':
Context = (DWORD)atoi(++*argv);
break;
case 'y':
AsyncMode = TRUE;
break;
case 'o':
fOffline = TRUE;
break;
default:
printf("error: unrecognized command line flag: '%c'\n", **argv);
usage();
}
} else if (expectingProxy) {
proxyServer = *argv;
expectingProxy = FALSE;
} else if (ptszSite == NULL) {
ptszSite = *argv;
} else if (ptszUser == NULL) {
ptszUser = *argv;
} else if (ptszPass == NULL) {
ptszPass = *argv;
} else {
printf("error: unrecognized command line argument: \"%s\"\n", *argv);
usage();
}
}
if (ptszSite == NULL) {
printf("error: required server name argument missing\n");
exit(1);
}
if (AsyncMode) {
//
// create auto-reset, initially unsignalled event
//
AsyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (AsyncEvent == NULL) {
print_error("ftpcat", "CreateEvent()");
exit(1);
}
}
//
// add a control-c handler
//
signal(SIGINT, control_c_handler);
#if DBG
if (CheckHandleLeak) {
printf("initial handle count = %d\n", GetProcessHandleCount());
}
#endif
#if DBG
if (CheckHandleLeak && Verbose) {
printf("Initial handle count = %d\n", GetProcessHandleCount());
}
#endif
if (Verbose) {
printf("calling InternetOpen()...\n");
}
hInternet = InternetOpen("ftpcat",
accessMethod,
proxyServer,
NULL,
AsyncMode ? INTERNET_FLAG_ASYNC : 0
| (fOffline ? INTERNET_FLAG_OFFLINE : 0)
);
if (hInternet == NULL) {
print_error("ftpcat", "InternetOpen()");
exit(1);
} else if (Verbose) {
printf("Internet handle = %x\n", hInternet);
hCancel = hInternet;
}
#if DBG
if (CheckHandleLeak) {
printf("after InternetOpen(): handle count = %d\n", GetProcessHandleCount());
}
#endif
if (enableCallbacks) {
//
// let's have a status callback
//
// Note that callbacks can be set even before we have opened a handle
// to the internet/gateway
//
PreviousCallback = InternetSetStatusCallback(hInternet, my_callback);
if (PreviousCallback == INTERNET_INVALID_STATUS_CALLBACK) {
print_error("ftpcat", "InternetSetStatusCallback()");
} else if (Verbose) {
printf("previous Internet callback = %x\n", PreviousCallback);
}
}
if (Verbose) {
printf("calling InternetConnect()...\n");
}
hFtpSession = InternetConnect(hInternet,
ptszSite,
0,
ptszUser,
ptszPass,
INTERNET_SERVICE_FTP,
flags,
FTPCAT_CONNECT_CONTEXT
);
if ((hFtpSession == NULL) && AsyncMode) {
if (Verbose) {
printf("waiting for async InternetConnect()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
hFtpSession = (HINTERNET)AsyncResult;
SetLastError(AsyncError);
}
if (hFtpSession == NULL) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("ftpcat",
"%sInternetConnect()",
AsyncMode ? "async " : ""
);
get_response(hFtpSession);
close_handle(hInternet);
exit(1);
} else if (Verbose) {
printf("FTP session handle = %x\n", hFtpSession);
}
#if DBG
if (CheckHandleLeak) {
printf("after InternetConnect(): handle count = %d\n", GetProcessHandleCount());
}
#endif
printf("Connected to %s.\n", ptszSite);
get_response(hFtpSession);
#if DBG
if (CheckHandleLeak) {
printf("after InternetGetLastResponseInfo(): handle count = %d\n", GetProcessHandleCount());
}
#endif
//
// set the (top level) cancellable handle
//
hCancel = hFtpSession;
while (!fQuit) {
if (Prompt(TEXT("ftp> "), &lpszCmd)) {
DispatchCommand(lpszCmd, hFtpSession);
}
}
if (Verbose) {
printf("Closing %x\n", hFtpSession);
}
close_handle(hFtpSession);
#if DBG
if (CheckHandleLeak) {
printf("after InternetCloseHandle(): handle count = %d\n", GetProcessHandleCount());
}
#endif
get_response(hFtpSession);
#if DBG
if (CheckHandleLeak) {
printf("after InternetGetLastResponseInfo(): handle count = %d\n", GetProcessHandleCount());
}
#endif
close_handle(hInternet);
#if DBG
if (CheckHandleLeak) {
printf("after InternetCloseHandle(): handle count = %d\n", GetProcessHandleCount());
}
if (CheckHandleLeak && Verbose) {
printf("Final handle count = %d\n", GetProcessHandleCount());
}
#endif
exit(0);
}
void __cdecl control_c_handler(int sig) {
//
// disable signals
//
signal(SIGINT, SIG_IGN);
//
// cancel the current operation
//
if (Verbose) {
printf("control-c handler\n");
}
if (hCancel == NULL) {
if (Verbose) {
printf("control-c handler: no Internet operation in progress\n");
}
} else {
close_handle(hCancel);
}
//
// re-enable this signal handler
//
signal(SIGINT, control_c_handler);
}
void usage() {
printf("\n"
"usage: ftpcat [-a{g{[ ]server}|l|d|p}] [-c] [-d] [-n] [-p] [-v] [-x#] [-y]\n"
" {servername} [username] [password]\n"
"\n"
"where: -a = access type. Default is pre-configured:\n"
" g = gateway access via <gateway server>\n"
" l = local internet access\n"
" d = local internet access\n"
" p = CERN proxy access\n"
" -c = Enable callbacks\n"
" -n = Don't cache\n"
" -p = Use Passive transfer mode\n"
" -v = Verbose mode. Default is off\n"
" -x = Set context value\n"
" -y = Asynchronous APIs\n"
);
exit(1);
}
BOOL
Prompt(
IN LPCTSTR pszPrompt,
OUT LPTSTR* ppszCommand
)
{
static CHAR Command[MAX_COMMAND_LENGTH + sizeof(TEXT('\0'))];
#ifdef UNICODE
static WCHAR wchBuf[MAX_COMMAND_LENGTH + sizeof(L'\0')];
#endif
DWORD dwBytesRead;
PTCHAR pch;
lprintf(TEXT("%s"), pszPrompt);
if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE),
Command,
MAX_COMMAND_LENGTH * sizeof(CHAR),
&dwBytesRead,
NULL)) {
return FALSE;
}
Command[dwBytesRead] = '\0';
#ifdef UNICODE
wsprintf(wchBuf, L"%S", Command);
*ppszCommand = wchBuf;
#else
*ppszCommand = Command;
#endif
pch = lstrchr(*ppszCommand, TEXT('\r'));
if (pch) {
*pch = TEXT('\0');
}
return TRUE;
}
VOID
my_callback(
HINTERNET Handle,
DWORD Context,
DWORD Status,
LPVOID Info,
DWORD Length
)
{
char* type$;
switch (Status) {
case INTERNET_STATUS_RESOLVING_NAME:
type$ = "RESOLVING NAME";
break;
case INTERNET_STATUS_NAME_RESOLVED:
type$ = "NAME RESOLVED";
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
type$ = "CONNECTING TO SERVER";
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
type$ = "CONNECTED TO SERVER";
break;
case INTERNET_STATUS_SENDING_REQUEST:
type$ = "SENDING REQUEST";
break;
case INTERNET_STATUS_REQUEST_SENT:
type$ = "REQUEST SENT";
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
type$ = "RECEIVING RESPONSE";
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
type$ = "RESPONSE RECEIVED";
break;
case INTERNET_STATUS_CLOSING_CONNECTION:
type$ = "CLOSING CONNECTION";
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
type$ = "CONNECTION CLOSED";
break;
case INTERNET_STATUS_HANDLE_CREATED:
type$ = "HANDLE CREATED";
hCancel = *(LPHINTERNET)Info;
break;
case INTERNET_STATUS_HANDLE_CLOSING:
type$ = "HANDLE CLOSING";
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
type$ = "REQUEST COMPLETE";
AsyncResult = ((LPINTERNET_ASYNC_RESULT)Info)->dwResult;
AsyncError = ((LPINTERNET_ASYNC_RESULT)Info)->dwError;
break;
default:
type$ = "???";
break;
}
if (Verbose) {
printf("callback: handle %x [context %x [%s]] %s ",
Handle,
Context,
(Context == FTPCAT_CONNECT_CONTEXT) ? "Connect"
: (Context == FTPCAT_FIND_CONTEXT) ? "Find"
: (Context == FTPCAT_FILE_CONTEXT) ? "File"
: (Context == FTPCAT_GET_CONTEXT) ? "Get"
: (Context == FTPCAT_PUT_CONTEXT) ? "Put"
: (Context == FTPCAT_COMMAND_CONTEXT) ? "Command"
: (Context == FTPCAT_OPEN_CONTEXT) ? "Open"
: "???",
type$
);
if (Info) {
if ((Status == INTERNET_STATUS_HANDLE_CREATED)
|| (Status == INTERNET_STATUS_HANDLE_CLOSING)) {
printf("%x", *(LPHINTERNET)Info);
} else if (Length == sizeof(DWORD)) {
printf("%d", *(LPDWORD)Info);
} else {
printf(Info);
}
}
putchar('\n');
}
if (Status == INTERNET_STATUS_REQUEST_COMPLETE) {
get_response(Handle);
if (AsyncMode) {
SetEvent(AsyncEvent);
} else {
printf("error: INTERNET_STATUS_REQUEST_COMPLETE returned. Not async\n");
}
}
}
void close_handle(HINTERNET handle) {
if (Verbose) {
printf("closing handle %#x\n", handle);
}
if (!InternetCloseHandle(handle)) {
print_error("close_handle", "InternetCloseHandle(%x)", handle);
}
}
#if DBG
DWORD GetProcessHandleCount() {
DWORD error;
DWORD count;
DWORD countSize;
countSize = sizeof(count);
if (!InternetQueryOption(NULL,
INTERNET_OPTION_GET_HANDLE_COUNT,
&count,
&countSize
)) {
print_error("GetProcessHandleCount", "InternetQueryOption()");
return 0;
}
return count;
}
#endif