/[AnywhereTS-MSSQL]/trunk/TSAdminTool/frmConfigServices.cs
ViewVC logotype

Contents of /trunk/TSAdminTool/frmConfigServices.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 180 - (show annotations) (download)
Mon Jul 16 12:58:43 2012 UTC (7 years, 7 months ago) by william
File size: 28298 byte(s)
folderbrowserdialog must be on a thread with ApartmentState.STA set

1 #define DISALLOW_SETTING_OF_TFTP_FOLDER_ACLS // when defined will not allow RDP only acl to be placed on TFTP folder
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.Data;
6 using System.Drawing;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.IO;
10 using System.Security.AccessControl;
11 using System.Security.Principal;
12 using System.Threading;
13
14 namespace AnywhereTS
15 {
16
17 public partial class frmConfigServices : Form
18 {
19 public frmConfigServices()
20 {
21 InitializeComponent();
22 }
23
24 private atsDataSet.TftpServerDataTable datatableTFTP; // TFTP server directories
25 private atsDataSet.TerminalServerDataTable datatableTerminalServer; // terminal servers
26 const string strATSshareName = @"AnywhereTS$"; // The name of the AnywhereTS Win32 file share for the local TFTP server.
27 const string strShareDesc = @"Used by AnywhereTS";
28 private List<string> tftpUncPaths; // List with the corresponding UNC paths for items in lstTFTP.
29
30 private void frmConfigureMode_Load(object sender, EventArgs e)
31 {
32 //this.Cursor = Cursors.WaitCursor;
33
34 tftpUncPaths = new List<string>(); // Create a list for the TFTP UNC paths.
35
36 // Setup database
37 if (ProSupport.tftpServerTableAdapter == null || ProSupport.terminalServerTableAdapter == null) // Is database initiated?
38 {
39 // Databases is not initiated, do it now
40 ProSupport.InitDatabase();
41 }
42
43 datatableTFTP = new atsDataSet.TftpServerDataTable();
44 ProSupport.tftpServerTableAdapter.Fill(datatableTFTP);
45 datatableTerminalServer = new atsDataSet.TerminalServerDataTable();
46 ProSupport.terminalServerTableAdapter.Fill(datatableTerminalServer);
47
48 if (ATSGlobals.configured == 0)
49 { // ATS not configured yet
50 RadTSthisComputer.Checked = true;
51 txtTFTPpath.Text = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\AnywhereTS\TFTP";
52 radTFTPinternal.Checked = true;
53 }
54 else
55 { // ATS already configured.
56 txtTFTPpath.Text = ATSGlobals.strTFTPdir;
57 radTFTPinternal.Checked = (ATSGlobals.tftpConfig == 0);
58 radTFTPexternal.Checked = (ATSGlobals.tftpConfig == 1);
59 if (ATSGlobals.terminalServerConfig == 0)
60 { // This computer is terminal server
61
62 if (datatableTerminalServer.Rows.Count == 0) //Any other terminal servers?
63 { // No other terminal servers
64 RadTSthisComputer.Checked = true;
65 }
66 else
67 { // At least one other
68 radTSboth.Checked = true;
69 }
70 }
71 else
72 { // This computer is not terminal server
73 radTSother.Checked = true;
74 }
75
76 }
77
78
79 // Update terminal server list
80 UpdateTerminalServerList();
81
82 // Update TFTP server directories list
83 if (ATSGlobals.tftpConfig == 1)
84 {
85 UpdateTftpList();
86 }
87
88 helpProvider.HelpNamespace = ATSGlobals.strHelpFilePath; // Initiate helpProvider
89
90 UpdateControls();
91
92 this.Cursor = Cursors.Default;
93 }
94
95
96 private void btnOK_Click(object sender, EventArgs e)
97 {
98 this.Cursor = Cursors.WaitCursor;
99
100 if (RadTSthisComputer.Checked)
101 ATSGlobals.terminalServerConfig = 0;
102 else if (radTSboth.Checked)
103 ATSGlobals.terminalServerConfig = 0;
104 else if (radTSother.Checked)
105 ATSGlobals.terminalServerConfig = 1;
106 else
107 {
108 string error = "Error: Undefined terminal servers config (42001)";
109 using (log4net.NDC.Push(string.Format("terminalServerConfig={0}", ATSGlobals.terminalServerConfig)))
110 {
111 Logging.ATSAdminLog.Error(error);
112 }
113 MessageBox.Show(string.Format("{0} -> {1}", error, string.Format("terminalServerConfig={0}", ATSGlobals.terminalServerConfig)));
114 return;
115 }
116
117
118 string strPath; // The TFTP path
119 strPath = txtTFTPpath.Text.Trim();
120
121 if (radTFTPinternal.Checked)
122 { // We are using the internal TFTP
123 ATSGlobals.tftpConfig = 0; // Use ATS TFTP
124 // Validate TFTP directory
125 if (strPath.Length == 0)
126 {
127 this.Cursor = Cursors.Default;
128 MessageBox.Show("You must specifiy a directory for the AnywhereTS shared network files.");
129 txtTFTPpath.Focus();
130 return;
131 }
132
133 if (strPath.StartsWith(".") || strPath.StartsWith(@"\"))
134 {
135 this.Cursor = Cursors.Default;
136 MessageBox.Show("Invalid path for the AnywhereTS shared network files.");
137 using (log4net.NDC.Push(string.Format("path={0}", strPath)))
138 {
139 Logging.ATSAdminLog.Error("Invalid path for the AnywhereTS shared network files.");
140 }
141 txtTFTPpath.Focus();
142 return;
143 }
144
145 // Create TFTP directory
146 try
147 {
148 Directory.CreateDirectory(strPath);
149 }
150 catch (Exception ex)
151 {
152 this.Cursor = Cursors.Default;
153 MessageBox.Show("Could not create directory '" + strPath + "'. Error: " + ex.Message);
154 using (log4net.NDC.Push(string.Format("SqlException: MESSAGE={0}{1}Diagnostics:{1}{2}", ex.Message, System.Environment.NewLine, ex.ToString())))
155 {
156 using (log4net.NDC.Push(string.Format("directory={0}", strPath)))
157 {
158 Logging.ATSAdminLog.Error("Could not create directory.");
159 }
160 }
161 txtTFTPpath.Select();
162 return;
163 }
164
165 // Check that the directory is local
166 ShareUtil shUtil = new ShareUtil(); // Create a util class
167 if (shUtil.IsNetworkPath(strPath))
168 { // The path is a network path
169 MessageBox.Show("A network path cannot be used for the local TFTP server. Please enter a local path.");
170 txtTFTPpath.Select();
171 return;
172 }
173 // Save the TFTP directory to registry
174 ATSGlobals.strTFTPdir = strPath; // Set the C# version of TFTP dir
175 Globals.strTFTPdir = strPath; // Set the VB version of TFTP dir
176 ATSGlobals.SetATSRegValue(ATSGlobals.strRegTFTP_root, ATSGlobals.strTFTPdir);
177
178 // Delete all TFTP roots from database
179 foreach (DataRow row in datatableTFTP.Rows)
180 {
181 row.Delete();
182 }
183 ProSupport.tftpServerTableAdapter.Update(datatableTFTP);
184
185 if (!RadTSthisComputer.Checked)
186 { // There are external terminal servers.
187
188 // Create a share, save the UNC path to the database, add rights to TFTP directory
189 AddTFTPpath(ATSGlobals.strTFTPdir);
190 }
191 else
192 { // We are only using this computer as terminal server
193 SetTFTPrights(ATSGlobals.strTFTPdir);
194 }
195 }
196 else
197 {
198 // Use other TFTP
199 ATSGlobals.tftpConfig = 1; // Use other TFTP
200
201 if (lstTFTP.Items.Count == 0)
202 {
203 this.Cursor = Cursors.Default;
204 MessageBox.Show("You must choose at least one TFTP server root directory, where AnywhereTS can place client images and configurations.");
205 btnAddTFTPpath.Focus();
206 return;
207 }
208 }
209
210 // Check if we are using external terminal servers
211 if (RadTSthisComputer.Checked)
212 { // Only this computer is a terminal server. Delete all other terminal servers.
213 foreach (DataRow row in datatableTerminalServer.Rows)
214 {
215 row.Delete();
216 }
217 ProSupport.terminalServerTableAdapter.Update(datatableTerminalServer);
218 }
219 else
220 { // We have external terminal servers
221 if (lstTerminalServer.Items.Count == 0)
222 {
223 this.Cursor = Cursors.Default;
224 MessageBox.Show("You must specify at least one Terminal Server!");
225 btnAddTerminalServer.Focus();
226 return;
227 }
228
229 // Close database connections
230 datatableTFTP.Dispose();
231 datatableTerminalServer.Dispose();
232 ProSupport.clientTableAdapter.Connection.Close();
233 ProSupport.terminalServerTableAdapter.Connection.Close();
234 ProSupport.clientTableAdapter.Dispose();
235 ProSupport.terminalServerTableAdapter.Dispose();
236
237 // Configure SQL browser service (needed for the control panel to be able to access the database).
238
239 bool sqlServerRestarted = DatabaseSupport.EnableNamedPipes(); // Enable named pipes in the SQL server
240 DatabaseSupport.AutostartSQLbrowserService(); // Configure the SQL Browser service to autostart.
241 DatabaseSupport.StartSQLbrowserService(); // Start the SQL Browser service
242
243 if (sqlServerRestarted)
244 {
245 // SQL server was restarted. Try to reconnect to database in order to repair the database connectivity
246 ProSupport.InitDatabase();
247
248 try
249 {
250 datatableTFTP = new atsDataSet.TftpServerDataTable();
251 ProSupport.tftpServerTableAdapter.Fill(datatableTFTP); // This operation causes an error and forces the connectivity to recover.
252 }
253 catch
254 { // Do nothing, just catch the error that will most likely occur here.
255 }
256 finally
257 {
258 System.Threading.Thread.Sleep(5000); // Wait for the SQL connection to recover.
259 }
260 }
261 }
262
263 // Save DHCP options
264 if (radAtsDhcp.Checked)
265 {
266 ATSGlobals.dhcpConfig = 0; // Use the internal DCHP server
267 }
268 else
269 {
270 ATSGlobals.dhcpConfig = 1; // Use the other DCHP server
271 }
272
273 // Save TFTP configuration to registry
274 ATSGlobals.SetATSRegValue(ATSGlobals.strRegTFTPconfig,ATSGlobals.tftpConfig);
275
276 // Save DCHP configuration to registry
277 ATSGlobals.SetATSRegValue(ATSGlobals.strRegDHCPconfig, ATSGlobals.dhcpConfig);
278
279 // Terminate window
280 this.Cursor = Cursors.Default;
281 DialogResult = DialogResult.OK;
282 }
283
284
285 private void AddTFTPpath(string strPath)
286 {
287 string uncPath; // The path in UNC format
288 string strLocalPath = ""; // Local path to save in database for display purposes. Only set if path is local
289
290 ShareUtil shUtil = new ShareUtil(); // Create a util class
291
292 // Check if path is a network path
293 if (shUtil.IsNetworkPath(strPath))
294 { // The path is a network path
295 if (strPath.StartsWith("\\"))
296 { // The network path is a UNC path, no need to convert it
297 uncPath = strPath;
298 }
299 else
300 { // The network path is not a UNC path, convert it
301 uncPath = UNCconverter.ConvertLocalPathToUnc(strPath);
302 }
303 }
304 else
305 { // User is adding a local path
306 strLocalPath = strPath;
307 string strThisComputer = Environment.MachineName; // The name of this computer
308 // Compile the UNC path
309 uncPath = @"\\" + strThisComputer + @"\" + strATSshareName;
310
311 // Delete ATS share if it exists
312 shUtil.DeleteShare(strATSshareName);
313
314 // Delete share from database if it exists
315 ProSupport.tftpServerTableAdapter.Fill(datatableTFTP); // Refresh data table
316 DataRow rowToDelete;
317 rowToDelete = datatableTFTP.Rows.Find(uncPath);
318 if (rowToDelete != null)
319 { // The local TFTP path exists in database, delete it
320 rowToDelete.Delete();
321 ProSupport.tftpServerTableAdapter.Update(datatableTFTP);
322 }
323
324 // Create network share
325
326 uint nRetVal;
327 nRetVal = shUtil.CreateShare(strShareDesc, strATSshareName, strPath);
328 if (nRetVal == 0)
329 {
330 // Share created
331 }
332 else
333 {
334 // Error
335 MessageBox.Show("Could not create a share for the AnywereTS TFTP data. Do you have sufficient rights? (25322)");
336 return;
337 }
338
339 }
340
341 // Add the remote or local directory path to the database
342 if (uncPath.Length <= 255)
343 { // The path will fit in the database
344 atsDataSet.TftpServerRow row = (atsDataSet.TftpServerRow)datatableTFTP.NewRow();
345 row["Path"] = uncPath;
346 row["LocalPath"] = strLocalPath;
347
348 try
349 {
350 datatableTFTP.AddTftpServerRow(row);
351 }
352 catch (ConstraintException)
353 {
354 MessageBox.Show("'" + uncPath + "' is already in the list.");
355 return;
356 }
357
358 ProSupport.tftpServerTableAdapter.Update(datatableTFTP);
359
360 // Ask if we are going to add righs to the TFTP root directory, set rights.
361 SetTFTPrights(row["Path"].ToString());
362 UpdateTftpList(); // Update the list box
363 lstTFTP.Select();
364 }
365 else
366 { // Path is too long
367 MessageBox.Show("The directory path is too long, please use a path that is max 255 character");
368 }
369
370 }
371
372 private void radAtsDhcp_CheckedChanged(object sender, EventArgs e)
373 {
374 UpdateControls(); // Set text "Next >" or "Finish" on the Ok button
375 }
376
377 private void radExternalDhcp_CheckedChanged(object sender, EventArgs e)
378 {
379 UpdateControls(); // Set text "Next >" or "Finish" on the Ok button
380 }
381
382 private void UpdateControls()
383 {
384 if (RadTSthisComputer.Checked)
385 { // Only this computer as terminal server
386 lblTerminalServers.Enabled = false;
387 lstTerminalServer.Enabled = false;
388 btnAddTerminalServer.Enabled = false;
389 btnDeleteTerminalServer.Enabled = false;
390 }
391 else
392 { // Other terminal servers
393 lblTerminalServers.Enabled = true;
394 lstTerminalServer.Enabled = true;
395 btnAddTerminalServer.Enabled = true;
396 if (lstTerminalServer.SelectedIndex == -1)
397 btnDeleteTerminalServer.Enabled = false;
398 else
399 btnDeleteTerminalServer.Enabled = true;
400 }
401
402 if (radTFTPinternal.Checked)
403 {
404 lblTFTPpath.Enabled = true;
405 txtTFTPpath.Enabled = true;
406 btnBrowseTFTP.Enabled = true;
407 lblTFTPdirectories.Enabled = false;
408 lstTFTP.Enabled = false;
409 btnAddTFTPpath.Enabled = false;
410 btnDeleteTFTP.Enabled = false;
411 radAtsDhcp.Enabled = true;
412 lstTFTP.SelectedIndex = -1;
413 btnOK.Text = "Next >";
414 }
415 else
416 {
417 lblTFTPdirectories.Enabled = true;
418 lstTFTP.Enabled = true;
419 btnAddTFTPpath.Enabled = true;
420 if (lstTFTP.SelectedIndex == -1)
421 btnDeleteTFTP.Enabled = false;
422 else
423 btnDeleteTFTP.Enabled = true;
424 lblTFTPpath.Enabled = false;
425 txtTFTPpath.Enabled = false;
426 btnBrowseTFTP.Enabled = false;
427 btnOK.Text = "Finish";
428 radAtsDhcp.Enabled = false;
429 radExternalDhcp.Checked = true;
430 }
431 }
432
433 private void radTFTPinternal_CheckedChanged(object sender, EventArgs e)
434 {
435 UpdateControls();
436 }
437
438 private void radTFTPexternal_CheckedChanged(object sender, EventArgs e)
439 {
440 if (radTFTPexternal.Checked && ATSGlobals.tftpConfig == 0)
441 { // We have just de-selected internal TFTP server
442
443 // Delete all TFTP roots from database
444 foreach (DataRow row in datatableTFTP.Rows)
445 {
446 row.Delete();
447 }
448 ProSupport.tftpServerTableAdapter.Update(datatableTFTP);
449 UpdateTftpList();
450
451 // Delete the file share for the internal TFTP directory if it exists.
452 ShareUtil shUtil = new ShareUtil(); // Create a util class
453 shUtil.DeleteShare("AnywhereTS$");
454
455 // ATS is now in a non configured state
456 ATSGlobals.configured = 0;
457 ATSGlobals.SetATSRegValue(ATSGlobals.strRegConfigured, ATSGlobals.configured);
458 }
459 UpdateControls();
460 }
461
462 // Update the list with TFTP directories from database.
463 private void UpdateTftpList()
464 {
465 lstTFTP.Items.Clear();
466 tftpUncPaths.Clear();
467 ProSupport.tftpServerTableAdapter.Fill(datatableTFTP);
468 foreach (DataRow row in datatableTFTP.Rows)
469 { // Display local path if possible
470
471
472 lstTFTP.Items.Add(ProSupport.GetTftpPath(row));
473 //string gg = row["Path"].ToString();
474 //tftpUncPaths.Add(gg);
475 tftpUncPaths.Add(row["Path"].ToString()); // Add the UNC path to the list.
476 }
477 btnDeleteTFTP.Enabled = false;
478 }
479
480 // Update the list with terminal servers from database.
481 private void UpdateTerminalServerList()
482 {
483 lstTerminalServer.Items.Clear();
484 foreach (DataRow row in datatableTerminalServer.Rows)
485 {
486 lstTerminalServer.Items.Add(row["Path"].ToString());
487 }
488 btnDeleteTerminalServer.Enabled = false;
489 }
490
491 private void lstTFTP_SelectedIndexChanged(object sender, EventArgs e)
492 {
493 if (lstTFTP.SelectedIndex == -1)
494 { // No item selcted in the TFTP directory list
495 btnDeleteTFTP.Enabled = false;
496 }
497 else
498 { // User has selcted an item in the list
499 btnDeleteTFTP.Enabled = true;
500 }
501 }
502
503 // Delete the row selected in the TFTP directory list box.
504 private void btnDeleteTFTP_Click(object sender, EventArgs e)
505 {
506 DataRow rowToDelete;
507 rowToDelete = datatableTFTP.Rows.Find(tftpUncPaths[lstTFTP.SelectedIndex]);
508 rowToDelete.Delete();
509 ProSupport.tftpServerTableAdapter.Update(datatableTFTP);
510 UpdateTftpList(); // Update the list box
511
512 if (datatableTFTP.Rows.Count == 0)
513 { // Last row deleted
514 // ATS is now in a non configured state
515 ATSGlobals.configured = 0;
516 ATSGlobals.SetATSRegValue(ATSGlobals.strRegConfigured, ATSGlobals.configured);
517 }
518 }
519
520 // Set user rights to TFTP directory, all remote desktop users should be able to write files.
521 void SetTFTPrights(string path)
522 {
523 #if DISALLOW_SETTING_OF_TFTP_FOLDER_ACLS
524 return;
525 #else
526 // Ask if we are going to add righs to the TFTP root directory
527 DialogResult resultRights;
528 resultRights = MessageBox.Show(this, "In order for users to use the AnywhereTS control panel, they need rights to write in the TFTP root directory. Do you want AnywhereTS to add these rights now?", "AnywhereTS", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
529 if (resultRights == DialogResult.Yes)
530 {
531 try
532 {
533 // Create a new DirectoryInfo object.
534 DirectoryInfo dInfo = new DirectoryInfo(path);
535 // Get a DirectorySecurity object that represents the
536 // current security settings.
537 DirectorySecurity dSecurity = dInfo.GetAccessControl();
538 // Add a FileSystemAccessRule to the security settings, to allow write.
539 // No general rights to delete files. These rights are set on the individual files.
540 dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinRemoteDesktopUsersSid, null), FileSystemRights.WriteData, AccessControlType.Allow));
541 // Set the new access settings.
542 dInfo.SetAccessControl(dSecurity);
543 }
544 catch (Exception ex)
545 {
546 this.Cursor = Cursors.Default;
547 MessageBox.Show("Could not set user access rights for TFTP directory. Do you have sufficient right? (29991). Error: " + ex.Message);
548 using (log4net.NDC.Push(string.Format("SqlException: MESSAGE={0}{1}Diagnostics:{1}{2}", ex.Message, System.Environment.NewLine, ex.ToString())))
549 {
550 Logging.ATSAdminLog.Error("Could not set user access rights for TFTP directory.");
551 }
552 return;
553 }
554 }
555 #endif
556 }
557
558 private void btnDeleteTerminalServer_Click(object sender, EventArgs e)
559 {
560 DataRow rowToDelete;
561 rowToDelete = datatableTerminalServer.Rows.Find(lstTerminalServer.SelectedItem);
562 rowToDelete.Delete();
563 ProSupport.terminalServerTableAdapter.Update(datatableTerminalServer);
564 UpdateTerminalServerList(); // Update the list box
565 }
566
567 private void btnAddTerminalServer_Click(object sender, EventArgs e)
568 {
569 // Show dialog
570 frmAddTerminalServer addTSdialog = new frmAddTerminalServer();
571 DialogResult result = addTSdialog.ShowDialog();
572 if (result == DialogResult.OK)
573 {
574 // Add the server to the database
575 if (addTSdialog.inputstring.Trim().Length <= 255)
576 { // The path will fit in the database
577 atsDataSet.TerminalServerRow row = (atsDataSet.TerminalServerRow)datatableTerminalServer.NewRow();
578 row["Path"] = addTSdialog.inputstring.Trim();
579 try
580 {
581 datatableTerminalServer.AddTerminalServerRow(row);
582 }
583 catch (ConstraintException)
584 {
585 MessageBox.Show("'" + row["Path"] + "' is already in the list.");
586 return;
587 }
588
589 ProSupport.terminalServerTableAdapter.Update(datatableTerminalServer);
590
591 UpdateTerminalServerList(); // Update the list box
592 lstTerminalServer.Select();
593 }
594 else
595 { // Path is too long
596 MessageBox.Show("The server path is too long, please use a path that is max 255 character");
597 }
598 }
599 }
600
601 private void lstTerminalServer_SelectedIndexChanged(object sender, EventArgs e)
602 {
603 if (lstTerminalServer.SelectedIndex == -1)
604 { // No item selcted in the TFTP directory list
605 btnDeleteTerminalServer.Enabled = false;
606 }
607 else
608 { // User has selcted an item in the list
609 btnDeleteTerminalServer.Enabled = true;
610 }
611 }
612
613 private void RadTSthisComputer_CheckedChanged(object sender, EventArgs e)
614 {
615 UpdateControls();
616 }
617
618 private void radTSother_CheckedChanged(object sender, EventArgs e)
619 {
620 UpdateControls();
621 }
622
623 private void radTSboth_CheckedChanged(object sender, EventArgs e)
624 {
625 UpdateControls();
626 }
627
628 // Add a TFTP server
629 private void btnAddTFTPpath_Click(object sender, EventArgs e)
630 {
631 // Show dialog
632 frmAddTFTP addTFTPdialog = new frmAddTFTP();
633 DialogResult result = addTFTPdialog.ShowDialog();
634 if (result == DialogResult.OK)
635 {
636 string strPath;
637 strPath = addTFTPdialog.inputstring.Trim();
638
639 if (Directory.Exists(strPath))
640 {
641 // Convert to UNC, share local directory, add directory to database
642 AddTFTPpath(strPath);
643 }
644 else
645 {
646 MessageBox.Show("Error: Cannot find or access the directory. Please check name and rights. (34212)");
647 }
648 UpdateTftpList();
649 }
650 }
651 string tftp_path = string.Empty;
652 private void btnBrowseTFTP_Click(object sender, EventArgs e)
653 {
654 var t = new Thread(new ThreadStart(CreateFolderBrowser));
655 t.IsBackground = true;
656 t.SetApartmentState(ApartmentState.STA);
657 t.Start();
658 while (t.IsAlive) { Application.DoEvents(); }
659 txtTFTPpath.Text = tftp_path;
660 txtTFTPpath.Select();
661 }
662 private void CreateFolderBrowser()
663 {
664 folderBrowserDialog = new FolderBrowserDialog();
665 folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
666 DialogResult result = folderBrowserDialog.ShowDialog();
667 if (result != DialogResult.OK) return;
668 tftp_path = folderBrowserDialog.SelectedPath.Trim();
669 }
670 }
671 }
672

  ViewVC Help
Powered by ViewVC 1.1.22