OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [tools/] [configtool/] [standalone/] [wxwin/] [ecutils.cpp] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
// ####ECOSHOSTGPLCOPYRIGHTBEGIN####                                        
2
// -------------------------------------------                              
3
// This file is part of the eCos host tools.                                
4
// Copyright (C) 1998, 1999, 2000, 2003, 2008 Free Software Foundation, Inc.
5
//
6
// This program is free software; you can redistribute it and/or modify     
7
// it under the terms of the GNU General Public License as published by     
8
// the Free Software Foundation; either version 2 or (at your option) any   
9
// later version.                                                           
10
//
11
// This program is distributed in the hope that it will be useful, but      
12
// WITHOUT ANY WARRANTY; without even the implied warranty of               
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        
14
// General Public License for more details.                                 
15
//
16
// You should have received a copy of the GNU General Public License        
17
// along with this program; if not, write to the                            
18
// Free Software Foundation, Inc., 51 Franklin Street,                      
19
// Fifth Floor, Boston, MA  02110-1301, USA.                                
20
// -------------------------------------------                              
21
// ####ECOSHOSTGPLCOPYRIGHTEND####                                          
22
//
23
//===========================================================================
24
//===========================================================================
25
//#####DESCRIPTIONBEGIN####
26
//
27
// Author(s):   sdf, jld
28
// Contact(s):  sdf
29
// Date:                1998/08/11
30
// Version:             0.01
31
// Purpose:     
32
// Description: This is a collection of utility functions.
33
//              Modified by julians for wxWindows (originally CTUtils.h)
34
// Requires:    
35
// Provides:    
36
// See also:    
37
// Known bugs:  
38
// Usage:       
39
//
40
//####DESCRIPTIONEND####
41
//
42
//===========================================================================
43
 
44
#ifdef __GNUG__
45
#pragma implementation "ecutils.h"
46
#endif
47
 
48
// Includes other headers for precompiled compilation
49
#include "ecpch.h"
50
 
51
#ifdef __BORLANDC__
52
#pragma hdrstop
53
#endif
54
 
55
#include "ecutils.h"
56
#include "wx/listctrl.h"
57
#include "wx/stream.h"
58
 
59
#include <float.h> // for DBL_DIG macro
60
#include <sys/types.h>
61
#include <sys/stat.h>
62
 
63
#ifndef __WXMSW__
64
#include <errno.h>
65
#endif
66
 
67
#ifdef __WXMSW__
68
#include <tlhelp32.h>
69
#endif
70
 
71
#ifdef __CYGWIN__
72
#include <sys/cygwin.h> /* for cygwin_conv_to_*_path() */
73
#endif
74
 
75
#if 0
76
 
77
#define INCLUDEFILE <string>
78
#include "IncludeSTL.h"
79
 
80
#endif
81
 
82
// Chop str into pieces, using cSep as separator.
83
// " and \ have usual semantics
84
// Return value is array of pieces found.
85
 
86
int ecUtils::Chop(const wxString& psz, wxArrayString &ar, wxChar cSep,
87
                  bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/)
88
 
89
{
90
    if(wxT(' ') == cSep)
91
    {
92
        return Chop(psz, ar, wxT("\t\n\v\f\r "), bObserveStrings, bBackslashQuotes);
93
    } else {
94
        wxASSERT(wxT('\0')!=cSep);
95
        wxChar c[2]={cSep,wxT('\0')};
96
        return Chop(psz,ar,wxString(c),bObserveStrings,bBackslashQuotes);
97
    }
98
}
99
 
100
int ecUtils::Chop(const wxString& str, wxArrayString &ar, const wxString& sep,
101
                  bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/)
102
{
103
    ar.Clear();
104
 
105
    const wxChar* pszSep = (const wxChar*) sep;
106
    const wxChar* psz = (const wxChar*) str;
107
 
108
    int i=0;
109
    for(;;){
110
        // Skip multiple separators
111
        while(*psz && wxStrchr(pszSep,*psz)){
112
            psz++;
113
        }
114
        if(!*psz){
115
            return i;
116
        }
117
        wxString strTok;
118
        if(bObserveStrings){
119
            bool bInString=FALSE;
120
            do{
121
                if(*psz == wxT('\\') && bBackslashQuotes && psz[1]){
122
                    strTok += psz[1];
123
                    psz++;
124
                } else if(*psz == wxT('"')){
125
                    bInString ^= 1;
126
                } else if (!bInString && *psz && NULL != wxStrchr(pszSep,*psz)) {
127
                    break;
128
                } else {
129
                    strTok+=*psz;
130
                }
131
            } while (*++psz);
132
        } else {
133
            const wxChar* pszStart=psz;
134
            do {
135
                psz++;
136
            } while (*psz && ! wxStrchr(pszSep,*psz));
137
            strTok=wxString(pszStart,psz-pszStart);
138
        }
139
        ar.Add(strTok);
140
        i++;
141
    }
142
    return ar.GetCount();
143
}
144
 
145
#if 0
146
 
147
// vararg-style message box formatter
148
int ecUtils::MessageBoxF (LPCTSTR pszFormat, ...)
149
{
150
  int rc;
151
  va_list args;
152
  va_start(args, pszFormat);
153
  rc=ecUtils::vMessageBox(MB_OK, pszFormat,args);
154
  va_end(args);
155
  return rc;
156
}
157
 
158
// As above, but with type as first parameter.
159
int ecUtils::MessageBoxFT (UINT nType, LPCTSTR pszFormat, ...)
160
{
161
  int rc;
162
  va_list args;
163
  va_start(args, pszFormat);
164
  rc=ecUtils::vMessageBox(nType, pszFormat,args);
165
  va_end(args);
166
  return rc;
167
}
168
 
169
int ecUtils::vMessageBox(UINT nType, LPCTSTR  pszFormat, va_list marker)
170
{
171
  int rc=0;
172
  for(int nLength=100;nLength;) {
173
    TCHAR *buf=new TCHAR[1+nLength];
174
    int n=_vsntprintf(buf, nLength, pszFormat, marker );
175
    if(-1==n){
176
      nLength*=2;  // NT behavior
177
    } else if (n<nLength){
178
      rc=AfxMessageBox(buf,nType);
179
      nLength=0;   // trigger exit from loop
180
    } else {
181
      nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
182
    }
183
    delete [] buf;
184
  }
185
  return rc;
186
}
187
 
188
#endif
189
 
190
bool ecUtils::StrToItemIntegerType(const wxString & str, long &d)
191
{
192
        wxChar* pEnd;
193
        bool rc;
194
        errno=0;
195
        bool bHex=(str.Len() > 2 && str[0]==wxT('0') && (str[1]==wxT('x')||str[1]==wxT('X')));
196
        //d=_tcstol(str,&pEnd,bHex?16:10);
197
        d=wxStrtol(str,&pEnd,bHex?16:10);
198
        rc=(0==errno && (*pEnd==wxT('\0')));
199
        return rc;
200
}
201
 
202
const wxString ecUtils::IntToStr(long d,bool bHex)
203
{
204
  wxString s;
205
  s.Printf(bHex?wxT("0x%08x"):wxT("%d"),d);
206
  return s;
207
}
208
 
209
const wxString ecUtils::DoubleToStr (double dValue)
210
{
211
  wxString s;
212
  s.Printf(wxT("%.*e"), DBL_DIG, dValue);
213
  return s;
214
}
215
 
216
bool ecUtils::StrToDouble (const wxString & strValue, double &dValue)
217
{
218
        wxChar* pEnd;
219
        errno = 0;
220
        //dValue = _tcstod (strValue, &pEnd);
221
        dValue = wxStrtod(strValue, &pEnd);
222
        return (0 == errno) && (*pEnd == wxT('\0'));
223
}
224
 
225
#if 0
226
const wxString ecUtils::Explanation(CFileException & exc)
227
{
228
        wxString strMsg;
229
        switch(exc.m_cause){
230
                case CFileException::none: strMsg=wxT("No error occurred.");break;
231
                case CFileException::generic: strMsg=wxT("   An unspecified error occurred.");break;
232
                case CFileException::fileNotFound: strMsg=wxT("   The file could not be located.");break;
233
                case CFileException::badPath: strMsg=wxT("   All or part of the path is invalid.");break;
234
                case CFileException::tooManyOpenFiles: strMsg=wxT("   The permitted number of open files was exceeded.");break;
235
                case CFileException::accessDenied: strMsg=wxT("   The file could not be accessed.");break;
236
                case CFileException::invalidFile: strMsg=wxT("   There was an attempt to use an invalid file handle.");break;
237
                case CFileException::removeCurrentDir: strMsg=wxT("   The current working directory cannot be removed.");break;
238
                case CFileException::directoryFull: strMsg=wxT("   There are no more directory entries.");break;
239
                case CFileException::badSeek: strMsg=wxT("   There was an error trying to set the file pointer.");break;
240
                case CFileException::hardIO: strMsg=wxT("   There was a hardware error.");break;
241
                case CFileException::sharingViolation: strMsg=wxT("   SHARE.EXE was not loaded, or a shared region was locked.");break;
242
                case CFileException::lockViolation: strMsg=wxT("   There was an attempt to lock a region that was already locked.");break;
243
                case CFileException::diskFull: strMsg=wxT("   The disk is full.");break;
244
                case CFileException::endOfFile: strMsg=wxT("   The end of file was reached. ");break;
245
                default:
246
                        strMsg=wxT(" Unknown cause");
247
                        break;
248
        }
249
        return strMsg;
250
}
251
 
252
 
253
const wxString ecUtils::LoadString(UINT id)
254
{
255
        wxString str;
256
        str.LoadString(id);
257
        return str;
258
}
259
#endif
260
 
261
const wxString ecUtils::NativeToPosixPath(const wxString & native)
262
{
263
#ifdef __CYGWIN__
264
    if (native.IsEmpty())
265
        return native;
266
    else
267
    {
268
        wxString posix;
269
        cygwin_conv_to_posix_path(native.c_str(), posix.GetWriteBuf(PATH_MAX + 1));
270
        posix.UngetWriteBuf();
271
        return posix;
272
    }
273
#else
274
    return native;
275
#endif
276
}
277
 
278
const wxString ecUtils::PosixToNativePath(const wxString & posix)
279
{
280
#ifdef __CYGWIN__
281
    if (posix.IsEmpty())
282
        return posix;
283
    else
284
    {
285
        wxString native;
286
        cygwin_conv_to_win32_path(posix.c_str(), native.GetWriteBuf(PATH_MAX + 1));
287
        native.UngetWriteBuf();
288
        return native;
289
    }
290
#else
291
    return posix;
292
#endif
293
}
294
 
295
bool ecUtils::AddToPath(const ecFileName & strFolder, bool bAtFront)
296
{
297
    wxString strPath,strOldPath;
298
 
299
    if (wxGetEnv(wxT("PATH"), & strOldPath))
300
    {
301
        // Place the user tools folders at the head or tail of the new path
302
        if(bAtFront)
303
        {
304
            strPath.Printf(wxT("%s;%s"), (const wxChar*) strFolder.ShortName(), (const wxChar*) strOldPath);
305
        } else
306
        {
307
            strPath.Printf(wxT("%s;%s"), (const wxChar*) strOldPath, (const wxChar*) strFolder.ShortName());
308
        }
309
    } else
310
    {
311
        // unlikely, but ...
312
        strPath = strFolder;
313
    }
314
    return (TRUE == wxSetEnv(wxT("PATH"),strPath));
315
}
316
 
317
#if 0           
318
wxString ecUtils::GetLastErrorMessageString()
319
{
320
        wxString str;
321
        PTCHAR pszMsg;
322
        FormatMessage(
323
                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
324
                NULL,
325
                GetLastError(),
326
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
327
                (LPTSTR)&pszMsg,
328
                0,
329
                NULL
330
        );
331
 
332
        // Display the string.
333
        str=pszMsg;
334
  str.TrimRight();
335
        // Free the buffer.
336
        LocalFree(pszMsg);
337
        return str;
338
 
339
}
340
 
341
bool ecUtils::Launch(const ecFileName &strFileName, const ecFileName &strViewer)
342
{
343
        bool rc=false;
344
 
345
        if(!strViewer.IsEmpty())//use custom editor
346
        {
347
                wxString strCmdline(strViewer);
348
 
349
                PTCHAR pszCmdLine=strCmdline.GetBuffer(strCmdline.GetLength());
350
                GetShortPathName(pszCmdLine,pszCmdLine,strCmdline.GetLength());
351
                strCmdline.ReleaseBuffer();
352
 
353
                strCmdline+=_TCHAR(' ');
354
                strCmdline+=strFileName;
355
                PROCESS_INFORMATION pi;
356
                STARTUPINFO si;
357
 
358
                si.cb = sizeof(STARTUPINFO);
359
                si.lpReserved = NULL;
360
                si.lpReserved2 = NULL;
361
                si.cbReserved2 = 0;
362
                si.lpDesktop = NULL;
363
                si.dwFlags = 0;
364
                si.lpTitle=NULL;
365
 
366
                if(CreateProcess(
367
                        NULL, // app name
368
                        //strCmdline.GetBuffer(strCmdline.GetLength()),    // command line
369
                        strCmdline.GetBuffer(strCmdline.GetLength()),    // command line
370
                        NULL, // process security
371
                        NULL, // thread security
372
                        TRUE, // inherit handles
373
                        0,
374
                        NULL, // environment
375
                        NULL, // current dir
376
                        &si, // startup info
377
                        &pi)){
378
            CloseHandle(pi.hProcess);
379
            CloseHandle(pi.hThread);
380
                        rc=true;
381
                } else {
382
                        MessageBoxF(wxT("Failed to invoke %s.\n"),strCmdline);
383
                }
384
                strCmdline.ReleaseBuffer();
385
        } else {// Use association
386
                TCHAR szExe[MAX_PATH];
387
                HINSTANCE h=FindExecutable(strFileName,wxT("."),szExe);
388
                if(int(h)<=32){
389
                        wxString str;
390
                        switch(int(h)){
391
                                case 0:  str=wxT("The system is out of memory or resources.");break;
392
                                case 31: str=wxT("There is no association for the specified file type.");break;
393
                                case ERROR_FILE_NOT_FOUND: str=wxT("The specified file was not found.");break;
394
                                case ERROR_PATH_NOT_FOUND: str=wxT("The specified path was not found.");break;
395
                                case ERROR_BAD_FORMAT:     str=wxT("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).");break;
396
                                default: break;
397
                        }
398
                        MessageBoxF(wxT("Failed to open document %s.\r\n%s"),strFileName,str);
399
                } else {
400
 
401
                        SHELLEXECUTEINFO sei = {sizeof(sei), 0, AfxGetMainWnd()->GetSafeHwnd(), wxT("open"),
402
                                        strFileName, NULL, NULL, SW_SHOWNORMAL, AfxGetInstanceHandle( )};
403
 
404
                        sei.hInstApp=0;
405
                        HINSTANCE hInst=ShellExecute(AfxGetMainWnd()->GetSafeHwnd(),wxT("open"), strFileName, NULL, wxT("."), 0)/*ShellExecuteEx(&sei)*/;
406
                        if(int(hInst)<=32/*sei.hInstApp==0*/)
407
                        {
408
                                wxString str;
409
                                switch(int(hInst))
410
                                {
411
                                        case 0 : str=wxT("The operating system is out of memory or resources. ");break;
412
                                        case ERROR_FILE_NOT_FOUND : str=wxT("The specified file was not found. ");break;
413
                                        case ERROR_PATH_NOT_FOUND : str=wxT("The specified path was not found. ");break;
414
                                        case ERROR_BAD_FORMAT : str=wxT("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image). ");break;
415
                                        case SE_ERR_ACCESSDENIED : str=wxT("The operating system denied access to the specified file. ");break;
416
                                        case SE_ERR_ASSOCINCOMPLETE : str=wxT("The filename association is incomplete or invalid. ");break;
417
                                        case SE_ERR_DDEBUSY : str=wxT("The DDE transaction could not be completed because other DDE transactions were being processed. ");break;
418
                                        case SE_ERR_DDEFAIL : str=wxT("The DDE transaction failed. ");break;
419
                                        case SE_ERR_DDETIMEOUT : str=wxT("The DDE transaction could not be completed because the request timed out. ");break;
420
                                        case SE_ERR_DLLNOTFOUND : str=wxT("The specified dynamic-link library was not found. ");break;
421
                                        //case SE_ERR_FNF : str=wxT("The specified file was not found. ");break;
422
                                        case SE_ERR_NOASSOC : str=wxT("There is no application associated with the given filename extension. ");break;
423
                                        case SE_ERR_OOM : str=wxT("There was not enough memory to complete the operation. ");break;
424
                                        //case SE_ERR_PNF : str=wxT("The specified path was not found. ");break;
425
                                        case SE_ERR_SHARE : str=wxT("A sharing violation occurred. ");break;
426
                                        default: str=wxT("An unexpected error occurred");break;
427
                                }
428
                                MessageBoxF(wxT("Failed to open document %s using %s.\r\n%s"),strFileName,szExe,str);
429
                        } else {
430
                                rc=true;
431
                        }
432
                }
433
        }
434
        return rc;
435
}
436
 
437
#endif
438
 
439
void ecUtils::UnicodeToCStr(const wxChar* str,char *&psz)
440
{
441
    int nLength=1 + wxStrlen(str);
442
    psz=new char[nLength];
443
#ifdef _UNICODE
444
    WideCharToMultiByte(CP_ACP, 0, str, -1, psz, nLength, NULL, NULL);
445
#else
446
    strcpy(psz,str);
447
#endif
448
}
449
 
450
std::string ecUtils::UnicodeToStdStr(const wxChar* str)
451
{
452
    std::string stdstr;
453
    char *psz;
454
    UnicodeToCStr(str,psz);
455
    stdstr=std::string(psz);
456
    delete psz;
457
    return stdstr;
458
}
459
 
460
// ecUtils::StripExtraWhitespace() returns a modified version of
461
// a string in which each sequence of whitespace characters is
462
// replaced by a single space
463
 
464
static bool ecIsSpace(wxChar ch)
465
{
466
        return (ch == wxT(' ') || ch == wxT('\r') || ch == wxT('\n') || ch == wxT('\t'));
467
}
468
 
469
wxString ecUtils::StripExtraWhitespace (const wxString & strInput)
470
{
471
    wxString strOutput;
472
    wxChar* o=strOutput.GetWriteBuf(1+strInput.Len());
473
    for(const wxChar* c=strInput.GetData();*c;c++){
474
        if(ecIsSpace(*c)){
475
            *o++=wxT(' ');
476
            if (ecIsSpace(c[1])){
477
                for(c=c+2; ecIsSpace(*c);c++);
478
                c--;
479
            }
480
        } else {
481
            *o++=*c;
482
        }
483
    }
484
    *o=0;
485
    strOutput.UngetWriteBuf();
486
    strOutput.Trim(TRUE);
487
    strOutput.Trim(FALSE);
488
    return strOutput;
489
#if 0    
490
    wxString strOutput;
491
    LPTSTR o=strOutput.GetBuffer(1+strInput.GetLength());
492
    for(LPCTSTR c=strInput;*c;c++){
493
        if(_istspace(*c)){
494
            *o++=_TCHAR(' ');
495
            if (_istspace(c[1])){
496
                for(c=c+2;_istspace(*c);c++);
497
                c--;
498
            }
499
        } else {
500
            *o++=*c;
501
        }
502
    }
503
    *o=0;
504
    strOutput.ReleaseBuffer();
505
    strOutput.TrimLeft();
506
    strOutput.TrimRight();
507
    return strOutput;
508
#endif
509
}
510
 
511
#if 0
512
ecFileName ecUtils::WPath(const std::string &str)
513
{
514
  // Convert a path as read from cdl into host format
515
  // Change / to \ throughout
516
  ecFileName
517
    strPath(str.c_str());
518
  strPath.Replace (_TCHAR('/'), _TCHAR('\\'));
519
  return strPath;
520
}
521
 
522
// Copy file helper function.
523
// This makes sure the destination file is only touched as necessary.
524
// It is written using Posix calls lest it should be more broadly applicable.
525
 
526
bool ecUtils::CopyFile(LPCTSTR pszSource,LPCTSTR pszDest)
527
{
528
  // Compare the files.  First set rc to the result of the comparison (true if the same)
529
  bool rc=false;
530
 
531
  struct _stat s1,s2;
532
  if(-1!=_tstat(pszSource,&s1) && -1!=_tstat(pszDest,&s2) && s1.st_size==s2.st_size){
533
    // Files both exist and are of equal size
534
    FILE *f1=_tfopen(pszSource,wxT("rb"));
535
    if(f1){
536
      FILE *f2=_tfopen(pszDest,wxT("rb"));
537
      if(f2){
538
        int nSize1,nSize2;
539
        rc=true;
540
        do{
541
          char buf1[4096],buf2[4096];
542
          nSize1=fread(buf1,1,sizeof buf1,f1);
543
          nSize2=fread(buf2,1,sizeof buf2,f2);
544
          if(nSize1!=nSize2 || 0!=memcmp(buf1,buf2,nSize1)){
545
            rc=false;
546
            break;
547
          }
548
        } while (nSize1>0);
549
        fclose(f2);
550
      }
551
      fclose(f1);
552
    }
553
  }
554
 
555
  if(rc){
556
    // Files are identical
557
  } else {
558
    rc=TRUE==::CopyFile(pszSource,pszDest,FALSE);
559
    if(rc){
560
    } else {
561
      MessageBoxF(wxT("Failed to copy '%s' to '%s' - %s"),pszSource,pszDest,GetLastErrorMessageString());
562
    }
563
  }
564
 
565
  return rc;
566
}
567
 
568
#endif
569
 
570
/*
571
 * wxStringToStringMap
572
 *
573
 * Stores string values keyed by strings
574
 */
575
 
576
void wxStringToStringMap::Set(const wxString& key, const wxString& value)
577
{
578
    wxString oldValue;
579
    if (Find(key, oldValue))
580
        Remove(key);
581
    m_hashTable.Put(key, (wxObject*) new wxString(value));
582
}
583
 
584
bool wxStringToStringMap::Remove(const wxString& key)
585
{
586
    wxString* str = (wxString*) m_hashTable.Delete(key);
587
    if (str)
588
    {
589
        delete str;
590
        return TRUE;
591
    }
592
    else
593
        return FALSE;
594
}
595
 
596
bool wxStringToStringMap::Find(const wxString& key, wxString& value)
597
{
598
    wxString* str = (wxString*) m_hashTable.Get(key);
599
    if (str)
600
    {
601
        value = * str;
602
        return TRUE;
603
    }
604
    else
605
        return FALSE;
606
}
607
 
608
void wxStringToStringMap::Clear()
609
{
610
    m_hashTable.BeginFind();
611
#if wxCHECK_VERSION(2, 6, 0)
612
    wxHashTable::Node* node;
613
    while ((node = m_hashTable.Next()))
614
    {
615
        wxString* str = (wxString*) node->GetData();
616
#else
617
    wxNode* node;
618
    while ((node = m_hashTable.Next()))
619
    {
620
        wxString* str = (wxString*) node->Data();
621
#endif
622
        delete str;
623
    }
624
}
625
 
626
void wxStringToStringMap::BeginFind()
627
{
628
    m_hashTable.BeginFind();
629
}
630
 
631
bool wxStringToStringMap::Next(wxString& key, wxString& value)
632
{
633
#if wxCHECK_VERSION(2, 6, 0)
634
    wxHashTable::Node* node = m_hashTable.Next();
635
    if (node)
636
    {
637
        value = * (wxString*) node->GetData();
638
#else
639
    wxNode* node = m_hashTable.Next();
640
    if (node)
641
    {
642
        value = * (wxString*) node->Data();
643
#endif
644
        return TRUE;
645
    }
646
    else
647
        return FALSE;
648
}
649
 
650
// Is str a member of arr?
651
bool wxArrayStringIsMember(const wxArrayString& arr, const wxString& str)
652
{
653
    size_t i;
654
    for (i = (size_t) 0; i < arr.GetCount(); i++)
655
        if (arr[i] == str)
656
            return TRUE;
657
 
658
    return FALSE;
659
}
660
 
661
// Eliminate .. and .
662
wxString wxGetRealPath(const wxString& path)
663
{
664
    wxChar* p = new wxChar[path.Len() + 1];
665
    wxStrcpy(p, (const wxChar*) path);
666
    wxRealPath(p);
667
 
668
    wxString str(p);
669
    delete[] p;
670
    return str;
671
}
672
 
673
// A version of the above but prepending 'cwd' (current path) first
674
// if 'path' is relative
675
wxString wxGetRealPath(const wxString& cwd, const wxString& path)
676
{
677
    wxString path1(path);
678
 
679
    if (!wxIsAbsolutePath(path))
680
    {
681
        path1 = cwd;
682
        if (path1.Last() != wxFILE_SEP_PATH)
683
            path1 += wxFILE_SEP_PATH;
684
        path1 += path;
685
    }
686
 
687
    return wxGetRealPath(path1);
688
}
689
 
690
// Find the absolute path where this application has been run from.
691
// argv0 is wxTheApp->argv[0]
692
// cwd is the current working directory (at startup)
693
// appVariableName is the name of a variable containing the directory for this app, e.g.
694
// MYAPPDIR. This is checked first.
695
 
696
wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
697
{
698
    wxString str;
699
 
700
    // Try appVariableName
701
    if (!appVariableName.IsEmpty())
702
    {
703
        str = wxGetenv(appVariableName);
704
        if (!str.IsEmpty())
705
            return str;
706
    }
707
 
708
    if (wxIsAbsolutePath(argv0))
709
        return wxPathOnly(argv0);
710
    else
711
    {
712
        // Is it a relative path?
713
        wxString currentDir(cwd);
714
        if (currentDir.Last() != wxFILE_SEP_PATH)
715
            currentDir += wxFILE_SEP_PATH;
716
 
717
        str = currentDir + argv0;
718
        if (wxFileExists(str))
719
            return wxPathOnly(str);
720
    }
721
 
722
    // OK, it's neither an absolute path nor a relative path.
723
    // Search PATH.
724
 
725
    wxPathList pathList;
726
    pathList.AddEnvList(wxT("PATH"));
727
    str = pathList.FindAbsoluteValidPath(argv0);
728
    if (!str.IsEmpty())
729
        return wxPathOnly(str);
730
 
731
    // Failed
732
    return wxEmptyString;
733
}
734
 
735
// Make a path name with no separators, out of a full pathname,
736
// e.g. opt_ecos_ecos-1.4.5 out of /opt/ecos/ecos-1.4.5
737
wxString ecMakeNameFromPath(const wxString& path)
738
{
739
    wxString p(path);
740
    p.Replace(wxT("/"), wxT("_"));
741
    p.Replace(wxT("\\"), wxT("_"));
742
    p.Replace(wxT(":"), wxT("_"));
743
    return p;
744
}
745
 
746
 
747
// Find the text of the list control item at the given column
748
wxString wxListCtrlGetItemTextColumn(wxListCtrl& listCtrl, long item, int col)
749
{
750
    wxListItem listItem;
751
    listItem.m_mask = wxLIST_MASK_TEXT;
752
    listItem.m_itemId = item;
753
    listItem.m_col = col;
754
 
755
    if (listCtrl.GetItem(listItem))
756
        return listItem.m_text;
757
    else
758
        return wxEmptyString;
759
}
760
 
761
// Select the given item
762
void wxListCtrlSelectItem(wxListCtrl& listCtrl, long sel, bool deselectOthers)
763
{
764
    long n = listCtrl.GetItemCount();
765
    long i;
766
    if (deselectOthers)
767
    {
768
        for (i = 0; i < n; i++)
769
        {
770
            if (listCtrl.GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
771
            {
772
                listCtrl.SetItemState(i, wxLIST_STATE_SELECTED, 0);
773
            }
774
        }
775
    }
776
    listCtrl.SetItemState(sel, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
777
}
778
 
779
// Find the selection
780
long wxListCtrlGetSelection(wxListCtrl& listCtrl)
781
{
782
    long n = listCtrl.GetItemCount();
783
    long i;
784
    for (i = 0; i < n; i++)
785
    {
786
        if (listCtrl.GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
787
        {
788
            return i;
789
        }
790
    }
791
    return -1;
792
}
793
 
794
// Find which column the cursor is on
795
int wxListCtrlFindColumn(wxListCtrl& listCtrl, int noCols, int x)
796
{
797
    int col = 0;
798
 
799
    // Find which column we're on
800
    int width = 0;
801
    int i;
802
    for (i = 0; i < noCols; i++)
803
    {
804
        width += listCtrl.GetColumnWidth(i);
805
        if (x <= width)
806
        {
807
            col = i;
808
            break;
809
        }
810
    }
811
    return col;
812
}
813
 
814
// Utility function
815
void wxRefreshControls(wxWindow* win)
816
{
817
#if wxCHECK_VERSION(2, 6, 0)
818
    wxNode *node = (wxNode *) win->GetChildren().GetFirst();
819
    while (node)
820
    {
821
        wxWindow* win = (wxWindow*) node->GetData();
822
        win->Refresh();
823
        node = node->GetNext();
824
    }
825
#else
826
    wxNode *node = win->GetChildren().First();
827
    while (node)
828
    {
829
        wxWindow* win = (wxWindow*) node->Data();
830
        win->Refresh();
831
        node = node->Next();
832
    }
833
#endif
834
}
835
 
836
wxOutputStream& operator <<(wxOutputStream& stream, const wxString& s)
837
{
838
    stream.Write(s, s.Length());
839
    return stream;
840
}
841
 
842
wxOutputStream& operator <<(wxOutputStream& stream, long l)
843
{
844
    wxString str;
845
    str.Printf("%ld", l);
846
    return stream << str;
847
}
848
 
849
wxOutputStream& operator <<(wxOutputStream& stream, const char c)
850
{
851
    wxString str;
852
    str.Printf("%c", c);
853
    return stream << str;
854
}
855
 
856
/*
857
 * ecDialog
858
 * Supports features we want to have for all dialogs in the application.
859
 * So far, this just allows dialogs to be resizeable under MSW by
860
 * refreshing the controls in OnSize (otherwise there's a mess)
861
 */
862
 
863
IMPLEMENT_CLASS(ecDialog, wxDialog)
864
 
865
BEGIN_EVENT_TABLE(ecDialog, wxDialog)
866
#ifdef __WXMSW__
867
    EVT_SIZE(ecDialog::OnSize)
868
#endif
869
END_EVENT_TABLE()
870
 
871
void ecDialog::OnSize(wxSizeEvent& event)
872
{
873
    wxDialog::OnSize(event);
874
 
875
    wxRefreshControls(this);
876
}
877
 
878
/*
879
 * Implements saving/loading of window settings - fonts only for now
880
 */
881
 
882
wxWindowSettingsObject* wxWindowSettings::FindSettings(const wxString& windowName) const
883
{
884
#if wxCHECK_VERSION(2, 6, 0)
885
    wxNode* node = m_settings.GetFirst();
886
    while (node)
887
    {
888
        wxWindowSettingsObject* obj = (wxWindowSettingsObject*) node->GetData();
889
        if (obj->m_windowName.CmpNoCase(windowName) == 0)
890
            return obj;
891
        node = node->GetNext();
892
    }
893
#else
894
    wxNode* node = m_settings.First();
895
    while (node)
896
    {
897
        wxWindowSettingsObject* obj = (wxWindowSettingsObject*) node->Data();
898
        if (obj->m_windowName.CmpNoCase(windowName) == 0)
899
            return obj;
900
        node = node->Next();
901
    }
902
#endif
903
 
904
    return NULL;
905
}
906
 
907
bool wxWindowSettings::LoadConfig(wxConfigBase& config)
908
{
909
    unsigned int i = 0;
910
 
911
    for (i = 0; i < GetCount(); i++)
912
    {
913
        wxWindowSettingsObject* obj = GetNth(i);
914
 
915
        wxString name(obj->m_windowName);
916
        name.Replace(wxT(" "), wxT(""));
917
 
918
        LoadFont(config, name, obj->m_font);
919
    }
920
 
921
    return TRUE;
922
}
923
 
924
bool wxWindowSettings::SaveConfig(wxConfigBase& config)
925
{
926
    unsigned int i = 0;
927
    for (i = 0; i < GetCount(); i++)
928
    {
929
        wxWindowSettingsObject* obj = GetNth(i);
930
 
931
        wxString name(obj->m_windowName);
932
        name.Replace(wxT(" "), wxT(""));
933
 
934
        SaveFont(config, name, obj->m_font);
935
    }
936
 
937
    return TRUE;
938
}
939
 
940
// Load and save font descriptions
941
bool wxWindowSettings::LoadFont(wxConfigBase& config, const wxString& windowName, wxFont& font)
942
{
943
    wxString pathBase(wxT("/Fonts/"));
944
    pathBase += windowName;
945
    pathBase += wxT("/");
946
 
947
    int pointSize, family, style, weight;
948
    bool underlined = FALSE;
949
    wxString faceName;
950
 
951
    if (!config.Read(pathBase + wxT("PointSize"), & pointSize))
952
        return FALSE;
953
 
954
    if (!config.Read(pathBase + wxT("Family"), & family))
955
        return FALSE;
956
 
957
    if (!config.Read(pathBase + wxT("Style"), & style))
958
        return FALSE;
959
 
960
    if (!config.Read(pathBase + wxT("Weight"), & weight))
961
        return FALSE;
962
 
963
    config.Read(pathBase + wxT("Underlined"), (bool*) & underlined);
964
    config.Read(pathBase + wxT("FaceName"), & faceName);
965
 
966
    wxFont font1(pointSize, family, style, weight, underlined, faceName);
967
    font = font1;
968
 
969
    return TRUE;
970
}
971
 
972
bool wxWindowSettings::SaveFont(wxConfigBase& config, const wxString& windowName, const wxFont& font)
973
{
974
    if (!font.Ok())
975
        return FALSE;
976
 
977
    wxString pathBase(wxT("/Fonts/"));
978
    pathBase += windowName;
979
    pathBase += wxT("/");
980
 
981
    config.Write(pathBase + wxT("PointSize"), (long) font.GetPointSize());
982
    config.Write(pathBase + wxT("Family"), (long) font.GetFamily());
983
    config.Write(pathBase + wxT("Style"), (long) font.GetStyle());
984
    config.Write(pathBase + wxT("Weight"), (long) font.GetWeight());
985
    config.Write(pathBase + wxT("Underlined"), (long) font.GetUnderlined());
986
    config.Write(pathBase + wxT("FaceName"), font.GetFaceName());
987
 
988
    return TRUE;
989
}
990
 
991
wxFont wxWindowSettings::GetFont(const wxString& name) const
992
{
993
    wxWindowSettingsObject* obj = FindSettings(name);
994
    if (!obj)
995
        return wxFont();
996
    else
997
        return obj->m_font;
998
}
999
 
1000
void wxWindowSettings::SetFont(const wxString& name, const wxFont& font)
1001
{
1002
    wxWindowSettingsObject* obj = FindSettings(name);
1003
    if (!obj)
1004
    {
1005
        obj = new wxWindowSettingsObject(name, NULL) ;
1006
        obj->m_font = font;
1007
        m_settings.Append(obj);
1008
    }
1009
    obj->m_font = font;
1010
}
1011
 
1012
wxWindow* wxWindowSettings::GetWindow(const wxString& name) const
1013
{
1014
    wxWindowSettingsObject* obj = FindSettings(name);
1015
    if (!obj)
1016
        return NULL;
1017
    if (obj->m_arrWindow.GetCount() > 0)
1018
        return (wxWindow*) obj->m_arrWindow[0];
1019
    else
1020
        return NULL;
1021
}
1022
 
1023
void wxWindowSettings::SetWindow(const wxString& name, wxWindow* win)
1024
{
1025
    wxWindowSettingsObject* obj = FindSettings(name);
1026
    if (!obj)
1027
    {
1028
        obj = new wxWindowSettingsObject(name, win) ;
1029
        m_settings.Append(obj);
1030
    }
1031
    obj->m_arrWindow.Clear();
1032
 
1033
    if (win)
1034
        obj->m_arrWindow.Add(win);
1035
}
1036
 
1037
wxArrayPtrVoid* wxWindowSettings::GetWindows(const wxString& name) const
1038
{
1039
    wxWindowSettingsObject* obj = FindSettings(name);
1040
    if (!obj)
1041
        return NULL;
1042
    return & obj->m_arrWindow ;
1043
}
1044
 
1045
void wxWindowSettings::SetWindows(const wxString& name, wxArrayPtrVoid& arr)
1046
{
1047
    wxWindowSettingsObject* obj = FindSettings(name);
1048
    if (!obj)
1049
    {
1050
        obj = new wxWindowSettingsObject(name, NULL) ;
1051
        m_settings.Append(obj);
1052
    }
1053
    obj->m_arrWindow.Clear() ;
1054
    obj->m_arrWindow = arr;
1055
}
1056
 
1057
bool wxWindowSettings::ApplyFontsToWindows()
1058
{
1059
    if (m_useDefaults)
1060
        return FALSE;
1061
 
1062
    unsigned int i = 0;
1063
    for (i = 0; i < GetCount(); i++)
1064
    {
1065
        wxWindowSettingsObject* obj = GetNth(i);
1066
 
1067
        unsigned int j = 0;
1068
        for (j = 0; j < obj->m_arrWindow.GetCount(); j++)
1069
        {
1070
            wxWindow* win = (wxWindow*) obj->m_arrWindow[j];
1071
            win->SetFont(obj->m_font);
1072
            win->Refresh();
1073
        }
1074
    }
1075
    return TRUE;
1076
}
1077
 
1078
#ifdef __WIN32__
1079
// This will be obsolete when we switch to using the version included
1080
// in wxWindows (from wxWin 2.3.1 onwards)
1081
enum ecKillError
1082
{
1083
    ecKILL_OK,              // no error
1084
    ecKILL_BAD_SIGNAL,      // no such signal
1085
    ecKILL_ACCESS_DENIED,   // permission denied
1086
    ecKILL_NO_PROCESS,      // no such process
1087
    ecKILL_ERROR            // another, unspecified error
1088
};
1089
#endif
1090
 
1091
// ----------------------------------------------------------------------------
1092
// process management
1093
// ----------------------------------------------------------------------------
1094
 
1095
#ifdef __WIN32__
1096
 
1097
// structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
1098
struct wxNewFindByPidParams
1099
{
1100
    wxNewFindByPidParams() { hwnd = 0; pid = 0; }
1101
 
1102
    // the HWND used to return the result
1103
    HWND hwnd;
1104
 
1105
    // the PID we're looking from
1106
    DWORD pid;
1107
};
1108
 
1109
// wxKill helper: EnumWindows() callback which is used to find the first (top
1110
// level) window belonging to the given process
1111
static BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
1112
{
1113
    DWORD pid;
1114
    (void)::GetWindowThreadProcessId(hwnd, &pid);
1115
 
1116
    wxNewFindByPidParams *params = (wxNewFindByPidParams *)lParam;
1117
    if ( pid == params->pid )
1118
    {
1119
        // remember the window we found
1120
        params->hwnd = hwnd;
1121
 
1122
        // return FALSE to stop the enumeration
1123
        return FALSE;
1124
    }
1125
 
1126
    // continue enumeration
1127
    return TRUE;
1128
}
1129
 
1130
// This will be obsolete when we switch to using the version included
1131
// in wxWindows (from wxWin 2.3.1 onwards)
1132
int wxNewKill(long pid, wxSignal sig, ecKillError *krc = NULL)
1133
{
1134
#ifdef __WIN32__
1135
    // get the process handle to operate on
1136
    HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
1137
                                    PROCESS_TERMINATE |
1138
                                    PROCESS_QUERY_INFORMATION,
1139
                                    FALSE, // not inheritable
1140
                                    (DWORD)pid);
1141
    if ( hProcess == NULL )
1142
    {
1143
        if ( krc )
1144
        {
1145
            if ( ::GetLastError() == ERROR_ACCESS_DENIED )
1146
            {
1147
                *krc = ecKILL_ACCESS_DENIED;
1148
            }
1149
            else
1150
            {
1151
                *krc = ecKILL_NO_PROCESS;
1152
            }
1153
        }
1154
 
1155
        return -1;
1156
    }
1157
 
1158
    bool ok = TRUE;
1159
    switch ( sig )
1160
    {
1161
        case wxSIGKILL:
1162
            // kill the process forcefully returning -1 as error code
1163
            if ( !::TerminateProcess(hProcess, (UINT)-1) )
1164
            {
1165
                wxLogSysError(_("Failed to kill process %d"), pid);
1166
 
1167
                if ( krc )
1168
                {
1169
                    // this is not supposed to happen if we could open the
1170
                    // process
1171
                    *krc = ecKILL_ERROR;
1172
                }
1173
 
1174
                ok = FALSE;
1175
            }
1176
            break;
1177
 
1178
        case wxSIGNONE:
1179
            // do nothing, we just want to test for process existence
1180
            break;
1181
 
1182
        default:
1183
            // any other signal means "terminate"
1184
            {
1185
                wxNewFindByPidParams params;
1186
                params.pid = (DWORD)pid;
1187
 
1188
                // EnumWindows() has nice semantics: it returns 0 if it found
1189
                // something or if an error occured and non zero if it
1190
                // enumerated all the window
1191
                if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)&params) )
1192
                {
1193
                    // did we find any window?
1194
                    if ( params.hwnd )
1195
                    {
1196
                        // tell the app to close
1197
                        //
1198
                        // NB: this is the harshest way, the app won't have
1199
                        //     opportunity to save any files, for example, but
1200
                        //     this is probably what we want here. If not we
1201
                        //     can also use SendMesageTimeout(WM_CLOSE)
1202
                        if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) )
1203
                        {
1204
                            wxLogLastError(_T("PostMessage(WM_QUIT)"));
1205
                        }
1206
                    }
1207
                    else // it was an error then
1208
                    {
1209
                        wxLogLastError(_T("EnumWindows"));
1210
 
1211
                        ok = FALSE;
1212
                    }
1213
                }
1214
                else // no windows for this PID
1215
                {
1216
                    if ( krc )
1217
                    {
1218
                        *krc = ecKILL_ERROR;
1219
                    }
1220
 
1221
                    ok = FALSE;
1222
                }
1223
            }
1224
    }
1225
 
1226
    // the return code
1227
    DWORD rc;
1228
 
1229
    if ( ok )
1230
    {
1231
        // as we wait for a short time, we can use just WaitForSingleObject()
1232
        // and not MsgWaitForMultipleObjects()
1233
        switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) )
1234
        {
1235
            case WAIT_OBJECT_0:
1236
                // process terminated
1237
                if ( !::GetExitCodeProcess(hProcess, &rc) )
1238
                {
1239
                    wxLogLastError(_T("GetExitCodeProcess"));
1240
                }
1241
                break;
1242
 
1243
            default:
1244
                wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
1245
                // fall through
1246
 
1247
            case WAIT_FAILED:
1248
                wxLogLastError(_T("WaitForSingleObject"));
1249
                // fall through
1250
 
1251
            case WAIT_TIMEOUT:
1252
                if ( krc )
1253
                {
1254
                    *krc = ecKILL_ERROR;
1255
                }
1256
 
1257
                rc = STILL_ACTIVE;
1258
                break;
1259
        }
1260
    }
1261
    else // !ok
1262
    {
1263
        // just to suppress the warnings about uninitialized variable
1264
        rc = 0;
1265
    }
1266
 
1267
    ::CloseHandle(hProcess);
1268
 
1269
    // the return code is the same as from Unix kill(): 0 if killed
1270
    // successfully or -1 on error
1271
    if ( sig == wxSIGNONE )
1272
    {
1273
        if ( ok && rc == STILL_ACTIVE )
1274
        {
1275
            // there is such process => success
1276
            return 0;
1277
        }
1278
    }
1279
    else // not SIGNONE
1280
    {
1281
        if ( ok && rc != STILL_ACTIVE )
1282
        {
1283
            // killed => success
1284
            return 0;
1285
        }
1286
    }
1287
#else // Win15
1288
    wxFAIL_MSG( _T("not implemented") );
1289
#endif // Win32/Win16
1290
 
1291
    // error
1292
    return -1;
1293
}
1294
#endif
1295
 
1296
int ecKill(long pid, wxSignal sig)
1297
{
1298
#if defined(__UNIX__) && !defined(__CYGWIN__)
1299
    return wxKill(pid, sig);
1300
#elif defined(__WXMSW__)
1301
    return wxNewKill(pid, sig);
1302
#else
1303
    return -1;
1304
#endif
1305
}
1306
 
1307
#ifdef _WIN32
1308
  #include <tlhelp32.h>
1309
 
1310
  WXHINSTANCE wxProcessKiller::hInstLib1 = VER_PLATFORM_WIN32_NT==wxProcessKiller::GetPlatform()? (WXHINSTANCE) LoadLibrary(_T("PSAPI.DLL")) : (WXHINSTANCE) LoadLibrary(_T("Kernel32.DLL")) ;
1311
  WXHINSTANCE wxProcessKiller::hInstLib2 = VER_PLATFORM_WIN32_NT==wxProcessKiller::GetPlatform()? (WXHINSTANCE) LoadLibrary(_T("NTDLL.DLL")): (WXHINSTANCE) NULL;
1312
 
1313
#endif
1314
 
1315
const unsigned int wxProcessKiller::PROCESS_KILL_EXIT_CODE=0xCCFFCCFF;
1316
 
1317
wxProcessKiller::wxProcessKiller(int pid):
1318
  m_bVerbose(false),
1319
  m_nExitCode(-1),
1320
  m_idProcess(pid)
1321
{
1322
#ifdef _WIN32
1323
      m_hProcess = (WXHANDLE) ::OpenProcess(SYNCHRONIZE |
1324
          PROCESS_TERMINATE |
1325
          PROCESS_QUERY_INFORMATION,
1326
          FALSE, // not inheritable
1327
          (DWORD) m_idProcess);
1328
#endif
1329
}
1330
 
1331
wxProcessKiller::~wxProcessKiller()
1332
{
1333
#ifdef _WIN32
1334
    if (m_hProcess)
1335
    {
1336
        ::CloseHandle((HANDLE) m_hProcess);
1337
    }
1338
#endif
1339
}
1340
 
1341
bool wxProcessKiller::Kill(bool bRecurse)
1342
{
1343
    wxPInfoArray arPinfo;
1344
    bool rc=false;
1345
    if(m_idProcess && -1!=m_idProcess){
1346
        // Start of with the easy one:
1347
        if(bRecurse) {
1348
            // Need to gather this information before we orphan our grandchildren:
1349
            PSExtract(arPinfo);
1350
        }
1351
 
1352
#ifdef _WIN32
1353
 
1354
        if(m_hProcess){
1355
            rc=(TRUE==::TerminateProcess((HANDLE) m_hProcess,PROCESS_KILL_EXIT_CODE));
1356
            // dtor's (or subsequent Run's) responsibility to close the handle
1357
        }
1358
 
1359
#else
1360
        rc=(0==kill(m_idProcess,SIGTERM));
1361
        int status;
1362
        waitpid(m_idProcess,&status,WNOHANG);
1363
#endif
1364
 
1365
        if(bRecurse) {
1366
            // kill process *and* its children
1367
            // FIXME: needs to be top-down
1368
            for(int i=0;i<(signed)arPinfo.size();i++){
1369
                if(arPinfo[i].IsChildOf(m_idProcess)){
1370
 
1371
#ifdef _WIN32
1372
                    // begin hack
1373
                    // WHY NECESSARY??
1374
                    const wxString strName(Name(arPinfo[i].PID));
1375
                    if(_tcsstr(strName,_T("eCosTest")) || _tcsstr(strName,_T("cmd.EXE")) || _tcsstr(strName,_T("CMD.EXE")) || arPinfo[i].PID==(signed)GetCurrentProcessId()){
1376
                        continue;
1377
                    }
1378
                    // end hack
1379
                    HANDLE hProcess=::OpenProcess(PROCESS_TERMINATE,false,arPinfo[i].PID);
1380
                    if(hProcess){
1381
                        rc&=(TRUE==::TerminateProcess(hProcess,PROCESS_KILL_EXIT_CODE));
1382
                        CloseHandle(hProcess);
1383
                    } else {
1384
                        rc=false;
1385
                    }
1386
#else
1387
                    rc&=(0==kill(arPinfo[i].PID,SIGTERM));
1388
                    int status;
1389
                    waitpid(arPinfo[i].PID,&status,WNOHANG);
1390
#endif
1391
                }
1392
            }
1393
        }
1394
    }
1395
    return rc;
1396
}
1397
 
1398
#ifdef _WIN32
1399
bool wxProcessKiller::PSExtract(wxProcessKiller::wxPInfoArray &arPinfo)
1400
{
1401
    bool rc=false;
1402
    arPinfo.clear();
1403
    // If Windows NT:
1404
    switch(GetPlatform()) {
1405
    case VER_PLATFORM_WIN32_NT:
1406
        if(hInstLib1) {
1407
 
1408
            // Get procedure addresses.
1409
            static BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * ) = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))GetProcAddress( (HINSTANCE) hInstLib1, "EnumProcesses" ) ;
1410
            if( lpfEnumProcesses) {
1411
 
1412
                if(hInstLib2) {
1413
 
1414
                    static DWORD (WINAPI *lpfNtQueryInformationProcess)( HANDLE, int, void *, DWORD, LPDWORD ) =
1415
                        (DWORD(WINAPI *)(HANDLE, int, void *, DWORD, LPDWORD)) GetProcAddress( (HINSTANCE) hInstLib2,"NtQueryInformationProcess" ) ;
1416
 
1417
                    if(lpfNtQueryInformationProcess){
1418
                        DWORD dwMaxPids=256;
1419
                        DWORD dwPidSize;
1420
                        DWORD *arPids = NULL ;
1421
                        do {
1422
                            delete [] arPids;
1423
                            arPids=new DWORD[dwMaxPids];
1424
                        } while(lpfEnumProcesses(arPids, dwMaxPids, &dwPidSize) && dwPidSize/sizeof(DWORD)==dwMaxPids) ;
1425
 
1426
                        if(dwPidSize/sizeof(DWORD)<dwMaxPids){
1427
                            rc=true;
1428
                            for( DWORD dwIndex = 0 ; (signed)dwIndex < dwPidSize/sizeof(DWORD); dwIndex++ ) {
1429
                                // Regardless of OpenProcess success or failure, we
1430
                                // still call the enum func with the ProcID.
1431
                                DWORD pid=arPids[dwIndex];
1432
                                HANDLE hProcess=::OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid );
1433
                                if (hProcess ) {
1434
                                    struct {
1435
                                        DWORD ExitStatus; // receives process termination status
1436
                                        DWORD PebBaseAddress; // receives process environment block address
1437
                                        DWORD AffinityMask; // receives process affinity mask
1438
                                        DWORD BasePriority; // receives process priority class
1439
                                        ULONG UniqueProcessId; // receives process identifier
1440
                                        ULONG InheritedFromUniqueProcessId; // receives parent process identifier
1441
                                    } pbi;
1442
                                    memset( &pbi, 0, sizeof(pbi));
1443
                                    DWORD retLen;
1444
                                    __int64 ftCreation,ftExit,ftKernel,ftUser;
1445
                                    if(lpfNtQueryInformationProcess(hProcess, 0 /*ProcessBasicInformation*/, &pbi, sizeof(pbi), &retLen)>=0 &&
1446
                                        TRUE==::GetProcessTimes (hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){
1447
                                        // The second test is important.  It excludes orphaned processes who appear to have been adopted by virtue of a new
1448
                                        // process having been created with the same ID as their original parent.
1449
                                        wxPInfo p;
1450
                                        p.PID=pid;
1451
                                        p.PPID=pbi.InheritedFromUniqueProcessId;
1452
                                        p.tCreation=ftCreation;
1453
                                        p.tCpu=Time((ftKernel+ftUser)/10000);
1454
                                        arPinfo.push_back(p);
1455
                                    }
1456
 
1457
                                    CloseHandle(hProcess);
1458
 
1459
                                }
1460
                            }
1461
                        }
1462
                        delete [] arPids;
1463
                    }
1464
                }
1465
            }
1466
        }
1467
        break;
1468
    case VER_PLATFORM_WIN32_WINDOWS:
1469
 
1470
        if( hInstLib1) {
1471
 
1472
            static HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD)=
1473
                (HANDLE(WINAPI *)(DWORD,DWORD))GetProcAddress( (HINSTANCE) hInstLib1,"CreateToolhelp32Snapshot" ) ;
1474
            static BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32)=
1475
                (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( (HINSTANCE) hInstLib1, "Process32First" ) ;
1476
            static BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32)=
1477
                (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( (HINSTANCE) hInstLib1, "Process32Next" ) ;
1478
            if( lpfProcess32Next && lpfProcess32First && lpfCreateToolhelp32Snapshot) {
1479
 
1480
                // Get a handle to a Toolhelp snapshot of the systems
1481
                // processes.
1482
                HANDLE hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
1483
                if(INVALID_HANDLE_VALUE != hSnapShot) {
1484
                    // Get the first process' information.
1485
                    PROCESSENTRY32 procentry;
1486
                    procentry.dwSize = sizeof(PROCESSENTRY32) ;
1487
                    if(lpfProcess32First( hSnapShot, &procentry )){
1488
                        rc=true;
1489
                        do {
1490
                            wxPInfo p;
1491
                            p.PID=procentry.th32ProcessID;
1492
                            p.PPID=procentry.th32ParentProcessID;
1493
                            arPinfo.push_back(p);
1494
                        } while(lpfProcess32Next( hSnapShot, &procentry ));
1495
                    }
1496
                    CloseHandle(hSnapShot);
1497
                }
1498
            }
1499
        }
1500
        break;
1501
    default:
1502
        break;
1503
    }
1504
 
1505
    SetParents(arPinfo);
1506
 
1507
    if(!rc){
1508
        wxLogError(_T("Couldn't get process information!\n"));
1509
    }
1510
    return rc;
1511
}
1512
 
1513
#else // UNIX
1514
 
1515
bool wxProcessKiller::PSExtract(wxProcessKiller::wxPInfoArray &arPinfo)
1516
{
1517
    arPinfo.clear();
1518
    int i;
1519
    FILE *f=popen("ps -l",_T("r") MODE_TEXT);
1520
    if(f){
1521
        char buf[100];
1522
        while(fgets(buf,sizeof(buf)-1,f)){
1523
            TCHAR discard[100];
1524
            wxPInfo p;
1525
            // Output is in the form
1526
            //  F S   UID   PID  PPID  C PRI  NI ADDR    SZ WCHAN  TTY          TIME CMD
1527
            //100 S   490   877   876  0  70   0    -   368 wait4  pts/0    00:00:00 bash
1528
            int F,UID,C,PRI,NI,SZ,HH,MM,SS;
1529
            bool rc=(15==_stscanf(buf,_T("%d %s %d %d %d %d %d %d %s %d %s %s %d:%d:%d"),&F,discard,&UID,&p.PID,&p.PPID,&C,&PRI,&NI,discard,&SZ,discard,discard,&HH,&MM,&SS));
1530
            if(rc){
1531
                p.tCpu=1000*(SS+60*(60*HH+MM));
1532
                arPinfo.push_back(p);
1533
            }
1534
        }
1535
        pclose(f);
1536
        for(i=0;i<(signed)arPinfo.size();i++){
1537
            int pid=arPinfo[i].PPID;
1538
            arPinfo[i].pParent=0;
1539
            for(int j=0;j<(signed)arPinfo.size();j++){
1540
                if(i!=j && arPinfo[j].PID==pid){
1541
                    arPinfo[i].pParent=&arPinfo[j];
1542
                    break;
1543
                }
1544
            }
1545
        }
1546
    } else {
1547
        wxLogError(_T("Failed to run ps -l\n"));
1548
    }
1549
    return true; //FIXME
1550
}
1551
 
1552
#endif
1553
 
1554
void wxProcessKiller::SetParents(wxProcessKiller::wxPInfoArray &arPinfo)
1555
{
1556
    int i;
1557
    for(i=0;i<(signed)arPinfo.size();i++){
1558
        wxPInfo &p=arPinfo[i];
1559
        p.pParent=0;
1560
        for(int j=0;j<(signed)arPinfo.size();j++){
1561
            if(arPinfo[j].PID==p.PPID
1562
#ifdef _WIN32
1563
                && arPinfo[j].tCreation<p.tCreation
1564
#endif
1565
                )
1566
            {
1567
                arPinfo[i].pParent=&arPinfo[j];
1568
                break;
1569
            }
1570
        }
1571
    }
1572
 
1573
    // Check for circularity
1574
    bool bCircularity=false;
1575
    for(i=0;i<(signed)arPinfo.size();i++){
1576
        wxPInfo *p=&arPinfo[i];
1577
        for(int j=0;j<(signed)arPinfo.size() && p;j++){
1578
            p=p->pParent;
1579
        }
1580
        // If all is well, p should be NULL here.  Otherwise we have a loop.
1581
        if(p){
1582
            // Make sure it can't foul things up:
1583
            arPinfo[i].pParent=0;
1584
            bCircularity=true;
1585
        }
1586
    }
1587
 
1588
    if(bCircularity){
1589
        wxLogError(_T("!!! Circularly linked process list at index %d\n"),i);
1590
        for(int k=0;k<(signed)arPinfo.size();k++){
1591
            const wxPInfo &p=arPinfo[k];
1592
            wxLogError(_T("%d: %s ppid=%4d\n"),k,(LPCTSTR)Name(p.PID),p.PPID);
1593
        }
1594
    }
1595
}
1596
 
1597
bool wxProcessKiller::wxPInfo::IsChildOf(int pid) const
1598
{
1599
    for(wxPInfo *p=pParent;p && p!=this;p=p->pParent) { // guard against circular linkage
1600
        if(p->PID==pid){
1601
            return true;
1602
        }
1603
    }
1604
    return false;
1605
}
1606
 
1607
const wxString wxProcessKiller::Name(int pid)
1608
{
1609
    wxString str;
1610
    str.Printf(_T("id=%d"),pid);
1611
#ifdef _DEBUG
1612
#ifdef _WIN32
1613
    if(VER_PLATFORM_WIN32_NT==GetPlatform() && hInstLib1){
1614
        static BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *, DWORD, LPDWORD ) =
1615
            (BOOL(WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( (HINSTANCE) hInstLib1,"EnumProcessModules" ) ;
1616
        static DWORD (WINAPI *lpfGetModuleFileNameEx)( HANDLE, HMODULE, LPTSTR, DWORD )=
1617
            (DWORD (WINAPI *)(HANDLE, HMODULE,LPTSTR, DWORD )) GetProcAddress( (HINSTANCE) hInstLib1,"GetModuleFileNameExA" ) ;
1618
        if( lpfEnumProcessModules &&  lpfGetModuleFileNameEx ) {
1619
            HANDLE hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,pid);
1620
            if(hProcess) {
1621
                HMODULE hMod;
1622
                DWORD dwSize;
1623
                if(lpfEnumProcessModules( hProcess, &hMod, sizeof(HMODULE), &dwSize ) ){
1624
                    // Get Full pathname:
1625
                    TCHAR buf[1+MAX_PATH];
1626
                    lpfGetModuleFileNameEx( hProcess, hMod, buf, MAX_PATH);
1627
                    str+=_TCHAR(' ');
1628
                    str+=buf;
1629
                }
1630
                CloseHandle(hProcess);
1631
            }
1632
        }
1633
    }
1634
#endif
1635
#endif
1636
    return str;
1637
}
1638
 
1639
#ifdef _WIN32
1640
long wxProcessKiller::GetPlatform()
1641
{
1642
    OSVERSIONINFO  osver;
1643
    osver.dwOSVersionInfoSize = sizeof( osver ) ;
1644
    return GetVersionEx( &osver ) ? (long) osver.dwPlatformId : (long)-1;
1645
}
1646
#endif
1647
 
1648
const wxString wxProcessKiller::ErrorString() const
1649
{
1650
#ifdef _WIN32
1651
    TCHAR *pszMsg;
1652
    FormatMessage(
1653
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1654
        NULL,
1655
        m_nErr,
1656
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
1657
        (LPTSTR)&pszMsg,
1658
        0,
1659
        NULL
1660
        );
1661
    return pszMsg;
1662
#else 
1663
    return strerror(errno);
1664
#endif
1665
}
1666
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.