VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/UIGuestOSType.cpp

Last change on this file was 105523, checked in by vboxsync, 3 months ago

FE/Qt: bugref:10543: Make sure Guest OS Type Manager do not cache empty OS subtype (like for Windows etc).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/* $Id: UIGuestOSType.cpp 105523 2024-07-26 15:17:22Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestOSType class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* GUI includes: */
29#include "UICommon.h"
30#include "UIDesktopWidgetWatchdog.h"
31#include "UIGlobalSession.h"
32#include "UIGuestOSType.h"
33
34/* COM includes: */
35#include "CGuestOSType.h"
36#include "CPlatformProperties.h"
37#include "CSystemProperties.h"
38
39/* VirtualBox interface declarations: */
40#include <VBox/com/VirtualBox.h>
41
42
43/*********************************************************************************************************************************
44* Class UIGuestOSTypeHelpers implementation. *
45*********************************************************************************************************************************/
46
47#ifdef VBOX_WITH_3D_ACCELERATION
48bool UIGuestOSTypeHelpers::isWddmCompatibleOsType(const QString &strGuestOSTypeId)
49{
50 return strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("WindowsVista"))
51 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows7"))
52 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows8"))
53 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows81"))
54 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows10"))
55 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows11"))
56 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2008"))
57 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2012"))
58 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2016"))
59 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2019"));
60}
61#endif /* VBOX_WITH_3D_ACCELERATION */
62
63quint64 UIGuestOSTypeHelpers::requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors /* = 1 */)
64{
65 /* We create a list of the size of all available host monitors. This list
66 * is sorted by value and by starting with the biggest one, we calculate
67 * the memory requirements for every guest screen. This is of course not
68 * correct, but as we can't predict on which host screens the user will
69 * open the guest windows, this is the best assumption we can do, cause it
70 * is the worst case. */
71 const int cHostScreens = UIDesktopWidgetWatchdog::screenCount();
72 QVector<int> screenSize(qMax(cMonitors, cHostScreens), 0);
73 for (int i = 0; i < cHostScreens; ++i)
74 {
75 QRect r = gpDesktop->screenGeometry(i);
76 screenSize[i] = r.width() * r.height();
77 }
78 /* Now sort the vector: */
79 std::sort(screenSize.begin(), screenSize.end(), std::greater<int>());
80 /* For the case that there are more guest screens configured then host
81 * screens available, replace all zeros with the greatest value in the
82 * vector. */
83 for (int i = 0; i < screenSize.size(); ++i)
84 if (screenSize.at(i) == 0)
85 screenSize.replace(i, screenSize.at(0));
86
87 quint64 uNeedBits = 0;
88 for (int i = 0; i < cMonitors; ++i)
89 {
90 /* Calculate summary required memory amount in bits: */
91 uNeedBits += (screenSize.at(i) * /* with x height */
92 32 + /* we will take the maximum possible bpp for now */
93 8 * _1M) + /* current cache per screen - may be changed in future */
94 8 * 4096; /* adapter info */
95 }
96 /* Translate value into megabytes with rounding to highest side: */
97 quint64 uNeedMBytes = uNeedBits % (8 * _1M)
98 ? uNeedBits / (8 * _1M) + 1
99 : uNeedBits / (8 * _1M) /* convert to megabytes */;
100
101 if (strGuestOSTypeId.startsWith("Windows"))
102 {
103 /* Windows guests need offscreen VRAM too for graphics acceleration features: */
104#ifdef VBOX_WITH_3D_ACCELERATION
105 if (isWddmCompatibleOsType(strGuestOSTypeId))
106 {
107 /* WDDM mode, there are two surfaces for each screen: shadow & primary: */
108 uNeedMBytes *= 3;
109 }
110 else
111#endif /* VBOX_WITH_3D_ACCELERATION */
112 {
113 uNeedMBytes *= 2;
114 }
115 }
116
117 return uNeedMBytes * _1M;
118}
119
120
121/*********************************************************************************************************************************
122* Class UIGuestOSTypeManager implementation. *
123*********************************************************************************************************************************/
124
125void UIGuestOSTypeManager::reCacheGuestOSTypes()
126{
127 /* Acquire CVirtualBox: */
128 CVirtualBox comVBox = gpGlobalSession->virtualBox();
129
130 /* Acquire a total list of guest OS types, supported or not: */
131 CGuestOSTypeVector guestOSTypes = comVBox.GetGuestOSTypes();
132
133 /* Acquire a list of guest OS types supported by this host: */
134 CSystemProperties comSystemProps = comVBox.GetSystemProperties();
135 m_supportedArchTypes = comSystemProps.GetSupportedPlatformArchitectures();
136 m_supportedGuestOSTypeIDs.clear();
137 foreach (const KPlatformArchitecture &enmArch, m_supportedArchTypes)
138 {
139 CPlatformProperties comPlatformProps = comVBox.GetPlatformProperties(enmArch);
140 foreach (const CGuestOSType &comType, comPlatformProps.GetSupportedGuestOSTypes())
141 m_supportedGuestOSTypeIDs << comType.GetId();
142 }
143
144 /* Wipe out cache: */
145 m_typeIdIndexMap.clear();
146 m_guestOSTypes.clear();
147 m_guestOSFamilies.clear();
148 m_guestOSSubtypes.clear();
149
150 /* Enumerate guest OS types: */
151 QVector<CGuestOSType> otherOSTypes;
152 foreach (const CGuestOSType &comType, guestOSTypes)
153 {
154 /* Filter out "other" family types: */
155 if (comType.GetFamilyId().contains("other", Qt::CaseInsensitive))
156 {
157 otherOSTypes << comType;
158 continue;
159 }
160 addGuestOSType(comType);
161 }
162
163 /* Add OS types with family "other" to the end of the lists: */
164 foreach (const CGuestOSType &comType, otherOSTypes)
165 addGuestOSType(comType);
166}
167
168void UIGuestOSTypeManager::addGuestOSType(const CGuestOSType &comType)
169{
170 /* Acquire guest OS type ID and whether it's supported: */
171 const QString strId = comType.GetId();
172 const bool fSupported = m_supportedGuestOSTypeIDs.contains(strId);
173
174 /* Append guest OS type to a list of cached wrappers: */
175 m_guestOSTypes.append(UIGuestOSType(comType, fSupported));
176
177 /* Acquire a bit of attributes: */
178 const QString strFamilyId = m_guestOSTypes.last().getFamilyId();
179 const QString strFamilyDesc = m_guestOSTypes.last().getFamilyDescription();
180 const QString strSubtype = m_guestOSTypes.last().getSubtype();
181 const KPlatformArchitecture enmArch = m_guestOSTypes.last().getPlatformArchitecture();
182
183 /* Remember guest OS type index as well: */
184 m_typeIdIndexMap[strId] = m_guestOSTypes.size() - 1;
185
186 /* Cache or update family info: */
187 UIFamilyInfo fi(strFamilyId, strFamilyDesc, enmArch, fSupported);
188 if (!m_guestOSFamilies.contains(fi))
189 m_guestOSFamilies << fi;
190 else
191 {
192 const int iIndex = m_guestOSFamilies.indexOf(fi);
193 AssertReturnVoid(iIndex >= 0);
194 if (m_guestOSFamilies.at(iIndex).m_enmArch != enmArch)
195 m_guestOSFamilies[iIndex].m_enmArch = KPlatformArchitecture_None; // means any
196 if (m_guestOSFamilies.at(iIndex).m_fSupported != fSupported)
197 m_guestOSFamilies[iIndex].m_fSupported = true; // cause at least one is supported
198 }
199
200 /* Cache or update subtype info (if it's not empty): */
201 if (!strSubtype.isEmpty())
202 {
203 UISubtypeInfo si(strSubtype, enmArch, fSupported);
204 if (!m_guestOSSubtypes.contains(strFamilyId))
205 m_guestOSSubtypes[strFamilyId] << si;
206 else
207 {
208 UIGuestOSSubtypeInfo &subtypes = m_guestOSSubtypes[strFamilyId];
209 if (!subtypes.contains(si))
210 subtypes << si;
211 else
212 {
213 const int iIndex = subtypes.indexOf(si);
214 AssertReturnVoid(iIndex >= 0);
215 if (subtypes.at(iIndex).m_enmArch != enmArch)
216 subtypes[iIndex].m_enmArch = KPlatformArchitecture_None; // means any
217 if (subtypes.at(iIndex).m_fSupported != fSupported)
218 subtypes[iIndex].m_fSupported = true; // cause at least one is supported
219 }
220 }
221 }
222}
223
224UIGuestOSTypeManager::UIGuestOSFamilyInfo
225UIGuestOSTypeManager::getFamilies(bool fListAll /* = true */,
226 const QStringList &including /* = QStringList() */,
227 KPlatformArchitecture enmArch /* = KPlatformArchitecture_None */) const
228{
229 /* Prepare family list: */
230 UIGuestOSTypeManager::UIGuestOSFamilyInfo families;
231 foreach (const UIFamilyInfo &fi, m_guestOSFamilies)
232 {
233 /* Always include family which was asked for: */
234 if (including.contains(fi.m_strId))
235 {
236 families << fi;
237 continue;
238 }
239
240 /* Skip everyting if requested arch type is NOT supported: */
241 if ( enmArch != KPlatformArchitecture_None
242 && !m_supportedArchTypes.contains(enmArch))
243 continue;
244
245 /* Skip unsupported families if there was no request to show all: */
246 if ( !fListAll
247 && !fi.m_fSupported)
248 continue;
249
250 const KPlatformArchitecture enmCurrentArch = fi.m_enmArch;
251 if ( enmCurrentArch == enmArch
252 || enmCurrentArch == KPlatformArchitecture_None
253 || enmArch == KPlatformArchitecture_None)
254 families << fi;
255 }
256 return families;
257}
258
259UIGuestOSTypeManager::UIGuestOSSubtypeInfo
260UIGuestOSTypeManager::getSubtypesForFamilyId(const QString &strFamilyId,
261 bool fListAll /* = true */,
262 const QStringList &including /* = QStringList() */,
263 KPlatformArchitecture enmArch /* = KPlatformArchitecture_None */) const
264{
265 /* Prepare subtype list: */
266 UIGuestOSSubtypeInfo subtypes;
267 foreach (const UISubtypeInfo &si, m_guestOSSubtypes.value(strFamilyId))
268 {
269 /* Always include subtype which was asked for: */
270 if (including.contains(si.m_strName))
271 {
272 subtypes << si;
273 continue;
274 }
275
276 /* Skip everyting if requested arch type is NOT supported: */
277 if ( enmArch != KPlatformArchitecture_None
278 && !m_supportedArchTypes.contains(enmArch))
279 continue;
280
281 /* Skip unsupported subtypes if there was no request to show all: */
282 if ( !fListAll
283 && !si.m_fSupported)
284 continue;
285
286 const KPlatformArchitecture enmCurrentArch = si.m_enmArch;
287 if ( enmCurrentArch == enmArch
288 || enmCurrentArch == KPlatformArchitecture_None
289 || enmArch == KPlatformArchitecture_None)
290 subtypes << si;
291 }
292 return subtypes;
293}
294
295UIGuestOSTypeManager::UIGuestOSTypeInfo
296UIGuestOSTypeManager::getTypesForFamilyId(const QString &strFamilyId,
297 bool fListAll /* = true */,
298 const QStringList &including /* = QStringList() */,
299 KPlatformArchitecture enmArch /* = KPlatformArchitecture_None */) const
300{
301 UIGuestOSTypeInfo typeInfoList;
302 if (strFamilyId.isEmpty())
303 return typeInfoList;
304 foreach (const UIGuestOSType &type, m_guestOSTypes)
305 {
306 /* Check for redundant type: */
307 QPair<QString, QString> info(type.getId(), type.getDescription());
308 if (typeInfoList.contains(info))
309 continue;
310
311 /* Always include subtype which was asked for: */
312 if (including.contains(type.getId()))
313 {
314 typeInfoList << info;
315 continue;
316 }
317
318 /* Skip unsupported types if there was no request to show all: */
319 if ( !fListAll
320 && !type.isSupported())
321 continue;
322
323 /* Skip types of different family: */
324 if (type.getFamilyId() != strFamilyId)
325 continue;
326
327 if ( enmArch == KPlatformArchitecture_None
328 || type.getPlatformArchitecture() == enmArch)
329 typeInfoList << info;
330 }
331 return typeInfoList;
332}
333
334UIGuestOSTypeManager::UIGuestOSTypeInfo
335UIGuestOSTypeManager::getTypesForSubtype(const QString &strSubtype,
336 bool fListAll /* = true */,
337 const QStringList &including /* = QStringList() */,
338 KPlatformArchitecture enmArch /* = KPlatformArchitecture_None */) const
339{
340 UIGuestOSTypeInfo typeInfoList;
341 if (strSubtype.isEmpty())
342 return typeInfoList;
343 foreach (const UIGuestOSType &type, m_guestOSTypes)
344 {
345 /* Check for redundant type: */
346 QPair<QString, QString> info(type.getId(), type.getDescription());
347 if (typeInfoList.contains(info))
348 continue;
349
350 /* Always include subtype which was asked for: */
351 if (including.contains(type.getId()))
352 {
353 typeInfoList << info;
354 continue;
355 }
356
357 /* Skip unsupported types if there was no request to show all: */
358 if ( !fListAll
359 && !type.isSupported())
360 continue;
361
362 /* Skip types of different subtype: */
363 if (type.getSubtype() != strSubtype)
364 continue;
365
366 if ( enmArch == KPlatformArchitecture_None
367 || type.getPlatformArchitecture() == enmArch)
368 typeInfoList << info;
369 }
370 return typeInfoList;
371}
372
373bool UIGuestOSTypeManager::isGuestOSTypeIDSupported(const QString &strTypeId) const
374{
375 return m_supportedGuestOSTypeIDs.contains(strTypeId);
376}
377
378QString UIGuestOSTypeManager::getFamilyId(const QString &strTypeId) const
379{
380 /* Let QVector<>::value check for the bounds. It returns a default constructed value when it is out of bounds. */
381 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getFamilyId();
382}
383
384QString UIGuestOSTypeManager::getSubtype(const QString &strTypeId) const
385{
386 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getSubtype();
387}
388
389KGraphicsControllerType UIGuestOSTypeManager::getRecommendedGraphicsController(const QString &strTypeId) const
390{
391 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedGraphicsController();
392}
393
394KStorageControllerType UIGuestOSTypeManager::getRecommendedDVDStorageController(const QString &strTypeId) const
395{
396 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedDVDStorageController();
397}
398
399ULONG UIGuestOSTypeManager::getRecommendedRAM(const QString &strTypeId) const
400{
401 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedRAM();
402}
403
404ULONG UIGuestOSTypeManager::getRecommendedCPUCount(const QString &strTypeId) const
405{
406 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedCPUCount();
407}
408
409KFirmwareType UIGuestOSTypeManager::getRecommendedFirmware(const QString &strTypeId) const
410{
411 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedFirmware();
412}
413
414QString UIGuestOSTypeManager::getDescription(const QString &strTypeId) const
415{
416 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getDescription();
417}
418
419LONG64 UIGuestOSTypeManager::getRecommendedHDD(const QString &strTypeId) const
420{
421 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedHDD();
422}
423
424KStorageBus UIGuestOSTypeManager::getRecommendedHDStorageBus(const QString &strTypeId) const
425{
426 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedHDStorageBus();
427}
428
429KStorageBus UIGuestOSTypeManager::getRecommendedDVDStorageBus(const QString &strTypeId) const
430{
431 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedDVDStorageBus();
432}
433
434bool UIGuestOSTypeManager::getRecommendedFloppy(const QString &strTypeId) const
435{
436 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getRecommendedFloppy();
437}
438
439bool UIGuestOSTypeManager::isLinux(const QString &strTypeId) const
440{
441 QString strFamilyId = getFamilyId(strTypeId);
442 if (strFamilyId.contains("linux", Qt::CaseInsensitive))
443 return true;
444 return false;
445}
446
447bool UIGuestOSTypeManager::isWindows(const QString &strTypeId) const
448{
449 QString strFamilyId = getFamilyId(strTypeId);
450 if (strFamilyId.contains("windows", Qt::CaseInsensitive))
451 return true;
452 return false;
453}
454
455bool UIGuestOSTypeManager::is64Bit(const QString &strTypeId) const
456{
457 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).is64Bit();
458}
459
460KPlatformArchitecture UIGuestOSTypeManager::getPlatformArchitecture(const QString &strTypeId) const
461{
462 return m_guestOSTypes.value(m_typeIdIndexMap.value(strTypeId, -1)).getPlatformArchitecture();
463}
464
465/* static */
466bool UIGuestOSTypeManager::isDOSType(const QString &strOSTypeId)
467{
468 if ( strOSTypeId.left(3) == "dos"
469 || strOSTypeId.left(3) == "win"
470 || strOSTypeId.left(3) == "os2")
471 return true;
472
473 return false;
474}
475
476/*********************************************************************************************************************************
477* UIGuestOSType implementaion. *
478*********************************************************************************************************************************/
479
480UIGuestOSType::UIGuestOSType()
481 : m_fSupported(false)
482{
483}
484
485UIGuestOSType::UIGuestOSType(const CGuestOSType &comGuestOSType, bool fSupported)
486 : m_comGuestOSType(comGuestOSType)
487 , m_fSupported(fSupported)
488{
489}
490
491bool UIGuestOSType::isOk() const
492{
493 return (!m_comGuestOSType.isNull() && m_comGuestOSType.isOk());
494}
495
496bool UIGuestOSType::isSupported() const
497{
498 return m_fSupported;
499}
500
501const QString &UIGuestOSType::getFamilyId() const
502{
503 if (m_strFamilyId.isEmpty() && m_comGuestOSType.isOk())
504 m_strFamilyId = m_comGuestOSType.GetFamilyId();
505 return m_strFamilyId;
506}
507
508const QString &UIGuestOSType::getFamilyDescription() const
509{
510 if (m_strFamilyDescription.isEmpty() && m_comGuestOSType.isOk())
511 m_strFamilyDescription = m_comGuestOSType.GetFamilyDescription();
512 return m_strFamilyDescription;
513}
514
515const QString &UIGuestOSType::getId() const
516{
517 if (m_strId.isEmpty() && m_comGuestOSType.isOk())
518 m_strId = m_comGuestOSType.GetId();
519 return m_strId;
520}
521
522const QString &UIGuestOSType::getSubtype() const
523{
524 if (m_strSubtype.isEmpty() && m_comGuestOSType.isOk())
525 m_strSubtype = m_comGuestOSType.GetSubtype();
526 return m_strSubtype;
527}
528
529const QString &UIGuestOSType::getDescription() const
530{
531 if (m_strDescription.isEmpty() && m_comGuestOSType.isOk())
532 m_strDescription = m_comGuestOSType.GetDescription();
533 return m_strDescription;
534}
535
536KStorageBus UIGuestOSType::getRecommendedHDStorageBus() const
537{
538 if (m_comGuestOSType.isOk())
539 return m_comGuestOSType.GetRecommendedHDStorageBus();
540 return KStorageBus_Null;
541}
542
543ULONG UIGuestOSType::getRecommendedRAM() const
544{
545 if (m_comGuestOSType.isOk())
546 return m_comGuestOSType.GetRecommendedRAM();
547 return 0;
548}
549
550KStorageBus UIGuestOSType::getRecommendedDVDStorageBus() const
551{
552 if (m_comGuestOSType.isOk())
553 return m_comGuestOSType.GetRecommendedDVDStorageBus();
554 return KStorageBus_Null;
555}
556
557ULONG UIGuestOSType::getRecommendedCPUCount() const
558{
559 if (m_comGuestOSType.isOk())
560 return m_comGuestOSType.GetRecommendedCPUCount();
561 return 0;
562}
563
564KFirmwareType UIGuestOSType::getRecommendedFirmware() const
565{
566 if (m_comGuestOSType.isOk())
567 return m_comGuestOSType.GetRecommendedFirmware();
568 return KFirmwareType_Max;
569}
570
571bool UIGuestOSType::getRecommendedFloppy() const
572{
573 if (m_comGuestOSType.isOk())
574 return m_comGuestOSType.GetRecommendedFloppy();
575 return false;
576}
577
578LONG64 UIGuestOSType::getRecommendedHDD() const
579{
580 if (m_comGuestOSType.isOk())
581 return m_comGuestOSType.GetRecommendedHDD();
582 return 0;
583}
584
585KGraphicsControllerType UIGuestOSType::getRecommendedGraphicsController() const
586{
587 if (m_comGuestOSType.isOk())
588 return m_comGuestOSType.GetRecommendedGraphicsController();
589 return KGraphicsControllerType_Null;
590}
591
592KStorageControllerType UIGuestOSType::getRecommendedDVDStorageController() const
593{
594 if (m_comGuestOSType.isOk())
595 return m_comGuestOSType.GetRecommendedDVDStorageController();
596 return KStorageControllerType_Null;
597}
598
599bool UIGuestOSType::is64Bit() const
600{
601 if (m_comGuestOSType.isOk())
602 return m_comGuestOSType.GetIs64Bit();
603 return false;
604}
605
606KPlatformArchitecture UIGuestOSType::getPlatformArchitecture() const
607{
608 if (m_comGuestOSType.isOk())
609 return m_comGuestOSType.GetPlatformArchitecture();
610 return KPlatformArchitecture_Max;
611}
Note: See TracBrowser for help on using the repository browser.

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