[*] Refactor some APIs to use string views instead of strings

[+] Added new shell dirs API
[+] AuOptional<AuROString> GetUserDocuments()
[+] AuOptional<AuROString> GetUserDownloads()
[+] AuOptional<AuROString> GetUserDesktop()
[+] AuOptional<AuROString> GetUserPhotos()
[+] AuOptional<AuROString> GetUserVideos()
[+] AuOptional<AuROString> GetUserMusic()
[*] Amend IPCHandle::InitFromSharing (use string view)
[*] AuFS devices API should now use string views
[*] AuProcess, Process APIs now use string views (ModuleLoadRequest, LoadModule, GetProcAddressEx, etc)
[*] AuProcess, Paths APIs now use string views (GetProcessDirectory, GetProcessFullPath, etc)
[*] Fix XP using common my documents vs local user documents
This commit is contained in:
Reece Wilson 2024-09-24 18:53:54 +01:00
parent 9b1ff8889e
commit 7046ccec11
18 changed files with 708 additions and 340 deletions

View File

@ -107,53 +107,53 @@ namespace Aurora::IO::FS
* Provides the best-fit FSLogicalPartition::filesystemMountPoints of a string. * Provides the best-fit FSLogicalPartition::filesystemMountPoints of a string.
* Sometimes the platform shell can help, some platforms need to pull the fs devices cache. * Sometimes the platform shell can help, some platforms need to pull the fs devices cache.
*/ */
AUKN_SYM AuString GetRootFromPath(const AuString &fileOrDirPath); AUKN_SYM AuString GetRootFromPath(const AuROString &fileOrDirPath);
/** /**
* Provides a FSDevice::devicePath of a file or directory. * Provides a FSDevice::devicePath of a file or directory.
*/ */
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &fileOrDirPath); AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &fileOrDirPath);
/** /**
* Provides a FSDevice::devicePath of a root mountpoint. * Provides a FSDevice::devicePath of a root mountpoint.
*/ */
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString &root); AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root);
/** /**
* Provides the FSLogicalPartition::logicalMount of a file or directory. * Provides the FSLogicalPartition::logicalMount of a file or directory.
*/ */
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath); AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath);
AUKN_SYM AuString TrySimplifyDevicePath(const AuString &deviceOrLogicalMountPath); AUKN_SYM AuString TrySimplifyDevicePath(const AuROString &deviceOrLogicalMountPath);
// max: unbuffered pipe io // max: unbuffered pipe io
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &fileOrDirPath); AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &fileOrDirPath);
// min: unbuffered pipe io // min: unbuffered pipe io
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &fileOrDirPath); AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &fileOrDirPath);
// min viable sector size with abstractions on top of the disk // min viable sector size with abstractions on top of the disk
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuString &fileOrDirPath); AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuROString &fileOrDirPath);
/** /**
* Provides a FSLogicalPartition::space of a file or directory. * Provides a FSLogicalPartition::space of a file or directory.
*/ */
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &fileOrDirPath); AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &fileOrDirPath);
/** /**
* Provides a FSLogicalPartition::space of a logical volume path / FSLogicalPartition::logicalMount string. * Provides a FSLogicalPartition::space of a logical volume path / FSLogicalPartition::logicalMount string.
*/ */
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath); AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath);
// Convenience function // Convenience function
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuString& physicalDevicePath); AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuROString &physicalDevicePath);
// Convenience function // Convenience function
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuString& physicalDevicePath); AUKN_SYM AuResult<AuString> GetDeviceModel(const AuROString &physicalDevicePath);
// Convenience function // Convenience function
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuString &fileOrDirPath); AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuROString &fileOrDirPath);
// Convenience function // Convenience function
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuString &physicalDevicePath); AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuROString &physicalDevicePath);
/* /*
* Provides a copy of the internal FSDevice cache under lock * Provides a copy of the internal FSDevice cache under lock

View File

@ -10,17 +10,19 @@
namespace Aurora::IO::FS namespace Aurora::IO::FS
{ {
/** /**
* @brief Provides an application specific storage path for sharing data amongst Aurora applications sharing the same branding info (defer to the init structure) * @brief Provides an application specific storage path for sharing data amongst Aurora applications sharing the same branding info (defer to the init structure).
* This should be used for machine local configs and caches.
*/ */
AUKN_SYM AuOptional<const AuString &> GetSystemDomain(); AUKN_SYM AuOptional<AuROString> GetSystemDomain();
/** /**
* @brief Provides an application specific storage path for user-local application data, isolated with respect to your Aurora application brand info (defer to the init structure) * @brief Provides an application specific storage path for user-local application data, isolated with respect to your Aurora application brand info (defer to the init structure).
*/ * This should be used for storing private user configs under an application data subdirectory.
AUKN_SYM AuOptional<const AuString &> GetProfileDomain(); */
AUKN_SYM AuOptional<AuROString> GetProfileDomain();
AUKN_SYM bool GetSystemResourcePath(const AuString &fileName, AuString &path); AUKN_SYM bool GetSystemResourcePath(const AuROString &fileName, AuString &path);
/** /**
* @brief Get package path * @brief Get package path
@ -31,39 +33,64 @@ namespace Aurora::IO::FS
* ...on platforms with read-only application specific data directories * ...on platforms with read-only application specific data directories
* @param path * @param path
* @return * @return
*/ */
AUKN_SYM AuOptional<const AuString &> GetPackagePath(); AUKN_SYM AuOptional<AuROString> GetPackagePath();
/** /**
* @brief Pulls the application directory as defined by the operating system standard file system hierarchy * @brief Pulls the application directory as defined by the operating system standard file system hierarchy.
* Otherwise, XDG_CONFIG_CONFIG or %appdata%. * This is often $XDG_CONFIG_HOME or %APPDATA%.
* This directory might be sandboxed to the user or application by the operating system. * This directory might be sandboxed to the user or application by the operating system.
*/ * Are you looking for GetProfileDomain()/GetSystemDomain()? These will provide better paths for storing configs and caches respectively.
AUKN_SYM AuOptional<const AuString &> GetAppData(); */
AUKN_SYM AuOptional<AuROString> GetAppData();
/** /**
* @brief Pulls the users home directory, untouched * @brief Pulls the users home directory, untouched
*/ */
AUKN_SYM AuOptional<const AuString &> GetUserHome(); AUKN_SYM AuOptional<AuROString> GetUserHome();
AUKN_SYM AuOptional<AuROString> GetUserDocuments();
AUKN_SYM AuOptional<AuROString> GetUserDownloads();
AUKN_SYM AuOptional<AuROString> GetUserDesktop();
AUKN_SYM AuOptional<AuROString> GetUserPhotos();
AUKN_SYM AuOptional<AuROString> GetUserVideos();
AUKN_SYM AuOptional<AuROString> GetUserMusic();
/** /**
* @brief Global application data that requires no special permissions to access. * @brief Global application data that requires no special permissions to access.
* This could be an SD-Card or user profile. * This could be an SD-Card or user profile.
* This could be the root of the user managable aplication directory. * This could be the root of the user managable aplication directory.
*/ */
AUKN_SYM AuOptional<const AuString &> GetWritableAppdata(); AUKN_SYM AuOptional<AuROString> GetWritableAppdata();
/** /**
* @brief Global application data that requires special permissions to access, usually configured by a system account during installation * @brief Global application data that requires special permissions to access, usually configured by a system account during installation
*/ */
AUKN_SYM AuOptional<const AuString &> GetRootAppdata(); AUKN_SYM AuOptional<AuROString> GetRootAppdata();
/** /**
* @brief Get user installable application directory * @brief Get user installable application directory
*/ */
AUKN_SYM AuOptional<const AuString &> GetUserProgramsFolder(); AUKN_SYM AuOptional<AuROString> GetUserProgramsFolder();
AUKN_SYM AuOptional<AuString> NewTempFile(); /**
* @brief Creates an empty temp file and returns its' path.
* It should be marked for deletion on shutdown, or be located in a directory marked for auto-deletion, or be located on a temporary ramdisk, or exist in a temporary file system mount.
* If you can delete it for us, even better.
* Windows XP warning: this does not use C:\Windows\Temp. Check documents instead.
*/
AUKN_SYM AuOptional<AuString> NewTempFile();
AUKN_SYM AuOptional<AuString> NewTempDirectory(); /**
* @brief Creates an empty temp directory and returns its' path.
* It should be marked for deletion on shutdown, or be located in a directory marked for auto-deletion, or be located on a temporary ramdisk, or exist in a temporary file system mount.
* If you can delete it for us, even better.
* Windows XP warning: this does not use C:\Windows\Temp. Check documents instead.
*/
AUKN_SYM AuOptional<AuString> NewTempDirectory();
} }

View File

@ -129,7 +129,7 @@ namespace Aurora::IO
virtual bool InitFromStreamEnum(EStandardStream eStream) = 0; virtual bool InitFromStreamEnum(EStandardStream eStream) = 0;
virtual bool InitFromSharing(const AuString &handle) = 0; virtual bool InitFromSharing(const AuROString &handle) = 0;
virtual AuUInt64 GetOSHandle() const = 0; virtual AuUInt64 GetOSHandle() const = 0;

View File

@ -17,7 +17,7 @@ namespace Aurora::IO::UNIX
{ {
AUKN_SYM AuString ShareFileDescriptor(int fd); AUKN_SYM AuString ShareFileDescriptor(int fd);
AUKN_SYM void ShareFileDescriptorStop(const AuString &handle); AUKN_SYM void ShareFileDescriptorStop(const AuROString &handle);
AUKN_SYM int ShareFileDescriptorAccept(const AuString &handle); AUKN_SYM int ShareFileDescriptorAccept(const AuROString &handle);
} }

View File

@ -20,17 +20,17 @@ namespace Aurora::Process
* @brief Fetches the applications binary or package directory * @brief Fetches the applications binary or package directory
* @return * @return
*/ */
AUKN_SYM AuOptional<const AuString &> GetProcessDirectory(); AUKN_SYM AuOptional<AuROString> GetProcessDirectory();
/** /**
* @brief Fetches the full-path of the applications binary, if known * @brief Fetches the full-path of the applications binary, if known
* @return * @return
*/ */
AUKN_SYM AuOptional<const AuString &> GetProcessFullPath(); AUKN_SYM AuOptional<AuROString> GetProcessFullPath();
/** /**
* @brief Fetches the applications primary module name * @brief Fetches the applications primary module name
* @return * @return
*/ */
AUKN_SYM AuOptional<const AuString &> GetProcessName(); AUKN_SYM AuOptional<AuROString> GetProcessName();
} }

View File

@ -48,50 +48,136 @@ namespace Aurora::Process
static AuList<EModulePath> kCWDPath = { EModulePath::eModulePathCWD }; static AuList<EModulePath> kCWDPath = { EModulePath::eModulePathCWD };
static AuList<EModulePath> kProcPath = { EModulePath::eProcessDirectory }; static AuList<EModulePath> kProcPath = { EModulePath::eProcessDirectory };
// Binding warning: this object takes references to references/pointers within the full-expressions (we live here) to parent scope[s] (your callframe lives here, with the provided temp string views).
// this object is therefore not expected to outlive any references you pass at it.
// we should only exist in the scope of FULL-EXPRESSION := { LoadModule({ ModuleLoadRequest: { temp raw string pointer view to anywhere valid throughout the call }}) }
// binders will need to create a derived type to contain two AuStrings to fill mod and version.
struct ModuleLoadRequest struct ModuleLoadRequest
{ {
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod) : mod(mod), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict) inline ModuleLoadRequest() :
searchPath(&kSpecifiedPathStrict)
{
}
inline ModuleLoadRequest(const AuList<AuString> &directories,
const AuString &mod) :
mod(mod),
specifiedSearchPaths(&directories),
searchPath(&kSpecifiedPathStrict)
{} {}
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod, const AuString &version) : mod(mod), version(version), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict) inline ModuleLoadRequest(const AuList<AuString> &directories,
const AuROString &mod,
const AuROString &version) :
mod(mod), version(version),
specifiedSearchPaths(&directories),
searchPath(&kSpecifiedPathStrict)
{} {}
inline ModuleLoadRequest(const AuString &mod) : mod(mod), searchPath(&kAdminOverloadableSearchPath) inline ModuleLoadRequest(const AuROString &mod) :
mod(mod),
searchPath(&kAdminOverloadableSearchPath)
{} {}
inline ModuleLoadRequest(const AuString &mod, const AuString &version) : mod(mod), version(version), searchPath(&kAdminOverloadableSearchPath) inline ModuleLoadRequest(const AuROString &mod,
const AuROString &version) :
mod(mod),
version(version),
searchPath(&kAdminOverloadableSearchPath)
{} {}
AuString mod; AuROString mod;
AuString version; AuROString version;
AuList<AuString> const * specifiedSearchPaths {}; AuList<AuString> const * specifiedSearchPaths {};
AuList<EModulePath> const * searchPath {}; AuList<EModulePath> const * searchPath {};
bool verify {}; // always effectively true if the executable is signed and enableMitigations is true bool verify {}; // always effectively true if the executable is signed and enableMitigations is true
bool unixCheckPlusX { true }; bool unixCheckPlusX { true };
bool enableMitigations { true }; bool enableMitigations { true };
bool forceMitigations { false }; bool forceMitigations { false };
char padZero[128] { 0 };
}; };
/** /// Provides a scriptability style DLL suffix including the relevant file extension.
* @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'. /// I do not recommend trying to build DLL filenames yourself, use LoadModule instead.
* You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of /// Different version, file extension, and unique suffix order and values may apply.
* resolving the Aurora ABI, falling back to mod.platformext. AUKN_SYM AuROString GetViewOfAuroraDLLSuffix();
* @param request
* @return /// Provides the platform extension for dynamically linked objects.
*/ /// This may become before or after the version string, depending on the host platform style.
/// I do not recommend trying to build DLL filenames yourself, use LoadModule instead.
AUKN_SYM AuROString GetViewOfDynamicLibraryExtensionSuffix();
/// Provides the scriptability style architecture string for platform local build artefects.
AUKN_SYM AuROString GetViewOfArchitectureSuffix();
/// @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'.
/// You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of
/// resolving the Aurora build ABI strings, falling back to "${request.mod}.${GetViewOfDynamicLibraryExtensionSuffix()}".
/// @param request
/// @return
AUKN_SYM bool LoadModule(const ModuleLoadRequest &request); AUKN_SYM bool LoadModule(const ModuleLoadRequest &request);
/// Updated version of LoadModule.
/// Returns a VOID* handle to be used as a replacement for win32 LoadLibraryW(...) / posix dlopen(...), to be followed up by a/multiple GetProcessAddress / dlsym calls.
/// GetProcAddressEx is to be used with this VOID* handle.
AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request); AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request);
AUKN_SYM void *GetProcHandle(const AuString &name); /// Safe (without unloads) handle fetch of LoadModuleEx.
AUKN_SYM void *GetProcHandle(const AuROString &name);
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol); /// Safe process address fetch a symbol inside of a nammed LoadModule object.
AUKN_SYM AuMach GetProcAddress(const AuROString &mod, const AuRONString &symbol);
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol); /// Safe (without unloads) process address fetch a symbol inside of LoadModuleEx object.
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuRONString &symbol);
/// Returns a copy of the directories in which the requests of LoadModule can be fulfilled.
AUKN_SYM AuList<AuString> GetBinaryClassPath(); AUKN_SYM AuList<AuString> GetBinaryClassPath();
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll = false); /// Warning: in production applications, becareful about preloading binaries of unknown origin.
///
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll = false); /// Consider every directory in "list" to be within the perview of the plugin-write user group.
/// Anybody, presumably the local user and all its processes, can write/install plugins, is capable of loading any arbitrary code whatsoever.
/// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin.
/// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support.
/// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs).
/// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks.
/// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc).
/// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly.
///
/// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections.
/// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts),
/// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security.
/// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks.
///
/// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms.
/// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work.
/// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox.
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, AuOptional<bool> optBoolPreloadAll = { false });
/// Warning: in production applications, becareful about preloading binaries of unknown origin.
///
/// Consider every directory in "list" to be within the perview of the plugin-write user group.
/// Anybody, the local user and its processes, who can write/install plugins, is capable of loading any arbitrary code whatsoever.
/// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin.
/// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support.
/// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs).
/// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks.
/// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc).
/// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly.
///
/// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections.
/// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts),
/// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security.
/// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks.
///
/// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms.
/// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work.
/// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox.
AUKN_SYM bool AddBinaryClassPath(const AuROString &dir, AuOptional<bool> optBoolPreloadAll = { false });
/// TODO: Most platforms *hate* unloading dynamic linked libraries. on the otherhand, artists writing native scripts love them.
/// At some point, we'll probably add an API for unloading handles, and flushing out the internal cache table.
/// If the platform ignores it, and we just load the old internal handle from the os loader, oh well... guess we dont have dynamic code reloading.
} }

View File

@ -29,6 +29,7 @@ namespace Aurora::Async
{ {
gAsyncAppMem->Shutdown(); gAsyncAppMem->Shutdown();
AuResetMember(gAsyncAppMem); AuResetMember(gAsyncAppMem);
AuResetMember(gAsyncApp);
} }
} }

View File

@ -562,7 +562,7 @@ namespace Aurora::Debug
return; return;
} }
auto procNameWide = AuLocale::ConvertFromUTF8(pProcName->c_str()); auto procNameWide = AuLocale::ConvertFromUTF8(*pProcName);
HKEY hKey; HKEY hKey;
if (pRegOpenKeyExW && if (pRegOpenKeyExW &&

View File

@ -359,7 +359,7 @@ namespace Aurora::IO
return FS::UnapplyFileSectionLock(AuUnsafeRaiiToShared(this), uOffset, uLength); return FS::UnapplyFileSectionLock(AuUnsafeRaiiToShared(this), uOffset, uLength);
} }
bool AFileHandle::InitFromSharing(const AuString &handle) bool AFileHandle::InitFromSharing(const AuROString &handle)
{ {
AU_LOCK_GUARD(this); AU_LOCK_GUARD(this);

View File

@ -36,7 +36,7 @@ namespace Aurora::IO
bool InitFromHandleCopy(const IIOHandle *pHandle) override; bool InitFromHandleCopy(const IIOHandle *pHandle) override;
bool InitFromSharing(const AuString &handle) override; bool InitFromSharing(const AuROString &handle) override;
bool InitFromPath(HandleCreate create) override; bool InitFromPath(HandleCreate create) override;

View File

@ -279,27 +279,38 @@ namespace Aurora::IO::FS
//for (auto &character : str) //for (auto &character : str)
for (auto itr = str.begin(); for (auto itr = str.begin();
itr != str.end(); itr != str.end();
itr++) )
{ {
auto &character = *itr; auto &character = *itr;
auto holding = *itr; auto holding = *itr;
if ((character == '\\') || (character == '/')) if ((character == '\\') || (character == '/'))
{ {
// AuFS::Devices will break if this is not correct
// Turns out POSIX files can have valid NT separators
#if defined(AURORA_IS_POSIX_DERIVED) #if defined(AURORA_IS_POSIX_DERIVED)
if (character == '\\' && if (character == '\\' &&
prevC == '\\') prevC == '\\')
{ {
*(itr - 1) = '\\';
itr = str.erase(itr); itr = str.erase(itr);
doubleSlash--;
} }
#endif else
{
itr++;
doubleSlash++;
}
character = kPathSplitter;
#else
itr++;
character = kPathSplitter; character = kPathSplitter;
doubleSlash++; doubleSlash++;
#endif
} }
else else
{ {
itr++;
doubleSlash = 0; doubleSlash = 0;
} }

View File

@ -29,7 +29,7 @@ namespace Aurora::IO::FS
bool SpecialsInDirectory(const AuROString &string, AuList<AuString> &dirs); bool SpecialsInDirectory(const AuROString &string, AuList<AuString> &dirs);
static AuOptional<AuString> ReadLink(const AuString &path) static AuOptional<AuString> ReadLink(const AuROString &path)
{ {
AuString ret; AuString ret;
ret.resize(4096); ret.resize(4096);
@ -39,8 +39,12 @@ namespace Aurora::IO::FS
{ {
return {}; return {};
} }
else
{
ret.resize(count);
}
if (ret[0] != '/') if (ret.size() && ret[0] != '/')
{ {
AuROString dir; AuROString dir;
AuString path2 = path; AuString path2 = path;
@ -70,44 +74,52 @@ namespace Aurora::IO::FS
// to a handful of in thread IPC and intraprocess memcpy. posix and derived systems are // to a handful of in thread IPC and intraprocess memcpy. posix and derived systems are
// going to suck regardless. its not like there some magic database with a nice little // going to suck regardless. its not like there some magic database with a nice little
// pnp or wsock api that'll just dump all the related fields in a handful of API calls. // pnp or wsock api that'll just dump all the related fields in a handful of API calls.
static int CachedStat(const AuString &path, struct stat *pstat) static int CachedStat(const AuROString &path, struct stat *pstat)
{ {
AU_LOCK_GUARD(gMutex); AU_LOCK_GUARD(gMutex);
auto itr = gCachedStat.find(path); try
if (itr == gCachedStat.end())
{ {
int err = ::stat(path.c_str(), pstat); // TODO: use roxtl het lookup instead of allocating AuString
if (-1 == err) auto itr = gCachedStat.find(AuString(path));
if (itr == gCachedStat.end())
{ {
gCachedStat[path] = {}; int err = ::stat(path.c_str(), pstat);
errno = 0; if (-1 == err)
{
gCachedStat[path] = {};
errno = 0;
}
else
{
gCachedStat[path] = *pstat;
}
return err;
} }
else else
{ {
gCachedStat[path] = *pstat; auto &that = itr->second;
if (that)
{
*pstat = that.Value();
return 0;
}
else
{
return -1;
}
} }
return err;
} }
else catch (...)
{ {
auto &that = itr->second; return -1;
if (that)
{
*pstat = that.Value();
return 0;
}
else
{
return -1;
}
} }
} }
static bool BlockExists(const AuString &path) static bool BlockExists(const AuROString &path)
{ {
struct stat s; struct stat s;
int err = CachedStat(path.c_str(), &s); int err = CachedStat(path, &s);
if (-1 == err) if (-1 == err)
{ {
return false; return false;
@ -115,7 +127,7 @@ namespace Aurora::IO::FS
return S_ISBLK(s.st_mode); return S_ISBLK(s.st_mode);
} }
static AuString _DevFromPath(const AuString &path) static AuString _DevFromPath(const AuROString &path)
{ {
auto pos = path.find_last_of('/'); auto pos = path.find_last_of('/');
if (pos == AuString::npos) if (pos == AuString::npos)
@ -132,7 +144,7 @@ namespace Aurora::IO::FS
return dev; return dev;
} }
static AuString GetDevDevPathFromSysDev(const AuString &path) static AuString GetDevDevPathFromSysDev(const AuROString &path)
{ {
if (AuStartsWith(path, "/sys/block/")) if (AuStartsWith(path, "/sys/block/"))
{ {
@ -160,7 +172,7 @@ namespace Aurora::IO::FS
} }
} }
static AuPair<AuUInt32, AuUInt32> ReadIDPair(const AuString &path) static AuPair<AuUInt32, AuUInt32> ReadIDPair(const AuROString &path)
{ {
struct stat s; struct stat s;
if (path.empty()) if (path.empty())
@ -168,7 +180,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
auto err = CachedStat(path.c_str(), &s); auto err = CachedStat(path, &s);
if (err == -1) if (err == -1)
{ {
return {}; return {};
@ -182,7 +194,7 @@ namespace Aurora::IO::FS
return AuMakePair(major(s.st_rdev), minor(s.st_rdev)); return AuMakePair(major(s.st_rdev), minor(s.st_rdev));
} }
static AuPair<AuUInt32, AuUInt32> ReadIDPairSym(const AuString &path) static AuPair<AuUInt32, AuUInt32> ReadIDPairSym(const AuROString &path)
{ {
if (auto optLink = ReadLink(path)) if (auto optLink = ReadLink(path))
{ {
@ -194,7 +206,7 @@ namespace Aurora::IO::FS
} }
} }
static AuString GetSysDevFromPathLogical(const AuString &path) static AuString GetSysDevFromPathLogical(const AuROString &path)
{ {
struct stat s; struct stat s;
auto pathEx = NormalizePathRet(path); auto pathEx = NormalizePathRet(path);
@ -203,7 +215,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
auto err = CachedStat(pathEx.c_str(), &s); auto err = CachedStat(pathEx, &s);
if (err == -1) if (err == -1)
{ {
return {}; return {};
@ -212,7 +224,7 @@ namespace Aurora::IO::FS
return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_dev), minor(s.st_dev))); return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_dev), minor(s.st_dev)));
} }
static AuString GetSysDevFromDev(const AuString &path) static AuString GetSysDevFromDev(const AuROString &path)
{ {
struct stat s; struct stat s;
if (path.empty()) if (path.empty())
@ -220,7 +232,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
auto err = CachedStat(path.c_str(), &s); auto err = CachedStat(path, &s);
if (err == -1) if (err == -1)
{ {
return {}; return {};
@ -234,7 +246,7 @@ namespace Aurora::IO::FS
return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_rdev), minor(s.st_rdev))); return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_rdev), minor(s.st_rdev)));
} }
static AuString MagicPathRd(const AuString &shortLogical) static AuString MagicPathRd(const AuROString &shortLogical)
{ {
if (auto optLink = ReadLink(shortLogical)) if (auto optLink = ReadLink(shortLogical))
{ {
@ -257,7 +269,7 @@ namespace Aurora::IO::FS
} }
} }
static AuString MagicPath(const AuString &path) static AuString MagicPath(const AuROString &path)
{ {
auto shortLogical = GetSysDevFromPathLogical(path); auto shortLogical = GetSysDevFromPathLogical(path);
if (shortLogical.empty()) if (shortLogical.empty())
@ -269,7 +281,7 @@ namespace Aurora::IO::FS
} }
// isnt posshit a nice family of os? // isnt posshit a nice family of os?
static AuString GetSysDevFromPathPhysical(const AuString &path) static AuString GetSysDevFromPathPhysical(const AuROString &path)
{ {
if (AuStartsWith(path, "/dev/")) if (AuStartsWith(path, "/dev/"))
{ {
@ -311,7 +323,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
static AuString GetDevParent(const AuString &str) static AuString GetDevParent(const AuROString &str)
{ {
auto b = GetSysDevFromDev(str); auto b = GetSysDevFromDev(str);
auto slavesDir = fmt::format("{}/slaves", b); auto slavesDir = fmt::format("{}/slaves", b);
@ -418,7 +430,7 @@ namespace Aurora::IO::FS
return ret; return ret;
} }
static bool ReadIsROFromPartition(const AuString &path) static bool ReadIsROFromPartition(const AuROString &path)
{ {
if (auto optFile = ReadPosixFile(fmt::format("{}/ro", path))) if (auto optFile = ReadPosixFile(fmt::format("{}/ro", path)))
{ {
@ -520,7 +532,7 @@ namespace Aurora::IO::FS
return uuids::uuid(hash.begin(), hash.end()); return uuids::uuid(hash.begin(), hash.end());
} }
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &path) AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &path)
{ {
try try
{ {
@ -551,7 +563,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath) AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath)
{ {
try try
{ {
@ -576,7 +588,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString &root) AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root)
{ {
try try
{ {
@ -589,7 +601,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuString &path) AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuROString &path)
{ {
struct statvfs data; struct statvfs data;
@ -608,7 +620,7 @@ namespace Aurora::IO::FS
return data.f_bsize; return data.f_bsize;
} }
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &path) AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &path)
{ {
try try
{ {
@ -638,7 +650,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath) AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath)
{ {
try try
{ {
@ -677,7 +689,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuString &physicalDevicePath) AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuROString &physicalDevicePath)
{ {
try try
{ {
@ -716,7 +728,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &path) AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &path)
{ {
try try
{ {
@ -747,7 +759,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &path) AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &path)
{ {
struct statvfs data; struct statvfs data;
@ -1583,7 +1595,7 @@ namespace Aurora::IO::FS
return devices; return devices;
} }
AUKN_SYM AuString GetRootFromPath(const AuString &path) AUKN_SYM AuString GetRootFromPath(const AuROString &path)
{ {
AuString ret; AuString ret;

View File

@ -36,7 +36,7 @@ namespace Aurora::IO::FS
static AuString PathToMount(const AuString &root); static AuString PathToMount(const AuString &root);
AUKN_SYM AuString GetRootFromPath(const AuString &path) AUKN_SYM AuString GetRootFromPath(const AuROString &path)
{ {
auto widePath = Locale::ConvertFromUTF8(NormalizePathRet(path)); auto widePath = Locale::ConvertFromUTF8(NormalizePathRet(path));
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
@ -61,12 +61,12 @@ namespace Aurora::IO::FS
#endif #endif
} }
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &path) AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &path)
{ {
return GetDeviceFromRoot(GetRootFromPath(path)); return GetDeviceFromRoot(GetRootFromPath(path));
} }
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath) AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath)
{ {
auto root = GetRootFromPath(fileOrDirPath); auto root = GetRootFromPath(fileOrDirPath);
@ -91,7 +91,7 @@ namespace Aurora::IO::FS
return AuString(utf8Root); return AuString(utf8Root);
} }
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString& root) AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root)
{ {
VOLUME_DISK_EXTENTS extents; VOLUME_DISK_EXTENTS extents;
DWORD dwBytesWritten {}; DWORD dwBytesWritten {};
@ -104,6 +104,11 @@ namespace Aurora::IO::FS
} }
auto widePath = Locale::ConvertFromUTF8(utf8Root); auto widePath = Locale::ConvertFromUTF8(utf8Root);
if (widePath.empty() && utf8Root.size())
{
SysPushErrorMemory();
return {};
}
if (::GetDriveTypeW(Locale::ConvertFromUTF8(utf8Root2).data()) != DRIVE_FIXED) if (::GetDriveTypeW(Locale::ConvertFromUTF8(utf8Root2).data()) != DRIVE_FIXED)
{ {
@ -161,7 +166,7 @@ namespace Aurora::IO::FS
} }
} }
static AuUInt32 GetSectorSizeFromPathFromDevice(const AuString &path, bool bIsLogical) static AuUInt32 GetSectorSizeFromPathFromDevice(const AuROString &path, bool bIsLogical)
{ {
DISK_GEOMETRY_EX geo {}; DISK_GEOMETRY_EX geo {};
DWORD cbBytesReturned; DWORD cbBytesReturned;
@ -256,7 +261,7 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &path) AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &path)
{ {
if (kBUsePerformantIoRecommendation) if (kBUsePerformantIoRecommendation)
{ {
@ -289,12 +294,12 @@ namespace Aurora::IO::FS
} }
} }
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &path) AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &path)
{ {
return GetSectorSizeFromPathFromDevice(path, false); return GetSectorSizeFromPathFromDevice(path, false);
} }
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &path) AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &path)
{ {
auto rootPath = GetLogicalMountFromPath(path); auto rootPath = GetLogicalMountFromPath(path);
if (!rootPath) if (!rootPath)
@ -305,7 +310,7 @@ namespace Aurora::IO::FS
return GetLogicalUsedFromLogicalDevice(rootPath.GetResult()); return GetLogicalUsedFromLogicalDevice(rootPath.GetResult());
} }
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath) AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath)
{ {
auto widePath = Locale::ConvertFromUTF8(logicalMountPath); auto widePath = Locale::ConvertFromUTF8(logicalMountPath);
@ -1035,12 +1040,12 @@ namespace Aurora::IO::FS
} }
#endif #endif
AUKN_SYM AuString TrySimplifyDevicePath(const AuString &deviceOrLogicalMountPath) AUKN_SYM AuString TrySimplifyDevicePath(const AuROString &deviceOrLogicalMountPath)
{ {
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
return ResolveObjSymLink(deviceOrLogicalMountPath); return ResolveObjSymLink(AuString(deviceOrLogicalMountPath));
#else #else
return deviceOrLogicalMountPath; return AuString(deviceOrLogicalMountPath);
#endif #endif
} }

View File

@ -22,7 +22,7 @@ namespace Aurora::IO::FS
}); });
} }
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuString &physicalDevicePath) AUKN_SYM AuResult<AuString> GetDeviceModel(const AuROString &physicalDevicePath)
{ {
InitPlatformFSCacheAtLoad(); InitPlatformFSCacheAtLoad();
@ -39,7 +39,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuString &path) AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuROString &path)
{ {
AuPair<AuUInt, const FSDevice *> lastDev = AuPair<AuUInt, const FSDevice *> lastDev =
AuMakePair<AuUInt, const FSDevice *>(0, nullptr); AuMakePair<AuUInt, const FSDevice *>(0, nullptr);
@ -87,7 +87,7 @@ namespace Aurora::IO::FS
return gCachedDevices; return gCachedDevices;
} }
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuString &physicalDevicePath) AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuROString &physicalDevicePath)
{ {
InitPlatformFSCacheAtLoad(); InitPlatformFSCacheAtLoad();

View File

@ -32,6 +32,12 @@ namespace Aurora::IO::FS
static AuString gAdminWritableAppDirectory; static AuString gAdminWritableAppDirectory;
static AuString gProgramsFolder; static AuString gProgramsFolder;
static AuString gApplicationData; static AuString gApplicationData;
static AuString gUserShellDocuments;
static AuString gUserShellDownloads;
static AuString gUserShellPhotos;
static AuString gUserShellVideos;
static AuString gUserShellMusic;
static AuString gUserShellDesktop;
static AuOptional<AuString> gSystemLibPath; static AuOptional<AuString> gSystemLibPath;
static AuOptional<AuString> gSystemLibPath2; static AuOptional<AuString> gSystemLibPath2;
static AuOptional<AuString> gUserLibPath; static AuOptional<AuString> gUserLibPath;
@ -48,21 +54,21 @@ namespace Aurora::IO::FS
// we don't have any good examples of home family computer-esc posix machines // we don't have any good examples of home family computer-esc posix machines
static const char * kUnixAppData {"/var"}; static const char * kUnixAppData {"/var"};
AUKN_SYM AuOptional<const AuString &> GetSystemDomain() AUKN_SYM AuOptional<AuROString> GetSystemDomain()
{ {
return gApplicationData.size() ? return gApplicationData.size() ?
gApplicationData : gApplicationData :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM AuOptional<const AuString &> GetProfileDomain() AUKN_SYM AuOptional<AuROString> GetProfileDomain()
{ {
return gHomeDirectory.size() ? return gHomeDirectory.size() ?
gHomeDirectory : gHomeDirectory :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM bool GetSystemResourcePath(const AuString &fileName, AuString &path) AUKN_SYM bool GetSystemResourcePath(const AuROString &fileName, AuString &path)
{ {
path.clear(); path.clear();
@ -72,44 +78,52 @@ namespace Aurora::IO::FS
return false; return false;
} }
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG) try
{ {
AuString tempPath; #if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
if (Process::GetWorkingDirectory(tempPath))
{ {
tempPath += "/" + fileName; AuString tempPath;
if (FileExists(tempPath)) if (Process::GetWorkingDirectory(tempPath))
{ {
path = tempPath; tempPath += "/" + fileName;
return true; if (FileExists(tempPath))
{
path = tempPath;
return true;
}
} }
} }
} #endif
#endif
{
if (auto pProcPath = Process::GetProcessDirectory())
{ {
auto tempPath = *pProcPath + "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
{
if (auto optPackagePath = GetPackagePath())
{
auto tempPath = *optPackagePath + "/" + fileName;
if (auto pProcPath = Process::GetProcessDirectory()) if (auto pProcPath = Process::GetProcessDirectory())
{ {
auto tempPath2 = *pProcPath + "/" + fileName; auto tempPath = AuString(*pProcPath) + "/" + AuString(fileName);
if (tempPath2 == tempPath) if (FileExists(tempPath))
{ {
// nop path = tempPath;
return true;
}
}
}
{
if (auto optPackagePath = GetPackagePath())
{
auto tempPath = AuString(*optPackagePath) + "/" + AuString(fileName);
if (auto pProcPath = Process::GetProcessDirectory())
{
auto tempPath2 = AuString(*pProcPath) + "/" + AuString(fileName);
if (tempPath2 == tempPath)
{
// nop
}
else if (FileExists(tempPath))
{
path = tempPath;
return true;
}
} }
else if (FileExists(tempPath)) else if (FileExists(tempPath))
{ {
@ -117,45 +131,44 @@ namespace Aurora::IO::FS
return true; return true;
} }
} }
else if (FileExists(tempPath))
{
path = tempPath;
return true;
}
} }
}
#if defined(AU_CFG_ID_SHIP) #if defined(AU_CFG_ID_SHIP)
{
AuString tempPath;
if (Process::GetWorkingDirectory(tempPath))
{ {
tempPath += "/" + fileName; AuString tempPath;
if (FileExists(tempPath)) if (Process::GetWorkingDirectory(tempPath))
{ {
path = tempPath; tempPath += "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
#endif
{
auto systemPath = gHomeDirectory + AuString(fileName);
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
}
{
auto systemPath = gApplicationData + AuString(fileName);
if (FileExists(systemPath))
{
path = systemPath;
return true; return true;
} }
} }
} }
#endif catch (...)
{ {
auto systemPath = gHomeDirectory + fileName; SysPushErrorCatch();
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
}
{
auto systemPath = gApplicationData + fileName;
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
} }
return false; return false;
@ -175,9 +188,30 @@ namespace Aurora::IO::FS
return CSIDL_COMMON_APPDATA; return CSIDL_COMMON_APPDATA;
} }
if (rfid == FOLDERID_Documents) if (rfid == FOLDERID_Documents ||
rfid == FOLDERID_Downloads)
{ {
return CSIDL_COMMON_DOCUMENTS; return CSIDL_MYDOCUMENTS;
}
if (rfid == FOLDERID_Music)
{
return CSIDL_MYMUSIC;
}
if (rfid == FOLDERID_Pictures)
{
return CSIDL_MYPICTURES;
}
if (rfid == FOLDERID_Desktop)
{
return CSIDL_DESKTOP;
}
if (rfid == FOLDERID_Videos)
{
return CSIDL_MYVIDEO;
} }
if (rfid == FOLDERID_System || if (rfid == FOLDERID_System ||
@ -194,7 +228,6 @@ namespace Aurora::IO::FS
return {}; return {};
} }
static AuString GetSpecialDirOldOS(REFKNOWNFOLDERID rfid) static AuString GetSpecialDirOldOS(REFKNOWNFOLDERID rfid)
{ {
if (!pSHGetFolderPathA) if (!pSHGetFolderPathA)
@ -214,7 +247,7 @@ namespace Aurora::IO::FS
return ""; return "";
} }
static AuString GetSpecialDir(REFKNOWNFOLDERID rfid) static AuString GetSpecialDir(REFKNOWNFOLDERID rfid, bool bNoThrow = false)
{ {
PWSTR directory; PWSTR directory;
@ -231,10 +264,11 @@ namespace Aurora::IO::FS
return str; return str;
} }
if (rfid == FOLDERID_UserProgramFiles) if (rfid == FOLDERID_UserProgramFiles || bNoThrow)
{ {
return ""; return "";
} }
SysPanic("Couldn't get known special directory path of [MS:{}-{}-{}-{}{}{}{}{}{}{}{}] with a NULL access token", SysPanic("Couldn't get known special directory path of [MS:{}-{}-{}-{}{}{}{}{}{}{}{}] with a NULL access token",
rfid.Data1, rfid.Data2, rfid.Data3, rfid.Data4[0], rfid.Data4[1], rfid.Data4[2], rfid.Data4[3], rfid.Data4[4], rfid.Data4[5], rfid.Data4[6], rfid.Data4[7]); rfid.Data1, rfid.Data2, rfid.Data3, rfid.Data4[0], rfid.Data4[1], rfid.Data4[2], rfid.Data4[3], rfid.Data4[4], rfid.Data4[5], rfid.Data4[6], rfid.Data4[7]);
} }
@ -250,17 +284,17 @@ namespace Aurora::IO::FS
static void SetNamespaceDirectories() static void SetNamespaceDirectories()
{ {
gHomeDirectory = GetSpecialDir(FOLDERID_RoamingAppData); gHomeDirectory = GetSpecialDir(FOLDERID_RoamingAppData);
gApplicationData = GetSpecialDir(FOLDERID_ProgramData); gApplicationData = GetSpecialDir(FOLDERID_ProgramData);
if constexpr (AuBuild::IsPlatformX32()) if constexpr (AuBuild::IsPlatformX32())
{ {
gSystemLibPath = GetSpecialDir(FOLDERID_SystemX86); gSystemLibPath = GetSpecialDir(FOLDERID_SystemX86);
} }
else else
{ {
gSystemLibPath = GetSpecialDir(FOLDERID_System); gSystemLibPath = GetSpecialDir(FOLDERID_System);
} }
gUserHomeDirectory = GetSpecialDir(FOLDERID_Profile); gUserHomeDirectory = GetSpecialDir(FOLDERID_Profile);
gAdminWritableAppDirectory = gApplicationData; gAdminWritableAppDirectory = gApplicationData;
gUserWritableAppData = gHomeDirectory; gUserWritableAppData = gHomeDirectory;
gProgramsFolder = AuSwInfo::IsWindows7OrGreater() ? GetSpecialDir(FOLDERID_UserProgramFiles) : ""; gProgramsFolder = AuSwInfo::IsWindows7OrGreater() ? GetSpecialDir(FOLDERID_UserProgramFiles) : "";
@ -278,6 +312,13 @@ namespace Aurora::IO::FS
} }
} }
gUserShellDocuments = GetSpecialDir(FOLDERID_Documents, true);
gUserShellDownloads = GetSpecialDir(FOLDERID_Downloads, true);
gUserShellPhotos = GetSpecialDir(FOLDERID_Pictures, true);
gUserShellVideos = GetSpecialDir(FOLDERID_Videos, true);
gUserShellMusic = GetSpecialDir(FOLDERID_Music, true);
gUserShellDesktop = GetSpecialDir(FOLDERID_Desktop, true);
if (pGetTempPathW) if (pGetTempPathW)
{ {
wchar_t tempPath[2048]; wchar_t tempPath[2048];
@ -341,6 +382,20 @@ namespace Aurora::IO::FS
} }
} }
static void SetPosixOptionalUserShellDir(AuString &str, const AuROString &suffix)
{
AuString strA = gUserHomeDirectory + "/" + AuString({ AuToUpper(suffix[0]) }) + AuString(suffix.SubStr(1));
AuString strB = gUserHomeDirectory + "/" + AuString({ AuToLower(suffix[0]) }) + AuString(suffix.SubStr(1));
if (AuFS::DirExists(strA))
{
str = strA;
}
else if (AuFS::DirExists(strB))
{
str = strB;
}
}
static void SetNamespaceDirectories() static void SetNamespaceDirectories()
{ {
const char *homedir; const char *homedir;
@ -371,6 +426,17 @@ namespace Aurora::IO::FS
gAdminWritableAppDirectory = kUnixAppData; gAdminWritableAppDirectory = kUnixAppData;
gUserWritableAppData = gApplicationData; gUserWritableAppData = gApplicationData;
SetPosixOptionalUserShellDir(gUserShellDocuments, "Documents");
SetPosixOptionalUserShellDir(gUserShellDownloads, "Downloads");
SetPosixOptionalUserShellDir(gUserShellPhotos, "Pictures");
SetPosixOptionalUserShellDir(gUserShellVideos, "Videos");
SetPosixOptionalUserShellDir(gUserShellMusic, "Music");
SetPosixOptionalUserShellDir(gUserShellDesktop, "Desktop");
// Android: gApplicationData = ANativeActivity::internalDataPath
// Android: gHomeDirectory = ANativeActivity::externalDataPath (?)
// Android: SetPosixOptionalUserShellDir maybe overload the home path with emulated 0 DCIM if we have external file permissions? externalDataPath?
// iOS Package Dir: CFBundleCopyResourcesDirectoryURL
// iOS/MacOS : NSTemporaryDirectory // iOS/MacOS : NSTemporaryDirectory
#if defined(AURORA_PLATFORM_ANDROID) #if defined(AURORA_PLATFORM_ANDROID)
gTempDir = "/data/local/tmp/"; gTempDir = "/data/local/tmp/";
@ -504,21 +570,21 @@ namespace Aurora::IO::FS
gApplicationData.clear(); gApplicationData.clear();
} }
AUKN_SYM AuOptional<const AuString &> GetAppData() AUKN_SYM AuOptional<AuROString> GetAppData()
{ {
return gUserWritableAppData.size() ? return gUserWritableAppData.size() ?
gUserWritableAppData : gUserWritableAppData :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM AuOptional<const AuString &> GetUserHome() AUKN_SYM AuOptional<AuROString> GetUserHome()
{ {
return gUserHomeDirectory.size() ? return gUserHomeDirectory.size() ?
gUserHomeDirectory : gUserHomeDirectory :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM AuOptional<const AuString &> GetPackagePath() AUKN_SYM AuOptional<AuROString> GetPackagePath()
{ {
// TODO: iOS/mac OS -> CFBundleCopyResourcesDirectoryURL // TODO: iOS/mac OS -> CFBundleCopyResourcesDirectoryURL
if (auto optProcessDirectory = Process::GetProcessDirectory()) if (auto optProcessDirectory = Process::GetProcessDirectory())
@ -526,86 +592,156 @@ namespace Aurora::IO::FS
return optProcessDirectory; return optProcessDirectory;
} }
return AuOptional<const AuString &>{}; return AuOptional<AuROString>{};
} }
AUKN_SYM AuOptional<const AuString &> GetWritableAppdata() AUKN_SYM AuOptional<AuROString> GetWritableAppdata()
{ {
return gGlobalWritableAppDirectory.size() ? return gGlobalWritableAppDirectory.size() ?
gGlobalWritableAppDirectory : gGlobalWritableAppDirectory :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM AuOptional<const AuString &> GetRootAppdata() AUKN_SYM AuOptional<AuROString> GetRootAppdata()
{ {
return gAdminWritableAppDirectory.size() ? return gAdminWritableAppDirectory.size() ?
gAdminWritableAppDirectory : gAdminWritableAppDirectory :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
} }
AUKN_SYM AuOptional<const AuString &> GetUserProgramsFolder() AUKN_SYM AuOptional<AuROString> GetUserProgramsFolder()
{ {
return gProgramsFolder.size() ? return gProgramsFolder.size() ?
gProgramsFolder : gProgramsFolder :
AuOptional<const AuString &> {}; AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDocuments()
{
return gUserShellDocuments.size() ?
gUserShellDocuments :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDesktop()
{
return gUserShellDesktop.size() ?
gUserShellDesktop :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserPhotos()
{
return gUserShellPhotos.size() ?
gUserShellPhotos :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserVideos()
{
return gUserShellVideos.size() ?
gUserShellVideos :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserMusic()
{
return gUserShellMusic.size() ?
gUserShellMusic :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDownloads()
{
return gUserShellDownloads.size() ?
gUserShellDownloads :
GetUserDocuments();
} }
AUKN_SYM AuOptional<AuString> NewTempFile() AUKN_SYM AuOptional<AuString> NewTempFile()
{ {
AuString path; try
path = gTempDir;
if (path.empty())
{ {
SysPushErrorUninitialized(); AuString path;
path = gTempDir;
if (path.empty())
{
SysPushErrorUninitialized();
return {};
}
path += fmt::format("TempFile_{}", AuRNG::ReadString(64, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!AuFS::WriteNewFile(path, {}))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
if (normalizedPath.empty() && path.size())
{
SysPushErrorMemory();
return {};
}
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath;
}
catch (...)
{
// I hate C++ strings
SysPushErrorCatch();
return {}; return {};
} }
path += fmt::format("TempFile_{}", AuRNG::ReadString(64, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!AuFS::WriteNewFile(path, {}))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath;
} }
AUKN_SYM AuOptional<AuString> NewTempDirectory() AUKN_SYM AuOptional<AuString> NewTempDirectory()
{ {
AuString path; try
path = gTempDir;
if (path.empty())
{ {
SysPushErrorUninitialized(); AuString path;
path = gTempDir;
if (path.empty())
{
SysPushErrorUninitialized();
return {};
}
path += fmt::format("TempDirectory_{}", AuRNG::ReadString(32, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!_MkDir(path))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
if (normalizedPath.empty() && path.size())
{
SysPushErrorMemory();
return {};
}
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath + AuString(1, kPathSplitter);
}
catch (...)
{
// I hate C++ strings
SysPushErrorCatch();
return {}; return {};
} }
path += fmt::format("TempDirectory_{}", AuRNG::ReadString(32, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!_MkDir(path))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath + AuString(1, kPathSplitter);
} }
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)

View File

@ -26,7 +26,7 @@ namespace Aurora::IO::UNIX
return handle.ToString(); return handle.ToString();
} }
AUKN_SYM void ShareFileDescriptorStop(const AuString &handle) AUKN_SYM void ShareFileDescriptorStop(const AuROString &handle)
{ {
IPC::IPCHandle handle2; IPC::IPCHandle handle2;
if (!handle2.FromString(handle)) if (!handle2.FromString(handle))
@ -41,7 +41,7 @@ namespace Aurora::IO::UNIX
} }
} }
AUKN_SYM int ShareFileDescriptorAccept(const AuString &handle) AUKN_SYM int ShareFileDescriptorAccept(const AuROString &handle)
{ {
IPC::IPCHandle handle2; IPC::IPCHandle handle2;
if (!handle2.FromString(handle)) if (!handle2.FromString(handle))

View File

@ -259,7 +259,7 @@ namespace Aurora::Process
return true; return true;
} }
AUKN_SYM AuOptional<const AuString &> GetProcessName() AUKN_SYM AuOptional<AuROString> GetProcessName()
{ {
const AuString *pModule, *pPartial, *pFull; const AuString *pModule, *pPartial, *pFull;
@ -280,7 +280,7 @@ namespace Aurora::Process
return {}; return {};
} }
AUKN_SYM AuOptional<const AuString &> GetProcessDirectory() AUKN_SYM AuOptional<AuROString> GetProcessDirectory()
{ {
const AuString *pModule, *pPartial, *pFull; const AuString *pModule, *pPartial, *pFull;
@ -316,7 +316,7 @@ namespace Aurora::Process
return {}; return {};
} }
AUKN_SYM AuOptional<const AuString &> GetProcessFullPath() AUKN_SYM AuOptional<AuROString> GetProcessFullPath()
{ {
const AuString *pModule, *pPartial, *pFull; const AuString *pModule, *pPartial, *pFull;

View File

@ -39,6 +39,10 @@
namespace Aurora::Process namespace Aurora::Process
{ {
// Because we're only protecting gModuleHandles in practice, and we cannot fuck up any iterator handles, we can use renterable mutexes.
// We only use AuTryFind/AuTryInsert for the most part.
// The only iterators created for gModuleHandles call out to apis that should not allow for further recursion.
// So we should be fine.
static AuCriticalSection gSpinLock; static AuCriticalSection gSpinLock;
static AuList<AuString> gClassPath; static AuList<AuString> gClassPath;
static AuHashMap<AuString, void *> gModuleHandles; static AuHashMap<AuString, void *> gModuleHandles;
@ -102,18 +106,18 @@ namespace Aurora::Process
static AuString ConstructAuDllSuffixUncached() static AuString ConstructAuDllSuffixUncached()
{ {
auto platform = GetPlatformString(Build::kCurrentPlatform); auto platform = GetPlatformString(Build::kCurrentPlatform);
auto architecture = GetArchString(Build::kCurrentArchitecture); auto architecture = GetArchString(Build::kCurrentArchitecture);
auto ext = GetPlatformExt(Build::kCurrentPlatform); auto ext = GetPlatformExt(Build::kCurrentPlatform);
AuString ret; AuString ret;
#if defined(DEBUG) #if defined(DEBUG)
ret += ".Debug"; ret = ".Debug";
#elif defined(STAGING) #elif defined(STAGING)
ret += ".Stage"; ret = ".Stage";
#elif defined(SHIP) #elif defined(SHIP)
ret += ".Ship"; ret = ".Ship";
#endif #endif
if (platform) if (platform)
@ -134,28 +138,47 @@ namespace Aurora::Process
return ret; return ret;
} }
AUKN_SYM const AuString& ConstructAuDllSuffix() AUKN_SYM AuROString GetViewOfAuroraDLLSuffix()
{ {
static AuString dllSuffixString {}; static AuString dllSuffixString {};
static AuInitOnce gInitOnce; static AuInitOnce gInitOnce;
gInitOnce.Call([] gInitOnce.TryCall([]
{ {
dllSuffixString = ConstructAuDllSuffixUncached(); try
{
dllSuffixString = ConstructAuDllSuffixUncached();
return true;
}
catch (...)
{
// I hate C++ strings so much
return false;
}
}); });
return dllSuffixString; return dllSuffixString;
} }
AUKN_SYM AuROString GetViewOfDynamicLibraryExtensionSuffix()
{
return GetPlatformExt(Build::kCurrentPlatform);
}
AUKN_SYM AuROString GetViewOfArchitectureSuffix()
{
return GetArchString(Build::kCurrentArchitecture);
}
static AuString GetModuleNameFromFileName(const AuString &filename) static AuString GetModuleNameFromFileName(const AuString &filename)
{ {
static const auto &kStringSuffixA = ConstructAuDllSuffix(); static const auto kStringSuffixA = GetViewOfAuroraDLLSuffix();
static const auto kStringSuffixB = GetPlatformExt(Build::kCurrentPlatform); static const auto kStringSuffixB = GetPlatformExt(Build::kCurrentPlatform);
if (filename.ends_with(kStringSuffixA)) if (AuEndsWith(filename, kStringSuffixA))
{ {
return filename.substr(0, filename.size() - kStringSuffixA.size()); return filename.substr(0, filename.size() - kStringSuffixA.size());
} }
if (filename.ends_with(kStringSuffixB)) if (AuEndsWith(filename, kStringSuffixB))
{ {
return filename.substr(0, filename.size() - strlen(kStringSuffixB)); return filename.substr(0, filename.size() - strlen(kStringSuffixB));
} }
@ -292,12 +315,13 @@ namespace Aurora::Process
} }
#endif #endif
static void *LoadModule(const AuString &name, const AuString &path) static void *LoadModule(const AuROString &name, const AuROString &path)
{ {
auto itr = gModuleHandles.find(path); void *pFound {};
if (itr != gModuleHandles.end())
if (AuTryFind(gModuleHandles, path, pFound))
{ {
return itr->second; return pFound;
} }
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
@ -322,8 +346,8 @@ namespace Aurora::Process
#endif #endif
auto pRet = (void *)handle; auto pRet = (void *)handle;
gModuleHandles.insert(AuMakePair(name, pRet)); gModuleHandles.insert(AuMakePair(AuMove(AuString(name)), AuConstReference(pRet)));
gModuleHandles.insert(AuMakePair(path, pRet)); gModuleHandles.insert(AuMakePair(AuMove(AuString(path)), AuConstReference(pRet)));
return pRet; return pRet;
} }
@ -338,9 +362,20 @@ namespace Aurora::Process
fail = false; fail = false;
auto pathNrml = AuIOFS::NormalizePathRet(path); auto pathNrml = AuIOFS::NormalizePathRet(path);
if (pathNrml.empty() && path.size())
{
SysPushErrorMemory();
return nullptr;
}
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
auto widePath = Locale::ConvertFromUTF8(pathNrml); auto widePath = Locale::ConvertFromUTF8(pathNrml);
if (widePath.empty() && pathNrml.size())
{
SysPushErrorMemory();
return nullptr;
}
auto mitigateTimeOfUse = Win32Open(widePath.c_str(), GENERIC_READ, FILE_SHARE_READ, false, OPEN_EXISTING, 0, 0); auto mitigateTimeOfUse = Win32Open(widePath.c_str(), GENERIC_READ, FILE_SHARE_READ, false, OPEN_EXISTING, 0, 0);
if (mitigateTimeOfUse == INVALID_HANDLE_VALUE) if (mitigateTimeOfUse == INVALID_HANDLE_VALUE)
@ -351,6 +386,11 @@ namespace Aurora::Process
} }
auto absPath = AuIOFS::NormalizePathRet(abs); auto absPath = AuIOFS::NormalizePathRet(abs);
if (absPath.empty() && abs.size())
{
SysPushErrorMemory();
return nullptr;
}
#endif #endif
if (request.verify || ((kIsMainSigned || request.forceMitigations) && request.enableMitigations)) if (request.verify || ((kIsMainSigned || request.forceMitigations) && request.enableMitigations))
@ -404,10 +444,10 @@ namespace Aurora::Process
return returnValue; return returnValue;
} }
static void *TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail) static void *TryLoadModuleNTC(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
{ {
AuString a = path + AuString({ AuFS::kPathSplitter }) + auDll; AuString a = AuString(path) + AuString({ AuFS::kPathSplitter }) + AuString(auDll);
AuString b = path + AuString({ AuFS::kPathSplitter }) + genericDll; AuString b = AuString(path) + AuString({ AuFS::kPathSplitter }) + AuString(genericDll);
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
@ -430,8 +470,8 @@ namespace Aurora::Process
} }
#endif #endif
AuString aAbs = path + AuString({ AuFS::kPathSplitter }) + auDll + "."; AuString aAbs = AuString(path) + /*SOO save us pls*/ AuString({ AuFS::kPathSplitter }) + auDll + ".";
AuString bAbs = path + AuString({ AuFS::kPathSplitter }) + genericDll + "."; AuString bAbs = AuString(path) + /*SOO save us pls*/ AuString({ AuFS::kPathSplitter }) + genericDll + ".";
#endif #endif
if (AuIOFS::FileExists(a)) if (AuIOFS::FileExists(a))
@ -459,17 +499,29 @@ namespace Aurora::Process
return {}; return {};
} }
static void *TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
{
// TODO: need safe string container
try
{
return TryLoadModuleNTC(path, auDll, genericDll, request, fail);
}
catch (...)
{
return {};
}
}
static void *TryLoadModule(EModulePath path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request) static void *TryLoadModule(EModulePath path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request)
{ {
AuString pathA, pathB; AuString pathA, pathB;
AuList<AuString> arrayPaths; AuList<AuString> *pArrayPaths {};
switch (path) switch (path)
{ {
case EModulePath::eClassPath: case EModulePath::eClassPath:
{ {
AU_LOCK_GLOBAL_GUARD(gSpinLock); pArrayPaths = &gClassPath;
arrayPaths = gClassPath;
break; break;
} }
case EModulePath::eModulePathCWD: case EModulePath::eModulePathCWD:
@ -553,16 +605,21 @@ namespace Aurora::Process
} }
} }
for (const auto &dir : arrayPaths) if (pArrayPaths)
{ {
if (auto pRet = TryLoadModule(dir, auDll, genericDll, request, fail)) AU_LOCK_GLOBAL_GUARD(gSpinLock);
{
return pRet;
}
if (fail) for (const auto &dir : *pArrayPaths)
{ {
return {}; if (auto pRet = TryLoadModule(dir, auDll, genericDll, request, fail))
{
return pRet;
}
if (fail)
{
return {};
}
} }
} }
@ -593,33 +650,46 @@ namespace Aurora::Process
AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request) AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request)
{ {
AU_LOCK_GLOBAL_GUARD(gSpinLock); AU_LOCK_GLOBAL_GUARD(gSpinLock);
auto h = gModuleHandles.find(request.mod); void *pFound {};
if (h != gModuleHandles.end())
if (AuTryFind(gModuleHandles, request.mod, pFound))
{ {
return h->second; return pFound;
} }
auto au = request.mod + ConstructAuDllSuffix(); // TODO: need safe string container
auto base = request.mod; AuString base, au;
auto ext = GetPlatformExt(Build::kCurrentPlatform); const char *ext {};
try
if (ext && !Build::kIsNtDerived)
{ {
base += ext; base = AuString(request.mod);
au = base + AuString(GetViewOfAuroraDLLSuffix());
ext = GetPlatformExt(Build::kCurrentPlatform);
if (ext && !Build::kIsNtDerived)
{
base += ext;
}
if (request.version.size())
{
au += "." + request.version;
base += "." + request.version;
}
if (ext && Build::kIsNtDerived)
{
base += ext;
}
}
catch (...)
{
// stupid unsafe strings
SysPushErrorMemory();
return {};
} }
if (request.version.size())
{
au += "." + request.version;
base += "." + request.version;
}
if (ext && Build::kIsNtDerived)
{
base += ext;
}
auto searchPath = request.searchPath ? request.searchPath : &kUserOverloadableSearchPath; auto searchPath = request.searchPath ? request.searchPath : &kUserOverloadableSearchPath;
for (EModulePath path : *searchPath) for (EModulePath path : *searchPath)
{ {
@ -632,7 +702,7 @@ namespace Aurora::Process
return {}; return {};
} }
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol) AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuRONString &symbol)
{ {
AuMach ret {}; AuMach ret {};
@ -706,21 +776,22 @@ namespace Aurora::Process
return ret; return ret;
} }
AUKN_SYM void *GetProcHandle(const AuString &name) AUKN_SYM void *GetProcHandle(const AuROString &name)
{ {
AU_LOCK_GLOBAL_GUARD(gSpinLock); AU_LOCK_GLOBAL_GUARD(gSpinLock);
auto h = gModuleHandles.find(name); void *pFound {};
if (h == gModuleHandles.end())
if (!AuTryFind(gModuleHandles, name, pFound))
{ {
SysPushErrorGen("Module {} is not loaded", name); SysPushErrorGen("Module {} is not loaded", name);
return {}; return {};
} }
return h->second; return pFound;
} }
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol) AUKN_SYM AuMach GetProcAddress(const AuROString &mod, const AuRONString &symbol)
{ {
if (mod.empty()) if (mod.empty())
{ {
@ -771,10 +842,14 @@ namespace Aurora::Process
AuList<void *> cookieList; AuList<void *> cookieList;
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
for (const auto dir : dirs) for (const auto &dir : dirs)
{ {
void *pCookie {}; void *pCookie {};
// Yay I love required nevis era plugin load fighting
// MSDN still states this function should be dynamically loaded for some KB that probably wont work on Vista or 7.
// Also, GNU LibC - the architectures ld linker, cannot keep track of preload directory lists.
// So for older Win32 targets, and POSIX, we have to....
if (pRemoveDllDirectory) if (pRemoveDllDirectory)
{ {
if (pAddDllDirectory) if (pAddDllDirectory)
@ -787,7 +862,10 @@ namespace Aurora::Process
} }
#endif #endif
for (const auto dir : dirs) // ...just try to probe every file manually.
// ...and later on, try to load each file again manually by full real path
// This makes sure we have future basic dependencies loaded of LoadModuleXXX calls, at the very least, we hope.
for (const auto &dir : dirs)
{ {
AuList<AuString> files; AuList<AuString> files;
AuList<AuString> sharedObjects; AuList<AuString> sharedObjects;
@ -798,13 +876,13 @@ namespace Aurora::Process
continue; continue;
} }
auto endingPattern = ConstructAuDllSuffix(); auto endingPattern = GetViewOfAuroraDLLSuffix();
auto endingAlt = GetPlatformExt(Build::kCurrentPlatform); auto endingAlt = GetPlatformExt(Build::kCurrentPlatform);
for (const auto &file : files) for (const auto &file : files)
{ {
if (!(file.ends_with(endingPattern.c_str()) || if (!(AuEndsWith(file, endingPattern) ||
file.ends_with(endingAlt))) AuEndsWith(file, endingAlt)))
{ {
continue; continue;
} }
@ -840,7 +918,10 @@ namespace Aurora::Process
} }
auto modName = GetModuleNameFromFileName(sharedDLL); auto modName = GetModuleNameFromFileName(sharedDLL);
AuLogDbg("[attempt] Loading shared object: {} (path: {})", modName, sharedDLL); //AuLogDbg("[attempt] Loading shared object: {} (path: {})", modName, sharedDLL);
//This got really spammy some time
//Best just keep dynamic loads as a singular verbose, "hey dipshit, this file actually managed to get into our address space"
//...
bool fail {}; bool fail {};
ModuleLoadRequest request { AuList<AuString>{ dir }, modName }; ModuleLoadRequest request { AuList<AuString>{ dir }, modName };
@ -855,7 +936,8 @@ namespace Aurora::Process
{ {
if (!fail) if (!fail)
{ {
AuLogDbg("[attempt] Loaded shared object: {} (path: {})", modName, sharedDLL); //..here
AuLogDbg("[attempt] Loaded shared object: {} (path: {})", modName, sharedDLL); //get hacked retard
uSuccess++; uSuccess++;
itr = sharedObjects.erase(itr); itr = sharedObjects.erase(itr);
} }
@ -888,7 +970,7 @@ namespace Aurora::Process
#endif #endif
} }
static void PreloadDLLs(const AuString &dir) static void PreloadDLLs(const AuROString &dir)
{ {
AU_DEBUG_MEMCRUNCH; AU_DEBUG_MEMCRUNCH;
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath) if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
@ -897,17 +979,17 @@ namespace Aurora::Process
} }
else else
{ {
PreloadDLLsDoOnce({ dir }); PreloadDLLsDoOnce({ AuString(dir) });
} }
} }
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll) AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, AuOptional<bool> optBoolPreloadAll)
{ {
AU_DEBUG_MEMCRUNCH; AU_DEBUG_MEMCRUNCH;
AU_LOCK_GLOBAL_GUARD(gSpinLock); AU_LOCK_GLOBAL_GUARD(gSpinLock);
AuExchange(gClassPath, list); AuExchange(gClassPath, list);
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) || if (((optBoolPreloadAll.ValueOr(false) && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload)) (gRuntimeConfig.processConfig.bForcePreload))
{ {
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath) if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
@ -923,16 +1005,16 @@ namespace Aurora::Process
return true; return true;
} }
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll) AUKN_SYM bool AddBinaryClassPath(const AuROString &dir, AuOptional<bool> optBoolPreloadAll)
{ {
AU_LOCK_GLOBAL_GUARD(gSpinLock); AU_LOCK_GLOBAL_GUARD(gSpinLock);
if (!AuTryInsert(gClassPath, dir)) if (!AuTryInsert(gClassPath, AuString(dir)))
{ {
return false; return false;
} }
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) || if (((optBoolPreloadAll.ValueOr(false) && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload)) (gRuntimeConfig.processConfig.bForcePreload))
{ {
PreloadDLLs(dir); PreloadDLLs(dir);
@ -943,8 +1025,16 @@ namespace Aurora::Process
AUKN_SYM AuList<AuString> GetBinaryClassPath() AUKN_SYM AuList<AuString> GetBinaryClassPath()
{ {
AU_LOCK_GLOBAL_GUARD(gSpinLock); try
return gClassPath; {
AU_LOCK_GLOBAL_GUARD(gSpinLock);
return gClassPath;
}
catch (...)
{
SysPushErrorMemory();
return {};
}
} }
void InitProcess() void InitProcess()