Integrating up through commit 90f050496
This commit is contained in:
+2
-1
@@ -15,7 +15,8 @@
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, [[maybe_unused]] bool includeAllHardware)
|
||||
bool CollectIoHardwareInformation(
|
||||
HardwareInformation& info, [[maybe_unused]] bool includeAllHardware, [[maybe_unused]] bool reportHardware)
|
||||
{
|
||||
// The numbers below are based on common defaults from a local hardware survey.
|
||||
info.m_maxPageSize = 4096;
|
||||
|
||||
+2
-3
@@ -14,9 +14,8 @@
|
||||
|
||||
namespace AZ::Utils
|
||||
{
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace AZ::Utils
|
||||
} // namespace AZ::Utils
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace AZ
|
||||
|
||||
void NativeErrorMessageBox(const char*, const char*) {}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
if (const char* homePath = std::getenv("HOME"); homePath != nullptr)
|
||||
{
|
||||
@@ -33,7 +33,6 @@ namespace AZ
|
||||
if (!path.empty())
|
||||
{
|
||||
path /= ".o3de";
|
||||
path /= "o3de_manifest.json";
|
||||
}
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
+3
-1
@@ -31,6 +31,7 @@ namespace AZ::IO
|
||||
options.m_enableUnbufferedReads = m_enableUnbufferedReads;
|
||||
options.m_enableSharing = m_enableFileSharing;
|
||||
options.m_hasSeekPenalty = drive.m_hasSeekPenalty;
|
||||
options.m_minimalReporting = m_minimalReporting;
|
||||
|
||||
AZStd::vector<AZStd::string_view> drivePaths(drive.m_paths.begin(), drive.m_paths.end());
|
||||
AZ_Assert(!drive.m_paths.empty(), "Expected at least one drive path.");
|
||||
@@ -59,7 +60,8 @@ namespace AZ::IO
|
||||
->Field("MaxMetaDataCache", &WindowsStorageDriveConfig::m_maxMetaDataCache)
|
||||
->Field("Overcommit", &WindowsStorageDriveConfig::m_overcommit)
|
||||
->Field("EnableFileSharing", &WindowsStorageDriveConfig::m_enableFileSharing)
|
||||
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads);
|
||||
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads)
|
||||
->Field("MinimalReporting", &WindowsStorageDriveConfig::m_minimalReporting);
|
||||
}
|
||||
}
|
||||
} // namespace AZ::IO
|
||||
|
||||
@@ -34,5 +34,6 @@ namespace AZ::IO
|
||||
AZ::u32 m_overcommit{ 8 };
|
||||
bool m_enableFileSharing{ false };
|
||||
bool m_enableUnbufferedReads{ true };
|
||||
bool m_minimalReporting{ false };
|
||||
};
|
||||
} // namespace AZ::IO
|
||||
|
||||
+11
-13
@@ -41,6 +41,7 @@ namespace AZ::IO
|
||||
: m_hasSeekPenalty(true)
|
||||
, m_enableUnbufferedReads(true)
|
||||
, m_enableSharing(false)
|
||||
, m_minimalReporting(false)
|
||||
{}
|
||||
|
||||
//
|
||||
@@ -102,7 +103,10 @@ namespace AZ::IO
|
||||
m_name += m_drivePaths[i].substr(0, m_drivePaths[i].length()-1);
|
||||
}
|
||||
m_name += ')';
|
||||
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
|
||||
if (!m_constructionOptions.m_minimalReporting)
|
||||
{
|
||||
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
|
||||
}
|
||||
|
||||
if (m_physicalSectorSize == 0)
|
||||
{
|
||||
@@ -160,7 +164,10 @@ namespace AZ::IO
|
||||
::CloseHandle(file);
|
||||
}
|
||||
}
|
||||
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
|
||||
if (!m_constructionOptions.m_minimalReporting)
|
||||
{
|
||||
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void StorageDriveWin::PrepareRequest(FileRequest* request)
|
||||
@@ -483,7 +490,7 @@ namespace AZ::IO
|
||||
// Remove any alertable IO completion notifications that could be queued by the IO Manager.
|
||||
if (!::SetFileCompletionNotificationModes(file, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
|
||||
{
|
||||
AZ_Printf("StorageDriveWin", "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
|
||||
AZ_Warning("StorageDriveWin", false, "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
|
||||
}
|
||||
|
||||
if (m_fileCache_handles[cacheIndex] != INVALID_HANDLE_VALUE)
|
||||
@@ -651,15 +658,6 @@ namespace AZ::IO
|
||||
#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO
|
||||
}
|
||||
|
||||
// Keep this, it helps to see the critical info about every read.
|
||||
//AZ_Printf("StorageDriveWin", "FileRead: addr: 0x%p size: %zu offs: %zu alloc: %s direct: %.2f%% '%s'\n",
|
||||
// data->m_output,
|
||||
// data->m_size,
|
||||
// data->m_offset,
|
||||
// (isAligned) ? "Yes" : "No",
|
||||
// m_directReadsPercentageStat.GetAverage() * 100.0,
|
||||
// data->m_path.GetRelativePath());
|
||||
|
||||
FileReadStatus& readStatus = m_readSlots_statusInfo[readSlot];
|
||||
LPOVERLAPPED overlapped = &readStatus.m_overlapped;
|
||||
overlapped->Offset = aznumeric_caster(readOffs);
|
||||
@@ -678,7 +676,7 @@ namespace AZ::IO
|
||||
DWORD error = ::GetLastError();
|
||||
if (error != ERROR_IO_PENDING)
|
||||
{
|
||||
AZ_Printf("StorageDriveWin", "::ReadFile failed with error: %u\n", error);
|
||||
AZ_Warning("StorageDriveWin", false, "::ReadFile failed with error: %u\n", error);
|
||||
|
||||
m_context->GetStreamerThreadSynchronizer().DestroyEventHandle(overlapped->hEvent);
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace AZ::IO
|
||||
//! while in use by AZ::IO::Streamer. File sharing can negatively impact performance and is recommended for
|
||||
//! development only.
|
||||
u8 m_enableSharing : 1;
|
||||
//! If true, only information that's explicitly requested or issues are reported. If false, status information
|
||||
//! such as when drives are created and destroyed is reported as well.
|
||||
u8 m_minimalReporting : 1;
|
||||
};
|
||||
|
||||
//! Creates an instance of a storage device that's optimized for use on Windows.
|
||||
|
||||
+107
-62
@@ -34,7 +34,7 @@ namespace AZ::IO
|
||||
return value;
|
||||
}
|
||||
|
||||
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName)
|
||||
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName, bool reportHardware)
|
||||
{
|
||||
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -71,17 +71,21 @@ namespace AZ::IO
|
||||
|
||||
DWORD pageSize = NextPowerOfTwo(adapterDescriptor.MaximumTransferLength / adapterDescriptor.MaximumPhysicalPages);
|
||||
|
||||
AZ_Printf("Streamer",
|
||||
"Adapter for drive '%s':\n"
|
||||
" Bus: %s %i.%i\n"
|
||||
" Max transfer: %.3f kb\n"
|
||||
" Page size: %i kb for %i pages\n"
|
||||
" Supports queuing: %s\n",
|
||||
driveName,
|
||||
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
|
||||
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
|
||||
pageSize, adapterDescriptor.MaximumPhysicalPages,
|
||||
adapterDescriptor.CommandQueueing ? "Yes" : "No");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
"Adapter for drive '%s':\n"
|
||||
" Bus: %s %i.%i\n"
|
||||
" Max transfer: %.3f kb\n"
|
||||
" Page size: %i kb for %i pages\n"
|
||||
" Supports queuing: %s\n",
|
||||
driveName,
|
||||
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
|
||||
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
|
||||
pageSize, adapterDescriptor.MaximumPhysicalPages,
|
||||
adapterDescriptor.CommandQueueing ? "Yes" : "No");
|
||||
}
|
||||
|
||||
info.m_maxTransfer = adapterDescriptor.MaximumTransferLength;
|
||||
info.m_pageSize = pageSize;
|
||||
@@ -89,7 +93,7 @@ namespace AZ::IO
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
// Check for support for the TRIM command. This command is exclusively used by SSD drives so can be used to
|
||||
// tell the difference between SSD and HDD. Since these are the only 2 types supported right now, no further
|
||||
@@ -105,18 +109,24 @@ namespace AZ::IO
|
||||
&trimDescriptor, sizeof(trimDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_profile += trimDescriptor.TrimEnabled ? "_SSD" : "_HDD";
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type: %s\n",
|
||||
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
|
||||
if (reportHardware)
|
||||
{
|
||||
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type: %s\n",
|
||||
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type couldn't be determined.");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", " Drive type couldn't be determined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -129,15 +139,19 @@ namespace AZ::IO
|
||||
{
|
||||
information.m_physicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerPhysicalSector);
|
||||
information.m_logicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerLogicalSector);
|
||||
AZ_Printf("Streamer",
|
||||
" Physical sector size: %i bytes\n"
|
||||
" Logical sector size: %i bytes\n",
|
||||
alignmentDescriptor.BytesPerPhysicalSector,
|
||||
alignmentDescriptor.BytesPerLogicalSector);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
" Physical sector size: %i bytes\n"
|
||||
" Logical sector size: %i bytes\n",
|
||||
alignmentDescriptor.BytesPerPhysicalSector,
|
||||
alignmentDescriptor.BytesPerLogicalSector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName)
|
||||
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName, bool reportHardware)
|
||||
{
|
||||
STORAGE_DEVICE_DESCRIPTOR sizeRequest{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -154,21 +168,24 @@ namespace AZ::IO
|
||||
if (::DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
|
||||
buffer.get(), header->Size, &bytesReturned, nullptr))
|
||||
{
|
||||
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
|
||||
AZ_Printf("Streamer",
|
||||
"Drive info for '%s':\n"
|
||||
" Id: %s%s%s%s%s\n",
|
||||
driveName,
|
||||
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
|
||||
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
|
||||
if (reportHardware)
|
||||
{
|
||||
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
|
||||
AZ_Printf("Streamer",
|
||||
"Drive info for '%s':\n"
|
||||
" Id: %s%s%s%s%s\n",
|
||||
driveName,
|
||||
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
|
||||
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
STORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR capabilityDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -180,15 +197,19 @@ namespace AZ::IO
|
||||
&capabilityDescriptor, sizeof(capabilityDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_ioChannelCount = aznumeric_caster(capabilityDescriptor.LunMaxIoCount);
|
||||
AZ_Printf("Streamer",
|
||||
" Max IO count (LUN): %i\n"
|
||||
" Max IO count (Adapter): %i\n",
|
||||
capabilityDescriptor.LunMaxIoCount,
|
||||
capabilityDescriptor.AdapterMaxIoCount);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
" Max IO count (LUN): %i\n"
|
||||
" Max IO count (Adapter): %i\n",
|
||||
capabilityDescriptor.LunMaxIoCount,
|
||||
capabilityDescriptor.AdapterMaxIoCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
DWORD bytesReturned = 0;
|
||||
|
||||
@@ -201,9 +222,12 @@ namespace AZ::IO
|
||||
&seekPenaltyDescriptor, sizeof(seekPenaltyDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_hasSeekPenalty = seekPenaltyDescriptor.IncursSeekPenalty ? true : false;
|
||||
AZ_Printf("Streamer",
|
||||
" Has seek penalty: %s\n",
|
||||
information.m_hasSeekPenalty ? "Yes" : "No");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
" Has seek penalty: %s\n",
|
||||
information.m_hasSeekPenalty ? "Yes" : "No");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -267,7 +291,7 @@ namespace AZ::IO
|
||||
return visitor.m_found;
|
||||
}
|
||||
|
||||
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives)
|
||||
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives, bool reportHardware)
|
||||
{
|
||||
char drives[512];
|
||||
if (::GetLogicalDriveStrings(sizeof(drives) - 1, drives))
|
||||
@@ -286,7 +310,10 @@ namespace AZ::IO
|
||||
{
|
||||
if (!addAllDrives && !IsDriveUsed(driveIt))
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
|
||||
}
|
||||
while (*driveIt++);
|
||||
continue;
|
||||
}
|
||||
@@ -311,14 +338,14 @@ namespace AZ::IO
|
||||
DriveInformation driveInformation;
|
||||
driveInformation.m_paths.emplace_back(driveIt);
|
||||
|
||||
CollectIoAdaptor(deviceHandle, driveInformation, driveIt);
|
||||
CollectIoAdaptor(deviceHandle, driveInformation, driveIt, reportHardware);
|
||||
if (driveInformation.m_supportsQueuing)
|
||||
{
|
||||
CollectDriveInfo(deviceHandle, driveIt);
|
||||
AppendDriveTypeToProfile(deviceHandle, driveInformation);
|
||||
CollectDriveIoCapability(deviceHandle, driveInformation);
|
||||
CollectDriveSeekPenalty(deviceHandle, driveInformation);
|
||||
CollectAlignmentRequirements(deviceHandle, driveInformation);
|
||||
CollectDriveInfo(deviceHandle, driveIt, reportHardware);
|
||||
AppendDriveTypeToProfile(deviceHandle, driveInformation, reportHardware);
|
||||
CollectDriveIoCapability(deviceHandle, driveInformation, reportHardware);
|
||||
CollectDriveSeekPenalty(deviceHandle, driveInformation, reportHardware);
|
||||
CollectAlignmentRequirements(deviceHandle, driveInformation, reportHardware);
|
||||
|
||||
hardwareInfo.m_maxPhysicalSectorSize =
|
||||
AZStd::max(hardwareInfo.m_maxPhysicalSectorSize, driveInformation.m_physicalSectorSize);
|
||||
@@ -329,24 +356,39 @@ namespace AZ::IO
|
||||
|
||||
driveMappings.insert({ storageDeviceNumber.DeviceNumber, AZStd::move(driveInformation) });
|
||||
|
||||
AZ_Printf("Streamer", "\n");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
|
||||
driveIt, driveInformationEntry->second.m_paths[0].c_str());
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
|
||||
driveIt, driveInformationEntry->second.m_paths[0].c_str());
|
||||
}
|
||||
driveInformationEntry->second.m_paths.emplace_back(driveIt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
"Skipping drive '%s' because device is not registered with OS as a storage device.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Skipping drive '%s' because device is not registered with OS as a storage device.\n",
|
||||
driveIt);
|
||||
}
|
||||
}
|
||||
::CloseHandle(deviceHandle);
|
||||
}
|
||||
@@ -358,7 +400,10 @@ namespace AZ::IO
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next drive string. GetLogicalDriveStrings fills the target buffer with null-terminated strings, for instance
|
||||
@@ -384,9 +429,9 @@ namespace AZ::IO
|
||||
}
|
||||
}
|
||||
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware)
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware, bool reportHardware)
|
||||
{
|
||||
if (!CollectHardwareInfo(info, includeAllHardware))
|
||||
if (!CollectHardwareInfo(info, includeAllHardware, reportHardware))
|
||||
{
|
||||
// The numbers below are based on common defaults from a local hardware survey.
|
||||
info.m_maxPageSize = 4096;
|
||||
|
||||
@@ -22,20 +22,18 @@ namespace AZ::Utils
|
||||
::MessageBox(0, message, title, MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
char userProfileBuffer[AZ::IO::MaxPathLength] = {0};
|
||||
char userProfileBuffer[AZ::IO::MaxPathLength]{};
|
||||
size_t variableSize = 0;
|
||||
auto err = getenv_s(&variableSize, userProfileBuffer, AZ::IO::MaxPathLength, "USERPROFILE");
|
||||
if (!err)
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{userProfileBuffer};
|
||||
AZ::IO::FixedMaxPath path{ userProfileBuffer };
|
||||
path /= ".o3de";
|
||||
path /= "o3de_manifest.json";
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace AZ::Utils
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AZ::Utils
|
||||
|
||||
const char* src = [appSupportDir UTF8String];
|
||||
const size_t srcLen = strlen(src);
|
||||
if (srcLen > MaxPathLength - 1)
|
||||
if (srcLen > AZ::IO::MaxPathLength - 1)
|
||||
{
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user