summaryrefslogtreecommitdiffabout
path: root/DipstickDlg.cpp
authorMichael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
committer Michael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
commit5305ddd8332ebd905ebef3b8365fc0d736858a7a (patch) (unidiff)
treeba6dc874bdcb00bd2e116b377a92f347ab81a733 /DipstickDlg.cpp
downloaddipstick-5305ddd8332ebd905ebef3b8365fc0d736858a7a.zip
dipstick-5305ddd8332ebd905ebef3b8365fc0d736858a7a.tar.gz
dipstick-5305ddd8332ebd905ebef3b8365fc0d736858a7a.tar.bz2
initial commit into svn repository
git-svn-id: http://svn.klever.net/kin/dipstick/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8
Diffstat (limited to 'DipstickDlg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--DipstickDlg.cpp1586
1 files changed, 1586 insertions, 0 deletions
diff --git a/DipstickDlg.cpp b/DipstickDlg.cpp
new file mode 100644
index 0000000..ace2aff
--- a/dev/null
+++ b/DipstickDlg.cpp
@@ -0,0 +1,1586 @@
1// DipstickDlg.cpp : implementation file
2//
3
4#include "stdafx.h"
5#include "Dipstick.h"
6#include "DipstickDlg.h"
7#include "DragPad.h"
8#include "OptionsDlg.h"
9#include "HostNameDlg.h"
10#include "HostProperties.h"
11#include "AutoBestDlg.h"
12#include "ddeml.h"
13
14#include "URLSource.h"
15#include "SelectURLsDlg.h"
16
17#ifdef _DEBUG
18#define new DEBUG_NEW
19#undef THIS_FILE
20static char THIS_FILE[] = __FILE__;
21#endif
22
23/////////////////////////////////////////////////////////////////////////////
24// CAboutDlg dialog used for App About
25
26class CAboutDlg : public CDialog
27{
28public:
29 CAboutDlg();
30
31// Dialog Data
32 //{{AFX_DATA(CAboutDlg)
33 enum { IDD = IDD_ABOUTBOX };
34 //}}AFX_DATA
35
36 // ClassWizard generated virtual function overrides
37 //{{AFX_VIRTUAL(CAboutDlg)
38 protected:
39 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
40 //}}AFX_VIRTUAL
41
42// Implementation
43protected:
44 virtual BOOL OnInitDialog();
45 //{{AFX_MSG(CAboutDlg)
46 afx_msg void OnKlevernet();
47 //}}AFX_MSG
48 DECLARE_MESSAGE_MAP()
49};
50
51CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
52{
53 //{{AFX_DATA_INIT(CAboutDlg)
54 //}}AFX_DATA_INIT
55}
56
57void CAboutDlg::DoDataExchange(CDataExchange* pDX)
58{
59 CDialog::DoDataExchange(pDX);
60 //{{AFX_DATA_MAP(CAboutDlg)
61 //}}AFX_DATA_MAP
62}
63
64BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
65 //{{AFX_MSG_MAP(CAboutDlg)
66 ON_BN_CLICKED(IDC_KLEVERNET, OnKlevernet)
67 //}}AFX_MSG_MAP
68END_MESSAGE_MAP()
69
70/////////////////////////////////////////////////////////////////////////////
71// CDipstickDlg dialog
72
73CDipstickDlg::CDipstickDlg(CWnd* pParent /*=NULL*/)
74 : CDialog(CDipstickDlg::IDD, pParent),
75 m_DragPad(NULL), m_PingsPerHost(10), m_PingSize(32), m_TimeOut(5000), m_Interval(500),
76 m_SortCriteria(sortAvg), m_bShown(FALSE), m_MaxThreads(10), m_bExiting(FALSE),
77 m_bMSWorkAround(TRUE), m_MinSize(-1,-1), m_bAutoBest(TRUE), m_bSmartAdjust(TRUE),
78 m_bAdjustInnermost(TRUE), m_ActiveThreads(0), m_bIgnorelative(TRUE)
79{
80CWinApp *app = AfxGetApp();
81 ASSERT(app);
82WORD hi,lo;
83 hi=app->GetProfileInt("Options","IntervalHi",HIWORD(m_Interval));
84 lo=app->GetProfileInt("Options","IntervalLo",LOWORD(m_Interval));
85 m_Interval=MAKELONG(lo,hi);
86 m_MaxThreads=app->GetProfileInt("Options","MaxThreads",m_MaxThreads);
87 m_PingSize=app->GetProfileInt("Options","PingSize",m_PingSize);
88 m_PingsPerHost=app->GetProfileInt("Options","PingsPerHost",m_PingsPerHost);
89 m_SortCriteria=app->GetProfileInt("Options","SortBy",m_SortCriteria);
90 hi=app->GetProfileInt("Options","TimeOutHi",HIWORD(m_TimeOut));
91 lo=app->GetProfileInt("Options","TimeOutLo",LOWORD(m_TimeOut));
92 m_TimeOut=MAKELONG(lo,hi);
93 m_bMSWorkAround = app->GetProfileInt("Options","InnermostURL",m_bMSWorkAround);
94 m_bAutoBest = app->GetProfileInt("Options","AutoBest",m_bAutoBest);
95 m_bSmartAdjust = app->GetProfileInt("Options","SmartAdjust",m_bSmartAdjust);
96 m_bAdjustInnermost = app->GetProfileInt("Options","AdjustInnermost",m_bAdjustInnermost);
97 m_bIgnorelative = app->GetProfileInt("Options","IgnoreRelative",m_bIgnorelative);
98 m_impexPath = app->GetProfileString("Options","ImportExportPath",m_impexPath);
99 //{{AFX_DATA_INIT(CDipstickDlg)
100 //}}AFX_DATA_INIT
101 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
102 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
103 m_bmpBack.LoadBitmap(IDB_DIABACK);
104 m_bmpBack.GetBitmap(&m_bitmapBack);
105CString tmp;
106 VERIFY(tmp.LoadString(IDS_REGEX_HTMLURL));
107 VERIFY(m_reHTMLURL.Compile(tmp,CRegEx::regExtended|CRegEx::regIgnoreCase));
108}
109
110CDipstickDlg::~CDipstickDlg()
111{
112}
113
114void CDipstickDlg::DoDataExchange(CDataExchange* pDX)
115{
116 CDialog::DoDataExchange(pDX);
117 //{{AFX_DATA_MAP(CDipstickDlg)
118 DDX_Control(pDX, IDC_ADVANCED, m_AdvancedCtl);
119 DDX_Control(pDX, ID_HELP, m_HelpCtl);
120 DDX_Control(pDX, IDC_EXIT, m_ExitCtl);
121 DDX_Control(pDX, IDC_OPTIONS, m_OptionsCtl);
122 DDX_Control(pDX, IDC_MANUALPING, m_ManualPingCtl);
123 DDX_Control(pDX, IDC_REMOVE, m_RemoveCtl);
124 DDX_Control(pDX, IDC_REPINGALL, m_RepingAllCtl);
125 DDX_Control(pDX, IDC_REPING, m_RepingCtl);
126 DDX_Control(pDX, IDC_CLEAR, m_ClearListCtl);
127 DDX_Control(pDX, IDC_HOSTLIST, m_HostList);
128 //}}AFX_DATA_MAP
129}
130
131BEGIN_MESSAGE_MAP(CDipstickDlg, CDialog)
132 //{{AFX_MSG_MAP(CDipstickDlg)
133 ON_WM_SYSCOMMAND()
134 ON_WM_PAINT()
135 ON_WM_QUERYDRAGICON()
136 ON_WM_DESTROY()
137 ON_BN_CLICKED(IDC_OPTIONS, OnOptions)
138 ON_MESSAGE(WM_DNP_URLPING, OnUrlPing)
139 ON_MESSAGE(WM_DNP_ACTIVITYCOUNT, OnActivityCount)
140 ON_MESSAGE(WM_DNP_UPDATEHOSTDATA, OnUpdateHostData)
141 ON_MESSAGE(WM_DNP_HTML, OnHTMLTransfer)
142 ON_NOTIFY(LVN_COLUMNCLICK, IDC_HOSTLIST, OnColumnclickHostlist)
143 ON_WM_WINDOWPOSCHANGING()
144 ON_COMMAND(ID_DRAGPAD_OPTIONS, OnDragpadOptions)
145 ON_COMMAND(ID_DRAGPAD_SHOWMAINWINDOW, OnDragpadShowmainwindow)
146 ON_COMMAND(ID_DRAGPAD_HELP, OnDragpadHelp)
147 ON_COMMAND(ID_DRAGPAD_ABOUT, OnDragpadAbout)
148 ON_COMMAND(ID_DRAGPAD_EXIT, OnDragpadExit)
149 ON_BN_CLICKED(IDC_MANUALPING, OnManualping)
150 ON_COMMAND(ID_DRAGPAD_MANUALPING, OnDragpadManualping)
151 ON_COMMAND(ID_DRAGPAD_REPINGALL, OnDragpadRepingAll)
152 ON_COMMAND(ID_DRAGPAD_REMOVEALL, OnDragpadRemoveAll)
153 ON_BN_CLICKED(IDC_REPING, OnReping)
154 ON_BN_CLICKED(IDC_REPINGALL, OnRepingall)
155 ON_BN_CLICKED(IDC_CLEAR, OnClear)
156 ON_NOTIFY(LVN_INSERTITEM, IDC_HOSTLIST, OnInsertitemHostlist)
157 ON_NOTIFY(LVN_DELETEITEM, IDC_HOSTLIST, OnDeleteitemHostlist)
158 ON_NOTIFY(LVN_DELETEALLITEMS, IDC_HOSTLIST, OnDeleteallitemsHostlist)
159 ON_BN_CLICKED(IDC_EXIT, OnExit)
160 ON_NOTIFY(LVN_ITEMCHANGED, IDC_HOSTLIST, OnItemchangedHostlist)
161 ON_BN_CLICKED(IDC_REMOVE, OnRemove)
162 ON_NOTIFY(NM_RCLICK, IDC_HOSTLIST, OnRclickHostlist)
163 ON_COMMAND(ID_HOSTLIST_REPING, OnHostListReping)
164 ON_COMMAND(ID_HOSTLIST_REMOVE, OnHostListRemove)
165 ON_COMMAND(ID_HOSTLIST_REPINGALL, OnHostListRepingAll)
166 ON_COMMAND(ID_HOSTLIST_REMOVEALL, OnHostListRemoveAll)
167 ON_COMMAND(ID_HOSTLIST_OPENURL, OnHostListOpenURL)
168 ON_COMMAND(ID_HOSTLIST_PROPERTIES, OnHostListProperties)
169 ON_NOTIFY(NM_DBLCLK, IDC_HOSTLIST, OnDblclkHostlist)
170 ON_WM_CLOSE()
171 ON_WM_GETMINMAXINFO()
172 ON_WM_SIZE()
173 ON_BN_CLICKED(ID_HELP, OnHelp)
174 ON_NOTIFY(LVN_BEGINDRAG, IDC_HOSTLIST, OnBegindragHostlist)
175 ON_COMMAND(ID_HOSTLIST_PASTEURL, OnPasteurl)
176 ON_COMMAND(ID_HOSTLIST_COPYURL, OnHostlistCopyurl)
177 ON_WM_HELPINFO()
178 ON_WM_DROPFILES()
179 ON_BN_CLICKED(IDC_ADVANCED, OnAdvanced)
180 ON_COMMAND(ID_ADVANCED_EXPORTLIST, OnAdvancedExportlist)
181 ON_COMMAND(ID_ADVANCED_IMPORTLIST, OnAdvancedImportlist)
182 ON_COMMAND(ID_DRAGPAD_PASTEURL, OnPasteurl)
183 ON_COMMAND(ID_DRAGPAD_ADVANCED_EXPORTLIST, OnDragpadAdvancedExportlist)
184 ON_COMMAND(ID_DRAGPAD_ADVANCED_IMPORTLIST, OnDragpadAdvancedImportlist)
185 //}}AFX_MSG_MAP
186END_MESSAGE_MAP()
187
188/////////////////////////////////////////////////////////////////////////////
189// CDipstickDlg message handlers
190
191BOOL CDipstickDlg::OnInitDialog()
192{
193 CDialog::OnInitDialog();
194
195 // Add "About..." menu item to system menu.
196
197 // IDM_ABOUTBOX must be in the system command range.
198 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
199 ASSERT(IDM_ABOUTBOX < 0xF000);
200
201 CMenu* pSysMenu = GetSystemMenu(FALSE);
202 CString strAboutMenu;
203 strAboutMenu.LoadString(IDS_ABOUTBOX);
204 if (!strAboutMenu.IsEmpty())
205 {
206 pSysMenu->AppendMenu(MF_SEPARATOR);
207 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
208 }
209
210 // Set the icon for this dialog. The framework does this automatically
211 // when the application's main window is not a dialog
212 SetIcon(m_hIcon, TRUE); // Set big icon
213 SetIcon(m_hIcon, FALSE); // Set small icon
214
215CRect wrci, wrco;
216 GetWindowRect(&wrco);
217 GetClientRect(&wrci);
218CRect brc1, brc2, lrc;
219 m_HostList.GetWindowRect(&lrc);
220 ScreenToClient(&lrc);
221 m_ManualPingCtl.GetWindowRect(&brc1);
222 ScreenToClient(brc1);
223 m_RepingCtl.GetWindowRect(&brc2);
224 ScreenToClient(&brc2);
225 m_OverX = lrc.left;
226 m_OverY = lrc.top;
227 m_GapY = brc2.top - brc1.bottom;
228 m_MinSize.cx = m_OverX+m_OverX+m_OverX+brc1.Width()+m_OverX;
229 m_MinSize.cy = m_OverY+(brc1.Height()+m_GapY)*6+(brc1.Height()+m_GapY)*3+m_OverY;
230 m_MinSize.cx+=wrco.Width()-wrci.Width();
231 m_MinSize.cy+=wrco.Height()-wrci.Height();
232
233CWinApp *app = AfxGetApp();
234 ASSERT(app);
235CRect wrc;
236 wrc.top=app->GetProfileInt("Windows","DlgTop",-1);
237 wrc.bottom=app->GetProfileInt("Windows","DlgBottom",-1);
238 wrc.left=app->GetProfileInt("Windows","DlgLeft",-1);
239 wrc.right=app->GetProfileInt("Windows","DlgRight",-1);
240 if((wrc.top!=-1|| wrc.bottom!=-1) && wrc.left!=-1&& wrc.right!=-1)
241 MoveWindow(&wrc);
242
243 RecalcLayout(-1,-1);
244
245 m_DragPad = new CDragPad();
246 m_DragPad->m_Daddy=this;
247 m_DragPad->Create(CDragPad::IDD);
248 m_Images.Create(16,16,TRUE,4,1);
249 m_iPending=m_Images.Add(app->LoadIcon(IDI_PENDING));
250 m_iPinging=m_Images.Add(app->LoadIcon(IDI_PINGING));
251 m_iCompleted=m_Images.Add(app->LoadIcon(IDI_COMPLETED));
252 m_iUnreachable=m_Images.Add(app->LoadIcon(IDI_UNREACHABLE));
253 ASSERT(!(m_iPending<0 || m_iPinging<0 || m_iCompleted<0 || m_iUnreachable<0));
254 m_HostList.SetImageList(&m_Images,LVSIL_NORMAL);
255 m_HostList.SetImageList(&m_Images,LVSIL_SMALL);
256 m_HostList.SetImageList(&m_Images,LVSIL_STATE);
257 m_HostList.SetTextColor(RGB(255,255,0));// Yellow
258 m_HostList.SetTextBkColor(RGB(12,167,0));// Green
259 m_HostList.SetBkColor(RGB(12,167,0)); // Green
260CRect listrc;
261 m_HostList.GetClientRect(&listrc);
262 m_HostList.InsertColumn(0,"Host Name",LVCFMT_LEFT,app->GetProfileInt("Columns","HostName",listrc.Width()-(listrc.Width()*2/16)*4-(listrc.Width()*3/16)),subitemHost);
263 m_HostList.InsertColumn(1,"Host IP",LVCFMT_LEFT,app->GetProfileInt("Columns","HostIP",listrc.Width()*3/16),subitemIP);
264 m_HostList.InsertColumn(2,"Min RTT",LVCFMT_RIGHT,app->GetProfileInt("Columns","MinRTT",listrc.Width()*2/16),subitemMin);
265 m_HostList.InsertColumn(3,"Avg RTT",LVCFMT_RIGHT,app->GetProfileInt("Columns","AvgRTT",listrc.Width()*2/16),subitemAvg);
266 m_HostList.InsertColumn(4,"Max RTT",LVCFMT_RIGHT,app->GetProfileInt("Columns","MaxRTT",listrc.Width()*2/16),subitemMax);
267 m_HostList.InsertColumn(5,"Pktloss", LVCFMT_RIGHT,app->GetProfileInt("Columns","PktLoss",listrc.Width()*2/16),subitemPacketloss);
268
269 DragAcceptFiles(TRUE);
270
271 return TRUE; // return TRUE unless you set the focus to a control
272}
273
274void CDipstickDlg::OnSysCommand(UINT nID, LPARAM lParam)
275{
276 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
277 {
278 CAboutDlg dlgAbout;
279 dlgAbout.DoModal();
280 }
281 else
282 {
283 CDialog::OnSysCommand(nID, lParam);
284 }
285}
286
287// If you add a minimize button to your dialog, you will need the code below
288// to draw the icon. For MFC applications using the document/view model,
289// this is automatically done for you by the framework.
290
291void CDipstickDlg::OnPaint()
292{
293 if (IsIconic())
294 {
295 CPaintDC dc(this); // device context for painting
296
297 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
298
299 // Center icon in client rectangle
300 int cxIcon = GetSystemMetrics(SM_CXICON);
301 int cyIcon = GetSystemMetrics(SM_CYICON);
302 CRect rect;
303 GetClientRect(&rect);
304 int x = (rect.Width() - cxIcon + 1) / 2;
305 int y = (rect.Height() - cyIcon + 1) / 2;
306
307 // Draw the icon
308 dc.DrawIcon(x, y, m_hIcon);
309 }
310 else
311 {
312 CPaintDC pDC(this);
313 CDC bmpDC;
314 bmpDC.CreateCompatibleDC(&pDC);
315 bmpDC.SelectObject(&m_bmpBack);
316 CRect rc;
317 GetClientRect(&rc);
318 for(int x=-m_bitmapBack.bmWidth*2/4;x<rc.Width();x+=m_bitmapBack.bmWidth)
319 for(int y=-m_bitmapBack.bmHeight*2/4;y<rc.Height();y+=m_bitmapBack.bmHeight)
320 pDC.BitBlt(x,y,m_bitmapBack.bmWidth,m_bitmapBack.bmHeight,&bmpDC,0,0,SRCCOPY);
321 bmpDC.DeleteDC();
322 CDialog::OnPaint();
323 }
324}
325
326// The system calls this to obtain the cursor to display while the user drags
327// the minimized window.
328HCURSOR CDipstickDlg::OnQueryDragIcon()
329{
330 return (HCURSOR) m_hIcon;
331}
332
333//////////////////////////
334
335void CDipstickDlg::OnDestroy()
336{
337 CDialog::OnDestroy();
338 TRACE0("DestroyMain\n");
339 m_DragPad->DestroyWindow();
340 delete m_DragPad;
341 m_DragPad=NULL;
342 // *** Eventually move the following code to separate function
343POSITION p = m_Hosts.GetHeadPosition();
344 while(p){
345 POSITION pp = p;
346 CPingyHost *host = m_Hosts.GetNext(p);
347 ASSERT(host);
348 m_Hosts.RemoveAt(pp);
349 host->Suicide();
350 }
351 ASSERT(m_Hosts.IsEmpty());
352}
353
354void CDipstickDlg::OnOptions()
355{
356COptionsDlg o(this);
357 o.m_Pings = m_PingsPerHost;
358 o.m_PingSize = m_PingSize;
359 o.m_TimeOut = max(1,m_TimeOut/1000);
360 o.m_Interval = max(1,m_Interval/1000);
361 o.m_MaxThreads = m_MaxThreads;
362 o.m_bMSWorkAround = m_bMSWorkAround;
363 o.m_bAutoBest = m_bAutoBest;
364 o.m_bAdjust = m_bSmartAdjust;
365 o.m_bAdjustInn = m_bAdjustInnermost;
366 o.m_bIgnorelative = m_bIgnorelative;
367 if(o.DoModal()==IDOK){
368 m_PingsPerHost = o.m_Pings;
369 m_PingSize = o.m_PingSize;
370 m_TimeOut = o.m_TimeOut*1000;
371 m_Interval = o.m_Interval*1000;
372 m_MaxThreads = o.m_MaxThreads;
373 m_bMSWorkAround = o.m_bMSWorkAround;
374 m_bAutoBest = o.m_bAutoBest;
375 m_bSmartAdjust = o.m_bAdjust;
376 m_bAdjustInnermost = o.m_bAdjustInn;
377 m_bIgnorelative = o.m_bIgnorelative;
378 }
379}
380
381BOOL CDipstickDlg::AddPingyHost(CPingyHost *host)
382{
383 m_Hosts.AddTail(host);
384int i = m_HostList.InsertItem(0,host->m_HostName);
385 m_HostList.SetItemData(i,(DWORD)host);
386 UpdateDragpadTitle();
387 return UpdatePingyHost(host,i);// *** Do someting if failed.
388}
389
390BOOL CDipstickDlg::UpdatePingyHost(CPingyHost *host,int index)
391{
392 UpdateDragpadTitle();
393int i = index;
394 if(i<0){
395 int is = m_HostList.GetItemCount();
396 for(i=0;i<is;i++)
397 if(m_HostList.GetItemData(i)==(DWORD)host)
398 break;
399 if(!(i<is))
400 return FALSE;
401 }
402 ASSERT(m_HostList.GetItemData(i)==(DWORD)host);
403 m_HostList.SetItemText(i,subitemHost,host->m_HostName.IsEmpty()?"...":host->m_HostName);
404 m_HostList.SetItemText(i,subitemIP,host->m_IP?inet_ntoa(*(in_addr*)&host->m_IP):"...");
405 if(host->m_Pinged && host->m_Packetloss>=0){
406 CString tmp;
407 if(host->m_Packetloss==100){
408 m_HostList.SetItemText(i,subitemMin,"-");
409 m_HostList.SetItemText(i,subitemAvg,"-");
410 m_HostList.SetItemText(i,subitemMax,"-");
411 }else{
412 tmp.Format("%lu",host->m_MinRTT);
413 m_HostList.SetItemText(i,subitemMin,tmp);
414 tmp.Format("%lu",host->m_AvgRTT);
415 m_HostList.SetItemText(i,subitemAvg,tmp);
416 tmp.Format("%lu",host->m_MaxRTT);
417 m_HostList.SetItemText(i,subitemMax,tmp);
418 }
419 tmp.Format("%d%%",host->m_Packetloss);
420 m_HostList.SetItemText(i,subitemPacketloss,tmp);
421 }else{
422 m_HostList.SetItemText(i,subitemMin,"...");
423 m_HostList.SetItemText(i,subitemAvg,"...");
424 m_HostList.SetItemText(i,subitemMax,"...");
425 m_HostList.SetItemText(i,subitemPacketloss,"...");
426 }
427 if(host->m_Pinging)
428 m_HostList.SetItem(i,subitemHost,LVIF_IMAGE,NULL,m_iPinging,0,0,0);
429 else{
430 if(host->m_bToPing)
431 m_HostList.SetItem(i,subitemHost,LVIF_IMAGE,NULL,m_iPending,0,0,0);
432 else{
433 if(host->m_Pinged){
434 if(host->m_Packetloss==100)
435 m_HostList.SetItem(i,subitemHost,LVIF_IMAGE,NULL,m_iUnreachable,0,0,0);
436 else
437 m_HostList.SetItem(i,subitemHost,LVIF_IMAGE,NULL,m_iCompleted,0,0,0);
438 }else
439 m_HostList.SetItem(i,subitemHost,LVIF_IMAGE,NULL,m_iPending,0,0,0);
440 }
441 }
442 m_HostList.SortItems(CompareItems,(DWORD)this);
443 UpdateControlButtons();
444 return TRUE;
445}
446
447BOOL CDipstickDlg::RemovePingyHost(CPingyHost *host,int index)
448{
449 if(host->m_Pinging)
450 return FALSE;
451int i = index;
452 if(i<0){
453 int is = m_HostList.GetItemCount();
454 for(i=0;i<is;i++)
455 if(m_HostList.GetItemData(i)==(DWORD)host)
456 break;
457 if(!(i<is))
458 return FALSE;
459 }
460 ASSERT(m_HostList.GetItemData(i)==(DWORD)host);
461POSITION p = m_Hosts.Find(host,NULL);
462 if(!p)
463 return FALSE;
464 m_HostList.DeleteItem(i);
465 m_Hosts.RemoveAt(p);
466 host->Suicide();
467 UpdateControlButtons();
468 UpdateDragpadTitle();
469 return TRUE;
470}
471
472LRESULT CDipstickDlg::OnUrlPing(WPARAM wP, LPARAM lP)
473{
474 ASSERT(lP);
475CString *u = (CString*)lP;
476CString hn;
477CPingyHost *host;
478 if(m_bMSWorkAround)
479 hn = CCrackURL::InnermostURL(*u);
480 else
481 hn = *u;
482 hn = CCrackURL::GetHostName(hn);
483DWORD ip = inet_addr(hn);
484 if(ip==INADDR_NONE)
485 host = new CPingyHost(this,(char*)(LPCTSTR)hn);
486 else
487 host = new CPingyHost(this,ip);
488 host->m_URL=*u;
489 delete u;
490 AddPingyHost(host);
491 CheckForPendingRequests();
492 return 0;
493}
494
495LRESULT CDipstickDlg::OnActivityCount(WPARAM wP,LPARAM)
496{
497 if(!wP)
498 return 0;
499 intcrement = (int)wP;
500 m_ActiveThreads+=crement;
501 if(m_ActiveThreads<0){
502 TRACE0("C'est n'est pas possible!\n");
503 m_ActiveThreads=0;
504 }
505 TRACE1("AC: %d\n",m_ActiveThreads);
506 if(m_ActiveThreads){
507 m_DragPad->m_DragNDropTarget.Play(0,(UINT)-1,(UINT)-1);
508 m_ClearListCtl.EnableWindow(FALSE);
509 }else{
510 m_DragPad->m_DragNDropTarget.Stop();
511 m_DragPad->m_DragNDropTarget.Seek(0);
512 if(m_HostList.GetItemCount())
513 m_ClearListCtl.EnableWindow(TRUE);
514 }
515 if(crement>0)
516 return 0;
517 UpdateDragpadTitle();
518int items = m_HostList.GetItemCount();
519 if((!CheckForPendingRequests()) && m_bAutoBest && items && !m_ActiveThreads){
520 // Come up with the best URL..
521 m_SortCriteria=sortAvg;
522 m_HostList.SortItems(CompareItems,(DWORD)this);
523 CPtrArray hs;
524 for(int tmp=0;tmp<items;tmp++){
525 CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(tmp);
526 ASSERT(!host->m_Pinging);
527 ASSERT(host->m_Pinged);
528 if(host->m_Packetloss==100 || host->m_URL.IsEmpty())
529 continue;
530 hs.Add(host);
531 }
532 if(hs.GetSize()){
533 int item = 0;
534 if(!::PlaySound((LPCTSTR)IDW_BESTURL,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_RESOURCE))
535 MessageBeep(0xFFFFFFFF);
536 for(;;){
537 CPingyHost *host = (CPingyHost*)hs[item];
538 CAutoBestDlg abd;
539 abd.m_bPrev = (item>0);
540 abd.m_bNext = (item<hs.GetUpperBound());
541 abd.m_PktLoss.Format("%d%%",host->m_Packetloss);
542 abd.m_RTT.Format("%lu",host->m_AvgRTT);
543 abd.m_URL=host->m_URL;
544 int rv = abd.DoModal();
545 if(rv==IDOK){
546 ShellExecute(::GetDesktopWindow(),"open",host->m_URL,NULL,NULL,SW_SHOWMAXIMIZED);
547 CString title, text;
548 VERIFY(title.LoadString(IDS_ABEST_TITLE));
549 VERIFY(text.LoadString(IDS_ABEST_CLEANUP));
550 if(MessageBox(text,title,MB_YESNO|MB_ICONQUESTION|MB_APPLMODAL)==IDYES)
551 OnClear();
552 break;
553 }else if(rv==IDCANCEL){
554 break;
555 }else if(rv==IDC_PREV){
556 item--;
557 ASSERT(item>=0);
558 }else if(rv==IDC_NEXT){
559 item++;
560 ASSERT(item<hs.GetSize());
561 }else
562 break;
563 }
564 }else{
565 CString title, text;
566 VERIFY(title.LoadString(IDS_ABEST_TITLE));
567 VERIFY(text.LoadString(IDS_ABEST_NONEFOUND));
568 MessageBox(text,title,MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
569 }
570 }
571 return 0;
572}
573
574LRESULT CDipstickDlg::OnUpdateHostData(WPARAM,LPARAM lP)
575{
576 TRACE0("UpdateHostData\n");
577CPingyHost *host = (CPingyHost*)lP;
578 ASSERT(host);
579 UpdatePingyHost(host);
580 UpdateDragpadTitle();
581 return 0;
582}
583
584int CALLBACK CDipstickDlg::CompareItems(LPARAM lp1, LPARAM lp2, LPARAM lp)
585{
586CDipstickDlg *dlg = (CDipstickDlg*)lp;
587CPingyHost *h1 = (CPingyHost*)lp1;
588CPingyHost *h2 = (CPingyHost*)lp2;
589 ASSERT(dlg);
590 ASSERT(h1);
591 ASSERT(h2);
592int criteria = dlg->m_SortCriteria;
593 switch(criteria){
594 case sortHost:
595 return h1->m_HostName.CompareNoCase(h2->m_HostName);
596 case sortIP:
597 return htonl(h1->m_IP)-htonl(h2->m_IP);
598 default:
599 if(h1->m_Pinged){
600 if(!h2->m_Pinged)
601 return -1;
602 if(h1->m_Packetloss==100){
603 if(h2->m_Packetloss!=100)
604 return 1;
605 return 0;
606 }else{
607 if(h2->m_Packetloss==100)
608 return -1;
609 }
610 }else{
611 if(h2->m_Pinged)
612 return 1;
613 break;
614 }
615 switch(criteria){
616 case sortMin:
617 return h1->m_MinRTT-h2->m_MinRTT;
618 case sortAvg:
619 return h1->m_AvgRTT-h2->m_AvgRTT;
620 case sortMax:
621 return h1->m_MaxRTT-h2->m_MaxRTT;
622 case sortLoss:
623 return h1->m_Packetloss-h2->m_Packetloss;
624 }
625 }
626 return 0;
627}
628
629void CDipstickDlg::OnColumnclickHostlist(NMHDR* pNMHDR, LRESULT* pResult)
630{
631 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
632 switch(pNMListView->iSubItem){
633 case subitemHost: m_SortCriteria=sortHost; break;
634 case subitemIP: m_SortCriteria=sortIP; break;
635 case subitemMin: m_SortCriteria=sortMin; break;
636 case subitemAvg: m_SortCriteria=sortAvg; break;
637 case subitemMax: m_SortCriteria=sortMax; break;
638 case subitemPacketloss: m_SortCriteria=sortLoss; break;
639 }
640 m_HostList.SortItems(CompareItems,(DWORD)this);
641 *pResult = 0;
642}
643
644BOOL CDipstickDlg::PreCreateWindow(CREATESTRUCT& cs)
645{
646 cs.style&=~WS_VISIBLE;
647 return CDialog::PreCreateWindow(cs);
648}
649
650void CDipstickDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
651{
652 CDialog::OnWindowPosChanging(lpwndpos);
653 if(!m_bExiting){
654 if(m_bShown){
655 lpwndpos->flags&=~SWP_HIDEWINDOW;
656 lpwndpos->flags|=SWP_SHOWWINDOW;
657 }else{
658 lpwndpos->flags&=~SWP_SHOWWINDOW;
659 lpwndpos->flags|=SWP_HIDEWINDOW;
660 }
661 }
662}
663
664void CDipstickDlg::OnDragpadOptions()
665{
666 OnOptions();
667}
668void CDipstickDlg::OnDragpadShowmainwindow()
669{
670 m_DragPad->ToggleMainWindowDisplay();
671}
672void CDipstickDlg::OnDragpadHelp()
673{
674 OnHelp();
675}
676void CDipstickDlg::OnDragpadAbout()
677{
678CAboutDlg dlgAbout;
679 dlgAbout.DoModal();
680}
681void CDipstickDlg::OnDragpadExit()
682{
683 // *** More threading-aware
684 OnOK();
685}
686
687int CDipstickDlg::CheckForPendingRequests()
688{
689static BOOL bChecking = FALSE;
690 if(bChecking)
691 return -1;
692 bChecking = TRUE;
693 TRACE1("CFPR: AC: %d\n",m_ActiveThreads);
694int newRequests = m_MaxThreads-m_ActiveThreads;
695POSITION p = m_Hosts.GetHeadPosition();
696int rv = 0;
697 while(newRequests>0 && p){
698 CPingyHost *host = m_Hosts.GetNext(p);
699 ASSERT(host);
700 if(host->m_Pinging)
701 continue;
702 if(!host->m_bToPing)
703 continue;
704 TRACE0("!");
705 host->Ping();
706 newRequests--;
707 rv++;
708 }
709 TRACE0("/CFPR\n");
710 bChecking = FALSE;
711 return rv;
712}
713
714void CAboutDlg::OnKlevernet()
715{
716CString url;
717 url.LoadString(IDS_KLEVERNET_URL);
718 ShellExecute(::GetDesktopWindow(),"open",url,NULL,NULL,SW_SHOWMAXIMIZED);
719}
720
721void CDipstickDlg::OnOK()
722{
723CWinApp *app = AfxGetApp();
724 ASSERT(app);
725 app->WriteProfileInt("Options","IntervalHi",HIWORD(m_Interval));
726 app->WriteProfileInt("Options","IntervalLo",LOWORD(m_Interval));
727 app->WriteProfileInt("Options","MaxThreads",m_MaxThreads);
728 app->WriteProfileInt("Options","PingSize",m_PingSize);
729 app->WriteProfileInt("Options","PingsPerHost",m_PingsPerHost);
730 app->WriteProfileInt("Options","SortBy",m_SortCriteria);
731 app->WriteProfileInt("Options","TimeOutHi",HIWORD(m_TimeOut));
732 app->WriteProfileInt("Options","TimeOutLo",LOWORD(m_TimeOut));
733 app->WriteProfileInt("Options","InnermostURL",m_bMSWorkAround);
734 app->WriteProfileInt("Options","AutoBest",m_bAutoBest);
735 app->WriteProfileInt("Options","SmartAdjust",m_bSmartAdjust);
736 app->WriteProfileInt("Options","AdjustInnermost",m_bAdjustInnermost);
737 app->WriteProfileInt("Options","IgnoreRelative",m_bIgnorelative);
738 app->WriteProfileString("Options","ImportExportPath",m_impexPath);
739CRect rc;
740 GetWindowRect(&rc);
741 app->WriteProfileInt("Windows","DlgTop",rc.top);
742 app->WriteProfileInt("Windows","DlgBottom",rc.bottom);
743 app->WriteProfileInt("Windows","DlgLeft",rc.left);
744 app->WriteProfileInt("Windows","DlgRight",rc.right);
745 m_DragPad->GetWindowRect(&rc);
746 app->WriteProfileInt("Windows","DragPadTop",rc.top);
747 app->WriteProfileInt("Windows","DragPadLeft",rc.left);
748 // Columns
749 app->WriteProfileInt("Columns","HostName",m_HostList.GetColumnWidth(0));
750 app->WriteProfileInt("Columns","HostIP",m_HostList.GetColumnWidth(1));
751 app->WriteProfileInt("Columns","MinRTT",m_HostList.GetColumnWidth(2));
752 app->WriteProfileInt("Columns","AvgRTT",m_HostList.GetColumnWidth(3));
753 app->WriteProfileInt("Columns","MaxRTT",m_HostList.GetColumnWidth(4));
754 app->WriteProfileInt("Columns","PktLoss",m_HostList.GetColumnWidth(5));
755 m_bExiting=TRUE;
756 CDialog::OnOK();
757}
758
759void CDipstickDlg::OnCancel()
760{
761}
762
763void CDipstickDlg::OnManualping()
764{
765CHostNameDlg hnd(this);
766 if(hnd.DoModal()==IDOK && !hnd.m_Host.IsEmpty()){
767 CString *host = new CString(hnd.m_Host);
768 ASSERT(host);
769 PostMessage(WM_DNP_URLPING,0,(LPARAM)host);
770 }
771}
772
773void CDipstickDlg::OnDragpadManualping()
774{
775 OnManualping();
776}
777
778void CDipstickDlg::OnDragpadRepingAll()
779{
780 OnRepingall();
781}
782void CDipstickDlg::OnDragpadRemoveAll()
783{
784 OnClear();
785}
786
787void CDipstickDlg::OnReping()
788{
789 if(!m_HostList.GetSelectedCount())
790 return;
791 intitems = m_HostList.GetItemCount();
792 for(int tmp=0;tmp<items;tmp++){
793 if(!(m_HostList.GetItemState(tmp,LVIS_SELECTED)&LVIS_SELECTED))
794 continue;
795 CPingyHost *host = (CPingyHost*) m_HostList.GetItemData(tmp);
796 ASSERT(host);
797 if(host->m_Pinged && !host->m_Pinging)
798 host->m_bToPing=TRUE;
799 }
800 UpdateDragpadTitle();
801 CheckForPendingRequests();
802}
803
804void CDipstickDlg::OnRepingall()
805{
806POSITION p = m_Hosts.GetHeadPosition();
807 while(p){
808 CPingyHost *host = m_Hosts.GetNext(p);
809 ASSERT(host);
810 if(host->m_Pinged && !host->m_Pinging)
811 host->m_bToPing=TRUE;
812 }
813 UpdateDragpadTitle();
814 CheckForPendingRequests();
815}
816
817void CDipstickDlg::OnClear()
818{
819 if(m_ActiveThreads)
820 return;
821 m_HostList.DeleteAllItems();
822 // *** Eventually move the following code to separate function
823POSITION p = m_Hosts.GetHeadPosition();
824 while(p){
825 POSITION pp = p;
826 CPingyHost *host = (CPingyHost*)m_Hosts.GetNext(p);
827 ASSERT(host);
828 m_Hosts.RemoveAt(pp);
829 host->Suicide();
830 }
831 ASSERT(m_Hosts.IsEmpty());
832 UpdateDragpadTitle();
833}
834
835void CDipstickDlg::OnInsertitemHostlist(NMHDR* pNMHDR, LRESULT* pResult)
836{
837NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
838 m_RepingCtl.EnableWindow(TRUE);
839 m_RepingAllCtl.EnableWindow(TRUE);
840 UpdateDragpadTitle();
841 *pResult = 0;
842}
843
844void CDipstickDlg::OnDeleteitemHostlist(NMHDR* pNMHDR, LRESULT* pResult)
845{
846NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
847 if(!m_HostList.GetItemCount()){
848 m_RepingCtl.EnableWindow(FALSE);
849 m_RepingAllCtl.EnableWindow(FALSE);
850 m_ClearListCtl.EnableWindow(FALSE);
851 }
852 UpdateDragpadTitle();
853 *pResult = 0;
854}
855
856void CDipstickDlg::OnDeleteallitemsHostlist(NMHDR* pNMHDR, LRESULT* pResult)
857{
858NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
859 m_RepingCtl.EnableWindow(FALSE);
860 m_RepingAllCtl.EnableWindow(FALSE);
861 m_ClearListCtl.EnableWindow(FALSE);
862 UpdateDragpadTitle();
863 *pResult = 0;
864}
865
866void CDipstickDlg::OnExit()
867{
868 OnOK();
869}
870
871void CDipstickDlg::OnItemchangedHostlist(NMHDR* pNMHDR, LRESULT* pResult)
872{
873NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
874 if(pNMListView->uChanged&LVIF_STATE && (pNMListView->uOldState&LVIS_SELECTED)!=(pNMListView->uNewState&LVIS_SELECTED))
875 UpdateControlButtons();
876 UpdateDragpadTitle();
877 *pResult = 0;
878}
879
880void CDipstickDlg::UpdateControlButtons()
881{
882int items = m_HostList.GetItemCount();
883 if(!items){
884 m_ClearListCtl.EnableWindow(FALSE);
885 m_RemoveCtl.EnableWindow(FALSE);
886 m_RepingAllCtl.EnableWindow(FALSE);
887 m_RepingCtl.EnableWindow(FALSE);
888 return;
889 }
890BOOL cl = m_ActiveThreads?FALSE:TRUE, rm = FALSE, ra = FALSE, rp = FALSE;
891 for(int tmp=0;tmp<items;tmp++){
892 CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(tmp);
893 if(!host->m_Pinging){
894 ra=TRUE;
895 if(m_HostList.GetItemState(tmp,LVIS_SELECTED)&LVIS_SELECTED){
896 rp = TRUE;
897 rm = TRUE;
898 break;
899 }
900 }
901 }
902 m_ClearListCtl.EnableWindow(cl);
903 m_RemoveCtl.EnableWindow(rm);
904 m_RepingAllCtl.EnableWindow(ra);
905 m_RepingCtl.EnableWindow(rp);
906}
907
908void CDipstickDlg::OnRemove()
909{
910 if(!m_HostList.GetSelectedCount())
911 return;
912 intitems = m_HostList.GetItemCount();
913 for(int tmp=0;tmp<items;tmp++){
914 if(!(m_HostList.GetItemState(tmp,LVIS_SELECTED)&LVIS_SELECTED))
915 continue;
916 CPingyHost *host = (CPingyHost*) m_HostList.GetItemData(tmp);
917 ASSERT(host);
918 if(!host->m_Pinging)
919 RemovePingyHost(host,tmp);
920 }
921}
922
923void CDipstickDlg::OnRclickHostlist(NMHDR* pNMHDR, LRESULT* pResult)
924{
925 if(!m_HostList.GetSelectedCount())
926 return;
927int items = m_HostList.GetItemCount();
928int item = -1;
929 for(int tmp=0;tmp<items;tmp++){
930 ints = m_HostList.GetItemState(tmp,LVIS_SELECTED|LVIS_FOCUSED);
931 if(s&LVIS_FOCUSED){
932 item = tmp;
933 break;
934 }
935 if(s&LVIS_SELECTED)
936 item=tmp;
937 }
938 ASSERT(item>=0);
939CPoint p;
940 VERIFY(m_HostList.GetItemPosition(item,&p));
941CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(item);
942 ASSERT(host);
943 m_HostList.ClientToScreen(&p);
944CMenu menus;
945 VERIFY(menus.LoadMenu(IDR_MENU));
946CMenu *popUp = menus.GetSubMenu(1);
947 ASSERT(popUp);
948 UpdateControlButtons();
949 popUp->EnableMenuItem(ID_HOSTLIST_REPING,MF_BYCOMMAND|(m_RepingCtl.IsWindowEnabled()?MF_ENABLED:MF_GRAYED));
950 popUp->EnableMenuItem(ID_HOSTLIST_REMOVE,MF_BYCOMMAND|(m_RemoveCtl.IsWindowEnabled()?MF_ENABLED:MF_GRAYED));
951 popUp->EnableMenuItem(ID_HOSTLIST_REMOVEALL,MF_BYCOMMAND|(m_ClearListCtl.IsWindowEnabled()?MF_ENABLED:MF_GRAYED));
952 popUp->EnableMenuItem(ID_HOSTLIST_REPINGALL,MF_BYCOMMAND|(m_RepingAllCtl.IsWindowEnabled()?MF_ENABLED:MF_GRAYED));
953 popUp->EnableMenuItem(ID_HOSTLIST_OPENURL,MF_BYCOMMAND|((m_HostList.GetSelectedCount()==1 && !host->m_URL.IsEmpty())?MF_ENABLED:MF_GRAYED));
954 popUp->EnableMenuItem(ID_HOSTLIST_COPYURL,MF_BYCOMMAND|((m_HostList.GetSelectedCount()==1 && !host->m_URL.IsEmpty())?MF_ENABLED:MF_GRAYED));
955 popUp->EnableMenuItem(ID_HOSTLIST_PROPERTIES,MF_BYCOMMAND|((m_HostList.GetSelectedCount()==1)?MF_ENABLED:MF_GRAYED));
956 popUp->EnableMenuItem(ID_HOSTLIST_PASTEURL,MF_BYCOMMAND|(IsPasteableClipboard()?MF_ENABLED:MF_GRAYED));
957 popUp->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_LEFTBUTTON,p.x,p.y,this);
958 *pResult = 0;
959}
960
961void CDipstickDlg::OnHostListReping()
962{
963 OnReping();
964}
965void CDipstickDlg::OnHostListRemove()
966{
967 OnRemove();
968}
969void CDipstickDlg::OnHostListRepingAll()
970{
971 OnRepingall();
972}
973void CDipstickDlg::OnHostListRemoveAll()
974{
975 OnClear();
976}
977void CDipstickDlg::OnHostListOpenURL()
978{
979 if(m_HostList.GetSelectedCount()!=1)
980 return;
981int items = m_HostList.GetItemCount();
982 for(int tmp=0;tmp<items;tmp++){
983 if((m_HostList.GetItemState(tmp,LVIS_SELECTED|LVIS_FOCUSED))&LVIS_SELECTED)
984 break;
985 }
986 ASSERT(tmp<items);
987CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(tmp);
988 ASSERT(host);
989 if(!host->m_URL.IsEmpty())
990 ShellExecute(::GetDesktopWindow(),NULL,host->m_URL,NULL,NULL,SW_SHOWMAXIMIZED);
991}
992
993void CDipstickDlg::OnHostListProperties()
994{
995 if(m_HostList.GetSelectedCount()!=1)
996 return;
997int items = m_HostList.GetItemCount();
998 for(int tmp=0;tmp<items;tmp++){
999 if((m_HostList.GetItemState(tmp,LVIS_SELECTED|LVIS_FOCUSED))&LVIS_SELECTED)
1000 break;
1001 }
1002 ASSERT(tmp<items);
1003CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(tmp);
1004 ASSERT(host);
1005CHostProperties hp(this);
1006 hp.SetHost(host);
1007 hp.DoModal();
1008}
1009
1010void CDipstickDlg::OnDblclkHostlist(NMHDR* pNMHDR, LRESULT* pResult)
1011{
1012 OnHostListOpenURL();
1013 *pResult = 0;
1014}
1015
1016void CDipstickDlg::OnClose()
1017{
1018 m_bShown=FALSE;
1019 ShowWindow(SW_HIDE);
1020}
1021
1022BOOL CAboutDlg::OnInitDialog()
1023{
1024 CDialog::OnInitDialog();
1025 return TRUE;
1026}
1027
1028void CDipstickDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
1029{
1030 CDialog::OnGetMinMaxInfo(lpMMI);
1031 if(m_MinSize.cx>0 && m_MinSize.cy>0){
1032 lpMMI->ptMinTrackSize.x = m_MinSize.cx;
1033 lpMMI->ptMinTrackSize.y = m_MinSize.cy;
1034 }
1035}
1036
1037void CDipstickDlg::OnSize(UINT nType, int cx, int cy)
1038{
1039 CDialog::OnSize(nType, cx, cy);
1040 if(nType==SIZE_RESTORED)
1041 RecalcLayout(cx,cy);
1042}
1043
1044void CDipstickDlg::RecalcLayout(int,int)
1045{
1046CRect wrc;
1047 GetClientRect(&wrc);
1048CRect brc;
1049 m_ManualPingCtl.GetWindowRect(&brc);
1050 m_HostList.SetWindowPos(NULL,m_OverX,m_OverY,wrc.Width()-m_OverX*3-brc.Width(),wrc.Height()-m_OverY*2,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER);
1051int xb = wrc.Width()-m_OverX-brc.Width();
1052int cyb = brc.Height()+m_GapY;
1053 m_ManualPingCtl.SetWindowPos(NULL,xb,m_OverY,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1054 m_RepingCtl.SetWindowPos(NULL,xb,m_OverY+cyb,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1055 m_RepingAllCtl.SetWindowPos(NULL,xb,m_OverY+cyb*2,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1056 m_RemoveCtl.SetWindowPos(NULL,xb,m_OverY+cyb*3,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1057 m_ClearListCtl.SetWindowPos(NULL,xb,m_OverY+cyb*4,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1058 m_AdvancedCtl.SetWindowPos(NULL,xb,m_OverY+cyb*5,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1059 m_ExitCtl.SetWindowPos(NULL,xb,wrc.Height()-m_OverY-brc.Height(),0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1060 m_OptionsCtl.SetWindowPos(NULL,xb,wrc.Height()-m_OverY-cyb-brc.Height(),0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1061 m_HelpCtl.SetWindowPos(NULL,xb,wrc.Height()-m_OverY-cyb*2-brc.Height(),0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
1062}
1063
1064void CDipstickDlg::OnHelp()
1065{
1066 WinHelp(0,HELP_FINDER);
1067}
1068
1069void CDipstickDlg::UpdateDragpadTitle()
1070{
1071int ic = m_HostList.GetItemCount();
1072CString title;
1073 if(!ic){
1074 VERIFY(title.LoadString(IDS_DRAGPAD_TITLE));
1075 }else{
1076 int ip = 0;
1077 POSITION p = m_Hosts.GetHeadPosition();
1078 while(p){
1079 CPingyHost *host = m_Hosts.GetNext(p);
1080 ASSERT(host);
1081 if(!(host->m_Pinging || host->m_bToPing))
1082 ip++;
1083 }
1084 title.Format(IDS_DRAGPAD_URLS,ip,ic);
1085 }
1086 if(m_DragPad)
1087 m_DragPad->SetWindowText(title);
1088}
1089
1090void CDipstickDlg::OnBegindragHostlist(NMHDR* pNMHDR, LRESULT* pResult)
1091{
1092 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
1093
1094 if(pNMListView->iItem>=0){
1095 CPingyHost *host = (CPingyHost*) m_HostList.GetItemData(pNMListView->iItem);
1096 ASSERT(host);
1097 if(!host->m_URL.IsEmpty()){
1098 CURLSource us(host->m_URL);
1099 us.DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_LINK);
1100 }
1101 }
1102
1103 *pResult = 0;
1104}
1105
1106void CDipstickDlg::OnPasteurl()
1107{
1108COleDataObject odo;
1109 if(!odo.AttachClipboard())
1110 return;
1111 CollectURLs(&odo,FALSE);
1112}
1113
1114BOOL CDipstickDlg::IsPasteableClipboard()
1115{
1116COleDataObject odo;
1117 if(!odo.AttachClipboard())
1118 return FALSE;
1119 if(CollectURLs(&odo,TRUE))
1120 return TRUE;
1121 return FALSE;
1122}
1123
1124BOOL CDipstickDlg::CollectURLs(COleDataObject* pDO,BOOL bTestOnly)
1125{
1126 UINTcfURL = RegisterClipboardFormat("UniformResourceLocator");
1127 UINTcfHTML = RegisterClipboardFormat("HTML Format");
1128 UINTcfNIF = RegisterClipboardFormat("Netscape Image Format");
1129 if(pDO->IsDataAvailable(cfURL)){
1130 if(!bTestOnly){
1131 HGLOBAL hg = pDO->GetGlobalData(cfURL);
1132 ASSERT(hg);
1133 LPVOID lpv = GlobalLock(hg);
1134 ASSERT(lpv);
1135 PostMessage(WM_DNP_URLPING,0,(LPARAM)new CString((LPCTSTR)lpv));
1136 GlobalUnlock(hg);
1137 GlobalFree(hg);
1138 }
1139 return TRUE;
1140 }
1141 if(pDO->IsDataAvailable(cfHTML)){
1142 HGLOBAL hg = pDO->GetGlobalData(cfHTML);
1143 ASSERT(hg);
1144 LPCTSTR lps = (LPCTSTR)GlobalLock(hg);
1145 ASSERT(lps);
1146 BOOL rv = FALSE;
1147 do{
1148 static LPCTSTR v10 = "Version:1.0\r\n";
1149 if(memcmp(v10,lps,strlen(v10)))
1150 break;
1151 static LPCTSTR strStartSelection = "StartSelection:";
1152 static LPCTSTR strEndSelection = "EndSelection:";
1153 static LPCTSTR strSourceURL = "SourceURL:";
1154 LPTSTR subs = strstr(lps,strStartSelection);
1155 if(!subs)
1156 break;
1157 LONG startSelection = atol(&subs[strlen(strStartSelection)]);
1158 if(!startSelection)
1159 break;
1160 if(!(subs=strstr(lps,strEndSelection)))
1161 break;
1162 LONG endSelection = atol(&subs[strlen(strEndSelection)]);
1163 if(!endSelection)
1164 break;
1165 if(!(subs=strstr(lps,strSourceURL)))
1166 break;
1167 subs = &subs[strlen(strSourceURL)];
1168 LPTSTR eol = strchr(subs,'\r');
1169 if(!eol)
1170 break;
1171 (*eol)=0;
1172 CString sourceURL = subs;
1173 if(!sourceURL.GetLength())
1174 break;
1175 TRACE0("SourceURL = "+sourceURL+"\n");
1176 _xferHTML* xf = new _xferHTML;
1177 VERIFY(xf->src.Crack(sourceURL));
1178 LPTSTR htmlBuff = xf->html.GetBuffer(endSelection-startSelection+2);
1179 ASSERT(htmlBuff);
1180 memmove(htmlBuff,&lps[startSelection],endSelection-startSelection+1);
1181 htmlBuff[endSelection-startSelection+1]=0;
1182 xf->html.ReleaseBuffer();
1183 if(bTestOnly){
1184 rv = m_reHTMLURL.Match(xf->html);
1185 delete xf;
1186 }else{
1187 PostMessage(WM_DNP_HTML,0,(LPARAM)xf);
1188 }
1189 }while(FALSE);
1190 GlobalUnlock(hg);
1191 GlobalFree(hg);
1192 return rv;
1193 }
1194 if(pDO->IsDataAvailable(cfNIF)){
1195 if(!bTestOnly){
1196 HGLOBAL hg = pDO->GetGlobalData(cfNIF);
1197 ASSERT(hg);
1198 LPVOID lpv = GlobalLock(hg);
1199 ASSERT(lpv);
1200 struct _nif{
1201 BYTE data[0x20];
1202 DWORD m_offDescr;
1203 DWORD m_offURL;
1204 DWORD m_offToImage;
1205 } *nif = (_nif*)lpv;
1206 PostMessage(WM_DNP_URLPING,0,(LPARAM)new CString((LPCTSTR)&nif->data[nif->m_offURL]));
1207 GlobalUnlock(hg);
1208 GlobalFree(hg);
1209 }
1210 return TRUE;
1211 }
1212 if(pDO->IsDataAvailable(CF_TEXT)){
1213 if(!bTestOnly){
1214 HGLOBAL hg = pDO->GetGlobalData(CF_TEXT);
1215 ASSERT(hg);
1216 LPVOID lpv = GlobalLock(hg);
1217 ASSERT(lpv);
1218 PostMessage(WM_DNP_URLPING,0,(LPARAM)new CString((LPCTSTR)lpv));
1219 GlobalUnlock(hg);
1220 GlobalFree(hg);
1221 }
1222 return TRUE;
1223 }
1224 return FALSE;
1225}
1226
1227LRESULT CDipstickDlg::OnHTMLTransfer(WPARAM wP, LPARAM lP)
1228{
1229_xferHTML* xf = (_xferHTML*)lP;
1230CSelectURLsDlg su;
1231 su.m_bAdjust = m_bSmartAdjust;
1232 su.m_bAdjustInnermost = m_bAdjustInnermost;
1233 BeginWaitCursor();
1234 while(m_reHTMLURL.Match(xf->html)){
1235 CString url = m_reHTMLURL.GetMatch(1);
1236 xf->html = m_reHTMLURL.GetMatch(CRegEx::matchPostMatch);
1237 if(CCrackURL::GetHostName(url)==url){
1238 if(m_bIgnorelative)
1239 continue;
1240 CCrackURL cracked;
1241 VERIFY(cracked.Crack(url));
1242 cracked.Adjust(xf->src);
1243 url = cracked.Build();
1244 }
1245 if(!su.m_URLs.Find(url))
1246 VERIFY(su.m_URLs.AddTail(url));
1247 }
1248 EndWaitCursor();
1249 delete xf;
1250 if(su.DoModal()==IDOK){
1251 POSITION p = su.m_URLs.GetHeadPosition();
1252 while(p){
1253 CString url = su.m_URLs.GetNext(p);
1254 PostMessage(WM_DNP_URLPING,0,(LPARAM)new CString(url));
1255 }
1256 }
1257 return 0;
1258}
1259
1260UINT CPingyHost::PingProc(LPVOID pParam)
1261{
1262CPingyHost* pThis = (CPingyHost*)pParam;
1263 ASSERT(pThis->m_Daddy);
1264 return pThis->DoPing();
1265}
1266
1267UINT CPingyHost::DoPing()
1268{
1269CSingleLock slock(&m_mutex);
1270 if(!slock.Lock(2000)){
1271 m_Status.LoadString(IDS_PS_FAILEDTOLOCK);
1272 return 1;
1273 }
1274 m_Pinging = TRUE;
1275 m_bToPing = FALSE;
1276 VERIFY(m_Daddy->m_eveStartup.SetEvent());
1277 m_Daddy->PostMessage(WM_DNP_UPDATEHOSTDATA,0,(LPARAM)this);
1278in_addr ip;
1279UINT packets, lost;
1280 packets=lost=0;
1281CICMP* pICMP = NULL;
1282UINT dataSize = m_Daddy->m_PingSize;
1283 intploss = 100;
1284 do{
1285 if(m_HostName.IsEmpty()){
1286 ip.s_addr = m_IP;
1287 hostent *he = gethostbyaddr((char*)&ip,4,PF_INET);
1288 if(!he)
1289 m_HostName.Empty();
1290 else
1291 m_HostName = he->h_name;
1292 }else{
1293 hostent *he = gethostbyname(m_HostName);
1294 if(!he){
1295 m_Status.LoadString(IDS_PS_FAILEDTORESOLVE);
1296 m_IP = 0;
1297 break;
1298 }
1299 memmove(&ip.s_addr,he->h_addr,sizeof(ip.s_addr));
1300 m_IP = ip.s_addr;
1301 }
1302 pICMP = CICMP::CreateICMP();
1303 if(!(pICMP && pICMP->Initialize())){
1304 m_Status.LoadString(IDS_PS_UNABLETOICMP);
1305 break;
1306 }
1307 m_Daddy->PostMessage(WM_DNP_UPDATEHOSTDATA,0,(LPARAM)this);
1308 ULONG sum, num, pmin, pmax;
1309 sum = num = 0;
1310 pmin = 0xFFFFFFFF;
1311 pmax = 0;
1312 UINT seq;
1313 for(seq = 0;seq<m_Daddy->m_PingsPerHost;seq++){
1314 INT status;
1315 LONG rtt = pICMP->Ping(ip,dataSize,m_Daddy->m_TimeOut,&status);
1316 UINT stString = 0;
1317 switch(status){
1318 case CICMP::ipSuccess:
1319 sum+=rtt; num++;
1320 if(rtt<pmin)
1321 pmin=rtt;
1322 if(rtt>pmax)
1323 pmax=rtt;
1324 break;
1325 case CICMP::ipBuffTooSmall: stString = IDS_PS_INTERNALERROR;
1326 break;
1327 case CICMP::ipDestNetUnreachable: stString = IDS_PS_NETUNREACHABLE;
1328 break;
1329 case CICMP::ipDestHostUnreachable: stString = IDS_PS_HOSTUNREACHABLE;
1330 break;
1331 case CICMP::ipDestProtUnreachable: stString = IDS_PS_PROTUNREACHABLE;
1332 break;
1333 case CICMP::ipDestPortUnreachable: stString = IDS_PS_PORTUNREACHABLE;
1334 break;
1335 case CICMP::ipNoResources: stString = IDS_PS_NORESOURCES;
1336 break;
1337 case CICMP::ipBadOption: stString = IDS_PS_INTERNALERROR;
1338 break;
1339 case CICMP::ipHWError: stString = IDS_PS_HWERROR;
1340 break;
1341 case CICMP::ipPacketTooBig: stString = IDS_PS_BIGPACKET;
1342 break;
1343 case CICMP::ipTimeOut: stString = IDS_PS_TIMEOUT;
1344 break;
1345 case CICMP::ipBadRequest: stString = IDS_PS_INTERNALERROR;
1346 break;
1347 case CICMP::ipBadRoute: stString = IDS_PS_BADROUTE;
1348 break;
1349 case CICMP::ipTTLExpiredInTransit: stString = IDS_PS_TTLEXPTRANSIT;
1350 break;
1351 case CICMP::ipTTLExpiredInReasm: stString = IDS_PS_TTLEXPREASM;
1352 break;
1353 case CICMP::ipParamProblem: stString = IDS_PS_IPARAMP;
1354 break;
1355 case CICMP::ipSourceQuench: stString = IDS_PS_SOURCEQUENCH;
1356 break;
1357 case CICMP::ipOptionTooBig: stString = IDS_PS_BIGOPTION;
1358 break;
1359 case CICMP::ipBadDest: stString = IDS_PS_BADDEST;
1360 break;
1361 default:
1362 stString = IDS_PS_UNKNOWNERROR;
1363 break;
1364 }
1365 if(stString)
1366 m_Status.LoadString(stString);
1367 packets++;
1368 if(rtt<0)
1369 lost++;
1370 Sleep(m_Daddy->m_Interval);
1371 }
1372 if(packets==lost || !packets){
1373 ploss=100;
1374 }else{
1375 ploss = lost*100/packets;
1376 m_MinRTT = pmin;
1377 m_MaxRTT = pmax;
1378 if(sum){
1379 ASSERT(num);
1380 m_AvgRTT = sum/num;
1381 }else{
1382 m_AvgRTT = 0;
1383 }
1384 }
1385 }while(FALSE);
1386 m_Packetloss=ploss;
1387 m_Pinged=TRUE;
1388 m_Pinging=FALSE;
1389 if(pICMP){
1390 pICMP->Deinitialize();
1391 delete pICMP;
1392 }
1393 m_Daddy->PostMessage(WM_DNP_UPDATEHOSTDATA,0,(LPARAM)this);
1394 m_Daddy->PostMessage(WM_DNP_ACTIVITYCOUNT,(WPARAM)-1);
1395 return 0;
1396}
1397
1398void CPingyHost::Ping()
1399{
1400 ASSERT(m_Daddy);
1401 m_Daddy->m_eveStartup.ResetEvent();
1402 if(!AfxBeginThread(CPingyHost::PingProc,this)){
1403 ASSERT(FALSE);
1404 }else{
1405 CSingleLock sl(&m_Daddy->m_eveStartup);
1406 sl.Lock();
1407 m_Daddy->SendMessage(WM_DNP_ACTIVITYCOUNT,(WPARAM)1);// *** AWFUL! Shouldn't be here!
1408 }
1409}
1410
1411void CDipstickDlg::OnHostlistCopyurl()
1412{
1413 if(m_HostList.GetSelectedCount()!=1)
1414 return;
1415int items = m_HostList.GetItemCount();
1416 for(int tmp=0;tmp<items;tmp++){
1417 if((m_HostList.GetItemState(tmp,LVIS_SELECTED|LVIS_FOCUSED))&LVIS_SELECTED)
1418 break;
1419 }
1420 ASSERT(tmp<items);
1421CPingyHost *host = (CPingyHost*)m_HostList.GetItemData(tmp);
1422 ASSERT(host);
1423 if(!host->m_URL.IsEmpty()){
1424 CURLSource *us = new CURLSource(host->m_URL);
1425 us->SetClipboard();
1426 us->FlushClipboard();
1427 }
1428}
1429
1430BOOL CDipstickDlg::OnHelpInfo(HELPINFO* pHelpInfo)
1431{
1432 WinHelp(IDD|0x20000l);
1433 return TRUE;
1434}
1435
1436void CDipstickDlg::OnDropFiles(HDROP hDropInfo)
1437{
1438 // *** Import only 1st file, but maybe we should fall into prompt mode if multiple files are dropped.
1439CString fileName;
1440int bufferSize = DragQueryFile(hDropInfo,0,NULL,0);
1441 DragQueryFile(hDropInfo,0,fileName.GetBuffer(bufferSize+2),bufferSize+1);
1442 fileName.ReleaseBuffer();
1443 if(fileName.IsEmpty())
1444 CDialog::OnDropFiles(hDropInfo);
1445 else
1446 ImportLocations(fileName);
1447}
1448
1449BOOL CDipstickDlg::ImportLocations(LPCTSTR file)
1450{
1451CString fileLine;
1452CString q;
1453 try{
1454 CStdioFile f(file,CFile::modeRead|CFile::typeText|CFile::shareDenyWrite);
1455 // *** Cleanup locations..
1456 while(f.ReadString(fileLine)){
1457 if(fileLine.IsEmpty())
1458 continue;
1459 if(fileLine[0]=='\"' || fileLine[0]=='\''){
1460 TCHAR q = fileLine[0];
1461 fileLine=fileLine.Mid(1);
1462 for(int tmp=0;tmp<fileLine.GetLength();tmp++){
1463 if(fileLine[tmp]!=q)
1464 continue;
1465 if(!tmp){
1466 fileLine.Empty();
1467 break;
1468 }
1469 fileLine=fileLine.Left(tmp);
1470 break;
1471 }
1472 }else{
1473 int co = fileLine.Find(',');
1474 if(co>=0)
1475 fileLine=fileLine.Left(co);
1476 }
1477 if(fileLine.IsEmpty())
1478 continue;
1479 if(!fileLine.CompareNoCase("url"))
1480 continue;
1481 PostMessage(WM_DNP_URLPING,0,(LPARAM)new CString(fileLine));
1482 }
1483 }catch(CException* e){
1484 e->Delete();
1485 TRACE0("Failed to import URLList file\n");
1486 return FALSE;
1487 }
1488 return TRUE;
1489}
1490
1491void CDipstickDlg::OnAdvanced()
1492{
1493CRect rc;
1494 m_AdvancedCtl.GetClientRect(rc);
1495 m_AdvancedCtl.ClientToScreen(rc);
1496CMenu menus;
1497 VERIFY(menus.LoadMenu(IDR_MENU));
1498CMenu *popUp = menus.GetSubMenu(2);
1499 ASSERT(popUp);
1500 popUp->EnableMenuItem(ID_ADVANCED_EXPORTLIST,MF_BYCOMMAND|(m_HostList.GetItemCount()?MF_ENABLED:MF_GRAYED));
1501 popUp->TrackPopupMenu(TPM_CENTERALIGN|TPM_RIGHTBUTTON|TPM_LEFTBUTTON,(rc.left+rc.right)/2,rc.top,this);
1502}
1503
1504void CDipstickDlg::OnAdvancedExportlist()
1505{
1506CString filter;
1507 filter.LoadString(IDS_CSVFILTER);
1508CFileDialog cfd(FALSE,".csv",NULL,OFN_EXPLORER|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,filter,this);
1509 if(!m_impexPath.IsEmpty())
1510 SetCurrentDirectory(m_impexPath);
1511 if(cfd.DoModal()==IDOK){
1512 GetCurrentDirectory(2048,m_impexPath.GetBuffer(2048));
1513 m_impexPath.ReleaseBuffer();
1514 ExportLocations(cfd.GetPathName());
1515 }
1516}
1517
1518void CDipstickDlg::OnAdvancedImportlist()
1519{
1520CString filter;
1521 filter.LoadString(IDS_CSVFILTER);
1522CFileDialog cfd(TRUE,".csv",NULL,OFN_EXPLORER|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST,filter,this);
1523 if(!m_impexPath.IsEmpty())
1524 SetCurrentDirectory(m_impexPath);
1525 if(cfd.DoModal()==IDOK){
1526 GetCurrentDirectory(2048,m_impexPath.GetBuffer(2048));
1527 m_impexPath.ReleaseBuffer();
1528 ImportLocations(cfd.GetPathName());
1529 }
1530}
1531
1532BOOL CDipstickDlg::ExportLocations(LPCTSTR file)
1533{
1534 try{
1535 CStdioFile f(file,CFile::modeCreate|CFile::modeWrite|CFile::typeText);
1536 f.WriteString("URL,Host Name,IP Address, Min RTT,Avg RTT,Max RTT,Pktloss\n");
1537 POSITION p = m_Hosts.GetHeadPosition();
1538 while(p){
1539 CPingyHost *host = m_Hosts.GetNext(p);
1540 ASSERT(host);
1541 CString ph;
1542 ph.Format("\"%s\",%s,%s,%lu,%lu,%lu,%d%%\n",host->m_URL,host->m_HostName,inet_ntoa(*(in_addr*)&host->m_IP),
1543 host->m_MinRTT,host->m_AvgRTT,host->m_MaxRTT,host->m_Packetloss
1544 );
1545 f.WriteString(ph);
1546 }
1547 f.Close();
1548 }catch(CException* e){
1549 TRACE0("Failed to export URLList\n");
1550 e->Delete();
1551 return FALSE;
1552 }
1553 return TRUE;
1554}
1555
1556void CDipstickDlg::OnDragpadAdvancedExportlist()
1557{
1558 OnAdvancedExportlist();
1559}
1560
1561void CDipstickDlg::OnDragpadAdvancedImportlist()
1562{
1563 OnAdvancedImportlist();
1564}
1565
1566void CPingyHost::Suicide()
1567{
1568CSingleLock sl(&m_mutex);
1569 if(sl.Lock(10)){
1570 sl.Unlock();
1571 delete this;
1572 }else{
1573 if(!AfxBeginThread(CPingyHost::SuicideProc,this))
1574 ASSERT(FALSE);
1575 }
1576}
1577
1578UINT CPingyHost::SuicideProc(LPVOID pParam)
1579{
1580CPingyHost* pThis = (CPingyHost*)pParam;
1581CSingleLock sl(&pThis->m_mutex);
1582 sl.Lock();
1583 VERIFY(sl.Unlock());
1584 delete pThis;
1585 return 0;
1586}