]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/pkgadmin/win32/PkgAdminDlg.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / pkgadmin / win32 / PkgAdminDlg.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 // PkgAdminDlg.cpp : implementation file
26 //
27
28 #include "stdafx.h"
29
30 #include "PkgAdmin.h"
31 #include "PkgAdminDlg.h"
32 #include "PkgAdminLicenseDlg.h"
33 #include "PkgAdminTclWaitDlg.h"
34
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #undef THIS_FILE
38 static char THIS_FILE[] = __FILE__;
39 #endif
40
41 /////////////////////////////////////////////////////////////////////////////
42 // CPkgadminAboutDlg dialog used for App About
43
44 class CPkgadminAboutDlg : public CDialog
45 {
46 public:
47         CPkgadminAboutDlg();
48
49 // Dialog Data
50         //{{AFX_DATA(CPkgadminAboutDlg)
51         enum { IDD = IDD_PKGADMIN_ABOUTBOX };
52         //}}AFX_DATA
53
54         // ClassWizard generated virtual function overrides
55         //{{AFX_VIRTUAL(CPkgadminAboutDlg)
56         protected:
57         virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
58         //}}AFX_VIRTUAL
59
60 // Implementation
61 protected:
62         //{{AFX_MSG(CPkgadminAboutDlg)
63         //}}AFX_MSG
64         DECLARE_MESSAGE_MAP()
65 };
66
67 CPkgadminAboutDlg::CPkgadminAboutDlg() : CDialog(CPkgadminAboutDlg::IDD)
68 {
69         //{{AFX_DATA_INIT(CPkgadminAboutDlg)
70         //}}AFX_DATA_INIT
71 }
72
73 void CPkgadminAboutDlg::DoDataExchange(CDataExchange* pDX)
74 {
75         CDialog::DoDataExchange(pDX);
76         //{{AFX_DATA_MAP(CPkgadminAboutDlg)
77         //}}AFX_DATA_MAP
78 }
79
80 BEGIN_MESSAGE_MAP(CPkgadminAboutDlg, CDialog)
81         //{{AFX_MSG_MAP(CPkgadminAboutDlg)
82                 // No message handlers
83         //}}AFX_MSG_MAP
84 END_MESSAGE_MAP()
85
86 /////////////////////////////////////////////////////////////////////////////
87 // CPkgAdminDlg dialog
88
89 CPkgAdminDlg::CPkgAdminDlg(LPCTSTR pszRepository,LPCTSTR pszUserTools)
90         : CeCosDialog(CPkgAdminDlg::IDD, NULL)
91 {
92         //{{AFX_DATA_INIT(CPkgAdminDlg)
93                 // NOTE: the ClassWizard will add member initialization here
94         //}}AFX_DATA_INIT
95         // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
96   if(pszRepository){
97           m_strRepository=pszRepository;
98   }
99   if(pszUserTools){
100           m_strUserTools=pszUserTools;
101   }
102         m_CdlPkgData = NULL;
103 }
104
105 void CPkgAdminDlg::DoDataExchange(CDataExchange* pDX)
106 {
107         CeCosDialog::DoDataExchange(pDX);
108         //{{AFX_DATA_MAP(CPkgAdminDlg)
109         DDX_Control(pDX, IDC_PKGADMIN_REMOVE, m_btnRemove);
110         DDX_Control(pDX, IDC_PKGADMIN_TREE, m_ctrlPackageTree);
111         //}}AFX_DATA_MAP
112 }
113
114 BEGIN_MESSAGE_MAP(CPkgAdminDlg, CeCosDialog)
115         //{{AFX_MSG_MAP(CPkgAdminDlg)
116         ON_WM_SYSCOMMAND()
117         ON_WM_PAINT()
118         ON_WM_QUERYDRAGICON()
119         ON_BN_CLICKED(IDC_PKGADMIN_REMOVE, OnPkgadminRemove)
120         ON_WM_DESTROY()
121         ON_BN_CLICKED(IDC_PKGADMIN_ADD, OnPkgadminAdd)
122         ON_BN_CLICKED(IDCLOSE, OnClose)
123         ON_BN_CLICKED(IDC_PKGADMIN_REPOSITORY, OnPkgadminRepository)
124         ON_NOTIFY(TVN_SELCHANGED, IDC_PKGADMIN_TREE, OnSelchangedPkgadminTree)
125         //}}AFX_MSG_MAP
126 END_MESSAGE_MAP()
127
128 /////////////////////////////////////////////////////////////////////////////
129 // CPkgAdminDlg message handlers
130
131 BOOL CPkgAdminDlg::OnInitDialog()
132 {
133         CeCosDialog::OnInitDialog();
134
135   if(this==AfxGetApp()->m_pMainWnd){ // only if the dialog is the application
136           // Add "About..." menu item to system menu.
137
138           // IDM_ABOUTBOX must be in the system command range.
139           ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
140           ASSERT(IDM_ABOUTBOX < 0xF000);
141
142           CMenu* pSysMenu = GetSystemMenu(FALSE);
143           if (pSysMenu != NULL)
144           {
145                   CString strAboutMenu;
146                   strAboutMenu.LoadString(IDS_ABOUTBOX);
147                   if (!strAboutMenu.IsEmpty())
148                   {
149                           pSysMenu->AppendMenu(MF_SEPARATOR);
150                           pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
151                   }
152           }
153
154         // Set the icon for this dialog.  The framework does this automatically
155         //  when the application's main window is not a dialog
156           SetIcon(m_hIcon, TRUE);                       // Set big icon
157         
158   // The following AppWizard-generated call was causing the 32x32 icon to
159         //  be resized for use as a 16x16 icon. Removing the call causes the
160         //  correct 16x16 icon to be displayed.
161 //      SetIcon(m_hIcon, FALSE);                // Set small icon
162         
163         // TODO: Add extra initialization here
164
165         // setup the repsoitory location
166
167           if (m_strRepository.IsEmpty()) // if the repository cannot be located
168           {
169                   OnPkgadminRepository (); // prompt the user for the repository location
170                   if (m_strRepository.IsEmpty ())
171                   {
172                           PostMessage (WM_COMMAND,IDCANCEL);
173                           return TRUE;
174                   }
175           }
176   } else {
177     GetDlgItem(IDC_PKGADMIN_REPOSITORY)->ShowWindow(SW_HIDE);
178   }
179
180         // setup the path to the user tools (tar and gunzip)
181
182         if ((! m_strUserTools.IsEmpty()) || FindUserToolsPath ()) // if the user tools can be located
183         {
184                 // add the user tools to the PATH environment variable
185                 const DWORD nLength = GetEnvironmentVariable (_T("PATH"), NULL, 0) + 1;
186                 TCHAR * pszOldPath  = new TCHAR [nLength];
187                 GetEnvironmentVariable (_T("PATH"), pszOldPath, nLength);
188                 SetEnvironmentVariable (_T("PATH"), CString (pszOldPath) + _T(";") + m_strUserTools);
189                 delete [] pszOldPath;
190         }
191
192         // setup the package tree image list
193
194         m_ilTreeIcons.Create (IDB_PKGADMIN_TREEICONS, 16, 1, RGB (0,128,128));
195         m_ctrlPackageTree.SetImageList (&m_ilTreeIcons, TVSIL_NORMAL);
196
197         // populate the package tree
198
199         while (! PopulatePackageTree (m_strRepository))
200         {
201                 m_strRepository = _T("");
202                 OnPkgadminRepository (); // prompt the user for the repository location
203                 if (m_strRepository.IsEmpty ()) // if dialog was cancelled
204                 {
205                         PostQuitMessage (1);
206                         return TRUE;
207                 }
208         }
209         
210         return TRUE;  // return TRUE  unless you set the focus to a control
211 }
212
213 void CPkgAdminDlg::OnSysCommand(UINT nID, LPARAM lParam)
214 {
215         if ((nID & 0xFFF0) == IDM_ABOUTBOX)
216         {
217                 CPkgadminAboutDlg dlgAbout;
218                 dlgAbout.DoModal();
219         }
220         else
221         {
222                 CeCosDialog::OnSysCommand(nID, lParam);
223         }
224 }
225
226 // If you add a minimize button to your dialog, you will need the code below
227 //  to draw the icon.  For MFC applications using the document/view model,
228 //  this is automatically done for you by the framework.
229
230 void CPkgAdminDlg::OnPaint() 
231 {
232         if (IsIconic())
233         {
234                 CPaintDC dc(this); // device context for painting
235
236                 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
237
238                 // Center icon in client rectangle
239                 int cxIcon = GetSystemMetrics(SM_CXICON);
240                 int cyIcon = GetSystemMetrics(SM_CYICON);
241                 CRect rect;
242                 GetClientRect(&rect);
243                 int x = (rect.Width() - cxIcon + 1) / 2;
244                 int y = (rect.Height() - cyIcon + 1) / 2;
245
246                 // Draw the icon
247                 dc.DrawIcon(x, y, m_hIcon);
248         }
249         else
250         {
251                 CeCosDialog::OnPaint();
252         }
253 }
254
255 // The system calls this to obtain the cursor to display while the user drags
256 //  the minimized window.
257 HCURSOR CPkgAdminDlg::OnQueryDragIcon()
258 {
259         return (HCURSOR) m_hIcon;
260 }
261
262 // Trivial handlers; otherwise CdlPackagesDatabaseBody::make asserts.
263 void CdlErrorHandler (std::string message)
264 {
265 };
266
267 void CdlWarningHandler (std::string message)
268 {
269 };
270
271
272 bool CPkgAdminDlg::PopulatePackageTree(LPCTSTR pszPackagesPath)
273 {
274         // delete any existing CDL database
275
276         if (m_CdlPkgData)
277         {
278                 delete m_CdlPkgData;
279                 m_CdlPkgData = NULL;
280         }
281
282         // load the package database
283
284         try
285         {
286         // Cdl asserts unless the handlers are present.
287 #if 1
288         m_CdlPkgData = CdlPackagesDatabaseBody::make (UnicodeToStdStr (pszPackagesPath), &CdlErrorHandler, &CdlWarningHandler);
289 #else
290         m_CdlPkgData = CdlPackagesDatabaseBody::make (UnicodeToStdStr (pszPackagesPath));
291 #endif
292         }
293         catch (CdlStringException exception)
294         {
295                 CString strMessage;
296                 strMessage.Format (_T("Error loading database:\n\n%s"), CString (exception.get_message ().c_str ()));
297                 AfxMessageBox (strMessage);
298                 return false;
299         }
300         catch (...)
301         {
302                 AfxMessageBox (_T("Error loading database"));
303                 return false;
304         }
305
306         // clear the old package tree
307
308         ClearPackageTree ();
309
310         // populate the new package tree
311
312         const std::vector<std::string>& packages = m_CdlPkgData->get_packages ();
313         for (std::vector<std::string>::const_iterator package = packages.begin (); package != packages.end (); package++)
314         {
315                 // add a package node
316
317                 TRACE (_T("Adding package %s:"), CString (package->c_str ()));
318                 HTREEITEM hPackage = m_ctrlPackageTree.InsertItem (CString (m_CdlPkgData->get_package_aliases (*package) [0].c_str ()));
319                 m_ctrlPackageTree.SetItemData (hPackage, (DWORD) new CString (package->c_str ()));
320                 m_ctrlPackageTree.SetItemImage (hPackage, 0, 0);
321
322                 const std::vector<std::string>& versions = m_CdlPkgData->get_package_versions (* package);
323                 for (std::vector<std::string>::const_iterator version = versions.begin (); version != versions.end (); version++)
324                 {
325                         // add a version node
326
327                         TRACE (_T(" %s"), CString (version->c_str ()));
328                         const HTREEITEM hVersion = m_ctrlPackageTree.InsertItem (CString (version->c_str ()), hPackage);
329                         m_ctrlPackageTree.SetItemImage (hVersion, 1, 1);
330                 }
331                 TRACE (_T("\n"));
332                 m_ctrlPackageTree.SortChildren (hPackage); // sort the version nodes
333         }
334
335         m_ctrlPackageTree.SortChildren (NULL); // sort the package nodes
336
337   if(this==AfxGetApp()->m_pMainWnd){ // if the dialog is the application
338           // update the caption bar
339           CString strCaption (m_strRepository);
340           strCaption.Replace (_TCHAR('/'), _TCHAR('\\'));
341           strCaption += _T(" - eCos Package Administration Tool");
342           SetWindowText (strCaption);
343   }
344
345         return true;
346 }
347
348 void CPkgAdminDlg::OnPkgadminRemove() 
349 {
350         const HTREEITEM hTreeItem = m_ctrlPackageTree.GetSelectedItem ();
351         if (! hTreeItem)
352                 return;
353
354         if (IDYES != CWnd::MessageBox (_T("The selected package will be deleted from the repository. Core eCos packages may be restored only by reinstalling eCos.\n\nDo you wish to continue?"),
355                 _T("Remove Package"), MB_YESNO | MB_ICONEXCLAMATION))
356                 return;
357
358         const CString * pstrPackage = (const CString *) m_ctrlPackageTree.GetItemData (hTreeItem);
359         if (pstrPackage) // if a package node is selected
360         {
361                 // remove all package version nodes
362
363                 bool bStatus = true;
364                 HTREEITEM hChildItem = m_ctrlPackageTree.GetChildItem (hTreeItem);
365                 while (hChildItem && bStatus)
366                 {
367                         const HTREEITEM hNextChildItem = m_ctrlPackageTree.GetNextSiblingItem (hChildItem);                     
368                         bStatus = RemovePackageVersion (hChildItem);
369                         hChildItem = hNextChildItem;
370                 }
371
372                 // remove the package node
373
374                 if (bStatus)
375                 {
376                         delete pstrPackage;
377                         m_ctrlPackageTree.DeleteItem (hTreeItem);
378                 }
379         }
380         else // a version node is selected
381         {
382                 // remove the version node
383
384                 const HTREEITEM hParentItem = m_ctrlPackageTree.GetParentItem (hTreeItem);
385                 ASSERT (hParentItem);
386                 if (RemovePackageVersion (hTreeItem) && ! m_ctrlPackageTree.ItemHasChildren (hParentItem)) // if the only version was deleted
387                 {
388                         // remove the package node
389
390                         delete pstrPackage;
391                         m_ctrlPackageTree.DeleteItem (hParentItem); 
392                 }
393         }
394 }
395
396 void CPkgAdminDlg::ClearPackageTree()
397 {
398         HTREEITEM hPackage = m_ctrlPackageTree.GetRootItem ();
399         if (! hPackage) // if no packages in the tree...
400                 return;     // ...nothing to do
401
402         while (hPackage)
403         {
404                 const HTREEITEM hNextPackage = m_ctrlPackageTree.GetNextSiblingItem (hPackage);
405                 TRACE (_T("Deleting package %s\n"), * ((CString *) m_ctrlPackageTree.GetItemData (hPackage)));
406                 delete (CString *) m_ctrlPackageTree.GetItemData (hPackage);
407                 m_ctrlPackageTree.DeleteItem (hPackage);
408                 hPackage = hNextPackage;
409         }
410 }
411
412 void CPkgAdminDlg::OnDestroy() 
413 {
414         CeCosDialog::OnDestroy();
415         
416         // free memory allocated to the tree item data CStrings
417
418         ClearPackageTree ();
419
420         // free memory allocated to the CDL database
421
422         if (m_CdlPkgData)
423                 delete m_CdlPkgData;
424
425 }
426
427 void CPkgAdminDlg::OnPkgadminAdd() 
428 {
429         CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, _T("eCos Package Files (*.epk)|*.epk||"), GetParent ());
430         TCHAR szBuffer [MAX_PATH * 16] = _T("");
431         dlg.m_ofn.lpstrFile = szBuffer;
432         dlg.m_ofn.nMaxFile = MAX_PATH * 16;
433         dlg.m_ofn.lpstrTitle = _T("Open eCos Package Files");
434         if (IDOK == dlg.DoModal ())
435         {
436                 bool bRepositoryChanged = false;
437                 POSITION posPathName = dlg.GetStartPosition ();
438                 while (posPathName)
439                 {
440                         // get an eCos package distribution file
441
442                         CString strPathName = dlg.GetNextPathName (posPathName);
443
444                         // extract the licence file
445
446                         CString strCommand;
447                         strCommand.Format (_T("add %s --extract_license"), strPathName);
448                         strCommand.Replace (_TCHAR('\\'), _TCHAR('/')); // backslashes -> forward slashes for Tcl_EvalFile
449                         EvalTclFile (3, strCommand);
450                         CString strLicenseFile = m_strRepository + _T("/pkgadd.txt");
451                         strLicenseFile.Replace (_TCHAR('/'), _TCHAR('\\')); // forward slashes -> backslashes for Win32
452
453                         // read the license file
454
455                         CFile fileLicenseFile;
456                         if (fileLicenseFile.Open (strLicenseFile, CFile::modeRead))
457                         {
458                                 TRACE (_T("License file found at %s\n"), strLicenseFile);
459                                 const DWORD dwLicenseLength = fileLicenseFile.GetLength ();
460                                 char * pszBuffer = new char [dwLicenseLength + 1]; // allocate a buffer
461                                 fileLicenseFile.Read (pszBuffer, dwLicenseLength);
462                                 fileLicenseFile.Close ();
463                                 CFile::Remove (strLicenseFile); // delete the license file when read
464                                 pszBuffer [dwLicenseLength] = NULL; // terminate the string in the buffer
465                                 CString strLicenseText (pszBuffer); // copy into a CString to convert to Unicode
466                                 delete [] pszBuffer;
467                                 if (-1 == strLicenseText.Find (_T("\r\n"))) // if the file has LF line endings...
468                                         strLicenseText.Replace (_T("\n"), _T("\r\n")); // ... replace with CRLF line endings
469
470                                 // display the license text
471
472                                 CPkgAdminLicenseDlg dlgLicense (this);
473                                 dlgLicense.m_strLicense = strLicenseText;
474                                 dlgLicense.SetCaption (strPathName + _T(" - Add Packages"));
475                                 if (IDOK != dlgLicense.DoModal ()) // if license not accepted by user
476                                         continue; // try the next file
477                         }
478
479                         // add the contents of the package distribution file
480
481                         strCommand.Format (_T("add %s --accept_license"), strPathName);
482                         strCommand.Replace (_TCHAR('\\'), _TCHAR('/')); // backslashes -> forward slashes for Tcl_EvalFile
483                         if (! EvalTclFile (3, strCommand))  // if not successful
484                                 continue; // try the next file
485
486                         bRepositoryChanged = true;
487                 }
488
489                 // refresh the package tree only if necessary
490
491                 if (bRepositoryChanged && ! PopulatePackageTree (m_strRepository))
492                         DestroyWindow ();
493         }
494 }
495
496 bool CPkgAdminDlg::EvalTclFile(int nArgc, LPCTSTR pszArgv)
497 {
498         CPkgAdminTclWaitDlg dlgWait;
499
500         TRACE (_T("Evaluating ecosadmin.tcl %s\n"), pszArgv);
501
502         // set up the data structure which is passed to the Tcl thread
503
504         CString strArgc;
505         strArgc.Format (_T("%d"), nArgc);
506         std::string argv0 = UnicodeToStdStr (m_strRepository) + "/ecosadmin.tcl";
507         std::string argv = UnicodeToStdStr (pszArgv);
508         std::string argc = UnicodeToStdStr (strArgc);
509         dlgWait.etsInfo.argv0 = (char *) argv0.c_str ();
510         dlgWait.etsInfo.argv = (char *) argv.c_str ();
511         dlgWait.etsInfo.argc = (char *) argc.c_str ();
512
513         // display the 'please wait' dialog
514         // the Tcl command is invoked from CPkgAdminTclWaitDlg::OnCreate()
515
516         CWaitCursor curWait;
517         dlgWait.DoModal ();
518         curWait.Restore ();
519
520         // retrieve status information from the data structure
521
522         int nStatus = dlgWait.etsInfo.status;
523         CString strErrorMessage (dlgWait.etsInfo.result);
524
525         // report any error
526
527         if (! strErrorMessage.IsEmpty ())
528         {
529                 AfxMessageBox (_T("Command execution error:\n\n") + strErrorMessage);
530                 return false;
531         }
532         else if (TCL_OK != nStatus)
533         {
534                 AfxMessageBox (_T("Command execution error"));
535                 return false;
536         }
537
538         return true;
539 }
540
541 bool CPkgAdminDlg::RemovePackageVersion(HTREEITEM hTreeItem)
542 {
543         const HTREEITEM hParentItem = m_ctrlPackageTree.GetParentItem (hTreeItem);
544         ASSERT (hParentItem);
545         CString * pstrPackage = (CString *) m_ctrlPackageTree.GetItemData (hParentItem);
546         ASSERT (pstrPackage);
547         CString strCommand;
548         strCommand.Format (_T("remove %s --version %s"), * pstrPackage, m_ctrlPackageTree.GetItemText (hTreeItem));
549         if (! EvalTclFile (3, strCommand)) // if not successful
550                 return false;
551         
552         m_ctrlPackageTree.DeleteItem (hTreeItem); // remove the selected item from the tree
553         return true;
554 }
555
556 void CPkgAdminDlg::OnPkgadminRepository() 
557 {
558         CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, _T("eCos Package Database Files (ecos.db)|ecos.db||"), GetParent ());
559         dlg.m_ofn.lpstrTitle = _T("Open eCos Package Database File");
560
561         int nStatus;
562         do
563         {
564                 nStatus = dlg.DoModal ();
565                 if (IDOK == nStatus)
566                 {
567                         const CString strPathName = dlg.GetPathName ();
568                         const int nPathNameIndex = strPathName.ReverseFind (_TCHAR('\\'));
569                         ASSERT (nPathNameIndex != -1);
570                         m_strRepository = strPathName.Mid (0, nPathNameIndex);
571                         m_strRepository.Replace (_TCHAR('\\'), _TCHAR('/'));
572                 }
573         }
574         while ((IDOK == nStatus) && ! PopulatePackageTree (m_strRepository));
575 }
576
577 void CPkgAdminDlg::OnSelchangedPkgadminTree(NMHDR*, LRESULT* pResult) 
578 {
579         //NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
580
581         // enable the remove button only if a node is selected
582         m_btnRemove.EnableWindow (NULL != m_ctrlPackageTree.GetSelectedItem ());
583
584         *pResult = 0;
585 }
586
587 std::string CPkgAdminDlg::UnicodeToStdStr(LPCTSTR str)
588 {
589         int nLength = 1 + _tcslen (str);
590         char * pszString = new char [nLength];
591
592         #ifdef _UNICODE
593         WideCharToMultiByte (CP_ACP, 0, str, -1, pszString, nLength, NULL, NULL);
594         #else
595         strcpy (pszString, str);
596         #endif
597
598         std::string stdstr = std::string (pszString);
599         delete [] pszString;
600         return stdstr;
601 }
602
603 bool CPkgAdminDlg::FindUserToolsPath()
604 {
605         HKEY hKey;
606         if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\Red Hat\\eCos\\Configuration Tool\\User Tools"), 0, KEY_READ, &hKey))
607                 return false;
608         
609         TCHAR szBuffer [MAX_PATH + 1];
610         DWORD dwBufferLength = MAX_PATH + 1;
611         LONG lStatus = RegQueryValueEx (hKey, _T("Folder"), NULL, NULL, (LPBYTE) szBuffer, &dwBufferLength);
612         RegCloseKey (hKey);
613         if (ERROR_SUCCESS != lStatus)
614                 return false;
615
616         m_strUserTools = szBuffer;
617         TRACE (_T("User tools found at %s\n"), m_strUserTools);
618         return ! m_strUserTools.IsEmpty ();
619 }