// PortScanner.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#pragma comment(lib,"Ws2_32.lib")

#include <winsock2.h>
#include <ws2tcpip.h>

HANDLE g_hEvent = NULL;
char* g_szIPAddress = NULL;
int g_iNumOfCurThread = 0;
DWORD ScanThread(PVOID lpParameter);

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hThread;
	int iStartPort = 0;
	int iEndPort = 0;
	int iNumOfThread = 0;
	WSADATA wsaData = {0};

	if (argc != 5) {
       wprintf(L"usage: %s <address> <StartPort> <EndPort> <NumberOfThread>\n", argv[0]);
       wprintf(L"%ws example usage\n", argv[0]);
       wprintf(L"   %ws 127.0.0.1 1 1024 10 \n", argv[0]);
       return 1;
   }

	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) 
	{
        wprintf(L"WSAStartup failed");
        return FALSE;
   }
	
	g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

   iStartPort = _wtoi(argv[2]);
	iEndPort = _wtoi(argv[3]);
	iNumOfThread = _wtoi(argv[4]);

	if (iNumOfThread < 1)
		iNumOfThread = 10;
	
	int iLength = lstrlenW(argv[1]);
	int nStrLen = WideCharToMultiByte(CP_ACP,0,argv[1], iLength, NULL, 0, NULL, NULL);
	g_szIPAddress = new char[nStrLen];
	nStrLen = WideCharToMultiByte(CP_ACP, 0, argv[1], iLength, g_szIPAddress, nStrLen, NULL, NULL);
	g_szIPAddress[nStrLen] = NULL;

	wprintf (_T("Start port scanning\n ..."));
	for (int i=iStartPort; i<iEndPort; i++)
	{
		if (g_iNumOfCurThread == iNumOfThread)
		{
			WaitForSingleObject(g_hEvent, INFINITE);
		}
		g_iNumOfCurThread++;
		hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ScanThread, (LPVOID)i, 0, NULL);
		Sleep(100);
		CloseHandle(hThread);
	}
	delete[] g_szIPAddress;
	wprintf (_T("Port scanning stopped\n\n"));
	return 0;
}

DWORD ScanThread(PVOID lpParameter)
{
	int iPort = (int)lpParameter;
	DWORD dwResult = 0;
	sockaddr_in clientService;
	clientService.sin_family = AF_INET;
	clientService.sin_addr.S_un.S_addr = inet_addr(g_szIPAddress);
	clientService.sin_port = htons(iPort);
	SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (clientSock == INVALID_SOCKET)
		return 1;

	dwResult = connect(clientSock, (SOCKADDR *)&clientService, sizeof(clientService));
		
	if (dwResult == 0)
	{
		wprintf(_T("\n\nPort %d is Open\n\n"), iPort);
	}
	else
	{
		wprintf(_T("."), iPort);
	}
	g_iNumOfCurThread--;
	SetEvent(g_hEvent);
	closesocket( clientSock );
	return (dwResult);
}


