/[RomCheater]/trunk/RomCheater/Main.cs
ViewVC logotype

Contents of /trunk/RomCheater/Main.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 587 - (show annotations) (download)
Thu Jun 6 09:12:35 2013 UTC (7 years, 10 months ago) by william
File size: 23764 byte(s)

1 #region Logging Defines
2 // include this any class or method that required logging, and comment-out what is not needed
3
4 #region Enabled logging levels
5 #define LOGGING_ENABLE_INFO
6 #define LOGGING_ENABLE_WARN
7 #define LOGGING_ENABLE_DEBUG
8 #define LOGGING_ENABLE_VERBOSEDEBUG
9 #define LOGGING_ENABLE_ERROR
10 #define LOGGING_ENABLE_VERBOSEERROR
11 #define LOGGING_ENABLE_PROFILER
12 #endregion
13 #endregion
14 #define FORCE_ALL_LOGGING_FLAGS // when defined will force logging flags to ALL
15 #define SHOW_DEBUG_MENU // when defined will show the debug menu or else it will be hidden
16 using System;
17 using System.Collections.Generic;
18 using System.ComponentModel;
19 using System.Data;
20 using System.Drawing;
21 using System.Linq;
22 using System.Text;
23 using System.Windows.Forms;
24 using RomCheater.Logging;
25 using RomCheater.Properties;
26 using RomCheater.UserSettingsSupport;
27 using RomCheater.PluginFramework.Core;
28 using System.Diagnostics;
29 using RomCheater.PluginFramework.Interfaces;
30 using WeifenLuo.WinFormsUI.Docking;
31 using RomCheater.Docking;
32 using System.IO;
33 using Sojaner.MemoryScanner;
34 using RomCheater.PluginFramework.Events;
35 using RomCheater.Serialization;
36
37 namespace RomCheater
38 {
39 public partial class Main : Form
40 {
41 private bool m_bSaveLayout = true;
42 private Process SelectedProcess = null;
43 private DeserializeDockContent m_deserializeDockContent;
44 private FloatingLogWindow m_LogWindow = new FloatingLogWindow();
45 private FloatingAboutBox m_AboutBox = new FloatingAboutBox();
46 private FloatingRamDumperDialog m_RamDump = new FloatingRamDumperDialog();
47 private FloatingPIDSelector m_PIDSelector = new FloatingPIDSelector();
48 private FloatingMemoryView m_memoryview = new FloatingMemoryView();
49 private FloatingDataTypeConverter m_typeconverter = new FloatingDataTypeConverter();
50 private FloatingMemorySearcher m_memsearcher = new FloatingMemorySearcher();
51 private FloatingPEViewer m_peviewer = new FloatingPEViewer();
52 private FloatingRVACalculator m_rvacalc = new FloatingRVACalculator();
53
54 private FloatingUserControlDock m_ucd = new FloatingUserControlDock();
55
56 //private bool log_window_expanded = false;
57 //private double log_window_splitter_default_position = 1.4045;
58 PluginLoader loader = null;
59 IConfigPlugin ConfigPlugin = null;
60 IInputPlugin InputPlugin = null;
61 IWindowPlugin WindowPlugin = null;
62 List<IUserControlPlugin> UserControlPlugins = null;
63 static Main() { SettingSubscriber.AddSubscriber(new Main(), Settings.Default); }
64 //private const string t = "RomCheater";
65 #region LogWriterSupport
66 static LogWriter _LoggerInstance;
67 static LogWriter LoggerInstance
68 {
69 get { return _LoggerInstance; }
70 set { _LoggerInstance = value; }
71 }
72 #endregion
73
74
75 private void OnProcessChanged(ProcessChangedEventArgs e)
76 {
77 if (m_memsearcher.SearchInProgess)
78 {
79 DialogResult result = MessageBox.Show("Do you want to start a new search with the selected process?", "A memory search is currently in progress", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3);
80 if (result != DialogResult.Yes || result != DialogResult.OK) { return; }
81 m_memsearcher = null; //free memory used by the memory searcher
82 m_memsearcher = new FloatingMemorySearcher();
83 }
84 SelectedProcess = Process.GetProcessById(e.ProcessID);
85 m_RamDump.AcceptedPlugin = this.ConfigPlugin;
86 m_RamDump.AcceptedProcess = SelectedProcess;
87
88 m_peviewer.AcceptedPlugin = this.ConfigPlugin;
89 m_peviewer.AcceptedProcess = SelectedProcess;
90 m_peviewer.OnPEDataUpdated += new BaseEventHandler<PEViewerDataUpdatedEventArgs>(OnPEDataUpdated);
91
92 m_memoryview.AcceptedPlugin = this.ConfigPlugin;
93 m_memoryview.AcceptedProcess = SelectedProcess;
94
95 m_memsearcher.AcceptedPlugin = this.ConfigPlugin;
96 m_memsearcher.AcceptedProcess = SelectedProcess;
97 m_memsearcher.OnBrowseMemoryRegion += new BaseEventHandler<BrowseMemoryRegionEvent>(OnBrowseMemoryRegion);
98
99 }
100
101 void OnPEDataUpdated(PEViewerDataUpdatedEventArgs e)
102 {
103 m_memoryview.SetPEViewerData(e.peData);
104 m_memsearcher.SetPEViewerData(e.peData);
105 m_rvacalc.SetPEViewerData(e.peData);
106 }
107 private void OnBrowseMemoryRegion(BrowseMemoryRegionEvent e)
108 {
109 m_memoryview.BrowseMemoryRegion(e.MemoryRegion);
110 }
111
112 #region Dock Support
113 void AddDockToWindowList(object sender, EventArgs e)
114 {
115 DockContent dc;
116 TypeBinder.Bind(sender, out dc);
117 ToolStripMenuItem tsmi = new ToolStripMenuItem(dc.Text);
118 tsmi.Name = dc.Name;
119 tsmi.Tag = dc;
120 tsmi.Click += new EventHandler(tsmi_Click);
121 mnuWindows.DropDownItems.Add(tsmi);
122 }
123 void tsmi_Click(object sender, EventArgs e)
124 {
125 ToolStripMenuItem tsmi;
126 TypeBinder.Bind(sender, out tsmi);
127 DockContent dc;
128 TypeBinder.Bind(tsmi.Tag, out dc);
129 dc.Activate();
130 }
131 void RemoveDockFromWindowList(object sender, FormClosedEventArgs e)
132 {
133 DockContent dc;
134 TypeBinder.Bind(sender, out dc);
135 mnuWindows.DropDownItems.RemoveByKey(dc.Name);
136 }
137 private IDockContent GetContentFromPersistString(string persistString)
138 {
139 if (persistString == typeof(FloatingLogWindow).ToString()) { return m_LogWindow; }
140 if (persistString == typeof(FloatingRamDumperDialog).ToString()) { return m_RamDump; }
141 if (persistString == typeof(FloatingPIDSelector).ToString()) { return m_PIDSelector; }
142 if (persistString == typeof(FloatingMemoryView).ToString()) { return m_memoryview; }
143 if (persistString == typeof(FloatingDataTypeConverter).ToString()) { return m_typeconverter; }
144 if (persistString == typeof(FloatingMemorySearcher).ToString()) { return m_memsearcher; }
145 if (persistString == typeof(FloatingPEViewer).ToString()) { return m_peviewer; }
146 if (persistString == typeof(FloatingRVACalculator).ToString()) { return m_rvacalc; }
147 if (persistString == typeof(FloatingUserControlDock).ToString()) { return m_ucd; }
148 else { return null; }
149 }
150 public void SetupDocks()
151 {
152 m_LogWindow = new FloatingLogWindow();
153 m_AboutBox = new FloatingAboutBox();
154 m_RamDump = new FloatingRamDumperDialog();
155 m_PIDSelector = new FloatingPIDSelector();
156 m_PIDSelector.OnSelectedProcessChanged += new BaseEventHandler<ProcessChangedEventArgs>(OnProcessChanged);
157 m_memoryview = new FloatingMemoryView();
158 m_typeconverter = new FloatingDataTypeConverter();
159 m_memsearcher = new FloatingMemorySearcher();
160 m_memsearcher.OnBrowseMemoryRegion += new BaseEventHandler<BrowseMemoryRegionEvent>(OnBrowseMemoryRegion);
161 m_peviewer = new FloatingPEViewer();
162 m_peviewer.OnPEDataUpdated += new BaseEventHandler<PEViewerDataUpdatedEventArgs>(OnPEDataUpdated);
163 m_rvacalc = new FloatingRVACalculator();
164 m_ucd = new FloatingUserControlDock();
165 m_deserializeDockContent = new DeserializeDockContent(GetContentFromPersistString);
166 }
167 #region SetupDockWindowHandler support
168 public void SetupDockWindowHandler()
169 {
170 SetupLogWindowHandler();
171 SetupRamDumpWindowHandler();
172 SetupMemoryViewWindowHandler();
173 SetupPIDSelectorWindowHandler();
174 SetupDataTypeConverterWindowHandler();
175 SetupMemorySearchWindowHandler();
176 SetupPEViewerWindowHandler();
177 SetupRVACalculatorWindowHandler();
178 SetupUserControlDockWindowHandler();
179 }
180 private void SetupLogWindowHandler()
181 {
182 if (m_LogWindow == null) return;
183 m_LogWindow.Shown += new EventHandler(AddDockToWindowList);
184 m_LogWindow.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
185 m_LogWindow.Activate();
186 }
187 private void SetupRamDumpWindowHandler()
188 {
189 if (m_RamDump == null) return;
190 m_RamDump.Shown += new EventHandler(AddDockToWindowList);
191 m_RamDump.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
192 m_RamDump.AcceptedPlugin = ConfigPlugin;
193 m_RamDump.Activate();
194 }
195 private void SetupMemoryViewWindowHandler()
196 {
197 if (m_memoryview == null) return;
198 m_memoryview.Shown += new EventHandler(AddDockToWindowList);
199 m_memoryview.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
200 m_memoryview.AcceptedPlugin = ConfigPlugin;
201 m_memoryview.Activate();
202 }
203 private void SetupPIDSelectorWindowHandler()
204 {
205 if (m_PIDSelector == null) return;
206 m_PIDSelector.Shown += new EventHandler(AddDockToWindowList);
207 m_PIDSelector.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
208 m_PIDSelector.AcceptedPlugin = ConfigPlugin;
209 m_PIDSelector.Activate();
210 }
211 private void SetupDataTypeConverterWindowHandler()
212 {
213 if (m_typeconverter == null) return;
214 m_typeconverter.Shown += new EventHandler(AddDockToWindowList);
215 m_typeconverter.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
216 m_typeconverter.Activate();
217 }
218 private void SetupMemorySearchWindowHandler()
219 {
220 if (m_memsearcher == null) return;
221 m_memsearcher.Shown += new EventHandler(AddDockToWindowList);
222 m_memsearcher.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
223 m_memsearcher.Activate();
224 }
225 private void SetupPEViewerWindowHandler()
226 {
227 if (m_peviewer == null) return;
228 m_peviewer.Shown += new EventHandler(AddDockToWindowList);
229 m_peviewer.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
230 m_PIDSelector.AcceptedPlugin = ConfigPlugin;
231 m_peviewer.Activate();
232 }
233 private void SetupRVACalculatorWindowHandler()
234 {
235 if (m_rvacalc == null) return;
236 m_rvacalc.Shown += new EventHandler(AddDockToWindowList);
237 m_rvacalc.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
238 m_rvacalc.AcceptedPlugin = ConfigPlugin;
239 m_rvacalc.Activate();
240 }
241 private void SetupUserControlDockWindowHandler()
242 {
243 if (m_ucd == null) return;
244 m_ucd.Shown += new EventHandler(AddDockToWindowList);
245 m_ucd.FormClosed += new FormClosedEventHandler(RemoveDockFromWindowList);
246 m_ucd.Activate();
247 }
248 #endregion
249 public void ShowDocks()
250 {
251 ShowLogWindow();
252 SetupLogWindowHandler();
253 //ShowAboutBox();
254 ShowRamDump();
255 SetupRamDumpWindowHandler();
256 ShowMemoryView();
257 SetupMemoryViewWindowHandler();
258 ShowPidSelector();
259 SetupPIDSelectorWindowHandler();
260 ShowDataTypeConverter();
261 SetupDataTypeConverterWindowHandler();
262
263 ShowRVACalculator();
264 SetupRVACalculatorWindowHandler();
265
266 ShowUserControlDock();
267 SetupUserControlDockWindowHandler();
268
269
270 ShowMemorySearch();
271 SetupMemorySearchWindowHandler();
272 ShowPEViewer();
273 SetupPEViewerWindowHandler();
274
275
276 }
277 public void ShowLogWindow()
278 {
279 if (m_LogWindow == null || m_LogWindow.IsDisposed) { m_LogWindow = new FloatingLogWindow(); }
280 LoggerInstance = m_LogWindow.Logwriter;
281 LoggerInstance.CreateNewLog(false);
282 m_LogWindow.Show(dockPanel, DockState.DockBottom);
283 }
284 public void ShowAboutBox()
285 {
286 if (m_AboutBox == null || m_AboutBox.IsDisposed) { m_AboutBox = new FloatingAboutBox(); }
287 m_AboutBox.ShowDialog();
288 }
289 public void ShowRamDump()
290 {
291 load_plugins_silent();
292 m_RamDump = new FloatingRamDumperDialog(ConfigPlugin);
293 m_RamDump.AcceptedProcess = SelectedProcess;
294 m_RamDump.Show(dockPanel);
295 }
296 public void ShowMemoryView()
297 {
298 load_plugins_silent();
299 m_memoryview = new FloatingMemoryView(ConfigPlugin);
300 m_memoryview.AcceptedProcess = SelectedProcess;
301 m_memoryview.Show(dockPanel);
302 }
303 public void ShowPidSelector()
304 {
305 load_plugins_silent();
306 //List<Process> procs = ConfigPlugin.ValidProcessesForPlugin;
307 m_PIDSelector = new FloatingPIDSelector(ConfigPlugin);
308 m_PIDSelector.OnSelectedProcessChanged += new BaseEventHandler<ProcessChangedEventArgs>(OnProcessChanged);
309 m_PIDSelector.Show(dockPanel);
310 }
311 public void ShowDataTypeConverter()
312 {
313 if (m_typeconverter == null || m_typeconverter.IsDisposed) { m_typeconverter = new FloatingDataTypeConverter(); }
314 m_typeconverter.Show(dockPanel, DockState.DockRightAutoHide);
315 }
316 public void ShowMemorySearch()
317 {
318 load_plugins_silent();
319 m_memsearcher = new FloatingMemorySearcher(ConfigPlugin);
320 m_memsearcher.AcceptedProcess = SelectedProcess;
321 m_memsearcher.OnBrowseMemoryRegion += new BaseEventHandler<BrowseMemoryRegionEvent>(OnBrowseMemoryRegion);
322 m_memsearcher.Show(dockPanel);
323 }
324 public void ShowPEViewer()
325 {
326 load_plugins_silent();
327 m_peviewer = new FloatingPEViewer(ConfigPlugin);
328 m_peviewer.AcceptedProcess = SelectedProcess;
329 m_peviewer.OnPEDataUpdated += new BaseEventHandler<PEViewerDataUpdatedEventArgs>(OnPEDataUpdated);
330 m_peviewer.Show(dockPanel);
331 }
332 public void ShowRVACalculator()
333 {
334 load_plugins_silent();
335 m_rvacalc = new FloatingRVACalculator(ConfigPlugin);
336 m_rvacalc.AcceptedProcess = SelectedProcess;
337 m_rvacalc.Show(dockPanel, DockState.DockRightAutoHide);
338 }
339 public void ShowUserControlDock()
340 {
341 load_plugins_silent();
342 m_ucd = new FloatingUserControlDock(UserControlPlugins);
343 m_ucd.Show(dockPanel, DockState.DockRightAutoHide);
344 }
345 #endregion
346
347
348 public Main() : this(false) { }
349 public Main(bool no_console_redirect)
350 {
351 InitializeComponent();
352 #if SHOW_DEBUG_MENU
353 mnuDebug.Visible = true;
354 #else
355 mnuDebug.Visible = false;
356 #endif
357 load_loggerflags();
358 SetupDocks();
359 LoggerInstance = m_LogWindow.Logwriter;
360 LoggerInstance.CreateNewLog(false);
361 logger.ForceLog.Info.WriteLine("LoggingFlags = 0x{0:x4} ({1})", logger.GetLoggingFlags().Value, logger.GetLoggingFlags().Name);
362 load_plugins();
363 if (no_console_redirect)
364 LoggerInstance.RedirectConsoleOutput = false;
365
366
367
368 }
369 private void load_loggerflags()
370 {
371 logger.SetLoggingFlags(Logging.Properties.Settings.Default.LoggingFlags);
372 #if FORCE_ALL_LOGGING_FLAGS
373 logger.SetLoggingFlags(loggerflags.ALL);
374 #endif
375 }
376 private void load_plugins() { load_plugins(false); }
377 private void load_plugins_silent() { load_plugins(true); }
378 private void load_plugins(bool silent)
379 {
380 loader = new PluginLoader();
381 loader.LoadPlugins(silent);
382
383 ConfigPlugin = loader.GetConfigPlugin(RomCheater.Properties.Settings.Default.LastConfigPlugin);
384 if (ConfigPlugin != null && !silent)
385 logger.Info.WriteLine("Loaded Config Plugin: {0}", ConfigPlugin.ToString());
386 InputPlugin = loader.GetInputPlugin(RomCheater.Properties.Settings.Default.LastInputPlugin);
387 if (InputPlugin != null && !silent)
388 logger.Info.WriteLine("Loaded Input Plugin: {0}", InputPlugin.ToString());
389 WindowPlugin = loader.GetWindowPlugin(RomCheater.Properties.Settings.Default.LastWindowPlugin);
390 if (WindowPlugin != null && !silent)
391 logger.Info.WriteLine("Loaded Window Plugin: {0}", WindowPlugin.ToString());
392
393
394 UserControlPlugins = new List<IUserControlPlugin>(loader.LoadedUserControlPlugins);
395 if (UserControlPlugins != null && !silent && UserControlPlugins.Count > 0)
396 {
397 foreach (var t in UserControlPlugins)
398 {
399 logger.Info.WriteLine("Loaded UserControl Plugin: {0}", t.ToString());
400 }
401 }
402
403
404
405 m_PIDSelector.AcceptedPlugin = ConfigPlugin;
406 m_RamDump.AcceptedPlugin = ConfigPlugin;
407 m_memoryview.AcceptedPlugin = ConfigPlugin;
408 m_memsearcher.AcceptedPlugin = ConfigPlugin;
409 m_PIDSelector.AcceptedPlugin = ConfigPlugin;
410 if (this.SelectedProcess != null)
411 {
412 m_RamDump.AcceptedProcess = SelectedProcess;
413 m_memoryview.AcceptedProcess = SelectedProcess;
414 m_memsearcher.AcceptedProcess = SelectedProcess;
415 }
416
417 }
418
419 private void mnuItemExit_Click(object sender, EventArgs e)
420 {
421 this.Close();
422 }
423
424
425 private void Main_Load(object sender, EventArgs e)
426 {
427
428 }
429
430 private void mnuItemConfig_Click(object sender, EventArgs e)
431 {
432 RomCheaterConfigDialog dlg = new RomCheaterConfigDialog(loader);
433 dlg.ShowDialog();
434 logger.ForceLog.Info.WriteLine("LoggingFlags = 0x{0:x4} ({1})", logger.GetLoggingFlags().Value, logger.GetLoggingFlags().Name);
435 // reload plugins
436 load_plugins(true);
437 }
438
439 private void mnuItemOpenProcess_Click(object sender, EventArgs e)
440 {
441 ////List<Process> procs = ConfigPlugin.ValidProcessesForPlugin;
442 //PIDSelector selector = new PIDSelector(ConfigPlugin);
443 //selector.ShowDialog();
444 }
445
446 private void Main_Shown(object sender, EventArgs e)
447 {
448 //dockPanel.SuspendLayout(true);
449 //ShowDocks();
450 string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");
451 if (File.Exists(configFile))
452 {
453 try
454 {
455 dockPanel.LoadFromXml(configFile, m_deserializeDockContent);
456 SetupDockWindowHandler();
457 }
458 catch (Exception)
459 {
460 this.Controls.Remove(dockPanel);
461 dockPanel = new DockPanel();
462 dockPanel.Dock = DockStyle.Fill;
463 dockPanel.DocumentStyle = DocumentStyle.DockingWindow;
464 this.Controls.Add(dockPanel);
465 ShowDocks();
466 }
467 }
468 else
469 {
470 ShowDocks();
471 }
472
473 //dockPanel.ResumeLayout(true, true);
474 }
475
476 private void mnuItemShowLogWindow_Click(object sender, EventArgs e)
477 {
478 ShowLogWindow();
479 }
480
481 private void mnuItemHelpAbout_Click(object sender, EventArgs e)
482 {
483 ShowAboutBox();
484 }
485
486 private void mnuItemShowRamDumpDialog_Click(object sender, EventArgs e)
487 {
488 ShowRamDump();
489 }
490
491 private void mnuItemShowPIDSelector_Click(object sender, EventArgs e)
492 {
493 ShowPidSelector();
494 }
495 private void mnuItemShowMemoryView_Click(object sender, EventArgs e)
496 {
497 ShowMemoryView();
498 }
499 private void Main_FormClosing(object sender, FormClosingEventArgs e)
500 {
501 string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");
502 if (m_bSaveLayout)
503 dockPanel.SaveAsXml(configFile);
504 else if (File.Exists(configFile))
505 File.Delete(configFile);
506
507 SearchResultWriter.CleanupTemporarySearchResultFiles();
508
509 }
510
511 private void mnuTestExeParse_Click(object sender, EventArgs e)
512 {
513 IPEDData peData = PEDataWrapper.GetPEData((IAcceptsProcessAndConfig)this);
514 }
515
516 private void mnuItemFindMaxNonNegativeHexValue_Click(object sender, EventArgs e)
517 {
518
519 //uint start = 0xf0000000;
520 uint end = uint.MaxValue;
521 //for (uint i = start; i < end; i++)
522 //{
523 ulong value = Convert.ToUInt64(end.ToString(), 16);
524 //}
525 }
526
527 private void mnuItemShowDataTypeConverter_Click(object sender, EventArgs e)
528 {
529 ShowDataTypeConverter();
530 }
531
532 private void mnuItemShowMemorySearch_Click(object sender, EventArgs e)
533 {
534 ShowMemorySearch();
535 }
536
537 private void mnuItemDateShift_Click(object sender, EventArgs e)
538 {
539 DateTime t = DateTime.Now;
540 int year = Convert.ToInt32(t.ToString("yy"));
541 int y = year << 9;
542 int m = t.Month << 5;
543 int d = t.Day;
544
545 ushort v1 = (ushort)(y | m | d);
546
547 t = t.AddDays(1);
548 year = Convert.ToInt32(t.ToString("yy"));
549 y = year << 9;
550 m = t.Month << 5;
551 d = t.Day;
552 ushort v2 = (ushort)(y | m | d);
553
554 t = t.AddDays(1);
555 year = Convert.ToInt32(t.ToString("yy"));
556 y = year << 9;
557 m = t.Month << 5;
558 d = t.Day;
559 ushort v3 = (ushort)(y | m | d);
560
561 t = new DateTime(9999,12,31);
562 year = Convert.ToInt32(t.ToString("yy"));
563 y = year << 9;
564 m = t.Month << 5;
565 d = t.Day;
566 ushort v4 = (ushort)(y | m | d);
567 }
568
569 private void mnuItemShowPEViewer_Click(object sender, EventArgs e)
570 {
571 ShowPEViewer();
572 }
573
574 private void mnuItemShowRVACalculator_Click(object sender, EventArgs e)
575 {
576 ShowRVACalculator();
577 }
578
579 private void mnuItemShowUserControlDock_Click(object sender, EventArgs e)
580 {
581 ShowUserControlDock();
582 }
583 }
584 }

  ViewVC Help
Powered by ViewVC 1.1.22