VirtualBox

source: vbox/trunk/src/VBox/Main/include/ConsoleImpl.h@ 53442

Last change on this file since 53442 was 53442, checked in by vboxsync, 10 years ago

PDM Audio: Branch -> trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.8 KB
Line 
1/* $Id: ConsoleImpl.h 53442 2014-12-04 13:49:43Z vboxsync $ */
2/** @file
3 * VBox Console COM Class definition
4 */
5
6/*
7 * Copyright (C) 2005-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ____H_CONSOLEIMPL
19#define ____H_CONSOLEIMPL
20
21#include "VirtualBoxBase.h"
22#include "VBox/com/array.h"
23#include "EventImpl.h"
24#include "ConsoleWrap.h"
25
26class Guest;
27class Keyboard;
28class Mouse;
29class Display;
30class MachineDebugger;
31class TeleporterStateSrc;
32class OUSBDevice;
33class RemoteUSBDevice;
34class SharedFolder;
35class VRDEServerInfo;
36class EmulatedUSB;
37#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
38class AudioVRDE;
39#else
40class AudioSniffer;
41#endif
42class AudioVRDE;
43class Nvram;
44#ifdef VBOX_WITH_USB_CARDREADER
45class UsbCardReader;
46#endif
47class ConsoleVRDPServer;
48class VMMDev;
49class Progress;
50class BusAssignmentManager;
51COM_STRUCT_OR_CLASS(IEventListener);
52#ifdef VBOX_WITH_EXTPACK
53class ExtPackManager;
54#endif
55class VMMDevMouseInterface;
56class DisplayMouseInterface;
57
58#include <iprt/uuid.h>
59#include <iprt/memsafer.h>
60#include <VBox/RemoteDesktop/VRDE.h>
61#include <VBox/vmm/pdmdrv.h>
62#ifdef VBOX_WITH_GUEST_PROPS
63# include <VBox/HostServices/GuestPropertySvc.h> /* For the property notification callback */
64#endif
65
66#ifdef RT_OS_WINDOWS
67# include "../src-server/win/VBoxComEvents.h"
68#endif
69
70struct VUSBIRHCONFIG;
71typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG;
72
73#include <list>
74#include <vector>
75
76// defines
77///////////////////////////////////////////////////////////////////////////////
78
79/**
80 * Checks the availability of the underlying VM device driver corresponding
81 * to the COM interface (IKeyboard, IMouse, IDisplay, etc.). When the driver is
82 * not available (NULL), sets error info and returns returns E_ACCESSDENIED.
83 * The translatable error message is defined in null context.
84 *
85 * Intended to used only within Console children (i.e. Keyboard, Mouse,
86 * Display, etc.).
87 *
88 * @param drv driver pointer to check (compare it with NULL)
89 */
90#define CHECK_CONSOLE_DRV(drv) \
91 do { \
92 if (!(drv)) \
93 return setError(E_ACCESSDENIED, tr("The console is not powered up")); \
94 } while (0)
95
96// Console
97///////////////////////////////////////////////////////////////////////////////
98
99class ConsoleMouseInterface
100{
101public:
102 virtual VMMDevMouseInterface *i_getVMMDevMouseInterface(){return NULL;}
103 virtual DisplayMouseInterface *i_getDisplayMouseInterface(){return NULL;}
104 virtual void i_onMouseCapabilityChange(BOOL supportsAbsolute,
105 BOOL supportsRelative,
106 BOOL supportsMT,
107 BOOL needsHostCursor){NOREF(supportsAbsolute); NOREF(supportsRelative); NOREF(supportsMT); NOREF(needsHostCursor);}
108};
109
110/** IConsole implementation class */
111class ATL_NO_VTABLE Console :
112 public ConsoleWrap,
113 public ConsoleMouseInterface
114{
115
116public:
117
118 DECLARE_EMPTY_CTOR_DTOR(Console)
119
120 HRESULT FinalConstruct();
121 void FinalRelease();
122
123 // public initializers/uninitializers for internal purposes only
124 HRESULT init(IMachine *aMachine, IInternalMachineControl *aControl, LockType_T aLockType);
125 void uninit();
126
127
128 // public methods for internal purposes only
129
130 /*
131 * Note: the following methods do not increase refcount. intended to be
132 * called only by the VM execution thread.
133 */
134
135 Guest *i_getGuest() const { return mGuest; }
136 Keyboard *i_getKeyboard() const { return mKeyboard; }
137 Mouse *i_getMouse() const { return mMouse; }
138 Display *i_getDisplay() const { return mDisplay; }
139 MachineDebugger *i_getMachineDebugger() const { return mDebugger; }
140#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
141 AudioVRDE *i_getAudioVRDE() const { return mAudioVRDE; }
142#else
143 AudioSniffer *i_getAudioSniffer() const { return mAudioSniffer; }
144#endif
145
146 const ComPtr<IMachine> &i_machine() const { return mMachine; }
147
148 bool i_useHostClipboard() { return mfUseHostClipboard; }
149
150 /** Method is called only from ConsoleVRDPServer */
151 IVRDEServer *i_getVRDEServer() const { return mVRDEServer; }
152
153 ConsoleVRDPServer *i_consoleVRDPServer() const { return mConsoleVRDPServer; }
154
155 HRESULT i_updateMachineState(MachineState_T aMachineState);
156
157 // events from IInternalSessionControl
158 HRESULT i_onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL changeAdapter);
159 HRESULT i_onSerialPortChange(ISerialPort *aSerialPort);
160 HRESULT i_onParallelPortChange(IParallelPort *aParallelPort);
161 HRESULT i_onStorageControllerChange();
162 HRESULT i_onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce);
163 HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove);
164 HRESULT i_onCPUExecutionCapChange(ULONG aExecutionCap);
165 HRESULT i_onClipboardModeChange(ClipboardMode_T aClipboardMode);
166 HRESULT i_onDnDModeChange(DnDMode_T aDnDMode);
167 HRESULT i_onVRDEServerChange(BOOL aRestart);
168 HRESULT i_onVideoCaptureChange();
169 HRESULT i_onUSBControllerChange();
170 HRESULT i_onSharedFolderChange(BOOL aGlobal);
171 HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs,
172 const Utf8Str &aCaptureFilename);
173 HRESULT i_onUSBDeviceDetach(IN_BSTR aId, IVirtualBoxErrorInfo *aError);
174 HRESULT i_onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup);
175 HRESULT i_onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove, BOOL aSilent);
176 HRESULT i_onExtraDataChange(IN_BSTR aMachineId, IN_BSTR aKey, IN_BSTR aVal);
177
178 HRESULT i_getGuestProperty(const Utf8Str &aName, Utf8Str *aValue, LONG64 *aTimestamp, Utf8Str *aFlags);
179 HRESULT i_setGuestProperty(const Utf8Str &aName, const Utf8Str &aValue, const Utf8Str &aFlags);
180 HRESULT i_deleteGuestProperty(const Utf8Str &aName);
181 HRESULT i_enumerateGuestProperties(const Utf8Str &aPatterns,
182 std::vector<Utf8Str> &aNames,
183 std::vector<Utf8Str> &aValues,
184 std::vector<LONG64> &aTimestamps,
185 std::vector<Utf8Str> &aFlags);
186 HRESULT i_onlineMergeMedium(IMediumAttachment *aMediumAttachment,
187 ULONG aSourceIdx, ULONG aTargetIdx,
188 IProgress *aProgress);
189 int i_hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName);
190 VMMDev *i_getVMMDev() { return m_pVMMDev; }
191#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
192 AudioVRDE *i_getAudioVRDE() { return mAudioVRDE; }
193#else
194 AudioSniffer *i_getAudioSniffer() { return mAudioSniffer; }
195#endif
196
197#ifdef VBOX_WITH_EXTPACK
198 ExtPackManager *i_getExtPackManager();
199#endif
200 EventSource *i_getEventSource() { return mEventSource; }
201#ifdef VBOX_WITH_USB_CARDREADER
202 UsbCardReader *i_getUsbCardReader() { return mUsbCardReader; }
203#endif
204
205 int i_VRDPClientLogon(uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain);
206 void i_VRDPClientStatusChange(uint32_t u32ClientId, const char *pszStatus);
207 void i_VRDPClientConnect(uint32_t u32ClientId);
208 void i_VRDPClientDisconnect(uint32_t u32ClientId, uint32_t fu32Intercepted);
209 void i_VRDPInterceptAudio(uint32_t u32ClientId);
210 void i_VRDPInterceptUSB(uint32_t u32ClientId, void **ppvIntercept);
211 void i_VRDPInterceptClipboard(uint32_t u32ClientId);
212
213 void i_processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *pDevList, uint32_t cbDevList, bool fDescExt);
214 void i_reportVmStatistics(ULONG aValidStats, ULONG aCpuUser,
215 ULONG aCpuKernel, ULONG aCpuIdle,
216 ULONG aMemTotal, ULONG aMemFree,
217 ULONG aMemBalloon, ULONG aMemShared,
218 ULONG aMemCache, ULONG aPageTotal,
219 ULONG aAllocVMM, ULONG aFreeVMM,
220 ULONG aBalloonedVMM, ULONG aSharedVMM,
221 ULONG aVmNetRx, ULONG aVmNetTx)
222 {
223 mControl->ReportVmStatistics(aValidStats, aCpuUser, aCpuKernel, aCpuIdle,
224 aMemTotal, aMemFree, aMemBalloon, aMemShared,
225 aMemCache, aPageTotal, aAllocVMM, aFreeVMM,
226 aBalloonedVMM, aSharedVMM, aVmNetRx, aVmNetTx);
227 }
228 void i_enableVMMStatistics(BOOL aEnable);
229
230 HRESULT i_pause(Reason_T aReason);
231 HRESULT i_resume(Reason_T aReason);
232 HRESULT i_saveState(Reason_T aReason, IProgress **aProgress);
233
234 // callback callers (partly; for some events console callbacks are notified
235 // directly from IInternalSessionControl event handlers declared above)
236 void i_onMousePointerShapeChange(bool fVisible, bool fAlpha,
237 uint32_t xHot, uint32_t yHot,
238 uint32_t width, uint32_t height,
239 const uint8_t *pu8Shape,
240 uint32_t cbShape);
241 void i_onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative,
242 BOOL supportsMT, BOOL needsHostCursor);
243 void i_onStateChange(MachineState_T aMachineState);
244 void i_onAdditionsStateChange();
245 void i_onAdditionsOutdated();
246 void i_onKeyboardLedsChange(bool fNumLock, bool fCapsLock, bool fScrollLock);
247 void i_onUSBDeviceStateChange(IUSBDevice *aDevice, bool aAttached,
248 IVirtualBoxErrorInfo *aError);
249 void i_onRuntimeError(BOOL aFatal, IN_BSTR aErrorID, IN_BSTR aMessage);
250 HRESULT i_onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId);
251 void i_onVRDEServerInfoChange();
252
253 static const PDMDRVREG DrvStatusReg;
254
255 static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *pcsz, ...);
256 HRESULT i_setInvalidMachineStateError();
257
258 static const char *i_convertControllerTypeToDev(StorageControllerType_T enmCtrlType);
259 static HRESULT i_convertBusPortDeviceToLun(StorageBus_T enmBus, LONG port, LONG device, unsigned &uLun);
260 // Called from event listener
261 HRESULT i_onNATRedirectRuleChange(ULONG ulInstance, BOOL aNatRuleRemove,
262 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort);
263
264 // Mouse interface
265 VMMDevMouseInterface *i_getVMMDevMouseInterface();
266 DisplayMouseInterface *i_getDisplayMouseInterface();
267
268 EmulatedUSB *i_getEmulatedUSB(void) { return mEmulatedUSB; }
269
270 /**
271 * Sets the disk encryption keys.
272 *
273 * @returns COM status code.
274 * @þaram strCfg The config for the disks.
275 *
276 * @note: One line in the config string contains all required data for one disk.
277 * The format for one disk is some sort of comma separated value using
278 * key=value pairs.
279 * There are two keys defined at the moment:
280 * - uuid: The uuid of the base image the key is for (with or without)
281 * the curly braces.
282 * - dek: The data encryption key in base64 encoding
283 */
284 HRESULT i_setDiskEncryptionKeys(const Utf8Str &strCfg);
285
286private:
287
288 // wraped IConsole properties
289 HRESULT getMachine(ComPtr<IMachine> &aMachine);
290 HRESULT getState(MachineState_T *aState);
291 HRESULT getGuest(ComPtr<IGuest> &aGuest);
292 HRESULT getKeyboard(ComPtr<IKeyboard> &aKeyboard);
293 HRESULT getMouse(ComPtr<IMouse> &aMouse);
294 HRESULT getDisplay(ComPtr<IDisplay> &aDisplay);
295 HRESULT getDebugger(ComPtr<IMachineDebugger> &aDebugger);
296 HRESULT getUSBDevices(std::vector<ComPtr<IUSBDevice> > &aUSBDevices);
297 HRESULT getRemoteUSBDevices(std::vector<ComPtr<IHostUSBDevice> > &aRemoteUSBDevices);
298 HRESULT getSharedFolders(std::vector<ComPtr<ISharedFolder> > &aSharedFolders);
299 HRESULT getVRDEServerInfo(ComPtr<IVRDEServerInfo> &aVRDEServerInfo);
300 HRESULT getEventSource(ComPtr<IEventSource> &aEventSource);
301 HRESULT getAttachedPCIDevices(std::vector<ComPtr<IPCIDeviceAttachment> > &aAttachedPCIDevices);
302 HRESULT getUseHostClipboard(BOOL *aUseHostClipboard);
303 HRESULT setUseHostClipboard(BOOL aUseHostClipboard);
304 HRESULT getEmulatedUSB(ComPtr<IEmulatedUSB> &aEmulatedUSB);
305
306 // wraped IConsole methods
307 HRESULT powerUp(ComPtr<IProgress> &aProgress);
308 HRESULT powerUpPaused(ComPtr<IProgress> &aProgress);
309 HRESULT powerDown(ComPtr<IProgress> &aProgress);
310 HRESULT reset();
311 HRESULT pause();
312 HRESULT resume();
313 HRESULT powerButton();
314 HRESULT sleepButton();
315 HRESULT getPowerButtonHandled(BOOL *aHandled);
316 HRESULT getGuestEnteredACPIMode(BOOL *aEntered);
317 HRESULT saveState(ComPtr<IProgress> &aProgress);
318 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
319 HRESULT discardSavedState(BOOL aFRemoveFile);
320 HRESULT getDeviceActivity(const std::vector<DeviceType_T> &aType,
321 std::vector<DeviceActivity_T> &aActivity);
322 HRESULT attachUSBDevice(const com::Guid &aId, const com::Utf8Str &aCaptureFilename);
323 HRESULT detachUSBDevice(const com::Guid &aId,
324 ComPtr<IUSBDevice> &aDevice);
325 HRESULT findUSBDeviceByAddress(const com::Utf8Str &aName,
326 ComPtr<IUSBDevice> &aDevice);
327 HRESULT findUSBDeviceById(const com::Guid &aId,
328 ComPtr<IUSBDevice> &aDevice);
329 HRESULT createSharedFolder(const com::Utf8Str &aName,
330 const com::Utf8Str &aHostPath,
331 BOOL aWritable,
332 BOOL aAutomount);
333 HRESULT removeSharedFolder(const com::Utf8Str &aName);
334 HRESULT takeSnapshot(const com::Utf8Str &aName,
335 const com::Utf8Str &aDescription,
336 ComPtr<IProgress> &aProgress);
337 HRESULT deleteSnapshot(const com::Guid &aId,
338 ComPtr<IProgress> &aProgress);
339 HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId,
340 ComPtr<IProgress> &aProgress);
341 HRESULT deleteSnapshotRange(const com::Guid &aStartId,
342 const com::Guid &aEndId,
343 ComPtr<IProgress> &aProgress);
344 HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
345 ComPtr<IProgress> &aProgress);
346 HRESULT teleport(const com::Utf8Str &aHostname,
347 ULONG aTcpport,
348 const com::Utf8Str &aPassword,
349 ULONG aMaxDowntime,
350 ComPtr<IProgress> &aProgress);
351
352 /**
353 * Base template for AutoVMCaller and SafeVMPtr. Template arguments
354 * have the same meaning as arguments of Console::addVMCaller().
355 */
356 template <bool taQuiet = false, bool taAllowNullVM = false>
357 class AutoVMCallerBase
358 {
359 public:
360 AutoVMCallerBase(Console *aThat) : mThat(aThat), mRC(E_FAIL)
361 {
362 Assert(aThat);
363 mRC = aThat->i_addVMCaller(taQuiet, taAllowNullVM);
364 }
365 ~AutoVMCallerBase()
366 {
367 doRelease();
368 }
369 /** Decreases the number of callers before the instance is destroyed. */
370 void releaseCaller()
371 {
372 Assert(SUCCEEDED(mRC));
373 doRelease();
374 }
375 /** Restores the number of callers after by #release(). #rc() must be
376 * rechecked to ensure the operation succeeded. */
377 void addYY()
378 {
379 AssertReturnVoid(!SUCCEEDED(mRC));
380 mRC = mThat->i_addVMCaller(taQuiet, taAllowNullVM);
381 }
382 /** Returns the result of Console::addVMCaller() */
383 HRESULT rc() const { return mRC; }
384 /** Shortcut to SUCCEEDED(rc()) */
385 bool isOk() const { return SUCCEEDED(mRC); }
386 protected:
387 Console *mThat;
388 void doRelease()
389 {
390 if (SUCCEEDED(mRC))
391 {
392 mThat->i_releaseVMCaller();
393 mRC = E_FAIL;
394 }
395 }
396 private:
397 HRESULT mRC; /* Whether the caller was added. */
398 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoVMCallerBase)
399 };
400
401#if 0
402 /**
403 * Helper class that protects sections of code using the mpUVM pointer by
404 * automatically calling addVMCaller() on construction and
405 * releaseVMCaller() on destruction. Intended for Console methods dealing
406 * with mpUVM. The usage pattern is:
407 * <code>
408 * AutoVMCaller autoVMCaller(this);
409 * if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
410 * ...
411 * VMR3ReqCall (mpUVM, ...
412 * </code>
413 *
414 * @note Temporarily locks the argument for writing.
415 *
416 * @sa SafeVMPtr, SafeVMPtrQuiet
417 * @obsolete Use SafeVMPtr
418 */
419 typedef AutoVMCallerBase<false, false> AutoVMCaller;
420#endif
421
422 /**
423 * Same as AutoVMCaller but doesn't set extended error info on failure.
424 *
425 * @note Temporarily locks the argument for writing.
426 * @obsolete Use SafeVMPtrQuiet
427 */
428 typedef AutoVMCallerBase<true, false> AutoVMCallerQuiet;
429
430 /**
431 * Same as AutoVMCaller but allows a null VM pointer (to trigger an error
432 * instead of assertion).
433 *
434 * @note Temporarily locks the argument for writing.
435 * @obsolete Use SafeVMPtr
436 */
437 typedef AutoVMCallerBase<false, true> AutoVMCallerWeak;
438
439 /**
440 * Same as AutoVMCaller but doesn't set extended error info on failure
441 * and allows a null VM pointer (to trigger an error instead of
442 * assertion).
443 *
444 * @note Temporarily locks the argument for writing.
445 * @obsolete Use SafeVMPtrQuiet
446 */
447 typedef AutoVMCallerBase<true, true> AutoVMCallerQuietWeak;
448
449 /**
450 * Base template for SafeVMPtr and SafeVMPtrQuiet.
451 */
452 template<bool taQuiet = false>
453 class SafeVMPtrBase : public AutoVMCallerBase<taQuiet, true>
454 {
455 typedef AutoVMCallerBase<taQuiet, true> Base;
456 public:
457 SafeVMPtrBase(Console *aThat) : Base(aThat), mRC(E_FAIL), mpUVM(NULL)
458 {
459 if (Base::isOk())
460 mRC = aThat->i_safeVMPtrRetainer(&mpUVM, taQuiet);
461 }
462 ~SafeVMPtrBase()
463 {
464 doRelease();
465 }
466 /** Direct PUVM access. */
467 PUVM rawUVM() const { return mpUVM; }
468 /** Release the handles. */
469 void release()
470 {
471 Assert(SUCCEEDED(mRC));
472 doRelease();
473 }
474
475 /** The combined result of Console::addVMCaller() and Console::safeVMPtrRetainer */
476 HRESULT rc() const { return Base::isOk()? mRC: Base::rc(); }
477 /** Shortcut to SUCCEEDED(rc()) */
478 bool isOk() const { return SUCCEEDED(mRC) && Base::isOk(); }
479
480 private:
481 void doRelease()
482 {
483 if (SUCCEEDED(mRC))
484 {
485 Base::mThat->i_safeVMPtrReleaser(&mpUVM);
486 mRC = E_FAIL;
487 }
488 Base::doRelease();
489 }
490 HRESULT mRC; /* Whether the VM ptr was retained. */
491 PUVM mpUVM;
492 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeVMPtrBase)
493 };
494
495public:
496
497 /*
498 * Helper class that safely manages the Console::mpUVM pointer
499 * by calling addVMCaller() on construction and releaseVMCaller() on
500 * destruction. Intended for Console children. The usage pattern is:
501 * <code>
502 * Console::SafeVMPtr ptrVM(mParent);
503 * if (!ptrVM.isOk())
504 * return ptrVM.rc();
505 * ...
506 * VMR3ReqCall(ptrVM.rawUVM(), ...
507 * ...
508 * printf("%p\n", ptrVM.rawUVM());
509 * </code>
510 *
511 * @note Temporarily locks the argument for writing.
512 *
513 * @sa SafeVMPtrQuiet, AutoVMCaller
514 */
515 typedef SafeVMPtrBase<false> SafeVMPtr;
516
517 /**
518 * A deviation of SafeVMPtr that doesn't set the error info on failure.
519 * Intended for pieces of code that don't need to return the VM access
520 * failure to the caller. The usage pattern is:
521 * <code>
522 * Console::SafeVMPtrQuiet pVM(mParent);
523 * if (pVM.rc())
524 * VMR3ReqCall(pVM, ...
525 * return S_OK;
526 * </code>
527 *
528 * @note Temporarily locks the argument for writing.
529 *
530 * @sa SafeVMPtr, AutoVMCaller
531 */
532 typedef SafeVMPtrBase<true> SafeVMPtrQuiet;
533
534 class SharedFolderData
535 {
536 public:
537 SharedFolderData()
538 { }
539
540 SharedFolderData(const Utf8Str &aHostPath,
541 bool aWritable,
542 bool aAutoMount)
543 : m_strHostPath(aHostPath),
544 m_fWritable(aWritable),
545 m_fAutoMount(aAutoMount)
546 { }
547
548 // copy constructor
549 SharedFolderData(const SharedFolderData& aThat)
550 : m_strHostPath(aThat.m_strHostPath),
551 m_fWritable(aThat.m_fWritable),
552 m_fAutoMount(aThat.m_fAutoMount)
553 { }
554
555 Utf8Str m_strHostPath;
556 bool m_fWritable;
557 bool m_fAutoMount;
558 };
559
560 /**
561 * Class for managing emulated USB MSDs.
562 */
563 class USBStorageDevice
564 {
565 public:
566 USBStorageDevice()
567 { }
568 /** The UUID associated with the USB device. */
569 RTUUID mUuid;
570 /** Port of the storage device. */
571 LONG iPort;
572 };
573
574 /**
575 * Class for managing cryptographic keys.
576 * @todo: Replace with a keystore implementation once it is ready.
577 */
578 class SecretKey
579 {
580 public:
581 SecretKey() { }
582
583 SecretKey(uint8_t *pbKey, size_t cbKey)
584 : m_cRefs(0),
585 m_pbKey(pbKey),
586 m_cbKey(cbKey)
587 { }
588
589 ~SecretKey()
590 {
591 RTMemSaferFree(m_pbKey, m_cbKey);
592 m_cRefs = 0;
593 m_pbKey = NULL;
594 m_cbKey = 0;
595 }
596
597 /** Reference counter of the key. */
598 volatile uint32_t m_cRefs;
599 /** Key material. */
600 uint8_t *m_pbKey;
601 /** Size of the key in bytes. */
602 size_t m_cbKey;
603 };
604
605 typedef std::map<Utf8Str, ComObjPtr<SharedFolder> > SharedFolderMap;
606 typedef std::map<Utf8Str, SharedFolderData> SharedFolderDataMap;
607 typedef std::map<Utf8Str, ComPtr<IMediumAttachment> > MediumAttachmentMap;
608 typedef std::list <USBStorageDevice> USBStorageDeviceList;
609 typedef std::map<Utf8Str, SecretKey *> SecretKeyMap;
610
611private:
612
613 typedef std::list <ComObjPtr<OUSBDevice> > USBDeviceList;
614 typedef std::list <ComObjPtr<RemoteUSBDevice> > RemoteUSBDeviceList;
615
616 HRESULT i_addVMCaller(bool aQuiet = false, bool aAllowNullVM = false);
617 void i_releaseVMCaller();
618 HRESULT i_safeVMPtrRetainer(PUVM *a_ppUVM, bool aQuiet);
619 void i_safeVMPtrReleaser(PUVM *a_ppUVM);
620
621 HRESULT i_consoleInitReleaseLog(const ComPtr<IMachine> aMachine);
622
623 HRESULT i_powerUp(IProgress **aProgress, bool aPaused);
624 HRESULT i_powerDown(IProgress *aProgress = NULL);
625
626/* Note: FreeBSD needs this whether netflt is used or not. */
627#if ((defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)) || defined(RT_OS_FREEBSD))
628 HRESULT i_attachToTapInterface(INetworkAdapter *networkAdapter);
629 HRESULT i_detachFromTapInterface(INetworkAdapter *networkAdapter);
630#endif
631 HRESULT i_powerDownHostInterfaces();
632
633 HRESULT i_setMachineState(MachineState_T aMachineState, bool aUpdateServer = true);
634 HRESULT i_setMachineStateLocally(MachineState_T aMachineState)
635 {
636 return i_setMachineState(aMachineState, false /* aUpdateServer */);
637 }
638
639 HRESULT i_findSharedFolder(const Utf8Str &strName,
640 ComObjPtr<SharedFolder> &aSharedFolder,
641 bool aSetError = false);
642
643 HRESULT i_fetchSharedFolders(BOOL aGlobal);
644 bool i_findOtherSharedFolder(const Utf8Str &straName,
645 SharedFolderDataMap::const_iterator &aIt);
646
647 HRESULT i_createSharedFolder(const Utf8Str &strName, const SharedFolderData &aData);
648 HRESULT i_removeSharedFolder(const Utf8Str &strName);
649
650 HRESULT i_suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume);
651 void i_resumeAfterConfigChange(PUVM pUVM);
652
653 static DECLCALLBACK(int) i_configConstructor(PUVM pUVM, PVM pVM, void *pvConsole);
654 int i_configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock);
655 int i_configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine);
656 int i_configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine);
657
658 int i_configGraphicsController(PCFGMNODE pDevices,
659 const GraphicsControllerType_T graphicsController,
660 BusAssignmentManager *pBusMgr,
661 const ComPtr<IMachine> &pMachine,
662 const ComPtr<IBIOSSettings> &biosSettings,
663 bool fHMEnabled);
664 int i_configMediumAttachment(PCFGMNODE pCtlInst,
665 const char *pcszDevice,
666 unsigned uInstance,
667 StorageBus_T enmBus,
668 bool fUseHostIOCache,
669 bool fBuiltinIoCache,
670 bool fSetupMerge,
671 unsigned uMergeSource,
672 unsigned uMergeTarget,
673 IMediumAttachment *pMediumAtt,
674 MachineState_T aMachineState,
675 HRESULT *phrc,
676 bool fAttachDetach,
677 bool fForceUnmount,
678 bool fHotplug,
679 PUVM pUVM,
680 DeviceType_T *paLedDevType,
681 PCFGMNODE *ppLunL0);
682 int i_configMedium(PCFGMNODE pLunL0,
683 bool fPassthrough,
684 DeviceType_T enmType,
685 bool fUseHostIOCache,
686 bool fBuiltinIoCache,
687 bool fSetupMerge,
688 unsigned uMergeSource,
689 unsigned uMergeTarget,
690 const char *pcszBwGroup,
691 bool fDiscard,
692 IMedium *pMedium,
693 MachineState_T aMachineState,
694 HRESULT *phrc);
695 static DECLCALLBACK(int) i_reconfigureMediumAttachment(Console *pThis,
696 PUVM pUVM,
697 const char *pcszDevice,
698 unsigned uInstance,
699 StorageBus_T enmBus,
700 bool fUseHostIOCache,
701 bool fBuiltinIoCache,
702 bool fSetupMerge,
703 unsigned uMergeSource,
704 unsigned uMergeTarget,
705 IMediumAttachment *aMediumAtt,
706 MachineState_T aMachineState,
707 HRESULT *phrc);
708 static DECLCALLBACK(int) i_changeRemovableMedium(Console *pThis,
709 PUVM pUVM,
710 const char *pcszDevice,
711 unsigned uInstance,
712 StorageBus_T enmBus,
713 bool fUseHostIOCache,
714 IMediumAttachment *aMediumAtt,
715 bool fForce);
716
717 HRESULT i_attachRawPCIDevices(PUVM pUVM, BusAssignmentManager *BusMgr, PCFGMNODE pDevices);
718 void i_attachStatusDriver(PCFGMNODE pCtlInst, PPDMLED *papLeds,
719 uint64_t uFirst, uint64_t uLast,
720 Console::MediumAttachmentMap *pmapMediumAttachments,
721 const char *pcszDevice, unsigned uInstance);
722
723 int i_configNetwork(const char *pszDevice, unsigned uInstance, unsigned uLun,
724 INetworkAdapter *aNetworkAdapter, PCFGMNODE pCfg,
725 PCFGMNODE pLunL0, PCFGMNODE pInst,
726 bool fAttachDetach, bool fIgnoreConnectFailure);
727
728 static DECLCALLBACK(int) i_configGuestProperties(void *pvConsole, PUVM pUVM);
729 static DECLCALLBACK(int) i_configGuestControl(void *pvConsole);
730 static DECLCALLBACK(void) i_vmstateChangeCallback(PUVM pUVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
731 static DECLCALLBACK(int) i_unplugCpu(Console *pThis, PUVM pUVM, VMCPUID idCpu);
732 static DECLCALLBACK(int) i_plugCpu(Console *pThis, PUVM pUVM, VMCPUID idCpu);
733 HRESULT i_doMediumChange(IMediumAttachment *aMediumAttachment, bool fForce, PUVM pUVM);
734 HRESULT i_doCPURemove(ULONG aCpu, PUVM pUVM);
735 HRESULT i_doCPUAdd(ULONG aCpu, PUVM pUVM);
736
737 HRESULT i_doNetworkAdapterChange(PUVM pUVM, const char *pszDevice, unsigned uInstance,
738 unsigned uLun, INetworkAdapter *aNetworkAdapter);
739 static DECLCALLBACK(int) i_changeNetworkAttachment(Console *pThis, PUVM pUVM, const char *pszDevice,
740 unsigned uInstance, unsigned uLun,
741 INetworkAdapter *aNetworkAdapter);
742
743 void i_changeClipboardMode(ClipboardMode_T aClipboardMode);
744 int i_changeDnDMode(DnDMode_T aDnDMode);
745
746#ifdef VBOX_WITH_USB
747 HRESULT i_attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs, const Utf8Str &aCaptureFilename);
748 HRESULT i_detachUSBDevice(const ComObjPtr<OUSBDevice> &aHostDevice);
749
750 static DECLCALLBACK(int) i_usbAttachCallback(Console *that, PUVM pUVM, IUSBDevice *aHostDevice, PCRTUUID aUuid,
751 bool aRemote, const char *aAddress, void *pvRemoteBackend,
752 USHORT aPortVersion, ULONG aMaskedIfs, const char *pszCaptureFilename);
753 static DECLCALLBACK(int) i_usbDetachCallback(Console *that, PUVM pUVM, PCRTUUID aUuid);
754#endif
755
756 static DECLCALLBACK(int) i_attachStorageDevice(Console *pThis,
757 PUVM pUVM,
758 const char *pcszDevice,
759 unsigned uInstance,
760 StorageBus_T enmBus,
761 bool fUseHostIOCache,
762 IMediumAttachment *aMediumAtt,
763 bool fSilent);
764 static DECLCALLBACK(int) i_detachStorageDevice(Console *pThis,
765 PUVM pUVM,
766 const char *pcszDevice,
767 unsigned uInstance,
768 StorageBus_T enmBus,
769 IMediumAttachment *aMediumAtt,
770 bool fSilent);
771 HRESULT i_doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PUVM pUVM, bool fSilent);
772 HRESULT i_doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUVM pUVM, bool fSilent);
773
774 static DECLCALLBACK(int) i_fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser);
775
776 static DECLCALLBACK(int) i_stateProgressCallback(PUVM pUVM, unsigned uPercent, void *pvUser);
777
778 static DECLCALLBACK(void) i_genericVMSetErrorCallback(PUVM pUVM, void *pvUser, int rc, RT_SRC_POS_DECL,
779 const char *pszErrorFmt, va_list va);
780
781 void i_setVMRuntimeErrorCallbackF(uint32_t fFatal, const char *pszErrorId, const char *pszFormat, ...);
782 static DECLCALLBACK(void) i_setVMRuntimeErrorCallback(PUVM pUVM, void *pvUser, uint32_t fFatal,
783 const char *pszErrorId, const char *pszFormat, va_list va);
784
785 HRESULT i_captureUSBDevices(PUVM pUVM);
786 void i_detachAllUSBDevices(bool aDone);
787
788 static DECLCALLBACK(int) i_powerUpThread(RTTHREAD Thread, void *pvUser);
789 static DECLCALLBACK(int) i_saveStateThread(RTTHREAD Thread, void *pvUser);
790 static DECLCALLBACK(int) i_powerDownThread(RTTHREAD Thread, void *pvUser);
791
792 static DECLCALLBACK(int) i_vmm2User_SaveState(PCVMM2USERMETHODS pThis, PUVM pUVM);
793 static DECLCALLBACK(void) i_vmm2User_NotifyEmtInit(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu);
794 static DECLCALLBACK(void) i_vmm2User_NotifyEmtTerm(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu);
795 static DECLCALLBACK(void) i_vmm2User_NotifyPdmtInit(PCVMM2USERMETHODS pThis, PUVM pUVM);
796 static DECLCALLBACK(void) i_vmm2User_NotifyPdmtTerm(PCVMM2USERMETHODS pThis, PUVM pUVM);
797 static DECLCALLBACK(void) i_vmm2User_NotifyResetTurnedIntoPowerOff(PCVMM2USERMETHODS pThis, PUVM pUVM);
798
799 static DECLCALLBACK(void *) i_drvStatus_QueryInterface(PPDMIBASE pInterface, const char *pszIID);
800 static DECLCALLBACK(void) i_drvStatus_UnitChanged(PPDMILEDCONNECTORS pInterface, unsigned iLUN);
801 static DECLCALLBACK(int) i_drvStatus_MediumEjected(PPDMIMEDIANOTIFY pInterface, unsigned iLUN);
802 static DECLCALLBACK(void) i_drvStatus_Destruct(PPDMDRVINS pDrvIns);
803 static DECLCALLBACK(int) i_drvStatus_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags);
804
805 static DECLCALLBACK(int) i_pdmIfSecKey_KeyRetain(PPDMISECKEY pInterface, const char *pszId, const uint8_t **ppbKey,
806 size_t *pcbKey);
807 static DECLCALLBACK(int) i_pdmIfSecKey_KeyRelease(PPDMISECKEY pInterface, const char *pszId);
808
809 static DECLCALLBACK(int) i_pdmIfSecKeyHlp_KeyMissingNotify(PPDMISECKEYHLP pInterface);
810
811 int mcAudioRefs;
812 volatile uint32_t mcVRDPClients;
813 uint32_t mu32SingleRDPClientId; /* The id of a connected client in the single connection mode. */
814 volatile bool mcGuestCredentialsProvided;
815
816 static const char *sSSMConsoleUnit;
817 static uint32_t sSSMConsoleVer;
818
819 HRESULT i_loadDataFromSavedState();
820 int i_loadStateFileExecInternal(PSSMHANDLE pSSM, uint32_t u32Version);
821
822 static DECLCALLBACK(void) i_saveStateFileExec(PSSMHANDLE pSSM, void *pvUser);
823 static DECLCALLBACK(int) i_loadStateFileExec(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
824
825#ifdef VBOX_WITH_GUEST_PROPS
826 static DECLCALLBACK(int) i_doGuestPropNotification(void *pvExtension, uint32_t, void *pvParms, uint32_t cbParms);
827 HRESULT i_doEnumerateGuestProperties(const Utf8Str &aPatterns,
828 std::vector<Utf8Str> &aNames,
829 std::vector<Utf8Str> &aValues,
830 std::vector<LONG64> &aTimestamps,
831 std::vector<Utf8Str> &aFlags);
832
833 void i_guestPropertiesHandleVMReset(void);
834 bool i_guestPropertiesVRDPEnabled(void);
835 void i_guestPropertiesVRDPUpdateLogon(uint32_t u32ClientId, const char *pszUser, const char *pszDomain);
836 void i_guestPropertiesVRDPUpdateActiveClient(uint32_t u32ClientId);
837 void i_guestPropertiesVRDPUpdateClientAttach(uint32_t u32ClientId, bool fAttached);
838 void i_guestPropertiesVRDPUpdateNameChange(uint32_t u32ClientId, const char *pszName);
839 void i_guestPropertiesVRDPUpdateIPAddrChange(uint32_t u32ClientId, const char *pszIPAddr);
840 void i_guestPropertiesVRDPUpdateLocationChange(uint32_t u32ClientId, const char *pszLocation);
841 void i_guestPropertiesVRDPUpdateOtherInfoChange(uint32_t u32ClientId, const char *pszOtherInfo);
842 void i_guestPropertiesVRDPUpdateDisconnect(uint32_t u32ClientId);
843#endif
844
845 bool i_isResetTurnedIntoPowerOff(void);
846
847 /** @name Disk encryption support
848 * @{ */
849 HRESULT i_consoleParseDiskEncryption(const char *psz, const char **ppszEnd);
850 HRESULT i_configureEncryptionForDisk(const char *pszUuid);
851 HRESULT i_clearDiskEncryptionKeysOnAllAttachments(void);
852 int i_consoleParseKeyValue(const char *psz, const char **ppszEnd,
853 char **ppszKey, char **ppszVal);
854 /** @} */
855
856 /** @name Teleporter support
857 * @{ */
858 static DECLCALLBACK(int) i_teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser);
859 HRESULT i_teleporterSrc(TeleporterStateSrc *pState);
860 HRESULT i_teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich, const char *pszNAckMsg = NULL);
861 HRESULT i_teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand, bool fWaitForAck = true);
862 HRESULT i_teleporterTrg(PUVM pUVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused,
863 Progress *pProgress, bool *pfPowerOffOnFailure);
864 static DECLCALLBACK(int) i_teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser);
865 /** @} */
866
867 bool mSavedStateDataLoaded : 1;
868
869 const ComPtr<IMachine> mMachine;
870 const ComPtr<IInternalMachineControl> mControl;
871
872 const ComPtr<IVRDEServer> mVRDEServer;
873
874 ConsoleVRDPServer * const mConsoleVRDPServer;
875 bool mfVRDEChangeInProcess;
876 bool mfVRDEChangePending;
877
878 const ComObjPtr<Guest> mGuest;
879 const ComObjPtr<Keyboard> mKeyboard;
880 const ComObjPtr<Mouse> mMouse;
881 const ComObjPtr<Display> mDisplay;
882 const ComObjPtr<MachineDebugger> mDebugger;
883 const ComObjPtr<VRDEServerInfo> mVRDEServerInfo;
884 /** This can safely be used without holding any locks.
885 * An AutoCaller suffices to prevent it being destroy while in use and
886 * internally there is a lock providing the necessary serialization. */
887 const ComObjPtr<EventSource> mEventSource;
888#ifdef VBOX_WITH_EXTPACK
889 const ComObjPtr<ExtPackManager> mptrExtPackManager;
890#endif
891 const ComObjPtr<EmulatedUSB> mEmulatedUSB;
892
893 USBDeviceList mUSBDevices;
894 RemoteUSBDeviceList mRemoteUSBDevices;
895
896 SharedFolderDataMap m_mapGlobalSharedFolders;
897 SharedFolderDataMap m_mapMachineSharedFolders;
898 SharedFolderMap m_mapSharedFolders; // the console instances
899
900 /** The user mode VM handle. */
901 PUVM mpUVM;
902 /** Holds the number of "readonly" mpUVM callers (users). */
903 uint32_t mVMCallers;
904 /** Semaphore posted when the number of mpUVM callers drops to zero. */
905 RTSEMEVENT mVMZeroCallersSem;
906 /** true when Console has entered the mpUVM destruction phase. */
907 bool mVMDestroying : 1;
908 /** true when power down is initiated by vmstateChangeCallback (EMT). */
909 bool mVMPoweredOff : 1;
910 /** true when vmstateChangeCallback shouldn't initiate a power down. */
911 bool mVMIsAlreadyPoweringOff : 1;
912 /** true if we already showed the snapshot folder size warning. */
913 bool mfSnapshotFolderSizeWarningShown : 1;
914 /** true if we already showed the snapshot folder ext4/xfs bug warning. */
915 bool mfSnapshotFolderExt4WarningShown : 1;
916 /** true if we already listed the disk type of the snapshot folder. */
917 bool mfSnapshotFolderDiskTypeShown : 1;
918 /** true if a USB controller is available (i.e. USB devices can be attached). */
919 bool mfVMHasUsbController : 1;
920 /** true if the VM power off was caused by reset. */
921 bool mfPowerOffCausedByReset : 1;
922
923 /** Pointer to the VMM -> User (that's us) callbacks. */
924 struct MYVMM2USERMETHODS : public VMM2USERMETHODS
925 {
926 Console *pConsole;
927 } *mpVmm2UserMethods;
928
929 /** The current network attachment type in the VM.
930 * This doesn't have to match the network attachment type maintained in the
931 * NetworkAdapter. This is needed to change the network attachment
932 * dynamically.
933 */
934 typedef std::vector<NetworkAttachmentType_T> NetworkAttachmentTypeVector;
935 NetworkAttachmentTypeVector meAttachmentType;
936
937 VMMDev * m_pVMMDev;
938#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
939 AudioVRDE * const mAudioVRDE;
940#else
941 AudioSniffer * const mAudioSniffer;
942#endif
943 Nvram * const mNvram;
944#ifdef VBOX_WITH_USB_CARDREADER
945 UsbCardReader * const mUsbCardReader;
946#endif
947 BusAssignmentManager* mBusMgr;
948
949 enum
950 {
951 iLedFloppy = 0,
952 cLedFloppy = 2,
953 iLedIde = iLedFloppy + cLedFloppy,
954 cLedIde = 4,
955 iLedSata = iLedIde + cLedIde,
956 cLedSata = 30,
957 iLedScsi = iLedSata + cLedSata,
958 cLedScsi = 16,
959 iLedSas = iLedScsi + cLedScsi,
960 cLedSas = 8,
961 iLedUsb = iLedSas + cLedSas,
962 cLedUsb = 8,
963 cLedStorage = cLedFloppy + cLedIde + cLedSata + cLedScsi + cLedSas + cLedUsb
964 };
965 DeviceType_T maStorageDevType[cLedStorage];
966 PPDMLED mapStorageLeds[cLedStorage];
967 PPDMLED mapNetworkLeds[36]; /**< @todo adapt this to the maximum network card count */
968 PPDMLED mapSharedFolderLed;
969 PPDMLED mapUSBLed[2];
970 PPDMLED mapCrOglLed;
971
972 MediumAttachmentMap mapMediumAttachments;
973
974 /** List of attached USB storage devices. */
975 USBStorageDeviceList mUSBStorageDevices;
976
977 /** Map of secret keys used for disk encryption. */
978 SecretKeyMap m_mapSecretKeys;
979
980 /** Pointer to the key consumer -> provider (that's us) callbacks. */
981 struct MYPDMISECKEY : public PDMISECKEY
982 {
983 Console *pConsole;
984 } *mpIfSecKey;
985
986 /** Pointer to the key helpers -> provider (that's us) callbacks. */
987 struct MYPDMISECKEYHLP : public PDMISECKEYHLP
988 {
989 Console *pConsole;
990 } *mpIfSecKeyHlp;
991
992/* Note: FreeBSD needs this whether netflt is used or not. */
993#if ((defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)) || defined(RT_OS_FREEBSD))
994 Utf8Str maTAPDeviceName[8];
995 RTFILE maTapFD[8];
996#endif
997
998 bool mVMStateChangeCallbackDisabled;
999
1000 bool mfUseHostClipboard;
1001
1002 /** Local machine state value. */
1003 MachineState_T mMachineState;
1004
1005 /** Pointer to the progress object of a live cancelable task.
1006 *
1007 * This is currently only used by Console::Teleport(), but is intended to later
1008 * be used by the live snapshot code path as well. Actions like
1009 * Console::PowerDown, which automatically cancels out the running snapshot /
1010 * teleportation operation, will cancel the teleportation / live snapshot
1011 * operation before starting. */
1012 ComObjPtr<Progress> mptrCancelableProgress;
1013
1014 ComPtr<IEventListener> mVmListener;
1015
1016 friend struct VMTask;
1017};
1018
1019#endif // !____H_CONSOLEIMPL
1020/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette