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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [configtool/] [standalone/] [wxwin/] [ecutils.cpp] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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