1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2010 Andrey Rijov <ANDron142@yandex.ru>
4 ** Copyright (C) 2016 Tobias Gläßer
5 **
6 ** This file is part of AQEMU.
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ** Boston, MA  02110-1301, USA.
21 **
22 ****************************************************************************/
23 
24 #ifndef VM_H
25 #define VM_H
26 
27 #include <QDateTime>
28 #include <QProcess>
29 #include <QTcpSocket>
30 #include <QFile>
31 
32 #include "VM_Devices.h"
33 #include "Error_Log_Window.h"
34 #include "Create_Template_Window.h"
35 #include "QDom.h"
36 
37 class Emulator_Control_Window;
38 
39 // Vitrual Machine
40 class Virtual_Machine: public QObject
41 {
42     friend class MachineView;
43 
44 	Q_OBJECT
45 
46 	public:
47 		// Constructors...
48 		Virtual_Machine();
49 		Virtual_Machine( const QString &name );
50 		Virtual_Machine( const Virtual_Machine &vm );
51 		~Virtual_Machine();
52 		void Shared_Constructor();
53 
54 		// oprators
55 		bool operator==( const Virtual_Machine &v1 ) const;
56 		bool operator!=( const Virtual_Machine &v1 ) const;
57 		Virtual_Machine &operator=( const Virtual_Machine &vm );
58 
59 		// Create, Read, Save VM XML Files
60 		const QString &Get_VM_XML_File_Path() const;
61 		void Set_VM_XML_File_Path( const QString &path );
62 		bool Create_VM_File( const QString &file_name, bool template_mode );
63 
64 		bool Create_Template( const QString &vm_path, const QString &template_name,
65 							  Create_Template_Window::Template_Options opts );
66 
67 		bool Load_VM( const QString &file_name );
68 		bool Save_VM();
69 		bool Save_VM( const QString &file_name );
70 
71 		QStringList Build_QEMU_Args(); // build all args for QEMU
72 		QStringList Build_QEMU_Args_For_Tab_Info();
73 		QStringList Build_QEMU_Args_For_Script();
74 
75 		QStringList Build_Nativ_Device_Args( VM_Nativ_Storage_Device device, bool Build_QEMU_Args_for_Script_Mode );
76 		QStringList Build_Shared_Folder_Args( VM_Shared_Folder folder, int id, bool Build_QEMU_Args_for_Script_Mode );
77 
78 		bool Start();
79 		void Pause(); // qemu command stop
80 		void Stop();  // shutdown
81 		void Reset();
82 
83 		void Save_VM_State(); // Save default snapshot
84 		void Save_VM_State( const QString &tag, bool quit );
85 		void Load_VM_State( const QString &tag );
86 		bool Start_Snapshot( const QString &tag );
87 		void Delete_Snapshot( const QString &tag );
88 
89 		const QString &Get_UID() const;
90 		void Set_UID( const QString &uid );
91 
92 		// Emu_Ctl
93 		void Show_Emu_Ctl_Win();
94 		void Hide_Emu_Ctl_Win();
95 		void Update_Removable_Devices_List();
96 		const QString &Get_Removable_Devices_List() const;
97 
98 		// Error Log Window
99 		void Show_Error_Log_Window();
100 
101 		// QEMU Log
102 		void Show_QEMU_Error( const QString &err_str );
103 		void Hide_QEMU_Error_Log();
104 
105 		// Plase wait win
106 		void Show_VM_Load_Window();
107 		void Hide_VM_Load_Window();
108 
109 		void Show_VM_Save_Window();
110 		void Hide_VM_Save_Window();
111 
112 		// Screenshot
113 		bool Take_Screenshot( const QString &file_name, int width=-1, int height=-1 );
114 
115 		VM::Machine_Accelerator Get_Machine_Accelerator() const;
116 		void Set_Machine_Accelerator( VM::Machine_Accelerator accel );
117 
118 		const Emulator &Get_Emulator() const;
119 		void Set_Emulator( const Emulator &emul );
120 
121 		void Update_Current_Emulator_Devices();
122 		const Available_Devices *Get_Current_Emulator_Devices() const;
123 
124 		QString Get_Current_Emulator_Binary_Path( const QString &names ) const;
125 
126         QString Get_State_Text() const;
127 		VM::VM_State Get_State() const;
128 		void Set_State( VM::VM_State s, bool real_poewer_off = false );
129 
130 		const QString &Get_Icon_Path() const;
131 		void Set_Icon_Path( const QString &file_name );
132 
133 		const QString &Get_Screenshot_Path() const;
134 		void Set_Screenshot_Path( const QString &file_name );
135 
136 		const QString &Get_Machine_Name() const;
137 		void Set_Machine_Name( const QString &name );
138 
139 		const QString &Get_Computer_Type() const;
140 		void Set_Computer_Type( const QString &type );
141 
142 		const QString &Get_Machine_Type() const;
143 		void Set_Machine_Type( const QString &type );
144 
145 		const QString &Get_CPU_Type() const;
146 		void Set_CPU_Type( const QString &type );
147 
148 		VM::SMP_Options Get_SMP() const;
149 		void Set_SMP( const VM::SMP_Options &smp );
150 
151 		int Get_SMP_CPU_Count() const;
152 		void Set_SMP_CPU_Count( int count );
153 
154 		const QString &Get_Keyboard_Layout() const;
155 		void Set_Keyboard_Layout( const QString &kl );
156 
157 		const QList<VM::Boot_Order> &Get_Boot_Order_List() const;
158 		void Set_Boot_Order_List( QList<VM::Boot_Order> &list );
159 
160 		bool Get_Show_Boot_Menu() const;
161 		void Set_Show_Boot_Menu( bool use );
162 
163 		const QString &Get_Video_Card() const;
164 		void Set_Video_Card( const QString &card );
165 
166 		VM::Acseleration_Mode Get_KQEMU_Mode() const;
167 		void Set_KQEMU_Mode( VM::Acseleration_Mode mode );
168 
169 		VM::Sound_Cards Get_Audio_Cards() const;
170 		void Set_Audio_Cards( VM::Sound_Cards card );
171 
172 		int Get_Memory_Size() const;
173 		void Set_Memory_Size( int megs );
174 
175 		bool Get_Remove_RAM_Size_Limitation() const;
176 		void Set_Remove_RAM_Size_Limitation( bool on );
177 
178 		bool Use_Fullscreen_Mode() const;
179 		void Use_Fullscreen_Mode( bool use );
180 
181 		bool Use_Win2K_Hack() const;
182 		void Use_Win2K_Hack( bool use );
183 
184 		bool Use_Local_Time() const;
185 		void Use_Local_Time( bool use );
186 
187 		bool Use_Check_FDD_Boot_Sector() const;
188 		void Use_Check_FDD_Boot_Sector( bool use );
189 
190 		bool Use_ACPI() const;
191 		void Use_ACPI( bool use );
192 
193 		bool Use_Snapshot_Mode() const;
194 		void Use_Snapshot_Mode( bool use );
195 
196 		bool Use_Start_CPU() const;
197 		void Use_Start_CPU( bool start );
198 
199 		bool Use_No_Reboot() const;
200 		void Use_No_Reboot( bool use );
201 
202 		bool Use_No_Shutdown() const;
203 		void Use_No_Shutdown( bool use );
204 
205 		const VM_Storage_Device &Get_FD0() const;
206 		void Set_FD0( const VM_Storage_Device &floppy );
207 
208 		const VM_Storage_Device &Get_FD1() const;
209 		void Set_FD1( const VM_Storage_Device &floppy );
210 
211 		const VM_Storage_Device &Get_CD_ROM() const;
212 		void Set_CD_ROM( const VM_Storage_Device &cdrom );
213 
214 		const VM_HDD &Get_HDA() const;
215 		void Set_HDA( const VM_HDD &hdd );
216 
217 		const VM_HDD &Get_HDB() const;
218 		void Set_HDB( const VM_HDD &hdd );
219 
220 		const VM_HDD &Get_HDC() const;
221 		void Set_HDC( const VM_HDD &hdd );
222 
223 		const VM_HDD &Get_HDD() const;
224 		void Set_HDD( const VM_HDD &hdd );
225 
226 		const QList<VM_Snapshot> &Get_Snapshots() const;
227 		void Set_Snapshots( const QList<VM_Snapshot> &list );
228 
229 		void Add_Snapshot( const QString &tag, const QString &name, const QString &desc );
230 		void Add_Snapshot( const VM_Snapshot &snapshot );
231 
232 		void Set_Snapshot( int index, const VM_Snapshot &s );
233 
234 		const QList<VM_Nativ_Storage_Device> &Get_Storage_Devices_List() const;
235 		void Set_Storage_Devices_List( const QList<VM_Nativ_Storage_Device> &list );
236 
237 		const VM_Nativ_Storage_Device &Get_Storage_Device( int index ) const;
238 		void Set_Storage_Device( int index, const VM_Nativ_Storage_Device &device );
239 
240 		const QList<VM_Shared_Folder> &Get_Shared_Folders_List() const;
241 		void Set_Shared_Folders_List( const QList<VM_Shared_Folder> &list );
242 
243 		bool Get_Use_Network() const;
244 		void Set_Use_Network( bool use );
245 
246 		bool Use_Nativ_Network() const;
247 		void Use_Nativ_Network( bool use );
248 
249 		bool Get_Use_Redirections() const;
250 		void Set_Use_Redirections( bool r );
251 
252 		const QString &Get_TFTP_Prefix() const;
253 		void Set_TFTP_Prefix( const QString &p );
254 
255 		const QString &Get_SMB_Directory() const;
256 		void Set_SMB_Directory( const QString &dir );
257 
258 		const QList<VM_Net_Card> &Get_Network_Cards() const;
259 		void Set_Network_Cards( const QList<VM_Net_Card> &cards );
260 
261 		const QList<VM_Net_Card_Nativ> &Get_Network_Cards_Nativ() const;
262 		void Set_Network_Cards_Nativ( const QList<VM_Net_Card_Nativ> &cards );
263 
264 		const VM_Net_Card &Get_Network_Card( int index ) const;
265 		void Set_VM_Network_Card( int index, const VM_Net_Card &nc );
266 
267 		bool Add_Network_Card( const VM_Net_Card &nc );
268 		bool Delete_Network_Card( int ix );
269 
270 		void Clear_Network_Cards_List();
271 
272 		int Get_Network_Cards_Count() const;
273 
274 		const VM_Redirection &Get_Network_Redirection( int index ) const;
275 		void Set_Network_Redirection( int index, const VM_Redirection &r );
276 
277 		void Add_Network_Redirection( const VM_Redirection &r );
278 		bool Delete_Network_Redirection( int ix );
279 
280 		int Get_Network_Redirections_Count() const;
281 
282 		const QList<VM_Port> &Get_Serial_Ports() const;
283 		void Set_Serial_Ports( const QList<VM_Port> &list );
284 
285 		const QList<VM_Port> &Get_Parallel_Ports() const;
286 		void Set_Parallel_Ports( const QList<VM_Port> &list );
287 
288 		void Add_USB_Port( const VM_USB &u );
289 		bool Delete_USB_Port( int index );
290 
291 		const QList<VM_USB> &Get_USB_Ports() const;
292 		void Set_USB_Ports( const QList<VM_USB> &list );
293 
294 		bool Get_Use_Linux_Boot() const;
295 		void Set_Use_Linux_Boot( bool use );
296 
297 		const QString &Get_bzImage_Path() const;
298 		void Set_bzImage_Path( const QString &path );
299 
300 		const QString &Get_Initrd_Path() const;
301 		void Set_Initrd_Path( const QString &path );
302 
303 		const QString &Get_Kernel_ComLine() const;
304 		void Set_Kernel_ComLine( const QString &cl );
305 
306 		const QString &Get_Additional_Args() const;
307 		void Set_Additional_Args( const QString &aa );
308 
309 		bool Get_Only_User_Args() const;
310 		void Set_Only_User_Args( bool use );
311 
312 		bool Get_Use_User_Emulator_Binary() const;
313 		void Set_Use_User_Emulator_Binary( bool use );
314 
315 		bool Get_Use_ROM_File() const;
316 		void Set_Use_ROM_File( bool use );
317 
318 		const QString &Get_ROM_File() const;
319 		void Set_ROM_File( const QString &path );
320 
321 		bool Use_MTDBlock_File() const;
322 		void Use_MTDBlock_File( bool use );
323 
324 		const QString &Get_MTDBlock_File() const;
325 		void Set_MTDBlock_File( const QString &file );
326 
327 		bool Use_SecureDigital_File() const;
328 		void Use_SecureDigital_File( bool use );
329 
330 		const QString &Get_SecureDigital_File() const;
331 		void Set_SecureDigital_File( const QString &file );
332 
333 		bool Use_PFlash_File() const;
334 		void Use_PFlash_File( bool use );
335 
336 		const QString &Get_PFlash_File() const;
337 		void Set_PFlash_File( const QString &file );
338 
339 		bool Use_KVM() const;
340 		void Use_KVM( bool use );
341 
342 		bool Use_KVM_IRQChip() const;
343 		void Use_KVM_IRQChip( bool use );
344 
345 		bool Use_No_KVM_Pit() const;
346 		void Use_No_KVM_Pit( bool use );
347 
348 		bool Use_KVM_No_Pit_Reinjection() const;
349 		void Use_KVM_No_Pit_Reinjection( bool use );
350 
351 		bool Use_KVM_Nesting() const;
352 		void Use_KVM_Nesting( bool use );
353 
354 		bool Use_KVM_Shadow_Memory() const;
355 		void Use_KVM_Shadow_Memory( bool use );
356 
357 		int Get_KVM_Shadow_Memory_Size() const;
358 		void Set_KVM_Shadow_Memory_Size( int size );
359 
360 		const VM_Init_Graphic_Mode &Get_Init_Graphic_Mode() const;
361 		void Set_Init_Graphic_Mode( const VM_Init_Graphic_Mode &mode );
362 
363 		bool Use_No_Frame() const;
364 		void Use_No_Frame( bool use );
365 
366 		bool Use_Alt_Grab() const;
367 		void Use_Alt_Grab( bool use );
368 
369 		bool Use_No_Quit() const;
370 		void Use_No_Quit( bool use );
371 
372 		bool Use_Portrait() const;
373 		void Use_Portrait( bool use );
374 
375 		bool Use_Show_Cursor() const;
376 		void Use_Show_Cursor( bool use );
377 
378 		bool Use_Curses() const;
379 		void Use_Curses( bool use );
380 
381 		bool Use_RTC_TD_Hack() const;
382 		void Use_RTC_TD_Hack( bool use );
383 
384 		bool Use_Start_Date() const;
385 		void Use_Start_Date( bool use );
386 
387 		const QDateTime &Get_Start_Date() const;
388 		void Set_Start_Date( const QDateTime &dt );
389 
390 		const VM_SPICE &Get_SPICE() const;
391 		void Set_SPICE( const VM_SPICE &spice );
392 
393 		bool Use_VNC() const;
394 		void Use_VNC( bool use );
395 
396 		bool Get_VNC_Socket_Mode() const;
397 		void Set_VNC_Socket_Mode( bool use );
398 
399 		const QString &Get_VNC_Unix_Socket_Path() const;
400 		void Set_VNC_Unix_Socket_Path( const QString &path );
401 
402 		int Get_VNC_Display_Number() const;
403 		void Set_VNC_Display_Number( int num );
404 
405 		bool Use_VNC_Password() const;
406 		void Use_VNC_Password( bool use );
407 
408 		void Set_VNC_Password( const QString &pas );
409 
410 		bool Use_VNC_TLS() const;
411 		void Use_VNC_TLS( bool use );
412 
413 		bool Use_VNC_x509() const;
414 		void Use_VNC_x509( bool use );
415 
416 		const QString &Get_VNC_x509_Folder_Path() const;
417 		void Set_VNC_x509_Folder_Path( const QString &path );
418 
419 		bool Use_VNC_x509verify() const;
420 		void Use_VNC_x509verify( bool use );
421 
422 		const QString &Get_VNC_x509verify_Folder_Path() const;
423 		void Set_VNC_x509verify_Folder_Path( const QString &path );
424 
425 		int Get_Embedded_Display_Port() const;
426 		void Set_Embedded_Display_Port( int port );
427 
428 		// Window for control qemu/kvm
429 		Emulator_Control_Window *Emu_Ctl;
430 
431 	signals:
432 		void State_Changed( Virtual_Machine *vm, VM::VM_State s );
433 
434 		void Ready_StdIn( const QString &text );
435 		void Ready_StdOut( const QString &text );
436 		void Ready_StdErr( const QString &text );
437 
438 		void QEMU_Start();
439 		void Loading_Complete();
440 		void QEMU_End();
441 
442 		void Clean_Console( const QString &text );
443 
444 		void Ready_Removable_Devices_List();
445 
446 	private slots:
447 		void Parse_StdErr();
448 		void Parse_StdOut();
449 
450 		void Send_Emulator_Command( const QString &text );
451 
452 		void QEMU_Started();
453 		void QEMU_Finished( int exitCode, QProcess::ExitStatus exitStatus );
454 
455 		void Resume_Finished( const QString &neturned_text );
456 		void Suspend_Finished( const QString &neturned_text );
457 		void Started_Booting( const QString &text );
458 
459 		// for Emulator_Control_Window
460 		void Execute_Emu_Ctl_Command( const QString &com );
461 
462 		VM_Nativ_Storage_Device Load_VM_Nativ_Storage_Device( const TXML2QDOM::QDomElement &Second_Element ) const;
463 		VM_Shared_Folder Load_VM_Shared_Folder( const TXML2QDOM::QDomElement &Second_Element ) const;
464 		void Save_VM_Nativ_Storage_Device( TXML2QDOM::QDomDocument &New_Dom_Document, TXML2QDOM::QDomElement &Dom_Element,
465 										   const VM_Nativ_Storage_Device &device ) const;
466 
467 		void Save_VM_Shared_Folder( TXML2QDOM::QDomDocument &New_Dom_Document, TXML2QDOM::QDomElement &Dom_Element,
468 										   const VM_Shared_Folder &device ) const;
469 	private:
470 		QProcess *QEMU_Process;
471 
472 		QTcpSocket *Monitor_Socket; // Used for "-monitor tcp" connection type
473 		bool Use_Monitor_TCP; // This value set in VM start time and no changes after
474 		QString Monitor_Hostname;
475 		unsigned int Monitor_Port;
476 
477 		VM::VM_State State; // Saved, Running, etc...
478 		VM::VM_State Old_State;
479 		QString VM_XML_File_Path; // for load and save
480 		QString Start_Snapshot_Tag;
481 		bool Load_Mode;
482 		bool Dont_Reinit;
483 		bool Build_QEMU_Args_for_Tab_Info;
484 		bool Build_QEMU_Args_for_Script_Mode;
485 
486 		QString UID;
487 
488 		VM::Machine_Accelerator Machine_Accelerator;
489 		Emulator Current_Emulator;
490 		Available_Devices Current_Emulator_Devices;
491 
492 		QString Snapshot_Name_String;
493 		QString Last_Output;
494 		QStringList Output_Parts;
495 
496 		QString Icon_Path; // OS Logo Icon
497 		QString Screenshot_Path; // Screenshot in save mode
498 
499 		QString Computer_Type; // PC, MAC, ARM...
500 		QString Machine_Name; // this machine name
501 		QString Machine_Type; // All QEMU Mach Types
502 		QString CPU_Type; // x86, ppc, sparc...
503 		VM::SMP_Options SMP; // All SMP Settings
504 		QString Keyboard_Layout; // language en, ru, jp...
505 		QList<VM::Boot_Order> Boot_Order_List; // New boot order
506 		bool Show_Boot_Menu; // Enable interactive boot menu
507 		QString Video_Card; // std vga, cirus logic
508 		VM::Acseleration_Mode KQEMU_Mode; // acceleration mode
509 		VM::Sound_Cards Audio_Card; // sb16, es1370
510 		bool Remove_RAM_Size_Limitation; // true - limitation off
511 		int Memory_Size; // RAM Size
512 
513 		// General Tab Options
514 		bool Fullscreen;
515 		bool Win2K_Hack;
516 		bool Local_Time;
517 		bool Check_FDD_Boot_Sector;
518 		bool ACPI;
519 		bool Snapshot_Mode;
520 		bool Start_CPU;
521 		bool No_Reboot;
522 		bool No_Shutdown;
523 
524 		// storage devices
525 		VM_Storage_Device FD0; // floppy 0
526 		VM_Storage_Device FD1; // floppy 1
527 		VM_Storage_Device CD_ROM; // cdrom device ide2
528 		VM_HDD HDA; // ide0
529 		VM_HDD HDB; // ide1
530 		VM_HDD HDC; // ide2 if cdrom is enabled, hdc be disabled
531 		VM_HDD HDD; // ide3
532 		QList<VM_Snapshot> Snapshots; // VM State Snapshots
533 		QList<VM_Nativ_Storage_Device> Storage_Devices; // For QEMU 0.8.2 Device Style
534 
535         // shared folders
536         QList<VM_Shared_Folder> Shared_Folders;
537 
538 		// Network
539 		bool Use_Network;
540 		bool Nativ_Network;
541 		bool Use_Redirections; // 1 or more net cards be avirable
542 
543 		QList<VM_Net_Card> Network_Cards; // Network Cards. Max 8
544 		QList<VM_Net_Card_Nativ> Network_Cards_Nativ; // Nativ QEMU Network Cards. Max 8
545 		QList<VM_Redirection> Network_Redirections; // List Redirections
546 
547 		QString TFTP_Prefix; // Buildin TFTP Server
548 		QString SMB_Directory; // SAMBA most be Installed on host!
549 
550 		// Ports
551 		QList<VM_Port> Serial_Ports;
552 		QList<VM_Port> Parallel_Ports;
553 		QList<VM_USB> USB_Ports;
554 
555 		// Other page
556 		bool Linux_Boot;
557 		QString bzImage_Path;
558 		QString Initrd_Path;
559 		QString Kernel_ComLine;
560 
561 		QString Additional_Args; // user arguments
562 		bool Only_User_Args;
563 		bool Use_User_Emulator_Binary;
564 
565 		bool Use_ROM_File;
566 		QString ROM_File; // ROM File for EtherBoot
567 
568 		// QEMU 0.9.1 Options
569 		bool MTDBlock;
570 		QString MTDBlock_File;
571 
572 		bool SecureDigital;
573 		QString SecureDigital_File;
574 
575 		bool PFlash;
576 		QString PFlash_File;
577 
578 		bool Enable_KVM;
579 		bool KVM_IRQChip;
580 		bool No_KVM_Pit;
581 		bool KVM_No_Pit_Reinjection;
582 		bool KVM_Nesting;
583 		bool KVM_Shadow_Memory;
584 		int KVM_Shadow_Memory_Size;
585 
586 		VM_Init_Graphic_Mode Init_Graphic_Mode;
587 
588 		bool No_Frame;
589 		bool Alt_Grab;
590 		bool No_Quit;
591 		bool Portrait;
592 		bool Show_Cursor;
593 		bool Curses;
594 		bool RTC_TD_Hack;
595 
596 		// DateTime
597 		bool Start_Date;
598 		QDateTime Start_DateTime;
599 
600 		// SPICE
601 		VM_SPICE SPICE;
602 
603 		// VNC
604 		bool VNC;
605 		bool VNC_Socket_Mode;
606 		QString VNC_Unix_Socket_Path;
607 		int VNC_Display_Number;
608 		bool VNC_Password;
609 		bool VNC_TLS;
610 		bool VNC_x509;
611 		QString VNC_x509_Folder_Path;
612 		bool VNC_x509verify;
613 		QString VNC_x509verify_Folder_Path;
614 
615 		// VNC Port for Embedded Display
616 		int Embedded_Display_Port;
617 
618 		// Additional Windows
619 		QWidget *Load_VM_Window;
620 		QWidget *Save_VM_Window;
621 		Error_Log_Window* QEMU_Error_Win;
622 		bool Quit_Before_Save;
623 		bool Update_Removable_Devices_Mode;
624 		QString Removable_Devices_List;
625 
626 		// For Create Templates
627 		QString Template_Name;
628 		Create_Template_Window::Template_Options Template_Opts;
629 
630 		QSettings Settings;
631 };
632 
633 #endif
634