// Net.cpp: implementation of the Net class.
//
//////////////////////////////////////////////////////////////////////
#include <Winsock2.h>
#include "Net.h"
#include <Lmapibuf.h>
#include <Lm.h>
#include <assert.h>
#include "Helpers.h"
#define OBJSTART(obj) if ( AutoStart && !cancelWork) obj->Start(AutoStart)
#ifdef UNICODE // '.' '..' <- bug if directory is '..dir'
#define IS_DOT_DIR(path) ((*(long*)path & 0xFFFFFFFF) == 0x0000002e || (*(long*)path & 0x0000FFFFFFFF)== 0x002e002e)
#else // '.' '..'
#define IS_DOT_DIR(path) ((*(short*)path & 0xFFFF) == 0x002e || (*(long*)path & 0xFFFFFF) == 0x002e2e)
#endif
#define MAX_LOGINNAME 20
#define MAX_LOGINPASS 10
typedef struct LOGININFO {
bool IsAdmin;
WCHAR UserName[MAX_LOGINNAME];
WCHAR Password[MAX_LOGINPASS];
} LOGININFO;
LOGININFO logins[2]= {
{true, L"Administrator", L""},
{false, L"Guest", L""}
};
DWORD LoginCount=sizeof(logins)/sizeof(LOGININFO);
HANDLE semScanLimit=NULL;
//////////////////////////////////////////////////////////////////////
// Enumerate Domain
//////////////////////////////////////////////////////////////////////
Domain::Domain(LPCTSTR domain , HWND control):
CWorker(control)
{
((NetResType)type) = NRT_DOMAIN;
m_Name = StrDup(domain);
err.SetIdentifier(m_Name);
//DebugWrite(TEXT("EnumDomain created"));
}
Domain::Domain(HANDLE file, CWorker* parentnode, HWND control):
CWorker(file, parentnode, control)
{
if (type != NRT_DOMAIN) {
DebugWrite(TEXT("ObjectType mismatch"));
DebugBreak();
return;
}
DWORD i = children_to_load;
while(i--) {
Computer *comp = new Computer(file, this, control);
}
}
Domain::~Domain()
{
//DebugWrite(TEXT("EnumDomain destroyed"));
//delete m_Domain;
}
void Domain::Work()
{
if (hEnum != NULL) return;
// Enumerate servers/containers in domain
NETRESOURCE resource = { 0 };
Computer *comp;
resource.dwScope = RESOURCE_GLOBALNET;
resource.dwType = RESOURCETYPE_ANY;
resource.dwDisplayType = RESOURCEDISPLAYTYPE_DOMAIN;
resource.dwUsage = RESOURCEUSAGE_CONTAINER;
resource.lpLocalName = NULL;
resource.lpRemoteName = m_Name;
// resolve IP of all existing machines
for (unsigned i=0; (comp =(Computer*) (*this)[i])!=NULL;i++)
comp->ResolveIP(true, true);
if (NO_ERROR != WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_CONTAINER, &resource, &hEnum )) {
SetState(FAIL_RUN);
return;
}
// Iterate, reading blocks of resources
while ( !cancelWork ) {
NETRESOURCE NetResourceList[ 512 ];
DWORD NetResourceMax = -1;
DWORD nb = sizeof(NetResourceList);
DWORD dwResult = WNetEnumResource( hEnum, &NetResourceMax, NetResourceList, &nb );
if ( dwResult == ERROR_NO_MORE_ITEMS ) break; // Done!
if ( dwResult != NO_ERROR ) {// Error!
SetState(FAIL_RUN);
break;
}
// Read items
for ( DWORD i = 0; !cancelWork && i < NetResourceMax; i++ ) {
NETRESOURCE * rp = NetResourceList + i;
if ( rp->dwDisplayType == RESOURCEDISPLAYTYPE_SERVER ) {
// Found a computer, so enumerate its shares
CWorker *ret;
comp = new Computer( rp->lpRemoteName, hwndNotify );
if ((ret = AddItem(comp))==comp) { // In case of success original pointer is returned
//if ( !cancelWork ) comp->Start(AutoStart);
comp->ResolveIP(true, true);
OBJSTART(comp);//if ( !cancelWork ) shares->Start();
} else { // otherwise returns NULL or found item
delete comp;
//OBJSTART(ret);//if (ret) ret->Start();
}
}
}
}
}
//////////////////////////////////////////////////////////////////////
// Enumerate Computer
//////////////////////////////////////////////////////////////////////
Computer::Computer(LPCTSTR ComputerName, HWND control ):
CWorker(control), HasLoginAdmin(false), icmp(NULL)
{
(NetResType)type = NRT_COMPUTER;
m_Name = StrDup(ComputerName);
IP_inet.S_un.S_addr=0;
*IP_str = 0;
err.SetIdentifier(m_Name);
}
Computer::Computer(IN_ADDR ComputerIP, HWND control ):
CWorker(control), HasLoginAdmin(false), icmp(NULL)
{
(NetResType)type = NRT_COMPUTER;
//m_Name = StrDup(ComputerIP);
IP_inet.S_un.S_addr = ComputerIP.S_un.S_addr;
//*IP_str = 0;
LPSTR szhost = inet_ntoa(IP_inet);
if (szhost) {//CharToUnicode(IP_str, szhost, StrLen(szhost));
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szhost, -1, IP_str , IP_STR_LEN);
#else
StrNCopy(IP_str, szhost, IP_STR_LEN);
#endif
}
m_Name = new TCHAR[IP_STR_LEN+2];
m_Name[0] = '\\';
m_Name[1] = '\\';
StrNCopy(m_Name+2, IP_str, IP_STR_LEN);
err.SetIdentifier(m_Name);
}
Computer::Computer(HANDLE file, CWorker* parentnode, HWND control):
CWorker(file, parentnode, control), HasLoginAdmin(false), icmp(NULL)
{
DWORD i = children_to_load;
while(i--)
Share *share = new Share(file, this, control);
IP_inet.S_un.S_addr = 0;
*IP_str = 0;
ReadFile(file, &IP_inet, sizeof(IP_inet),&i, NULL);
if (IP_inet.S_un.S_addr) {
LPSTR szhost = inet_ntoa(IP_inet);
if (szhost) {
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szhost, -1, IP_str , IP_STR_LEN);
#else
StrNCopy(IP_str, szhost, IP_STR_LEN);
#endif
}
}
}
Computer::~Computer()
{
//if (icmp) IcmpCloseHandle(icmp);
/*
if (WaitForSingleObject(hThreadResolve, INFINITE)==WAIT_OBJECT_0) {
CloseHandle(hThreadResolve);
hThreadResolve = NULL;
}
*/
//DebugWrite(TEXT("EnumComputer destroyed"));
}
bool Computer::Save(HANDLE file)
{
DWORD written;
if (CWorker::Save(file)) {
return (TRUE==WriteFile(file, &IP_inet, sizeof(IP_inet),&written, NULL));
}
return false;
}
void Computer::Draw(LPNMTVCUSTOMDRAW tv, PCOLUMNS cols)
{
RECT rc = tv->nmcd.rc;
if (HasLoginAdmin) tv->clrText = 0xFF;
CWorker::Draw(tv, cols);
rc.left = cols->item[3].left;
rc.right = rc.left + cols->item[3].width;
DrawText(tv->nmcd.hdc, IP_str , StrLen(IP_str), &rc, DT_SINGLELINE | DT_VCENTER);
/*
LPSTR host;
if (host = inet_ntoa(comp_ip)) {
rc.left = cols->item[3].left;
rc.right = rc.left + cols->item[3].width;
DrawTextA(tv->nmcd.hdc, host , StrLen(host), &rc, DT_SINGLELINE | DT_VCENTER);
}
*/
}
bool Computer::TryLogin(LPCTSTR host)
{
#ifdef UNICODE
WCHAR shareName[MAX_PATH],
username[MAX_LOGINNAME],
pass[MAX_LOGINPASS];
USE_INFO_2 ui={NULL};
DWORD i, dwErr=0;
NET_API_STATUS nas = ERROR_ACCESS_DENIED;
bool HasLoggedIn = false;
EnterCriticalSection(&secLogin);
if (host==NULL) host = m_Name;
wsprintfW(shareName,L"%s\\%s", host, L"IPC$");
ui.ui2_remote = shareName;
ui.ui2_username = username;
ui.ui2_password = pass;
ui.ui2_domainname = NULL;
ui.ui2_asg_type = USE_IPC;
HasLoginAdmin = false;
for (i=0; i< LoginCount && nas!=NERR_Success; i++) {
nas = NetUseDel(NULL, shareName, USE_FORCE);
StrNCopy(username, logins[i].UserName, MAX_LOGINNAME);
StrNCopy(pass, logins[i].Password, MAX_LOGINPASS);
nas = NetUseAdd(NULL,2, (LPBYTE) &ui, &dwErr);
if (nas==NERR_Success) {
HasLoggedIn = true;
if (HasLoginAdmin = logins[i].IsAdmin) {
TreeView_EnsureVisible(hwndNotify, tvItem);
wsprintf(shareName,L"Logged in: %s:%s", username, pass);
err.DebugWriteString(shareName,false);
}
break;
} else {
err.Refresh(nas);
}
}
if (!HasLoggedIn) {
nas = NetUseDel(NULL, shareName, USE_FORCE);
RevertToSelf();
}
LeaveCriticalSection(&secLogin);
return nas==NERR_Success;
#else // different logins are not supported by Win95/98/Me
return true;
#endif
}
#ifndef UNICODE
void Computer::Work()
{
NETRESOURCE resource = { 0 };
DWORD netcode;
bool TryIP = true;
resource.dwScope = RESOURCE_GLOBALNET;
resource.dwType = RESOURCETYPE_DISK;
resource.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
resource.dwUsage = RESOURCEUSAGE_CONNECTABLE;
resource.lpLocalName = NULL;
resource.lpRemoteName = m_Name;
if (hEnum != NULL) return;
BeginEnum:
//RevertToSelf();
//ResolveIP(); // Retrieve IP
netcode = WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_CONNECTABLE, &resource, &hEnum );
if (NO_ERROR != netcode) {
SetState(FAIL_RUN);
if (cancelWork) return;
if (netcode==ERROR_ACCESS_DENIED && TryLogin(resource.lpRemoteName)) {
netcode = WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_CONNECTABLE, &resource, &hEnum );
} else {
if (TryIP && IP_str && ERROR_BAD_NETPATH == netcode) {// try by IP
TCHAR host[IP_STR_LEN+2]={'\\','\\'};
StrNCopy(host+2,IP_str, IP_STR_LEN);
resource.lpRemoteName = IP_str;
TryIP = false;
goto BeginEnum;
}
}
if (NO_ERROR != netcode) return;
}
SetState(RUNNING);
// Iterate, reading blocks of resources
while ( !cancelWork ) {
NETRESOURCE NetResourceList[ 512 ];
DWORD NetResourceMax = -1;
DWORD nb = sizeof(NetResourceList);
DWORD dwResult = WNetEnumResource( hEnum, &NetResourceMax, NetResourceList, &nb );
if ( dwResult == ERROR_NO_MORE_ITEMS ) break; // Done!
if ( dwResult != NO_ERROR ) {// Error!
SetState(FAIL_RUN);
break;
}
// Read items
for ( DWORD i = 0; !cancelWork && i < NetResourceMax; i++ ) {
NETRESOURCE * rp = NetResourceList + i;
if ( rp->dwDisplayType == RESOURCEDISPLAYTYPE_SHARE ) {
CWorker *ret;
Share *share = new Share(rp->lpRemoteName, hwndNotify);
if ((ret = AddItem(share))==share) { // In case of success returned original pointer
//share->Find(TEXT("*.avi"));
} else {
delete share;
//if (ret) ret->Start();
}
}
}
}
}
#else // This is UNICODE version
void Computer::Work()
{
SHARE_INFO_1 *si = NULL;// ={{NULL, STYPE_DISKTREE | STYPE_SPECIAL, NULL};
NET_API_STATUS netcode;
DWORD read=0, total=0, resume=0;
bool TryIP = true, CheckLogin = true, Finished=false;
LPTSTR remote = m_Name;
TCHAR host[IP_STR_LEN+2]={'\\','\\'};
//HasLoginAdmin = true;
while(!cancelWork && !Finished) {
Finished = true;
//TryLogin(remote);
if (cancelWork) break;
netcode = NetShareEnum(remote, 1, (LPBYTE*) &si, MAX_PREFERRED_LENGTH, &read, &total, &resume);
if (NERR_Success == netcode) {
SetState(RUNNING);
for ( DWORD i = 0; !cancelWork && i < read; i++ ) {
//if (si[i].shi1_type == STYPE_DISKTREE || (HasLoginAdmin && si[i].shi1_type == (STYPE_SPECIAL | STYPE_DISKTREE))) {
if (si[i].shi1_type == STYPE_DISKTREE || si[i].shi1_type == (STYPE_SPECIAL | STYPE_DISKTREE)) {
CWorker *ret;
Share *share = new Share(si[i].shi1_netname, hwndNotify);
if ((ret = AddItem(share))==share) { // In case of success returned original pointer
//share->Find(TEXT("*.avi"));
} else { // either returned NULL or pointer to existing member
delete share;
//if (ret) ret->Start();
}
}
}
} else {
SetLastError(netcode);
SetState(FAIL_RUN);
switch(netcode) {
case ERROR_BAD_NETPATH:
case ERROR_NETNAME_DELETED:
case ERROR_BAD_NET_NAME:
if (TryIP && IP_inet.S_un.S_addr) {
TryIP = false;
Finished = false;
StrNCopy(host+2,IP_str, IP_STR_LEN);
remote = host;
}
break;
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_PASSWORD:
case ERROR_LOGON_FAILURE:
if (CheckLogin && TryLogin(remote)) {
CheckLogin = false;
Finished = false;
}
}
}
if (si) NetApiBufferFree(si);
si = NULL;
}
}
#endif
// Work
DWORD WINAPI Computer::ResolveIP_Thread(Computer* This)
{
try{
if (This->ResolveIP(false, true)==0) {
This->UpdateStatus();
}
}
catch(...){
return -1;
}
return 0;
}
int Computer::ResolveIP(bool async, bool refresh)
{
LPHOSTENT lph;
int ret = -1; // Address already resolved, locking failed or Unicode conversion failed
if (IP_inet.S_un.S_addr == 0 || refresh) {
if (!ExclusiveLock()) return -1;
if (async) {
HANDLE tmp = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ResolveIP_Thread, this, 0, NULL);
if (tmp && tmp!=INVALID_HANDLE_VALUE) {
CloseHandle(tmp);
ExclusiveRelease();
return 0;
}
// otherwise Async failed -> perform sync
}
#ifdef UNICODE
char hostname[255];
if (UnicodeToChar(hostname, m_Name+2, StrLen(m_Name+2))) { // conversion successful
if (lph = gethostbyname(hostname)) {// resolve host IP
memmove(&IP_inet, lph->h_addr_list[0], sizeof(IP_inet));
ret = 0;
// create string IP
} else {
ret = WSAGetLastError();
err.Refresh(ret);
SetState(FAIL_FINISHED);
}
LPSTR szhost = inet_ntoa(IP_inet);
if (szhost) //CharToUnicode(IP_str, szhost, StrLen(szhost));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szhost, -1, IP_str , IP_STR_LEN);
}
#else
if (lph = gethostbyname(m_Name+2)) {// resolve host IP
memmove(&IP_inet, lph->h_addr_list[0], sizeof(IP_inet));
ret = 0;
LPSTR szhost = inet_ntoa(IP_inet);
if (szhost) StrCopy(IP_str, szhost);
} else {
ret = WSAGetLastError();
err.Refresh(ret);
}
LPSTR szhost = inet_ntoa(IP_inet);
if (szhost) StrNCopy(IP_str , szhost, IP_STR_LEN);
#endif
ExclusiveRelease();
}
return ret;
}
//////////////////////////////////////////////////////////////////////
// Enumerate Network
//////////////////////////////////////////////////////////////////////
Network::Network(HWND control):
CWorker(control)
{
Init();
}
bool Network::LoadAsync(LPTSTR file)
{
if (hThread) return false;
if (file) filename = StrDup(file);
else filename = NULL;
hThread = CreateRunningThread(LoadThread, this, &idThread);
return hThread != NULL;
}
DWORD Network::LoadThread(Network *This)
{
This->Load(This->filename);
DeletePtr(This->filename);
CloseHandle(This->hThread);
This->hThread = NULL;
//if (This->GetCount()) TreeView_Expand(This->hwndNotify, This->tvItem, TVE_EXPAND);
return 0;
}
bool Network::Load(LPCTSTR file)
{
NETPROPBAG npb;
DWORD ln = 0;
TCHAR internal_file[MAX_PATH];
bool ret = false;
if (file==NULL) {
file = internal_file;
ln= GetModuleFileName(NULL, internal_file, MAX_PATH);
if (ln==0) return false;
LPTSTR tmp = StrRChar(file, '.');
if (tmp==NULL) return false;
StrNCopy(tmp+1, TEXT("net"), 3);
}
HANDLE hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile ==INVALID_HANDLE_VALUE) return false;
if (ReadFile(hFile, &npb, sizeof(npb), &ln, NULL) && sizeof(npb)==ln) {
if (npb.children>0) SetState(COMPLETED);
SetFilePointer(hFile, (npb.NameLen+1)* sizeof(TCHAR), NULL, FILE_CURRENT);
while(npb.children--) {
Domain *domain = new Domain(hFile, this, hwndNotify);
UpdateStatus();
}
ret = true;
}
CloseHandle(hFile);
return ret;
}
bool Network::Save(LPCTSTR file)
{
TCHAR internal_file[MAX_PATH];
bool ret = false;
if (this) {
if (file==NULL) {
file = internal_file;
DWORD ln= GetModuleFileName(NULL, internal_file, MAX_PATH);
if (ln>0) {
LPTSTR tmp = StrRChar(file, '.');
if (tmp) {
StrNCopy(tmp+1,TEXT("net"), 3);
} else {
return false;
}
} else {
return false;
}
}
HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
ret =CWorker::Save(hFile);
CloseHandle(hFile);
}
}
return ret;
}
void Network::Init()
{
(NetResType)type = NRT_NETWORK;
m_Name = TEXT("Microsoft Network");
err.SetIdentifier(m_Name);
TVINSERTSTRUCT ins;
ins.hParent = NULL;
ins.hInsertAfter = TVI_ROOT;
ins.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
ins.item.cChildren = I_CHILDRENCALLBACK;
ins.item.pszText = m_Name;//LPSTR_TEXTCALLBACK;
ins.item.state = TVIS_EXPANDED;
ins.item.iImage = type;
ins.item.iSelectedImage = type;
ins.item.lParam = (LPARAM) this;
tvItem = TreeView_InsertItem(hwndNotify, &ins);
}
Network::~Network()
{
//DebugWrite(TEXT("EnumNetwork destroyed"));
m_Name = NULL;
}
void Network::Work()
{
if (hEnum == NULL) {
//DebugWrite(TEXT("Beging Domain enumeration"));
hEnum = INVALID_HANDLE_VALUE;
if (!EnumRecurse(NULL)) SetState(FAIL_RUN);
hEnum = NULL;
//DebugWrite(TEXT("Domain enumeration completed"));
}
}
bool Network::EnumRecurse(NETRESOURCE * resource )
{
// Enumerate servers/containers in container
//if (hEnum != NULL) return false;
HANDLE hEnumLoc;
if (NO_ERROR != WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_CONTAINER, resource, &hEnumLoc )) return false;
bool ret = true;
// Iterate, reading blocks of resources
while(!cancelWork) {
NETRESOURCE NetResourceList[ 100 ];
DWORD NetResourceMax = -1;
DWORD nb = sizeof(NetResourceList);
DWORD dwResult = WNetEnumResource( hEnumLoc, &NetResourceMax, NetResourceList, &nb );
// end-of-list reached or error occured -> exit
if ( (dwResult == ERROR_NO_MORE_ITEMS) || (dwResult != NO_ERROR) ) break;
// Read items
for ( DWORD i = 0; !cancelWork && i < NetResourceMax; i++ ) {
NETRESOURCE * rp = NetResourceList + i;
if ( rp->dwDisplayType == RESOURCEDISPLAYTYPE_DOMAIN ) {
// add to list
//if (StrCmp(rp->lpRemoteName, TEXT("ZOOPARK"))==0) {
CWorker *ret;
Domain *comps = new Domain(rp->lpRemoteName, hwndNotify);
if ((ret = AddItem(comps))==comps) {
OBJSTART(comps);//if ( !cancelWork ) comps->Start();
} else {
delete comps;
//OBJSTART(ret);//if (ret) ret->Start();
}
//}
} else if ( (rp->dwUsage & RESOURCEUSAGE_CONTAINER) == RESOURCEUSAGE_CONTAINER ) {
// Recurse
if (!EnumRecurse( rp )) ret = false;
}
}
}
WNetCloseEnum(hEnumLoc);
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// DirectScan class
//
/////////////////////////////////////////////////////////////////////////////////////////
DirectScan::DirectScan(HWND ctl): CWorker(ctl)
{
Init();
}
DirectScan::~DirectScan()
{
m_Name = NULL;
}
void DirectScan::Init()
{
(NetResType)type = NRT_NETWORK;
m_Name = TEXT("Direct IP Scan");
err.SetIdentifier(m_Name);
TVINSERTSTRUCT ins;
ins.hParent = NULL;
ins.hInsertAfter = TVI_ROOT;
ins.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
ins.item.cChildren = I_CHILDRENCALLBACK;
ins.item.pszText = m_Name;//LPSTR_TEXTCALLBACK;
ins.item.state = TVIS_EXPANDED;
ins.item.iImage = type;
ins.item.iSelectedImage = type;
ins.item.lParam = (LPARAM) this;
tvItem = TreeView_InsertItem(hwndNotify, &ins);
IP_cur.S_un.S_addr = IP_from.S_un.S_addr = IP_to.S_un.S_addr = 0;
}
void DirectScan::SetScanRange(IN_ADDR from_IP, IN_ADDR to_IP)
{
IP_from = from_IP;
IP_to = to_IP;
}
// checks specified host if there are NETBIOS-SSN ports open. Necessary but not enough condition for MS Network
DWORD DirectScan::CheckIP(CHECK_IP_STRUCT * cip)
{
bool ret = false;
if (!cip->This->cancelWork) {
InterlockedIncrement( &ActiveThreads );
cip->This->PostNotify(NNM_THREADCNTCHANGED, MAKELPARAM(ActiveThreads,ThreadCount));
SOCKET sckt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
LONG cntSem = 0;
if (sckt != INVALID_SOCKET) {
SOCKADDR_IN addr = {AF_INET};// addr.sin_family = AF_INET;
addr.sin_addr.S_un = cip->IP.S_un;
addr.sin_port = htons(139); // netbios-ssn
if (connect(sckt, (struct sockaddr*) &addr, sizeof(addr)) != SOCKET_ERROR) {
shutdown(sckt, SD_SEND | SD_RECEIVE);
ret = true;
cip->This->DebugWrite(TEXT("netbios-ssn detected"));
CWorker *comp = new Computer( cip->IP, cip->This->hwndNotify );
if (cip->This->AddItem(comp) == comp) { // In case of success original pointer is returned
//if ( !cancelWork ) comp->Start(AutoStart);
//comp->ResolveIP(true, true);
//OBJSTART(comp);//if ( !cancelWork ) shares->Start();
cip->This->UpdateStatus();
comp->Start(true);
} else { // otherwise returns NULL or found item
delete comp;
//OBJSTART(ret);//if (ret) ret->Start();
}
}
closesocket(sckt);
}
InterlockedDecrement( &ActiveThreads );
if (ReleaseSemaphore(semThreadLimit, 1, &cntSem)==0) {
//CloseHandle(semScanLimit);
//semScanLimit = NULL;
}
}
InterlockedDecrement( &ThreadCount );
cip->This->PostNotify(NNM_THREADCNTCHANGED, MAKELPARAM(ActiveThreads,ThreadCount));
if (ThreadCount==0) cip->This->PostNotify(NNM_ENUMFINISHED, 0);
delete cip;
return ret;
}
void DirectScan::Work()
{
//IN_ADDR IP_cur;
u_short b1,b2,b3,b4; //= IP_cur.S_un.S_un_b.s_b4;
ReleaseSemaphore(semThreadLimit, 1, NULL);
for (b1 = IP_from.S_un.S_un_b.s_b1; !cancelWork && b1 <= IP_to.S_un.S_un_b.s_b1; b1++) {
for (b2 = IP_from.S_un.S_un_b.s_b2; !cancelWork && b2 <= IP_to.S_un.S_un_b.s_b2; b2++) {
for (b3 = IP_from.S_un.S_un_b.s_b3; !cancelWork && b3 <= IP_to.S_un.S_un_b.s_b3; b3++) {
for (b4 = IP_from.S_un.S_un_b.s_b4; !cancelWork && b4 <= IP_to.S_un.S_un_b.s_b4; b4++) {
//IP_cur.S_un.S_addr = (b4<<24 | b3<<16 |b2<<8 | b1);
if (WaitForSingleObject(semThreadLimit, INFINITE)==WAIT_OBJECT_0) {
DWORD threadID;
CHECK_IP_STRUCT *pcip = new CHECK_IP_STRUCT;
if (pcip) {
IP_cur.S_un.S_addr = MAKEIPADDRESS(b4,b3, b2, b1);
pcip->IP = IP_cur;
pcip->This = this;
HANDLE thread = CreateSuspendedThread(CheckIP, pcip , &threadID);
if (thread) {
//
InterlockedIncrement( &ThreadCount );
PostNotify(NNM_THREADCNTCHANGED, MAKELPARAM(ActiveThreads,ThreadCount));
SetThreadPriority(thread, THREAD_PRIORITY_IDLE);
ResumeThread(thread);
//
CloseHandle(thread);
UpdateStatus();
} else {
delete pcip;
}
}
} else {
cancelWork = true;
}
//
}
}
}
}
}
void DirectScan::Draw(LPNMTVCUSTOMDRAW tv, PCOLUMNS cols)
{
RECT rc = tv->nmcd.rc;
//if (HasLoginAdmin) tv->clrText = 0xFF;
CWorker::Draw(tv, cols);
rc.left = cols->item[3].left;
rc.right = rc.left + cols->item[3].width;
//DrawText(tv->nmcd.hdc, IP_str , StrLen(IP_str), &rc, DT_SINGLELINE | DT_VCENTER);
LPSTR host;
if (host = inet_ntoa(IP_cur)) {
rc.left = cols->item[3].left;
rc.right = rc.left + cols->item[3].width;
DrawTextA(tv->nmcd.hdc, host , StrLen(host), &rc, DT_SINGLELINE | DT_VCENTER);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// SHARE look up
//
/////////////////////////////////////////////////////////////////////////////////////////
Share::Share(LPCTSTR share, HWND control):
CWorker(control), search(NULL) ,
found(NULL),found_count(0), found_alloc(0), current(NULL)
{
(NetResType)type = NRT_SHARE;
//fullname = StrDup(share);
m_Name = StrDup(share);
if (m_Name) err.SetIdentifier(m_Name);
/*
m_Name = StrChar(share+2, '\\');
if (m_Name) {
m_Name++;
m_Name = StrDup(m_Name);
if (m_Name) err.SetIdentifier(m_Name);
}
*/
expanded = true;
}
Share::Share(HANDLE file, CWorker* parentnode, HWND control):
CWorker(file, parentnode, control), search(NULL) ,
found(NULL),found_count(0), found_alloc(0), current(NULL)
{
if (type != NRT_SHARE) {
DebugWrite(TEXT("ObjectType mismatch"));
DebugBreak();
}
expanded = true;
}
Share::~Share()
{
//if (m_Mask) delete m_Mask;
ClearStrings();
if (search) delete search;
//m_Name = NULL;
//if (fullname) delete (LPTSTR)fullname;
}
// true - found mask; false - haven't found
bool Share::Search(LPCTSTR mask, DWORD minSizeMB, DWORD maxSizeMB)
{
//if (m_Mask) delete m_Mask;
//m_Mask = StrDup(mask);
if (search) {
if (hThread) return false;
DeletePtr(search);
};
cancelWork = false;
search = new CTokenFile(mask, minSizeMB, maxSizeMB);
Start(true);
//Work();
return true;
}
void Share::Work()
{
//TreeView_SetItem(hwndNotify,
if (search == NULL) return;
//*(char*)NULL=0;
TCHAR start[MAX_PATH];
LPTSTR end = StrCopy(start, parent->m_Name);
*(end++)='\\';
end = StrCopy(end,m_Name);
*(end++)='\\';
err.SetIdentifier(start);
StrCopy(end,TEXT("*.*"));
ClearStrings();
// ImpersonateAnonymousToken(hThread);
if (!SearchRecursive(start)) PostNotify(NNM_EMPTYDETECTED, (LPARAM)this);
// RevertToSelf();
DeletePtr(search);
err.SetIdentifier(m_Name);
}
bool Share::SearchRecursive(LPCTSTR mask)
{
if (cancelWork) return true;
WIN32_FIND_DATA wfd;
TCHAR subdir[MAX_PATH];
LPTSTR end;
HANDLE hFind = FindFirstFile(mask, &wfd);
current = mask;
UpdateStatus();
if (hFind && hFind != INVALID_HANDLE_VALUE) {
do {
if (search->IsMatch(wfd)) {
end = StrCopy(subdir,mask);
end = StrChar(subdir,'*');
//*(end++)='\\';
end = StrCopy(end,wfd.cFileName);
//*(end++)='\\';
//StrCopy(end,TEXT("*.*"));
//DebugWrite(subdir);
AddString(subdir);
//SendMessage(hList, LB_ADDSTRING, 0,(LPARAM) subdir);
}
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (!IS_DOT_DIR(wfd.cFileName)) {
end = StrCopy(subdir,mask);
end = StrChar(subdir,'*');
//*(end++)='\\';
end = StrCopy(end,wfd.cFileName);
*(end++)='\\';
StrCopy(end,TEXT("*.*"));
SearchRecursive(subdir);
current = mask;
}
}
} while(!cancelWork && FindNextFile(hFind, &wfd));
FindClose(hFind);
} else {
//DWORD code = GetLastError();
SetState(FAIL_RUN);
//wsprintf(subdir, TEXT("FindFirst failed: %d"), code);
//DebugWrite(subdir);
err.DebugWriteString(TEXT("FindFirst failed"), true);
//if (code == ERROR_TOO_MANY_CMDS) {
// DebugWrite(TEXT("NetBIOS command limit exceeded. Sleep for 1 second and retry"));
// Sleep(1000);
// goto SearchRecBegin:
//}
current = NULL;
return false;
}
current = NULL;
return true;
}
bool Share::AddString(LPCTSTR item)
{
if (item==NULL) return NULL;
bool ret=false;
if (ExclusiveLock()) {
if (found_count>=found_alloc) {
LPTSTR* tmp=new LPTSTR[found_alloc+5];
if (tmp==NULL) goto AddStringFail;
found_alloc += 5;
memmove(tmp, found, sizeof(LPTSTR)*found_count);
delete found;
found=tmp;
}
if (FindString(item)) goto AddStringFail; // already exist
found[found_count++] = StrDup(item);
ret = true;
PostMessage(GetParent(hwndNotify), MSG_NETNOTIFY, NNM_ITEMADDED, NULL);
AddStringFail:
ExclusiveRelease();
}
return ret;
}
LPCTSTR Share::FindString(LPCTSTR item)
{
for (unsigned i=0; i<found_count; i++) {
if (StrCmp(found[i], item)==0) return found[i];
}
return NULL;
}
void Share::ClearStrings()
{
if (ExclusiveLock()) {
if (found) {
while(found_count--) delete found[found_count];
delete found;
found = NULL;
}
found_count = found_alloc = 0;
ExclusiveRelease();
}
}
LPCTSTR Share::operator[](unsigned idx) const
{
if (found && idx<found_count) return found[idx];
return NULL;
}
void Share::Draw(LPNMTVCUSTOMDRAW tv, PCOLUMNS cols)
{
RECT rc = tv->nmcd.rc;
// TCHAR host[50];
CWorker::Draw(tv, cols);
if (current) {
rc.left = cols->item[3].left;
//if (state>=FAIL_RUN) rc.right = rc.left + cols->item[3].width;
DrawText(tv->nmcd.hdc, current , StrLen(current), &rc, DT_SINGLELINE | DT_VCENTER);
}
}
inline unsigned Share::GetCount()
{
return found_count;
}
inline bool Share::HasAnything()
{
return found_count!=0;
}
int Computer::GetIPName(LPTSTR outbuf, int len)
{
return (StrCopy(outbuf, IP_str)-outbuf);
}
int Computer::Filter(CToken *filter, int col)
{
assert(type == NRT_COMPUTER);
int ret;
if (col==3) {
if (filter==NULL || filter->IsMatch(IP_str)) {
if (tvItem==NULL) {
parent->AddNoCheck(this, true);
for(int i=GetCount(); i--;)
AddNoCheck((*this)[i],true);
}
return 1;
} else if (tvItem && parent){
TreeView_DeleteItem(hwndNotify, tvItem);
tvItem = NULL;
}
return 0;
}
ret = CWorker::Filter(filter, col);
if (tvItem && col==1) Unfold();
return ret;
}
/*************************************************************************************************
*
********************************************************************************************/
LPTSTR Share::FullName()
{
int ln = StrLen(parent->m_Name) + StrLen(m_Name) + 2; // slash and eol
LPTSTR ret = new TCHAR[ln];
if (ret) FullName(ret);
return ret;
}
void Share::FullName(LPTSTR buf)
{
LPTSTR tmp = StrCopy(buf, parent->m_Name);
*(tmp++)='\\';
StrCopy(tmp, m_Name);
}
bool Computer::Ping()
{
return true;
}