├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── UWPHelpers (CX) ├── StorageAccess.cpp ├── StorageAccess.h ├── StorageAsync.cpp ├── StorageAsync.h ├── StorageConfig.h ├── StorageExtensions.cpp ├── StorageExtensions.h ├── StorageFileW.h ├── StorageFolderW.h ├── StorageHandler.cpp ├── StorageHandler.h ├── StorageInfo.h ├── StorageItemW.h ├── StorageLog.h ├── StorageManager.cpp ├── StorageManager.h ├── StoragePath.cpp ├── StoragePath.h ├── StoragePickers.cpp ├── StoragePickers.h ├── UIHelpers.cpp ├── UIHelpers.h ├── UWP2C.cpp ├── UWP2C.h ├── UWPHelpersCX.sln └── UWPHelpersCX │ ├── App.cpp │ ├── App.h │ ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png │ ├── Common │ ├── DeviceResources.cpp │ ├── DeviceResources.h │ ├── DirectXHelper.h │ └── StepTimer.h │ ├── Content │ ├── Sample3DSceneRenderer.cpp │ ├── Sample3DSceneRenderer.h │ ├── SampleFpsTextRenderer.cpp │ ├── SampleFpsTextRenderer.h │ ├── SamplePixelShader.hlsl │ ├── SampleVertexShader.hlsl │ └── ShaderStructures.h │ ├── Package.appxmanifest │ ├── UWPHelpersCX.vcxproj │ ├── UWPHelpersCX.vcxproj.filters │ ├── UWPHelpersCXMain.cpp │ ├── UWPHelpersCXMain.h │ ├── pch.cpp │ └── pch.h └── UWPHelpers (WinRT) ├── StorageAccess.cpp ├── StorageAccess.h ├── StorageAsync.cpp ├── StorageAsync.h ├── StorageConfig.h ├── StorageExtensions.cpp ├── StorageExtensions.h ├── StorageFileW.h ├── StorageFolderW.h ├── StorageHandler.cpp ├── StorageHandler.h ├── StorageInfo.h ├── StorageItemW.h ├── StorageLog.h ├── StorageManager.cpp ├── StorageManager.h ├── StoragePath.cpp ├── StoragePath.h ├── StoragePickers.cpp ├── StoragePickers.h ├── UIHelpers.cpp ├── UIHelpers.h ├── UWP2C.cpp ├── UWP2C.h ├── UWPHelpersRT.sln └── UWPHelpersRT ├── Assets ├── LockScreenLogo.scale-200.png ├── SplashScreen.scale-200.png ├── Square150x150Logo.scale-200.png ├── Square44x44Logo.scale-200.png ├── Square44x44Logo.targetsize-24_altform-unplated.png ├── StoreLogo.png └── Wide310x150Logo.scale-200.png ├── Package.appxmanifest ├── PropertySheet.props ├── UWPHelpersRT.filters ├── UWPHelpersRT.vcxproj ├── UWPHelpersRT.vcxproj.filters ├── main.cpp └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2024 Bashar Astifan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageAccess.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "StorageConfig.h" 8 | #include "StorageLog.h" 9 | #include "StorageExtensions.h" 10 | #include "StorageAsync.h" 11 | #include "StorageAccess.h" 12 | #include "StorageItemW.h" 13 | 14 | using namespace Platform; 15 | using namespace Windows::Storage; 16 | using namespace Windows::Foundation; 17 | using namespace Windows::Foundation::Collections; 18 | using namespace Windows::Storage::AccessCache; 19 | using namespace Windows::ApplicationModel; 20 | 21 | // Main lookup list 22 | std::list FutureAccessItems; 23 | 24 | // Get value from app local settings 25 | Platform::String^ GetDataFromLocalSettings(Platform::String^ key) { 26 | ApplicationDataContainer^ localSettings{ ApplicationData::Current->LocalSettings }; 27 | IPropertySet^ values{ localSettings->Values }; 28 | if (key != nullptr) { 29 | Platform::Object^ tokenRetrive = values->Lookup(key); 30 | if (tokenRetrive != nullptr) { 31 | Platform::String^ ConvertedToken = (Platform::String^)tokenRetrive; 32 | return ConvertedToken; 33 | } 34 | } 35 | return nullptr; 36 | } 37 | 38 | std::string GetDataFromLocalSettings(std::string key) { 39 | return convert(GetDataFromLocalSettings(convert(key))); 40 | } 41 | 42 | // Add or replace value in app local settings 43 | bool AddDataToLocalSettings(Platform::String^ key, Platform::String^ data, bool replace) { 44 | ApplicationDataContainer^ localSettings{ ApplicationData::Current->LocalSettings }; 45 | IPropertySet^ values{ localSettings->Values }; 46 | 47 | Platform::String^ testResult = GetDataFromLocalSettings(key); 48 | if (testResult == nullptr) { 49 | values->Insert(key, PropertyValue::CreateString(data)); 50 | return true; 51 | } 52 | else if (replace) { 53 | values->Remove(key); 54 | values->Insert(key, PropertyValue::CreateString(data)); 55 | return true; 56 | } 57 | 58 | return false; 59 | } 60 | 61 | bool AddDataToLocalSettings(std::string key, std::string data, bool replace) { 62 | return AddDataToLocalSettings(convert(key), convert(data), replace); 63 | } 64 | 65 | // Add item to history list (FutureAccessItems) 66 | void AddToAccessibleItems(IStorageItem^ item) { 67 | bool isFolderAddedBefore = false; 68 | for each (auto folderItem in FutureAccessItems) { 69 | if (folderItem.Equal(item)) { 70 | isFolderAddedBefore = true; 71 | break; 72 | } 73 | } 74 | 75 | if (!isFolderAddedBefore) { 76 | FutureAccessItems.push_back(StorageItemW(item)); 77 | } 78 | } 79 | 80 | 81 | // Add folder to future list (to avoid request picker again) 82 | void AddItemToFutureList(IStorageItem^ item) { 83 | try { 84 | if (item != nullptr) { 85 | Platform::String^ folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList->Add(item); 86 | AddToAccessibleItems(item); 87 | } 88 | } 89 | catch (Platform::COMException^ e) { 90 | } 91 | } 92 | 93 | // Get item by key 94 | // This function can be used when you store token in LocalSettings as custom key 95 | IStorageItem^ GetItemByKey(Platform::String^ key) { 96 | IStorageItem^ item; 97 | Platform::String^ itemToken = GetDataFromLocalSettings(key); 98 | if (itemToken != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(itemToken)) { 99 | ExecuteTask(item, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(itemToken)); 100 | } 101 | 102 | return item; 103 | } 104 | 105 | // Append folder by token to (FutureAccessFolders) 106 | void AppendItemByToken(Platform::String^ token) { 107 | try { 108 | if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) { 109 | IStorageItem^ storageItem; 110 | ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token)); 111 | AddToAccessibleItems(storageItem); 112 | } 113 | } 114 | catch (Platform::COMException^ e) { 115 | } 116 | } 117 | 118 | // Update the history list by the future list (to restore all the picked items) 119 | void UpdateItemsByFutureList() { 120 | auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList->Entries; 121 | for each (auto ListItem in AccessList) { 122 | Platform::String^ itemToken = ListItem.Token; 123 | AppendItemByToken(itemToken); 124 | } 125 | } 126 | 127 | bool fillListsCalled = false; 128 | bool fillListInProgress = false; 129 | void FillLookupList() { 130 | if (fillListsCalled) { 131 | // Should be called only once 132 | // but let's wait in case we got too calls at once 133 | CoreWindow^ corewindow = CoreWindow::GetForCurrentThread(); 134 | while (fillListInProgress) 135 | { 136 | try { 137 | if (corewindow) { 138 | corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); 139 | } 140 | else { 141 | corewindow = CoreWindow::GetForCurrentThread(); 142 | } 143 | } 144 | catch (...) { 145 | 146 | } 147 | } 148 | return; 149 | } 150 | fillListsCalled = true; 151 | fillListInProgress = true; 152 | // Clean access list from any deleted/moved items 153 | for each (auto listItem in AccessCache::StorageApplicationPermissions::FutureAccessList->Entries) { 154 | try { 155 | IStorageItem^ test; 156 | ExecuteTask(test, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(listItem.Token)); 157 | if (test == nullptr) { 158 | // Access denied or file moved/deleted 159 | AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token); 160 | } 161 | } 162 | catch (Platform::COMException^ e) { 163 | // Access denied or file moved/deleted 164 | AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token); 165 | } 166 | } 167 | 168 | // Get files/folders selected by the user 169 | UpdateItemsByFutureList(); 170 | 171 | // Append known folders 172 | #if APPEND_APP_LOCALDATA_LOCATION 173 | AddToAccessibleItems(ApplicationData::Current->LocalFolder); 174 | AddToAccessibleItems(ApplicationData::Current->TemporaryFolder); 175 | #endif 176 | 177 | #if APPEND_APP_INSTALLATION_LOCATION 178 | AddToAccessibleItems(Package::Current->InstalledLocation); 179 | #endif 180 | 181 | #if APPEND_DOCUMENTS_LOCATION 182 | // >>>>DOCUMENTS (requires 'documentsLibrary' capability) 183 | AddToAccessibleItems(KnownFolders::DocumentsLibrary); 184 | #endif 185 | 186 | #if APPEND_VIDEOS_LOCATION 187 | // >>>>VIDEOS (requires 'videosLibrary' capability) 188 | AddToAccessibleItems(KnownFolders::VideosLibrary); 189 | #endif 190 | 191 | #if APPEND_PICTURES_LOCATION 192 | // >>>>VIDEOS (requires 'picturesLibrary' capability) 193 | AddToAccessibleItems(KnownFolders::PicturesLibrary); 194 | #endif 195 | 196 | #if APPEND_MUSIC_LOCATION 197 | // >>>>MUSIC (requires 'musicLibrary' capability) 198 | AddToAccessibleItems(KnownFolders::MusicLibrary); 199 | #endif 200 | 201 | // No need to append `RemovableDevices` 202 | // they will be allowed for access once you added the capability 203 | 204 | fillListInProgress = false; 205 | } 206 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageAccess.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | // Local settings 12 | std::string GetDataFromLocalSettings(std::string key); 13 | bool AddDataToLocalSettings(std::string key, std::string data, bool replace); 14 | 15 | // Lookup list 16 | void FillLookupList(); 17 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageAsync.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // Thanks to RetroArch/Libretro team for this idea 8 | // This is improved version of the original idea 9 | 10 | #include "StorageAsync.h" 11 | 12 | bool ActionPass(Windows::Foundation::IAsyncAction^ action) 13 | { 14 | return TaskHandler([&]() { 15 | return concurrency::create_task(action).then([]() { 16 | return true; 17 | }); 18 | }, false); 19 | } 20 | 21 | // Async action such as 'Delete' file 22 | // @action: async action 23 | // return false when action failed 24 | bool ExecuteTask(Windows::Foundation::IAsyncAction^ action) 25 | { 26 | return ActionPass(action); 27 | }; 28 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageAsync.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // Thanks to RetroArch/Libretro team for this idea 8 | // This is improved version of the original idea 9 | 10 | #pragma once 11 | 12 | #include "pch.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "StorageLog.h" 19 | #include "StorageExtensions.h" 20 | 21 | using namespace Windows::UI::Core; 22 | 23 | // Don't add 'using' 'Windows::Foundation' 24 | // it might cause confilct with some types like 'Point' 25 | 26 | #pragma region Async Handlers 27 | 28 | template 29 | T TaskHandler(std::function()> wtask, T def) 30 | { 31 | T result = def; 32 | bool done = false; 33 | wtask().then([&](concurrency::task t) { 34 | try 35 | { 36 | result = t.get(); 37 | } 38 | catch (Platform::Exception^ exception_) 39 | { 40 | UWP_ERROR_LOG(UWPSMT, convertToChar(exception_->Message)); 41 | } 42 | done = true; 43 | }); 44 | 45 | CoreWindow^ corewindow = CoreWindow::GetForCurrentThread(); 46 | while (!done) 47 | { 48 | try { 49 | if (corewindow) { 50 | corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); 51 | } 52 | else { 53 | corewindow = CoreWindow::GetForCurrentThread(); 54 | } 55 | } 56 | catch (...) { 57 | 58 | } 59 | } 60 | 61 | return result; 62 | }; 63 | 64 | template 65 | T TaskPass(Windows::Foundation::IAsyncOperation^ task, T def) 66 | { 67 | return TaskHandler([&]() { 68 | return concurrency::create_task(task).then([](T res) { 69 | return res; 70 | }); 71 | }, def); 72 | } 73 | 74 | bool ActionPass(Windows::Foundation::IAsyncAction^ action); 75 | 76 | #pragma endregion 77 | 78 | // Now it's more simple to execute async task 79 | // @out: output variable 80 | // @task: async task 81 | template 82 | void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation^ task) 83 | { 84 | out = TaskPass(task, T()); 85 | }; 86 | 87 | // For specific return default value 88 | // @out: output variable 89 | // @task: async task 90 | // @def: default value when fail 91 | template 92 | void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation^ task, T def) 93 | { 94 | out = TaskPass(task, def); 95 | }; 96 | 97 | 98 | // Async action such as 'Delete' file 99 | // @action: async action 100 | // return false when action failed 101 | bool ExecuteTask(Windows::Foundation::IAsyncAction^ action); 102 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageConfig.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | // Known locations 12 | // ACTIVATE BELOW ONLY IF YOU ADDED THE CAPABILITY 13 | #define APPEND_APP_LOCALDATA_LOCATION 1 // recommended to be always 1 14 | #define APPEND_APP_INSTALLATION_LOCATION 1 // recommended to be always 1 15 | #define APPEND_DOCUMENTS_LOCATION 0 // (requires 'documentsLibrary' capability) 16 | #define APPEND_VIDEOS_LOCATION 0 // (requires 'videosLibrary' capability) 17 | #define APPEND_MUSIC_LOCATION 0 // (requires musicLibrary' capability) 18 | #define APPEND_PICTURES_LOCATION 0 // (requires 'picturesLibrary' capability) 19 | 20 | // To force legacy APIs, define `UWP_LEGACY` (using header or project settings which is better) 21 | //#define UWP_LEGACY 1 22 | 23 | // Working folder 24 | // set this value by calling `SetWorkingFolder` from `StorageManager.h` 25 | static std::string AppWorkingFolder; 26 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageExtensions.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | typedef struct { 18 | DWORD dwDesiredAccess; 19 | DWORD dwShareMode; 20 | DWORD dwCreationDisposition; 21 | int flags; 22 | bool isWrite; 23 | bool isAppend; 24 | bool isCreate; 25 | } FILE_OPEN_UWP_MODE; 26 | 27 | bool replace(std::string& str, const std::string& from, const std::string& to); 28 | std::string replace2(const std::string str, const std::string& from, const std::string& to); 29 | std::vector split(const std::string s, char seperator); 30 | // Parent full path, child full path 31 | bool isChild(std::string parent, std::string child); 32 | // Parent full path, child full path, child name only 33 | bool isParent(std::string parent, std::string child, std::string childName); 34 | 35 | bool iequals(const std::string a, const std::string b); 36 | bool equals(const std::string a, const std::string b); 37 | bool ends_with(std::string const& value, std::string const& ending); 38 | bool starts_with(std::string str, std::string prefix); 39 | 40 | Platform::String^ convert(const std::string input); 41 | std::wstring convertToWString(const std::string input); 42 | std::string convert(Platform::String^ input); 43 | std::string convert(std::wstring input); 44 | std::string convert(const char* input); 45 | LPCWSTR convertToLPCWSTR(std::string input); 46 | LPCWSTR convertToLPCWSTR(Platform::String^ input); 47 | const char* convertToChar(Platform::String^ input); 48 | 49 | void tolower(std::string& input); 50 | void tolower(Platform::String^& input); 51 | void toupper(std::string& input); 52 | void toupper(Platform::String^& input); 53 | 54 | void windowsPath(std::string& path); 55 | void windowsPath(Platform::String^& path); 56 | 57 | std::string merge(std::string targetFullPath, std::string subFullPath); 58 | 59 | std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v"); 60 | std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v"); 61 | std::string& trim(std::string& s, const char* t = " \t\n\r\f\v"); 62 | 63 | template 64 | bool findInList(std::list& inputList, T& str) { 65 | return (std::find(inputList.begin(), inputList.end(), str) != inputList.end()); 66 | }; 67 | 68 | FILE_OPEN_UWP_MODE* GetFileMode(const char* mode); 69 | 70 | // Parent and child full path 71 | std::string getSubRoot(std::string parent, std::string child); 72 | 73 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageFileW.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include "pch.h" 10 | #include 11 | #include 12 | 13 | #include "StorageLog.h" 14 | #include "StoragePath.h" 15 | #include "StorageExtensions.h" 16 | #include "StorageHandler.h" 17 | #include "StorageAsync.h" 18 | #include "StorageInfo.h" 19 | 20 | using namespace Platform; 21 | using namespace Windows::Storage; 22 | using namespace Windows::Foundation; 23 | using namespace Windows::Storage::FileProperties; 24 | 25 | class StorageFileW { 26 | public: 27 | StorageFileW() { 28 | } 29 | 30 | StorageFileW(StorageFile^ file) { 31 | storageFile = file; 32 | fileSize = 0; 33 | } 34 | StorageFileW(IStorageItem^ file) { 35 | storageFile = (StorageFile^)file; 36 | fileSize = 0; 37 | } 38 | ~StorageFileW() { 39 | delete storageFile; 40 | delete properties; 41 | } 42 | 43 | // Detect if main storage file is not null 44 | bool IsValid() { 45 | return (storageFile != nullptr); 46 | } 47 | 48 | // Delete file 49 | bool Delete() { 50 | bool state = ExecuteTask(storageFile->DeleteAsync()); 51 | if (state) { 52 | storageFile = nullptr; 53 | } 54 | return state; 55 | } 56 | 57 | // Rename file 58 | bool Rename(std::string name) { 59 | auto path = PathUWP(name); 60 | if (path.IsAbsolute()) { 61 | name = path.GetFilename(); 62 | } 63 | return ExecuteTask(storageFile->RenameAsync(convert(name))); 64 | } 65 | 66 | // Copy file 67 | bool Copy(StorageFolder^ folder, std::string name) { 68 | bool state = false; 69 | StorageFile^ newFile; 70 | ExecuteTask(newFile, storageFile->CopyAsync(folder, convert(name), NameCollisionOption::ReplaceExisting)); 71 | if (newFile != nullptr) { 72 | state = true; 73 | } 74 | return state; 75 | } 76 | 77 | // Move file 78 | bool Move(StorageFolder^ folder, std::string name) { 79 | bool state = false; 80 | IStorageItem^ newFile; 81 | state = ExecuteTask(storageFile->MoveAsync(folder, convert(name), NameCollisionOption::GenerateUniqueName)); 82 | if (state) { 83 | ExecuteTask(newFile, folder->TryGetItemAsync(storageFile->Name)); 84 | if (newFile != nullptr) { 85 | storageFile = (StorageFile^)newFile; 86 | } 87 | else { 88 | state = false; 89 | } 90 | } 91 | return state; 92 | } 93 | 94 | // Get file path 95 | std::string GetPath() { 96 | return convert(storageFile->Path); 97 | } 98 | 99 | // Get file name 100 | std::string GetName() { 101 | return convert(storageFile->Name); 102 | } 103 | 104 | // Compare file with std::string 105 | bool Equal(std::string path) { 106 | std::string filePath = GetPath(); 107 | 108 | // Fix slashs back from '/' to '\' 109 | windowsPath(path); 110 | return iequals(filePath, path); 111 | } 112 | 113 | // Compare file with Platform::String 114 | bool Equal(Platform::String^ path) { 115 | return storageFile->Path->Equals(path); 116 | } 117 | 118 | // Compare file with Path 119 | bool Equal(PathUWP path) { 120 | return Equal(path.ToString()); 121 | } 122 | 123 | // Compare file with StorageFile 124 | bool Equal(StorageFile^ file) { 125 | return Equal(file->Path); 126 | } 127 | 128 | // Get file size 129 | __int64 GetSize(bool updateCache = false) { 130 | if (fileSize == 0 || updateCache) { 131 | // Let's try getting size by handle first 132 | HANDLE handle; 133 | HRESULT hr = GetHandle(&handle); 134 | if (handle == INVALID_HANDLE_VALUE || hr != S_OK) { 135 | // We have no other option, fallback to UWP 136 | fileSize = FetchProperties()->Size; 137 | } 138 | else { 139 | LARGE_INTEGER size{ 0 }; 140 | if (FALSE == GetFileSizeEx(handle, &size)) { 141 | LARGE_INTEGER end_offset; 142 | const LARGE_INTEGER zero{}; 143 | if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) { 144 | CloseHandle(handle); 145 | } 146 | else { 147 | fileSize = end_offset.QuadPart; 148 | SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN); 149 | CloseHandle(handle); 150 | } 151 | } 152 | else { 153 | fileSize = size.QuadPart; 154 | CloseHandle(handle); 155 | } 156 | } 157 | } 158 | return fileSize; 159 | } 160 | 161 | // Get file handle 162 | HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) { 163 | return GetFileHandle(storageFile, handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 164 | } 165 | 166 | // Get file stream 167 | FILE* GetStream(const char* mode) { 168 | HANDLE handle; 169 | auto fileMode = GetFileMode(mode); 170 | if (fileMode && !fileMode->isAppend && fileMode->isCreate) { 171 | ExecuteTask(Windows::Storage::FileIO::WriteTextAsync(storageFile, L"")); 172 | } 173 | HRESULT hr = GetHandle(&handle, fileMode->dwDesiredAccess, fileMode->dwShareMode); 174 | FILE* file{}; 175 | if (hr == S_OK && handle != INVALID_HANDLE_VALUE) { 176 | UWP_ERROR_LOG(UWPSMT, "Opening file (%s) with flag:%d mode:%s", GetPath().c_str(), fileMode->flags, mode); 177 | file = _fdopen(_open_osfhandle((intptr_t)handle, fileMode->flags), mode); 178 | } 179 | return file; 180 | } 181 | 182 | // Get file handle from stream 183 | HANDLE GetHandle(FILE* file) { 184 | return (HANDLE)_get_osfhandle(_fileno(file)); 185 | } 186 | 187 | // Get file properties 188 | FILE_BASIC_INFO* GetProperties() { 189 | HANDLE handle; 190 | HRESULT hr = GetHandle(&handle); 191 | 192 | size_t size = sizeof(FILE_BASIC_INFO); 193 | FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size)); 194 | if (hr == S_OK && handle != INVALID_HANDLE_VALUE && information) { 195 | information->FileAttributes = (DWORD)storageFile->Attributes; 196 | 197 | if (FALSE == GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) { 198 | // Fallback to UWP method (Slow) 199 | auto props = FetchProperties(); 200 | information->ChangeTime.QuadPart = props->DateModified.UniversalTime; 201 | information->CreationTime.QuadPart = props->ItemDate.UniversalTime; 202 | information->LastAccessTime.QuadPart = props->DateModified.UniversalTime; 203 | information->LastWriteTime.QuadPart = props->DateModified.UniversalTime; 204 | } 205 | CloseHandle(handle); 206 | } 207 | 208 | return information; 209 | } 210 | 211 | // Get main storage file 212 | StorageFile^ GetStorageFile() { 213 | return storageFile; 214 | } 215 | 216 | time_t filetime_to_timet(LARGE_INTEGER ull) const { 217 | return ull.QuadPart / 10000000ULL - 11644473600ULL; 218 | } 219 | ItemInfoUWP GetFileInfo() { 220 | ItemInfoUWP info; 221 | info.name = GetName(); 222 | info.fullName = GetPath(); 223 | info.isDirectory = false; 224 | 225 | auto sProperties = GetProperties(); 226 | 227 | info.size = (uint64_t)GetSize(); 228 | info.lastAccessTime = (uint64_t)filetime_to_timet(sProperties->LastAccessTime); 229 | info.lastWriteTime = (uint64_t)filetime_to_timet(sProperties->LastWriteTime); 230 | info.changeTime = (uint64_t)filetime_to_timet(sProperties->ChangeTime); 231 | info.creationTime = (uint64_t)filetime_to_timet(sProperties->CreationTime); 232 | 233 | 234 | info.attributes = sProperties->FileAttributes; 235 | 236 | return info; 237 | } 238 | 239 | private: 240 | StorageFile^ storageFile; 241 | BasicProperties^ properties; 242 | __int64 fileSize = 0; 243 | 244 | BasicProperties^ FetchProperties() { 245 | if (properties == nullptr) { 246 | // Very bad and slow way in UWP to get size and other properties 247 | // not preferred to be used on big list of files 248 | ExecuteTask(properties, storageFile->GetBasicPropertiesAsync()); 249 | } 250 | return properties; 251 | } 252 | }; 253 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageHandler.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #include "StorageHandler.h" 7 | #include "StorageExtensions.h" 8 | 9 | HRESULT GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode) 10 | { 11 | if (file != nullptr) { 12 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(file)); 13 | Microsoft::WRL::ComPtr handleAccess; 14 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 15 | { 16 | HANDLE hFile = INVALID_HANDLE_VALUE; 17 | 18 | if (SUCCEEDED(handleAccess->Create(accessMode, 19 | shareMode, 20 | HO_NONE, 21 | nullptr, 22 | &hFile))) 23 | { 24 | *handle = hFile; 25 | return S_OK; 26 | } 27 | } 28 | } 29 | return E_FAIL; 30 | } 31 | 32 | HRESULT GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode) 33 | { 34 | if (folder != nullptr) { 35 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(folder)); 36 | Microsoft::WRL::ComPtr handleAccess; 37 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 38 | { 39 | HANDLE hFolder = INVALID_HANDLE_VALUE; 40 | auto fn = convertToLPCWSTR(filename); 41 | if (SUCCEEDED(handleAccess->Create(fn, 42 | openMode, 43 | accessMode, 44 | shareMode, 45 | HO_NONE, 46 | nullptr, 47 | &hFolder))) 48 | { 49 | *handle = hFolder; 50 | return S_OK; 51 | } 52 | } 53 | } 54 | return E_FAIL; 55 | } 56 | 57 | HRESULT GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode) 58 | { 59 | if (folder != nullptr) { 60 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(folder)); 61 | Microsoft::WRL::ComPtr handleAccess; 62 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 63 | { 64 | HANDLE hFolder = INVALID_HANDLE_VALUE; 65 | 66 | if (SUCCEEDED(handleAccess->Create(accessMode, 67 | shareMode, 68 | HO_NONE, 69 | nullptr, 70 | &hFolder))) 71 | { 72 | *handle = hFolder; 73 | return S_OK; 74 | } 75 | } 76 | } 77 | return E_FAIL; 78 | } 79 | 80 | HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode) { 81 | switch (accessMode) { 82 | case GENERIC_READ: 83 | return HAO_READ | HAO_READ_ATTRIBUTES; 84 | case GENERIC_WRITE: 85 | return HAO_WRITE | HAO_READ; 86 | case GENERIC_ALL: 87 | return HAO_READ | HAO_READ_ATTRIBUTES | HAO_WRITE | HAO_DELETE; 88 | default: 89 | return HAO_READ; 90 | } 91 | } 92 | 93 | HANDLE_SHARING_OPTIONS GetShareMode(int shareMode) { 94 | switch (shareMode) 95 | { 96 | case FILE_SHARE_READ: 97 | return HSO_SHARE_READ; 98 | case FILE_SHARE_WRITE: 99 | return HSO_SHARE_READ | HSO_SHARE_WRITE; 100 | case FILE_SHARE_DELETE: 101 | return HSO_SHARE_DELETE; 102 | default: 103 | return HSO_SHARE_READ; 104 | } 105 | } 106 | 107 | HANDLE_CREATION_OPTIONS GetOpenMode(int openMode) { 108 | switch (openMode) 109 | { 110 | case CREATE_NEW: 111 | return HCO_CREATE_NEW; 112 | case CREATE_ALWAYS: 113 | return HCO_CREATE_ALWAYS; 114 | case OPEN_ALWAYS: 115 | return HCO_OPEN_ALWAYS; 116 | case OPEN_EXISTING: 117 | return HCO_OPEN_EXISTING; 118 | default: 119 | return HCO_OPEN_EXISTING; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageHandler.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #pragma once 7 | 8 | #include "pch.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace Windows::Storage; 15 | 16 | #pragma region WindowsStorageCOM 17 | // These APIs have been accidentally placed inside the WINAPI_PARTITION_DESKTOP partition 18 | // (they're not desktop-specific; they're available to UWPs). 19 | // This will be addressed in future SDK updates. 20 | // These are copied from WindowsStorageCOM.h 21 | // You can remove this region once the real file has been updated 22 | // to fix the WINAPI_PARTITION_DESKTOP block 23 | // Source: https://stackoverflow.com/questions/42799235/how-can-i-get-a-win32-handle-for-a-storagefile-or-storagefolder-in-uwp 24 | 25 | typedef interface IOplockBreakingHandler IOplockBreakingHandler; 26 | typedef interface IStorageItemHandleAccess IStorageItemHandleAccess; 27 | typedef interface IStorageFolderHandleAccess IStorageFolderHandleAccess; 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | typedef 34 | enum HANDLE_OPTIONS 35 | { 36 | HO_NONE = 0, 37 | HO_OPEN_REQUIRING_OPLOCK = 0x40000, 38 | HO_DELETE_ON_CLOSE = 0x4000000, 39 | HO_SEQUENTIAL_SCAN = 0x8000000, 40 | HO_RANDOM_ACCESS = 0x10000000, 41 | HO_NO_BUFFERING = 0x20000000, 42 | HO_OVERLAPPED = 0x40000000, 43 | HO_WRITE_THROUGH = 0x80000000 44 | } HANDLE_OPTIONS; 45 | 46 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_OPTIONS); 47 | typedef 48 | enum HANDLE_ACCESS_OPTIONS 49 | { 50 | HAO_NONE = 0, 51 | HAO_READ_ATTRIBUTES = 0x80, 52 | HAO_READ = 0x120089, 53 | HAO_WRITE = 0x120116, 54 | HAO_DELETE = 0x10000 55 | } HANDLE_ACCESS_OPTIONS; 56 | 57 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_ACCESS_OPTIONS); 58 | typedef 59 | enum HANDLE_SHARING_OPTIONS 60 | { 61 | HSO_SHARE_NONE = 0, 62 | HSO_SHARE_READ = 0x1, 63 | HSO_SHARE_WRITE = 0x2, 64 | HSO_SHARE_DELETE = 0x4 65 | } HANDLE_SHARING_OPTIONS; 66 | 67 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_SHARING_OPTIONS); 68 | typedef 69 | enum HANDLE_CREATION_OPTIONS 70 | { 71 | HCO_CREATE_NEW = 0x1, 72 | HCO_CREATE_ALWAYS = 0x2, 73 | HCO_OPEN_EXISTING = 0x3, 74 | HCO_OPEN_ALWAYS = 0x4, 75 | HCO_TRUNCATE_EXISTING = 0x5 76 | } HANDLE_CREATION_OPTIONS; 77 | 78 | 79 | EXTERN_C const IID IID_IOplockBreakingHandler; 80 | MIDL_INTERFACE("826ABE3D-3ACD-47D3-84F2-88AAEDCF6304") 81 | IOplockBreakingHandler : public IUnknown 82 | { 83 | public: 84 | virtual HRESULT STDMETHODCALLTYPE OplockBreaking(void) = 0; 85 | 86 | }; 87 | 88 | EXTERN_C const IID IID_IStorageItemHandleAccess; 89 | MIDL_INTERFACE("5CA296B2-2C25-4D22-B785-B885C8201E6A") 90 | IStorageItemHandleAccess : public IUnknown 91 | { 92 | public: 93 | virtual HRESULT STDMETHODCALLTYPE Create( 94 | HANDLE_ACCESS_OPTIONS accessOptions, 95 | HANDLE_SHARING_OPTIONS sharingOptions, 96 | HANDLE_OPTIONS options, 97 | __RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler, 98 | __RPC__deref_out_opt HANDLE * interopHandle) = 0; 99 | 100 | }; 101 | 102 | EXTERN_C const IID IID_IStorageFolderHandleAccess; 103 | MIDL_INTERFACE("DF19938F-5462-48A0-BE65-D2A3271A08D6") 104 | IStorageFolderHandleAccess : public IUnknown 105 | { 106 | public: 107 | virtual HRESULT STDMETHODCALLTYPE Create( 108 | __RPC__in_string LPCWSTR fileName, 109 | HANDLE_CREATION_OPTIONS creationOptions, 110 | HANDLE_ACCESS_OPTIONS accessOptions, 111 | HANDLE_SHARING_OPTIONS sharingOptions, 112 | HANDLE_OPTIONS options, 113 | __RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler, 114 | __RPC__deref_out_opt HANDLE * interopHandle) = 0; 115 | 116 | }; 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | #pragma endregion 121 | 122 | HRESULT GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode); 123 | HRESULT GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode); 124 | HRESULT GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode); 125 | 126 | HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode); 127 | HANDLE_SHARING_OPTIONS GetShareMode(int shareMode); 128 | HANDLE_CREATION_OPTIONS GetOpenMode(int openMode); 129 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageInfo.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // For updates check: https://github.com/basharast/UWP2Win32 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | struct ItemInfoUWP { 14 | std::string name; 15 | std::string fullName; 16 | 17 | bool isDirectory = false; 18 | 19 | uint64_t size = 0; 20 | uint64_t lastAccessTime = 0; 21 | uint64_t lastWriteTime = 0; 22 | uint64_t changeTime = 0; 23 | uint64_t creationTime = 0; 24 | 25 | DWORD attributes = 0; 26 | }; 27 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageItemW.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include "pch.h" 10 | #include 11 | #include 12 | 13 | #include "StorageLog.h" 14 | #include "StoragePath.h" 15 | #include "StorageExtensions.h" 16 | #include "StorageHandler.h" 17 | #include "StorageAsync.h" 18 | #include "StorageFolderW.h" 19 | 20 | using namespace Platform; 21 | using namespace Windows::Storage; 22 | using namespace Windows::Foundation; 23 | using namespace Windows::Storage::FileProperties; 24 | 25 | class StorageItemW { 26 | public: 27 | StorageItemW() { 28 | } 29 | 30 | StorageItemW(IStorageItem^ item) { 31 | storageItem = item; 32 | itemSize = 0; 33 | if (item != nullptr) { 34 | isDirectory = storageItem->IsOfType(StorageItemTypes::Folder); 35 | if (isDirectory) { 36 | storageFolderW = StorageFolderW(item); 37 | } 38 | else { 39 | storageFileW = StorageFileW(item); 40 | } 41 | } 42 | } 43 | StorageItemW(StorageFolderW folder) { 44 | StorageItemW((IStorageItem^)folder.GetStorageFolder()); 45 | } 46 | StorageItemW(StorageFileW file) { 47 | StorageItemW((IStorageItem^)file.GetStorageFile()); 48 | } 49 | ~StorageItemW() { 50 | delete storageItem; 51 | } 52 | 53 | bool IsDirectory() { 54 | return isDirectory; 55 | } 56 | 57 | // Detect if main storage item is not null 58 | bool IsValid() { 59 | return (storageItem != nullptr); 60 | } 61 | 62 | // Delete item 63 | bool Delete() { 64 | bool state = ExecuteTask(storageItem->DeleteAsync()); 65 | if (state) { 66 | storageItem = nullptr; 67 | } 68 | return state; 69 | } 70 | 71 | // Rename item 72 | bool Rename(std::string name) { 73 | auto path = PathUWP(name); 74 | if (path.IsAbsolute()) { 75 | name = path.GetFilename(); 76 | } 77 | return ExecuteTask(storageItem->RenameAsync(convert(name))); 78 | } 79 | 80 | // Copy item 81 | bool Copy(StorageFolder^ folder) { 82 | bool state = false; 83 | if (IsDirectory()) { 84 | state = storageFolderW.Copy(folder); 85 | } 86 | else { 87 | state = storageFileW.Copy(folder, storageFileW.GetName()); 88 | } 89 | return state; 90 | } 91 | 92 | 93 | // Copy item 94 | bool Copy(StorageItemW folder) { 95 | return Copy(folder.GetStorageFolder()); 96 | } 97 | 98 | bool Copy(StorageFolder^ folder, std::string name) { 99 | bool state = false; 100 | if (IsDirectory()) { 101 | state = storageFolderW.Copy(folder); 102 | } 103 | else { 104 | state = storageFileW.Copy(folder, name); 105 | } 106 | return state; 107 | } 108 | 109 | bool Copy(StorageItemW folder, std::string name) { 110 | return Copy(folder.GetStorageFolder(), name); 111 | } 112 | 113 | // Move item 114 | bool Move(StorageFolder^ folder) { 115 | bool state = false; 116 | if (IsDirectory()) { 117 | state = storageFolderW.Copy(folder, true); 118 | } 119 | else { 120 | state = storageFileW.Move(folder, storageFileW.GetName()); 121 | } 122 | return state; 123 | } 124 | 125 | bool Move(StorageItemW folder) { 126 | return Move(folder.GetStorageFolder()); 127 | } 128 | 129 | // Move item 130 | bool Move(StorageFolder^ folder, std::string name) { 131 | bool state = false; 132 | if (IsDirectory()) { 133 | state = storageFolderW.Copy(folder, true); 134 | } 135 | else { 136 | state = storageFileW.Move(folder, name); 137 | } 138 | return state; 139 | } 140 | 141 | bool Move(StorageItemW folder, std::string name) { 142 | return Move(folder.GetStorageFolder(), name); 143 | } 144 | 145 | // Get item path 146 | std::string GetPath() { 147 | return convert(storageItem->Path); 148 | } 149 | 150 | // Get item name 151 | std::string GetName() { 152 | return convert(storageItem->Name); 153 | } 154 | 155 | // Compare item with std::string 156 | bool Equal(std::string path) { 157 | std::string itemPath = GetPath(); 158 | 159 | // Fix slashs back from '/' to '\' 160 | windowsPath(path); 161 | return iequals(itemPath, path); 162 | } 163 | 164 | // Compare item with Platform::String 165 | bool Equal(Platform::String^ path) { 166 | return storageItem->Path->Equals(path); 167 | } 168 | 169 | // Compare item with Path 170 | bool Equal(PathUWP path) { 171 | return Equal(path.ToString()); 172 | } 173 | 174 | // Compare item with StorageItem 175 | bool Equal(IStorageItem^ item) { 176 | return Equal(item->Path); 177 | } 178 | 179 | // Get item size 180 | __int64 GetSize(bool updateCache = false) { 181 | if (itemSize == 0 || updateCache) { 182 | if (IsDirectory()) { 183 | itemSize = storageFolderW.GetSize(updateCache); 184 | } 185 | else { 186 | itemSize = storageFileW.GetSize(updateCache); 187 | } 188 | } 189 | return itemSize; 190 | } 191 | 192 | // Get item handle 193 | HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) { 194 | HRESULT hr = E_FAIL; 195 | if (IsDirectory()) { 196 | hr = GetFolderHandle(storageFolderW.GetStorageFolder(), handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 197 | } 198 | else { 199 | hr = GetFileHandle(storageFileW.GetStorageFile(), handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 200 | } 201 | return hr; 202 | } 203 | 204 | // Get file stream 205 | FILE* GetStream(const char* mode) { 206 | FILE* file{}; 207 | if (!IsDirectory()) { 208 | file = storageFileW.GetStream(mode); 209 | } 210 | return file; 211 | } 212 | 213 | // Get files stream from folder 214 | FILE* GetFileStream(std::string name, const char* mode) { 215 | FILE* file{}; 216 | if (IsDirectory()) { 217 | file = storageFolderW.GetFileStream(name, mode); 218 | } 219 | return file; 220 | } 221 | 222 | // Get item handle from stream 223 | HANDLE GetHandleFromStream(FILE* file) { 224 | return (HANDLE)_get_osfhandle(_fileno(file)); 225 | } 226 | 227 | 228 | // Create or open folder if exists 229 | StorageFolderW CreateFolder(PathUWP path) { 230 | return StorageFolderW(storageFolderW.GetOrCreateFolder(path)); 231 | } 232 | 233 | // Create or open file if exists 234 | StorageFileW CreateFile(PathUWP path) { 235 | return StorageFileW(storageFolderW.GetOrCreateFile(path)); 236 | } 237 | 238 | // Create new folder 239 | bool CreateFolder(std::string name, bool replaceExisting = true) { 240 | return storageFolderW.CreateFolder(name, replaceExisting); 241 | } 242 | 243 | // Create new file 244 | bool CreateFile(std::string name, bool replaceExisting = true) { 245 | return storageFolderW.CreateFile(name, replaceExisting); 246 | } 247 | 248 | // Check if folder contains item by name or path 249 | bool Contains(PathUWP path, IStorageItem^& storageItem) { 250 | return storageFolderW.Contains(path, storageItem); 251 | } 252 | 253 | // Get all sub folders (deep scan) 254 | std::list GetAllFolders(bool useWindowsIndexer = false) { 255 | return storageFolderW.GetAllFolders(useWindowsIndexer); 256 | } 257 | 258 | // Get all files including files in sub folders (deep scan) 259 | std::list GetAllFiles(bool useWindowsIndexer = false) { 260 | return storageFolderW.GetAllFiles(useWindowsIndexer); 261 | } 262 | 263 | std::list GetFolders() { 264 | return storageFolderW.GetFolders(); 265 | } 266 | 267 | std::list GetFiles() { 268 | return storageFolderW.GetFiles(); 269 | } 270 | 271 | // Get item properties 272 | FILE_BASIC_INFO* GetProperties() { 273 | if (IsDirectory()) { 274 | return storageFolderW.GetProperties(); 275 | } 276 | else { 277 | return storageFileW.GetProperties(); 278 | } 279 | } 280 | 281 | // Get main storage item 282 | IStorageItem^ GetStorageItem() { 283 | return storageItem; 284 | } 285 | 286 | // Get Wrapped StorageFolder 287 | StorageFolderW GetStorageFolderW() { 288 | return storageFolderW; 289 | } 290 | 291 | // Get Wrapped StorageFolder 292 | StorageFolder^ GetStorageFolder() { 293 | return storageFolderW.GetStorageFolder(); 294 | } 295 | 296 | // Get Wrapped StorageFile 297 | StorageFileW GetStorageFileW() { 298 | return storageFileW; 299 | } 300 | 301 | // Get StorageFile^ 302 | StorageFile^ GetStorageFile() { 303 | return storageFileW.GetStorageFile(); 304 | } 305 | 306 | ItemInfoUWP GetItemInfo() { 307 | ItemInfoUWP info; 308 | if (IsDirectory()) { 309 | info = storageFolderW.GetFolderInfo(); 310 | } 311 | else { 312 | info = storageFileW.GetFileInfo(); 313 | } 314 | return info; 315 | } 316 | 317 | private: 318 | IStorageItem^ storageItem; 319 | StorageFileW storageFileW; 320 | StorageFolderW storageFolderW; 321 | 322 | __int64 itemSize = 0; 323 | bool isDirectory = false; 324 | }; 325 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageLog.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #define UWPSMT = 4; // Change it based on your needs 10 | 11 | // Link your debug function below 12 | #define UWP_ERROR_LOG(t,...) do { } while (false) 13 | #define UWP_WARN_LOG(t,...) do { } while (false) 14 | #define UWP_NOTICE_LOG(t,...) do { } while (false) 15 | #define UWP_INFO_LOG(t,...) do { } while (false) 16 | #define UWP_DEBUG_LOG(t,...) do { } while (false) 17 | #define UWP_VERBOSE_LOG(t,...) do { } while (false) 18 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StorageManager.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "StoragePath.h" 12 | #include "StorageInfo.h" 13 | #include "StorageAccess.h" 14 | #include "StoragePickers.h" 15 | 16 | // Locations 17 | std::string GetWorkingFolder(); // Where main data is, default is app data 18 | void SetWorkingFolder(std::string location); // Change working location 19 | void SetWorkingFolder(std::wstring location); 20 | std::string GetInstallationFolder(); 21 | std::string GetLocalFolder(); 22 | std::string GetTempFolder(); 23 | std::string GetTempFile(std::string name); 24 | std::string GetTempFile(std::wstring name); 25 | std::string GetPicturesFolder(); // Requires 'picturesLibrary' capability 26 | std::string GetVideosFolder(); // Requires 'videosLibrary' capability 27 | std::string GetDocumentsFolder(); // Requires 'documentsLibrary' capability 28 | std::string GetMusicFolder(); // Requires 'musicLibrary' capability 29 | std::string GetPreviewPath(std::string path); 30 | bool isLocalState(std::string path); 31 | bool isLocalState(std::wstring path); 32 | 33 | // Management 34 | HANDLE CreateFileUWP(std::string path, long accessMode = GENERIC_READ, long shareMode = FILE_SHARE_READ, long openMode = OPEN_EXISTING); 35 | HANDLE CreateFileUWP(std::wstring path, long accessMode = GENERIC_READ, long shareMode = FILE_SHARE_READ, long openMode = OPEN_EXISTING); 36 | FILE* GetFileStream(std::string path, const char* mode); 37 | FILE* GetFileStream(std::wstring path, const char* mode); 38 | // `GetFileStreamFromApp` Will use Windows UWP API, use it instead of fopen..etc 39 | FILE* GetFileStreamFromApp(std::string path, const char* mode); 40 | FILE* GetFileStreamFromApp(std::wstring path, const char* mode); 41 | 42 | // Validation 43 | bool IsValidUWP(std::string path, bool allowForAppData = false); 44 | bool IsValidUWP(std::wstring path, bool allowForAppData = false); 45 | bool IsExistsUWP(std::string path); 46 | bool IsExistsUWP(std::wstring path); 47 | bool IsDirectoryUWP(std::string path); 48 | bool IsDirectoryUWP(std::wstring path); 49 | 50 | // File Contents 51 | std::string GetFileContent(std::string path, const char* mode); 52 | std::string GetFileContent(std::wstring path, const char* mode); 53 | bool PutFileContents(std::string path, std::string content, const char* mode = "w+", bool backup = false); 54 | bool PutFileContents(std::wstring path, std::wstring content, const char* mode = "w+", bool backup = false); 55 | 56 | // Folder Contents 57 | std::list GetFolderContents(std::string path, bool deepScan = false); 58 | std::list GetFolderContents(std::wstring path, bool deepScan = false); 59 | ItemInfoUWP GetItemInfoUWP(std::string path); 60 | ItemInfoUWP GetItemInfoUWP(std::wstring path); 61 | 62 | // Basics 63 | int64_t GetSizeUWP(std::string path); 64 | int64_t GetSizeUWP(std::wstring path); 65 | bool DeleteUWP(std::string path); 66 | bool DeleteUWP(std::wstring path); 67 | bool CreateDirectoryUWP(std::string path, bool replaceExisting = true); 68 | bool CreateDirectoryUWP(std::wstring path, bool replaceExisting = true); 69 | // Both (old, new) full path 70 | bool RenameUWP(std::string oldname, std::string newname); 71 | bool RenameUWP(std::wstring oldname, std::wstring newname); 72 | // Add file name to destination path 73 | bool CopyUWP(std::string path, std::string dest); 74 | bool CopyUWP(std::wstring path, std::wstring dest); 75 | // Add file name to destination path 76 | bool MoveUWP(std::string path, std::string dest); 77 | bool MoveUWP(std::wstring path, std::wstring dest); 78 | 79 | // Helpers 80 | bool OpenFile(std::string path); 81 | bool OpenFile(std::wstring path); 82 | bool OpenFolder(std::string path); 83 | bool OpenFolder(std::wstring path); 84 | 85 | // More 86 | bool IsFirstStart(); 87 | std::string ResolvePathUWP(std::string path); 88 | bool IsContainsAccessibleItems(std::string path); 89 | bool IsContainsAccessibleItems(std::wstring path); 90 | bool IsRootForAccessibleItems(std::string path); 91 | bool IsRootForAccessibleItems(std::wstring path); 92 | // 'checkIfContainsFutureAccessItems' for listing purposes not real access, 'driveName' like C: 93 | bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessItems); 94 | bool CheckDriveAccess(std::wstring driveName, bool checkIfContainsFutureAccessItems); 95 | bool GetDriveFreeSpace(PathUWP path, int64_t& space); 96 | 97 | // Log helpers 98 | std::string GetLogFile(); 99 | bool SaveLogs(); // With picker 100 | void CleanupLogs(); 101 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StoragePath.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Based on 'Path' from PPSSPP 3 | // For updates check: https://github.com/basharast/UWP2Win32 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "StoragePath.h" 10 | #include "StorageLog.h" 11 | #include "StorageExtensions.h" 12 | 13 | PathUWP::PathUWP(const std::string& str) { 14 | Init(str); 15 | } 16 | 17 | PathUWP::PathUWP(const std::wstring& str) { 18 | type_ = PathTypeUWP::NATIVE; 19 | Init(convert(str)); 20 | } 21 | 22 | void PathUWP::Init(const std::string& str) { 23 | if (str.empty()) { 24 | type_ = PathTypeUWP::UNDEFINED; 25 | path_.clear(); 26 | } 27 | else if (starts_with(str, "http://") || starts_with(str, "https://")) { 28 | type_ = PathTypeUWP::HTTP; 29 | path_ = str; 30 | } 31 | else { 32 | type_ = PathTypeUWP::NATIVE; 33 | path_ = str; 34 | } 35 | 36 | replace(path_, "??\\", ""); 37 | replace(path_, "\\??\\", ""); 38 | replace(path_, "\\\\?\\", ""); 39 | replace(path_, "?\\", ""); 40 | 41 | // Flip all the slashes around. We flip them back on ToWString(). 42 | for (size_t i = 0; i < path_.size(); i++) { 43 | if (path_[i] == '\\') { 44 | path_[i] = '/'; 45 | } 46 | } 47 | 48 | // Don't pop_back if it's just "/". 49 | if (type_ == PathTypeUWP::NATIVE && path_.size() > 1 && path_.back() == '/') { 50 | path_.pop_back(); 51 | } 52 | } 53 | 54 | // We always use forward slashes internally, we convert to backslash only when 55 | // converted to a wstring. 56 | PathUWP PathUWP::operator /(const std::string& subdir) const { 57 | // Direct string manipulation. 58 | 59 | if (subdir.empty()) { 60 | return PathUWP(path_); 61 | } 62 | std::string fullPath = path_; 63 | if (subdir.front() != '/' && (fullPath.empty() || fullPath.back() != '/')) { 64 | fullPath += "/"; 65 | } 66 | fullPath += subdir; 67 | // Prevent adding extra slashes. 68 | if (fullPath.back() == '/') { 69 | fullPath.pop_back(); 70 | } 71 | return PathUWP(fullPath); 72 | } 73 | 74 | void PathUWP::operator /=(const std::string& subdir) { 75 | *this = *this / subdir; 76 | } 77 | 78 | PathUWP PathUWP::WithExtraExtension(const std::string& ext) const { 79 | return PathUWP(path_ + ext); 80 | } 81 | 82 | PathUWP PathUWP::WithReplacedExtension(const std::string& oldExtension, const std::string& newExtension) const { 83 | if (ends_with(path_, oldExtension)) { 84 | std::string newPath = path_.substr(0, path_.size() - oldExtension.size()); 85 | return PathUWP(newPath + newExtension); 86 | } 87 | else { 88 | return PathUWP(*this); 89 | } 90 | } 91 | 92 | PathUWP PathUWP::WithReplacedExtension(const std::string& newExtension) const { 93 | if (path_.empty()) { 94 | return PathUWP(*this); 95 | } 96 | std::string extension = GetFileExtension(); 97 | std::string newPath = path_.substr(0, path_.size() - extension.size()) + newExtension; 98 | return PathUWP(newPath); 99 | } 100 | 101 | std::string PathUWP::GetFilename() const { 102 | size_t pos = path_.rfind('/'); 103 | if (pos != std::string::npos) { 104 | return path_.substr(pos + 1); 105 | } 106 | return path_; 107 | } 108 | 109 | static std::string GetExtFromString(const std::string& str) { 110 | size_t pos = str.rfind("."); 111 | if (pos == std::string::npos) { 112 | return ""; 113 | } 114 | size_t slash_pos = str.rfind("/"); 115 | if (slash_pos != std::string::npos && slash_pos > pos) { 116 | // Don't want to detect "df/file" from "/as.df/file" 117 | return ""; 118 | } 119 | std::string ext = str.substr(pos); 120 | tolower(ext); 121 | 122 | return ext; 123 | } 124 | 125 | std::string PathUWP::GetFileExtension() const { 126 | return GetExtFromString(path_); 127 | } 128 | 129 | std::string PathUWP::GetDirectory() const { 130 | size_t pos = path_.rfind('/'); 131 | if (type_ == PathTypeUWP::HTTP) { 132 | // Things are a bit different for HTTP, because we probably ended with /. 133 | if (pos + 1 == path_.size()) { 134 | pos = path_.rfind('/', pos - 1); 135 | if (pos != path_.npos && pos > 8) { 136 | return path_.substr(0, pos + 1); 137 | } 138 | } 139 | } 140 | 141 | if (pos != std::string::npos) { 142 | if (pos == 0) { 143 | return "/"; // We're at the root. 144 | } 145 | return path_.substr(0, pos); 146 | } 147 | else if (path_.size() == 2 && path_[1] == ':') { 148 | // Windows fake-root. 149 | return "/"; 150 | } 151 | else { 152 | // There could be a ':', too. Unlike the slash, let's include that 153 | // in the returned directory. 154 | size_t c_pos = path_.rfind(':'); 155 | if (c_pos != std::string::npos) { 156 | return path_.substr(0, c_pos + 1); 157 | } 158 | } 159 | // No directory components, we're a relative path. 160 | return path_; 161 | } 162 | 163 | bool PathUWP::FilePathContainsNoCase(const std::string& needle) const { 164 | std::string haystack; 165 | 166 | haystack = path_; 167 | auto pred = [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }; 168 | auto found = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), pred); 169 | return found != haystack.end(); 170 | } 171 | 172 | bool PathUWP::StartsWith(const PathUWP& other) const { 173 | if (type_ != other.type_) { 174 | // Bad 175 | return false; 176 | } 177 | return starts_with(path_, other.path_); 178 | } 179 | 180 | const std::string& PathUWP::ToString() const { 181 | return path_; 182 | } 183 | 184 | std::wstring PathUWP::ToWString() const { 185 | std::wstring w = convertToWString(path_); 186 | for (size_t i = 0; i < w.size(); i++) { 187 | if (w[i] == '/') { 188 | w[i] = '\\'; 189 | } 190 | } 191 | return w; 192 | } 193 | 194 | std::string PathUWP::ToVisualString() const { 195 | if (type_ == PathTypeUWP::NATIVE) { 196 | return replace2(path_, "/", "\\"); 197 | } 198 | else { 199 | return path_; 200 | } 201 | } 202 | 203 | bool PathUWP::CanNavigateUp() const { 204 | if (path_ == "/" || path_.empty()) { 205 | return false; 206 | } 207 | if (type_ == PathTypeUWP::HTTP) { 208 | size_t rootSlash = path_.find_first_of('/', strlen("https://")); 209 | if (rootSlash == path_.npos || path_.size() < rootSlash + 1) { 210 | // This means, "http://server" or "http://server/". Can't go up. 211 | return false; 212 | } 213 | } 214 | return true; 215 | } 216 | 217 | PathUWP PathUWP::NavigateUp() const { 218 | std::string dir = GetDirectory(); 219 | return PathUWP(dir); 220 | } 221 | 222 | PathUWP PathUWP::GetRootVolume() const { 223 | if (!IsAbsolute()) { 224 | // Can't do anything 225 | return PathUWP(path_); 226 | } 227 | 228 | if (path_[1] == ':') { 229 | // Windows path with drive letter 230 | std::string path = path_.substr(0, 2); 231 | return PathUWP(path); 232 | } 233 | // Support UNC and device paths. 234 | if (path_[0] == '/' && path_[1] == '/') { 235 | size_t next = 2; 236 | if ((path_[2] == '.' || path_[2] == '?') && path_[3] == '/') { 237 | // Device path, or "\\.\UNC" path, skip the dot and consider the device the root. 238 | next = 4; 239 | } 240 | 241 | size_t len = path_.find_first_of('/', next); 242 | return PathUWP(path_.substr(0, len)); 243 | } 244 | return PathUWP("/"); 245 | } 246 | 247 | bool PathUWP::IsAbsolute() const { 248 | if (path_.empty()) 249 | return true; 250 | else if (path_.front() == '/') 251 | return true; 252 | else if (path_.size() > 3 && path_[1] == ':') 253 | return true; // Windows path with drive letter 254 | else 255 | return false; 256 | } 257 | 258 | bool PathUWP::ComputePathTo(const PathUWP& other, std::string& path) const { 259 | if (other == *this) { 260 | path.clear(); 261 | return true; 262 | } 263 | 264 | if (!other.StartsWith(*this)) { 265 | // Can't do this. Should return an error. 266 | return false; 267 | } 268 | 269 | if (*this == other) { 270 | // Equal, the path is empty. 271 | path.clear(); 272 | return true; 273 | } 274 | 275 | if (path_ == "/") { 276 | path = other.path_.substr(1); 277 | return true; 278 | } 279 | else { 280 | path = other.path_.substr(path_.size() + 1); 281 | return true; 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StoragePath.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Based on 'Path' from PPSSPP 3 | // For updates check: https://github.com/basharast/UWP2Win32 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #define HOST_IS_CASE_SENSITIVE 0 10 | 11 | enum class PathTypeUWP { 12 | UNDEFINED = 0, 13 | NATIVE = 1, // Can be relative. 14 | CONTENT_URI = 2, // Android only. Can only be absolute! 15 | HTTP = 3, // http://, https:// 16 | }; 17 | 18 | // Windows paths are always stored with '/' slashes in a Path. 19 | // On .ToWString(), they are flipped back to '\'. 20 | 21 | class PathUWP { 22 | private: 23 | void Init(const std::string& str); 24 | 25 | public: 26 | PathUWP() : type_(PathTypeUWP::UNDEFINED) {} 27 | explicit PathUWP(const std::string& str); 28 | 29 | explicit PathUWP(const std::wstring& str); 30 | 31 | PathTypeUWP Type() const { 32 | return type_; 33 | } 34 | 35 | bool Valid() const { return !path_.empty(); } 36 | bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash. 37 | 38 | // Some std::string emulation for simplicity. 39 | bool empty() const { return !Valid(); } 40 | void clear() { 41 | type_ = PathTypeUWP::UNDEFINED; 42 | path_.clear(); 43 | } 44 | size_t size() const { 45 | return path_.size(); 46 | } 47 | 48 | // WARNING: Potentially unsafe usage, if it's not NATIVE. 49 | const char* c_str() const { 50 | return path_.c_str(); 51 | } 52 | 53 | bool IsAbsolute() const; 54 | 55 | // Returns a path extended with a subdirectory. 56 | PathUWP operator /(const std::string& subdir) const; 57 | 58 | // Navigates down into a subdir. 59 | void operator /=(const std::string& subdir); 60 | 61 | // File extension manipulation. 62 | PathUWP WithExtraExtension(const std::string& ext) const; 63 | PathUWP WithReplacedExtension(const std::string& oldExtension, const std::string& newExtension) const; 64 | PathUWP WithReplacedExtension(const std::string& newExtension) const; 65 | 66 | // Removes the last component. 67 | std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension. 68 | std::string GetFileExtension() const; // Always lowercase return. Includes the dot. 69 | std::string GetDirectory() const; 70 | 71 | const std::string& ToString() const; 72 | 73 | std::wstring ToWString() const; 74 | 75 | std::string ToVisualString() const; 76 | 77 | bool CanNavigateUp() const; 78 | PathUWP NavigateUp() const; 79 | 80 | // Navigates as far up as possible from this path. If not possible to navigate upwards, returns the same path. 81 | // Not actually always the root of the volume, especially on systems like Mac and Linux where things are often mounted. 82 | // For Android directory trees, navigates to the root of the tree. 83 | PathUWP GetRootVolume() const; 84 | 85 | bool ComputePathTo(const PathUWP& other, std::string& path) const; 86 | 87 | bool operator ==(const PathUWP& other) const { 88 | return path_ == other.path_ && type_ == other.type_; 89 | } 90 | bool operator !=(const PathUWP& other) const { 91 | return path_ != other.path_ || type_ != other.type_; 92 | } 93 | 94 | bool FilePathContainsNoCase(const std::string& needle) const; 95 | 96 | bool StartsWith(const PathUWP& other) const; 97 | 98 | bool operator <(const PathUWP& other) const { 99 | return path_ < other.path_; 100 | } 101 | bool operator >(const PathUWP& other) const { 102 | return path_ > other.path_; 103 | } 104 | 105 | private: 106 | // The internal representation is currently always the plain string. 107 | // For CPU efficiency we could keep an AndroidStorageContentURI too, 108 | // but I don't think the encode/decode cost is significant. We simply create 109 | // those for processing instead. 110 | std::string path_; 111 | 112 | PathTypeUWP type_; 113 | }; 114 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StoragePickers.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #include "pch.h" 7 | 8 | #include "StorageLog.h" 9 | #include "StorageExtensions.h" 10 | #include "StorageAsync.h" 11 | #include "StorageAccess.h" 12 | 13 | using namespace Platform; 14 | using namespace Windows::Storage; 15 | using namespace Windows::Foundation; 16 | 17 | extern void AddItemToFutureList(IStorageItem^ folder); 18 | 19 | // Call folder picker (the selected folder will be added to future list) 20 | concurrency::task PickSingleFolder() 21 | { 22 | auto folderPicker = ref new Windows::Storage::Pickers::FolderPicker(); 23 | folderPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; 24 | folderPicker->FileTypeFilter->Append("*"); 25 | 26 | return concurrency::create_task(folderPicker->PickSingleFolderAsync()).then([](StorageFolder^ folder) { 27 | auto path = ref new Platform::String(); 28 | if (folder != nullptr) 29 | { 30 | AddItemToFutureList(folder); 31 | path = folder->Path; 32 | } 33 | return path; 34 | }); 35 | } 36 | 37 | // Call file picker (the selected file will be added to future list) 38 | concurrency::task PickSingleFile(std::vector exts) 39 | { 40 | auto filePicker = ref new Windows::Storage::Pickers::FileOpenPicker(); 41 | filePicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; 42 | filePicker->ViewMode = Pickers::PickerViewMode::List; 43 | 44 | if (exts.size() > 0) { 45 | for each (auto ext in exts) { 46 | filePicker->FileTypeFilter->Append(convert(ext)); 47 | } 48 | } 49 | else 50 | { 51 | filePicker->FileTypeFilter->Append("*"); 52 | } 53 | return concurrency::create_task(filePicker->PickSingleFileAsync()).then([](StorageFile^ file) { 54 | auto path = ref new Platform::String(); 55 | if (file != nullptr) 56 | { 57 | AddItemToFutureList(file); 58 | path = file->Path; 59 | } 60 | return path; 61 | }); 62 | } 63 | 64 | 65 | concurrency::task ChooseFile(std::vector exts) { 66 | return PickSingleFile(exts).then([](Platform::String^ filePath) { 67 | return convert(filePath); 68 | }); 69 | } 70 | 71 | concurrency::task ChooseFolder() { 72 | return PickSingleFolder().then([](Platform::String^ folderPath) { 73 | return convert(folderPath); 74 | }); 75 | 76 | } 77 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/StoragePickers.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | concurrency::task ChooseFolder(); 14 | concurrency::task ChooseFile(std::vector exts); 15 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UIHelpers.cpp: -------------------------------------------------------------------------------- 1 | // UWP UI HELPER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "UIHelpers.h" 8 | 9 | using namespace Windows::System; 10 | using namespace Windows::Foundation; 11 | using namespace Windows::UI::Core; 12 | using namespace Windows::UI::ViewManagement; 13 | using namespace Windows::ApplicationModel::Core; 14 | using namespace Windows::Data::Xml::Dom; 15 | using namespace Windows::UI::Notifications; 16 | 17 | #pragma region Input Keyboard 18 | void ShowInputKeyboard() { 19 | InputPane::GetForCurrentView()->TryShow(); 20 | } 21 | 22 | void HideInputKeyboard() { 23 | InputPane::GetForCurrentView()->TryHide(); 24 | } 25 | #pragma endregion 26 | 27 | #pragma region Keys Status 28 | bool IsCapsLockOn() { 29 | auto capsLockState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::CapitalLock); 30 | return (capsLockState == CoreVirtualKeyStates::Locked); 31 | } 32 | bool IsShiftOnHold() { 33 | auto shiftState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Shift); 34 | return (shiftState == CoreVirtualKeyStates::Down); 35 | } 36 | bool IsCtrlOnHold() { 37 | auto ctrlState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Control); 38 | return (ctrlState == CoreVirtualKeyStates::Down); 39 | } 40 | #pragma endregion 41 | 42 | #pragma region Notifications 43 | void ShowToastNotification(std::string title, std::string message) { 44 | ToastNotifier^ toastNotifier = ToastNotificationManager::CreateToastNotifier(); 45 | XmlDocument^ toastXml = ToastNotificationManager::GetTemplateContent(ToastTemplateType::ToastText02); 46 | XmlNodeList^ toastNodeList = toastXml->GetElementsByTagName("text"); 47 | toastNodeList->Item(0)->AppendChild(toastXml->CreateTextNode(convert(title))); 48 | toastNodeList->Item(1)->AppendChild(toastXml->CreateTextNode(convert(message))); 49 | IXmlNode^ toastNode = toastXml->SelectSingleNode("/toast"); 50 | XmlElement^ audio = toastXml->CreateElement("audio"); 51 | audio->SetAttribute("src", "ms-winsoundevent:Notification.SMS"); 52 | ToastNotification^ toast = ref new ToastNotification(toastXml); 53 | toastNotifier->Show(toast); 54 | } 55 | #pragma endregion 56 | 57 | 58 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UIHelpers.h: -------------------------------------------------------------------------------- 1 | // UWP UI HELPER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "StorageExtensions.h" 8 | 9 | // Input Handler 10 | void ShowInputKeyboard(); 11 | void HideInputKeyboard(); 12 | 13 | 14 | // Keys Status 15 | bool IsCapsLockOn(); 16 | bool IsShiftOnHold(); 17 | bool IsCtrlOnHold(); 18 | 19 | // Notifications 20 | void ShowToastNotification(std::string title, std::string message); 21 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWP2C.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // This is small bridge to invoke UWP Storage manager 8 | 9 | #include "UWP2C.h" 10 | #include "StorageManager.h" 11 | #include "StorageExtensions.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode) { 17 | std::string fn = convert(path); 18 | return (void*)CreateFileUWP(fn, accessMode, shareMode, openMode); 19 | } 20 | 21 | int GetFileAttributesUWP(const void* name, void* lpFileInformation) { 22 | size_t size = sizeof(WIN32_FILE_ATTRIBUTE_DATA); 23 | WIN32_FILE_ATTRIBUTE_DATA* file_attributes = (WIN32_FILE_ATTRIBUTE_DATA*)(malloc(size)); 24 | 25 | std::string fn = convert((const char*)name); 26 | HANDLE handle = CreateFileUWP(fn); 27 | 28 | FILETIME createTime{}; 29 | FILETIME changeTime{}; 30 | 31 | DWORD fileSizeHigh = 0; 32 | DWORD fileSizeLow = 0; 33 | DWORD fileAttributes = 32; 34 | 35 | if (handle != INVALID_HANDLE_VALUE) { 36 | size_t size = sizeof(FILE_BASIC_INFO); 37 | FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size)); 38 | if (information) { 39 | if (FALSE != GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) { 40 | createTime.dwHighDateTime = information->CreationTime.HighPart; 41 | createTime.dwLowDateTime = information->CreationTime.LowPart; 42 | changeTime.dwHighDateTime = information->ChangeTime.HighPart; 43 | changeTime.dwLowDateTime = information->ChangeTime.LowPart; 44 | fileAttributes = information->FileAttributes; 45 | } 46 | } 47 | LARGE_INTEGER fsize{ 0 }; 48 | if (FALSE == GetFileSizeEx(handle, &fsize)) { 49 | LARGE_INTEGER end_offset; 50 | const LARGE_INTEGER zero{}; 51 | if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) { 52 | CloseHandle(handle); 53 | } 54 | else { 55 | fileSizeHigh = (DWORD)end_offset.HighPart; 56 | fileSizeLow = (DWORD)end_offset.LowPart; 57 | SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN); 58 | CloseHandle(handle); 59 | } 60 | } 61 | else { 62 | fileSizeHigh = (DWORD)fsize.HighPart; 63 | fileSizeLow = (DWORD)fsize.LowPart; 64 | 65 | CloseHandle(handle); 66 | } 67 | } 68 | 69 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftCreationTime = createTime; 70 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastAccessTime = changeTime; 71 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastWriteTime = changeTime; 72 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeHigh = fileSizeHigh; 73 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeLow = fileSizeLow; 74 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->dwFileAttributes = fileAttributes; 75 | 76 | return 1; 77 | } 78 | 79 | int DeleteFileUWP(const void* name) { 80 | std::string fn = convert((const char*)name); 81 | bool state = DeleteUWP(fn); 82 | 83 | return state ? 1 : 0; 84 | } 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWP2C.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // This is small bridge to invoke UWP Storage manager 8 | 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode); 16 | int GetFileAttributesUWP(const void* name, void* lpFileInformation); 17 | int DeleteFileUWP(const void* name); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.34909.67 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UWPHelpersCX", "UWPHelpersCX\UWPHelpersCX.vcxproj", "{50DDBD34-2BCF-40E3-B0FE-A39090800249}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM.Build.0 = Debug|ARM 22 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x64.ActiveCfg = Debug|x64 27 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x64.Build.0 = Debug|x64 28 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x64.Deploy.0 = Debug|x64 29 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x86.ActiveCfg = Debug|Win32 30 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x86.Build.0 = Debug|Win32 31 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Debug|x86.Deploy.0 = Debug|Win32 32 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM.ActiveCfg = Release|ARM 33 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM.Build.0 = Release|ARM 34 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM.Deploy.0 = Release|ARM 35 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM64.Build.0 = Release|ARM64 37 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x64.ActiveCfg = Release|x64 39 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x64.Build.0 = Release|x64 40 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x64.Deploy.0 = Release|x64 41 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x86.ActiveCfg = Release|Win32 42 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x86.Build.0 = Release|Win32 43 | {50DDBD34-2BCF-40E3-B0FE-A39090800249}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {277463BA-CFAF-4ADE-851D-5CFE2910AED5} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/App.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "App.h" 3 | 4 | #include 5 | 6 | using namespace UWPHelpersCX; 7 | 8 | using namespace concurrency; 9 | using namespace Windows::ApplicationModel; 10 | using namespace Windows::ApplicationModel::Core; 11 | using namespace Windows::ApplicationModel::Activation; 12 | using namespace Windows::UI::Core; 13 | using namespace Windows::UI::Input; 14 | using namespace Windows::System; 15 | using namespace Windows::Foundation; 16 | using namespace Windows::Graphics::Display; 17 | 18 | // The main function is only used to initialize our IFrameworkView class. 19 | [Platform::MTAThread] 20 | int main(Platform::Array^) 21 | { 22 | auto direct3DApplicationSource = ref new Direct3DApplicationSource(); 23 | CoreApplication::Run(direct3DApplicationSource); 24 | return 0; 25 | } 26 | 27 | IFrameworkView^ Direct3DApplicationSource::CreateView() 28 | { 29 | return ref new App(); 30 | } 31 | 32 | App::App() : 33 | m_windowClosed(false), 34 | m_windowVisible(true) 35 | { 36 | } 37 | 38 | // The first method called when the IFrameworkView is being created. 39 | void App::Initialize(CoreApplicationView^ applicationView) 40 | { 41 | // Register event handlers for app lifecycle. This example includes Activated, so that we 42 | // can make the CoreWindow active and start rendering on the window. 43 | applicationView->Activated += 44 | ref new TypedEventHandler(this, &App::OnActivated); 45 | 46 | CoreApplication::Suspending += 47 | ref new EventHandler(this, &App::OnSuspending); 48 | 49 | CoreApplication::Resuming += 50 | ref new EventHandler(this, &App::OnResuming); 51 | 52 | // At this point we have access to the device. 53 | // We can create the device-dependent resources. 54 | m_deviceResources = std::make_shared(); 55 | } 56 | 57 | // Called when the CoreWindow object is created (or re-created). 58 | void App::SetWindow(CoreWindow^ window) 59 | { 60 | window->SizeChanged += 61 | ref new TypedEventHandler(this, &App::OnWindowSizeChanged); 62 | 63 | window->VisibilityChanged += 64 | ref new TypedEventHandler(this, &App::OnVisibilityChanged); 65 | 66 | window->Closed += 67 | ref new TypedEventHandler(this, &App::OnWindowClosed); 68 | 69 | DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); 70 | 71 | currentDisplayInformation->DpiChanged += 72 | ref new TypedEventHandler(this, &App::OnDpiChanged); 73 | 74 | currentDisplayInformation->OrientationChanged += 75 | ref new TypedEventHandler(this, &App::OnOrientationChanged); 76 | 77 | DisplayInformation::DisplayContentsInvalidated += 78 | ref new TypedEventHandler(this, &App::OnDisplayContentsInvalidated); 79 | 80 | m_deviceResources->SetWindow(window); 81 | } 82 | 83 | // Initializes scene resources, or loads a previously saved app state. 84 | void App::Load(Platform::String^ entryPoint) 85 | { 86 | if (m_main == nullptr) 87 | { 88 | m_main = std::unique_ptr(new UWPHelpersCXMain(m_deviceResources)); 89 | } 90 | } 91 | 92 | // This method is called after the window becomes active. 93 | void App::Run() 94 | { 95 | while (!m_windowClosed) 96 | { 97 | if (m_windowVisible) 98 | { 99 | CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); 100 | 101 | m_main->Update(); 102 | 103 | if (m_main->Render()) 104 | { 105 | m_deviceResources->Present(); 106 | } 107 | } 108 | else 109 | { 110 | CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); 111 | } 112 | } 113 | } 114 | 115 | // Required for IFrameworkView. 116 | // Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView 117 | // class is torn down while the app is in the foreground. 118 | void App::Uninitialize() 119 | { 120 | } 121 | 122 | // Application lifecycle event handlers. 123 | 124 | void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) 125 | { 126 | // Run() won't start until the CoreWindow is activated. 127 | CoreWindow::GetForCurrentThread()->Activate(); 128 | } 129 | 130 | void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) 131 | { 132 | // Save app state asynchronously after requesting a deferral. Holding a deferral 133 | // indicates that the application is busy performing suspending operations. Be 134 | // aware that a deferral may not be held indefinitely. After about five seconds, 135 | // the app will be forced to exit. 136 | SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); 137 | 138 | create_task([this, deferral]() 139 | { 140 | m_deviceResources->Trim(); 141 | 142 | // Insert your code here. 143 | 144 | deferral->Complete(); 145 | }); 146 | } 147 | 148 | void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) 149 | { 150 | // Restore any data or state that was unloaded on suspend. By default, data 151 | // and state are persisted when resuming from suspend. Note that this event 152 | // does not occur if the app was previously terminated. 153 | 154 | // Insert your code here. 155 | } 156 | 157 | // Window event handlers. 158 | 159 | void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) 160 | { 161 | m_deviceResources->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height)); 162 | m_main->CreateWindowSizeDependentResources(); 163 | } 164 | 165 | void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) 166 | { 167 | m_windowVisible = args->Visible; 168 | } 169 | 170 | void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) 171 | { 172 | m_windowClosed = true; 173 | } 174 | 175 | // DisplayInformation event handlers. 176 | 177 | void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) 178 | { 179 | // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app 180 | // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources, 181 | // you should always retrieve it using the GetDpi method. 182 | // See DeviceResources.cpp for more details. 183 | m_deviceResources->SetDpi(sender->LogicalDpi); 184 | m_main->CreateWindowSizeDependentResources(); 185 | } 186 | 187 | void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) 188 | { 189 | m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation); 190 | m_main->CreateWindowSizeDependentResources(); 191 | } 192 | 193 | void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) 194 | { 195 | m_deviceResources->ValidateDevice(); 196 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pch.h" 4 | #include "Common\DeviceResources.h" 5 | #include "UWPHelpersCXMain.h" 6 | 7 | namespace UWPHelpersCX 8 | { 9 | // Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events. 10 | ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView 11 | { 12 | public: 13 | App(); 14 | 15 | // IFrameworkView Methods. 16 | virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView); 17 | virtual void SetWindow(Windows::UI::Core::CoreWindow^ window); 18 | virtual void Load(Platform::String^ entryPoint); 19 | virtual void Run(); 20 | virtual void Uninitialize(); 21 | 22 | protected: 23 | // Application lifecycle event handlers. 24 | void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); 25 | void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); 26 | void OnResuming(Platform::Object^ sender, Platform::Object^ args); 27 | 28 | // Window event handlers. 29 | void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args); 30 | void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); 31 | void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); 32 | 33 | // DisplayInformation event handlers. 34 | void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); 35 | void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); 36 | void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); 37 | 38 | private: 39 | std::shared_ptr m_deviceResources; 40 | std::unique_ptr m_main; 41 | bool m_windowClosed; 42 | bool m_windowVisible; 43 | }; 44 | } 45 | 46 | ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource 47 | { 48 | public: 49 | virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView(); 50 | }; 51 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/StoreLogo.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (CX)/UWPHelpersCX/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Common/DeviceResources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DX 4 | { 5 | // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. 6 | interface IDeviceNotify 7 | { 8 | virtual void OnDeviceLost() = 0; 9 | virtual void OnDeviceRestored() = 0; 10 | }; 11 | 12 | // Controls all the DirectX device resources. 13 | class DeviceResources 14 | { 15 | public: 16 | DeviceResources(); 17 | void SetWindow(Windows::UI::Core::CoreWindow^ window); 18 | void SetLogicalSize(Windows::Foundation::Size logicalSize); 19 | void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation); 20 | void SetDpi(float dpi); 21 | void ValidateDevice(); 22 | void HandleDeviceLost(); 23 | void RegisterDeviceNotify(IDeviceNotify* deviceNotify); 24 | void Trim(); 25 | void Present(); 26 | 27 | // The size of the render target, in pixels. 28 | Windows::Foundation::Size GetOutputSize() const { return m_outputSize; } 29 | 30 | // The size of the render target, in dips. 31 | Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } 32 | float GetDpi() const { return m_effectiveDpi; } 33 | 34 | // D3D Accessors. 35 | ID3D11Device3* GetD3DDevice() const { return m_d3dDevice.Get(); } 36 | ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); } 37 | IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } 38 | D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } 39 | ID3D11RenderTargetView1* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); } 40 | ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } 41 | D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } 42 | DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } 43 | 44 | // D2D Accessors. 45 | ID2D1Factory3* GetD2DFactory() const { return m_d2dFactory.Get(); } 46 | ID2D1Device2* GetD2DDevice() const { return m_d2dDevice.Get(); } 47 | ID2D1DeviceContext2* GetD2DDeviceContext() const { return m_d2dContext.Get(); } 48 | ID2D1Bitmap1* GetD2DTargetBitmap() const { return m_d2dTargetBitmap.Get(); } 49 | IDWriteFactory3* GetDWriteFactory() const { return m_dwriteFactory.Get(); } 50 | IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); } 51 | D2D1::Matrix3x2F GetOrientationTransform2D() const { return m_orientationTransform2D; } 52 | 53 | private: 54 | void CreateDeviceIndependentResources(); 55 | void CreateDeviceResources(); 56 | void CreateWindowSizeDependentResources(); 57 | void UpdateRenderTargetSize(); 58 | DXGI_MODE_ROTATION ComputeDisplayRotation(); 59 | 60 | // Direct3D objects. 61 | Microsoft::WRL::ComPtr m_d3dDevice; 62 | Microsoft::WRL::ComPtr m_d3dContext; 63 | Microsoft::WRL::ComPtr m_swapChain; 64 | 65 | // Direct3D rendering objects. Required for 3D. 66 | Microsoft::WRL::ComPtr m_d3dRenderTargetView; 67 | Microsoft::WRL::ComPtr m_d3dDepthStencilView; 68 | D3D11_VIEWPORT m_screenViewport; 69 | 70 | // Direct2D drawing components. 71 | Microsoft::WRL::ComPtr m_d2dFactory; 72 | Microsoft::WRL::ComPtr m_d2dDevice; 73 | Microsoft::WRL::ComPtr m_d2dContext; 74 | Microsoft::WRL::ComPtr m_d2dTargetBitmap; 75 | 76 | // DirectWrite drawing components. 77 | Microsoft::WRL::ComPtr m_dwriteFactory; 78 | Microsoft::WRL::ComPtr m_wicFactory; 79 | 80 | // Cached reference to the Window. 81 | Platform::Agile m_window; 82 | 83 | // Cached device properties. 84 | D3D_FEATURE_LEVEL m_d3dFeatureLevel; 85 | Windows::Foundation::Size m_d3dRenderTargetSize; 86 | Windows::Foundation::Size m_outputSize; 87 | Windows::Foundation::Size m_logicalSize; 88 | Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; 89 | Windows::Graphics::Display::DisplayOrientations m_currentOrientation; 90 | float m_dpi; 91 | 92 | // This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not. 93 | float m_effectiveDpi; 94 | 95 | // Transforms used for display orientation. 96 | D2D1::Matrix3x2F m_orientationTransform2D; 97 | DirectX::XMFLOAT4X4 m_orientationTransform3D; 98 | 99 | // The IDeviceNotify can be held directly as it owns the DeviceResources. 100 | IDeviceNotify* m_deviceNotify; 101 | }; 102 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Common/DirectXHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include // For create_task 4 | 5 | namespace DX 6 | { 7 | inline void ThrowIfFailed(HRESULT hr) 8 | { 9 | if (FAILED(hr)) 10 | { 11 | // Set a breakpoint on this line to catch Win32 API errors. 12 | throw Platform::Exception::CreateException(hr); 13 | } 14 | } 15 | 16 | // Function that reads from a binary file asynchronously. 17 | inline Concurrency::task> ReadDataAsync(const std::wstring& filename) 18 | { 19 | using namespace Windows::Storage; 20 | using namespace Concurrency; 21 | 22 | auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation; 23 | 24 | return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([] (StorageFile^ file) 25 | { 26 | return FileIO::ReadBufferAsync(file); 27 | }).then([] (Streams::IBuffer^ fileBuffer) -> std::vector 28 | { 29 | std::vector returnBuffer; 30 | returnBuffer.resize(fileBuffer->Length); 31 | Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference(returnBuffer.data(), fileBuffer->Length)); 32 | return returnBuffer; 33 | }); 34 | } 35 | 36 | // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. 37 | inline float ConvertDipsToPixels(float dips, float dpi) 38 | { 39 | static const float dipsPerInch = 96.0f; 40 | return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. 41 | } 42 | 43 | #if defined(_DEBUG) 44 | // Check for SDK Layer support. 45 | inline bool SdkLayersAvailable() 46 | { 47 | HRESULT hr = D3D11CreateDevice( 48 | nullptr, 49 | D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. 50 | 0, 51 | D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. 52 | nullptr, // Any feature level will do. 53 | 0, 54 | D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Microsoft Store apps. 55 | nullptr, // No need to keep the D3D device reference. 56 | nullptr, // No need to know the feature level. 57 | nullptr // No need to keep the D3D device context reference. 58 | ); 59 | 60 | return SUCCEEDED(hr); 61 | } 62 | #endif 63 | } 64 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Common/StepTimer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace DX 6 | { 7 | // Helper class for animation and simulation timing. 8 | class StepTimer 9 | { 10 | public: 11 | StepTimer() : 12 | m_elapsedTicks(0), 13 | m_totalTicks(0), 14 | m_leftOverTicks(0), 15 | m_frameCount(0), 16 | m_framesPerSecond(0), 17 | m_framesThisSecond(0), 18 | m_qpcSecondCounter(0), 19 | m_isFixedTimeStep(false), 20 | m_targetElapsedTicks(TicksPerSecond / 60) 21 | { 22 | if (!QueryPerformanceFrequency(&m_qpcFrequency)) 23 | { 24 | throw ref new Platform::FailureException(); 25 | } 26 | 27 | if (!QueryPerformanceCounter(&m_qpcLastTime)) 28 | { 29 | throw ref new Platform::FailureException(); 30 | } 31 | 32 | // Initialize max delta to 1/10 of a second. 33 | m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; 34 | } 35 | 36 | // Get elapsed time since the previous Update call. 37 | uint64 GetElapsedTicks() const { return m_elapsedTicks; } 38 | double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } 39 | 40 | // Get total time since the start of the program. 41 | uint64 GetTotalTicks() const { return m_totalTicks; } 42 | double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } 43 | 44 | // Get total number of updates since start of the program. 45 | uint32 GetFrameCount() const { return m_frameCount; } 46 | 47 | // Get the current framerate. 48 | uint32 GetFramesPerSecond() const { return m_framesPerSecond; } 49 | 50 | // Set whether to use fixed or variable timestep mode. 51 | void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } 52 | 53 | // Set how often to call Update when in fixed timestep mode. 54 | void SetTargetElapsedTicks(uint64 targetElapsed) { m_targetElapsedTicks = targetElapsed; } 55 | void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } 56 | 57 | // Integer format represents time using 10,000,000 ticks per second. 58 | static const uint64 TicksPerSecond = 10000000; 59 | 60 | static double TicksToSeconds(uint64 ticks) { return static_cast(ticks) / TicksPerSecond; } 61 | static uint64 SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } 62 | 63 | // After an intentional timing discontinuity (for instance a blocking IO operation) 64 | // call this to avoid having the fixed timestep logic attempt a set of catch-up 65 | // Update calls. 66 | 67 | void ResetElapsedTime() 68 | { 69 | if (!QueryPerformanceCounter(&m_qpcLastTime)) 70 | { 71 | throw ref new Platform::FailureException(); 72 | } 73 | 74 | m_leftOverTicks = 0; 75 | m_framesPerSecond = 0; 76 | m_framesThisSecond = 0; 77 | m_qpcSecondCounter = 0; 78 | } 79 | 80 | // Update timer state, calling the specified Update function the appropriate number of times. 81 | template 82 | void Tick(const TUpdate& update) 83 | { 84 | // Query the current time. 85 | LARGE_INTEGER currentTime; 86 | 87 | if (!QueryPerformanceCounter(¤tTime)) 88 | { 89 | throw ref new Platform::FailureException(); 90 | } 91 | 92 | uint64 timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; 93 | 94 | m_qpcLastTime = currentTime; 95 | m_qpcSecondCounter += timeDelta; 96 | 97 | // Clamp excessively large time deltas (e.g. after paused in the debugger). 98 | if (timeDelta > m_qpcMaxDelta) 99 | { 100 | timeDelta = m_qpcMaxDelta; 101 | } 102 | 103 | // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. 104 | timeDelta *= TicksPerSecond; 105 | timeDelta /= m_qpcFrequency.QuadPart; 106 | 107 | uint32 lastFrameCount = m_frameCount; 108 | 109 | if (m_isFixedTimeStep) 110 | { 111 | // Fixed timestep update logic 112 | 113 | // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp 114 | // the clock to exactly match the target value. This prevents tiny and irrelevant errors 115 | // from accumulating over time. Without this clamping, a game that requested a 60 fps 116 | // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually 117 | // accumulate enough tiny errors that it would drop a frame. It is better to just round 118 | // small deviations down to zero to leave things running smoothly. 119 | 120 | if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) 121 | { 122 | timeDelta = m_targetElapsedTicks; 123 | } 124 | 125 | m_leftOverTicks += timeDelta; 126 | 127 | while (m_leftOverTicks >= m_targetElapsedTicks) 128 | { 129 | m_elapsedTicks = m_targetElapsedTicks; 130 | m_totalTicks += m_targetElapsedTicks; 131 | m_leftOverTicks -= m_targetElapsedTicks; 132 | m_frameCount++; 133 | 134 | update(); 135 | } 136 | } 137 | else 138 | { 139 | // Variable timestep update logic. 140 | m_elapsedTicks = timeDelta; 141 | m_totalTicks += timeDelta; 142 | m_leftOverTicks = 0; 143 | m_frameCount++; 144 | 145 | update(); 146 | } 147 | 148 | // Track the current framerate. 149 | if (m_frameCount != lastFrameCount) 150 | { 151 | m_framesThisSecond++; 152 | } 153 | 154 | if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) 155 | { 156 | m_framesPerSecond = m_framesThisSecond; 157 | m_framesThisSecond = 0; 158 | m_qpcSecondCounter %= m_qpcFrequency.QuadPart; 159 | } 160 | } 161 | 162 | private: 163 | // Source timing data uses QPC units. 164 | LARGE_INTEGER m_qpcFrequency; 165 | LARGE_INTEGER m_qpcLastTime; 166 | uint64 m_qpcMaxDelta; 167 | 168 | // Derived timing data uses a canonical tick format. 169 | uint64 m_elapsedTicks; 170 | uint64 m_totalTicks; 171 | uint64 m_leftOverTicks; 172 | 173 | // Members for tracking the framerate. 174 | uint32 m_frameCount; 175 | uint32 m_framesPerSecond; 176 | uint32 m_framesThisSecond; 177 | uint64 m_qpcSecondCounter; 178 | 179 | // Members for configuring fixed timestep mode. 180 | bool m_isFixedTimeStep; 181 | uint64 m_targetElapsedTicks; 182 | }; 183 | } 184 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/Sample3DSceneRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "..\Common\DeviceResources.h" 4 | #include "ShaderStructures.h" 5 | #include "..\Common\StepTimer.h" 6 | 7 | namespace UWPHelpersCX 8 | { 9 | // This sample renderer instantiates a basic rendering pipeline. 10 | class Sample3DSceneRenderer 11 | { 12 | public: 13 | Sample3DSceneRenderer(const std::shared_ptr& deviceResources); 14 | void CreateDeviceDependentResources(); 15 | void CreateWindowSizeDependentResources(); 16 | void ReleaseDeviceDependentResources(); 17 | void Update(DX::StepTimer const& timer); 18 | void Render(); 19 | void StartTracking(); 20 | void TrackingUpdate(float positionX); 21 | void StopTracking(); 22 | bool IsTracking() { return m_tracking; } 23 | 24 | 25 | private: 26 | void Rotate(float radians); 27 | 28 | private: 29 | // Cached pointer to device resources. 30 | std::shared_ptr m_deviceResources; 31 | 32 | // Direct3D resources for cube geometry. 33 | Microsoft::WRL::ComPtr m_inputLayout; 34 | Microsoft::WRL::ComPtr m_vertexBuffer; 35 | Microsoft::WRL::ComPtr m_indexBuffer; 36 | Microsoft::WRL::ComPtr m_vertexShader; 37 | Microsoft::WRL::ComPtr m_pixelShader; 38 | Microsoft::WRL::ComPtr m_constantBuffer; 39 | 40 | // System resources for cube geometry. 41 | ModelViewProjectionConstantBuffer m_constantBufferData; 42 | uint32 m_indexCount; 43 | 44 | // Variables used with the rendering loop. 45 | bool m_loadingComplete; 46 | float m_degreesPerSecond; 47 | bool m_tracking; 48 | }; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/SampleFpsTextRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SampleFpsTextRenderer.h" 3 | 4 | #include "Common/DirectXHelper.h" 5 | 6 | using namespace UWPHelpersCX; 7 | using namespace Microsoft::WRL; 8 | 9 | // Initializes D2D resources used for text rendering. 10 | SampleFpsTextRenderer::SampleFpsTextRenderer(const std::shared_ptr& deviceResources) : 11 | m_text(L""), 12 | m_deviceResources(deviceResources) 13 | { 14 | ZeroMemory(&m_textMetrics, sizeof(DWRITE_TEXT_METRICS)); 15 | 16 | // Create device independent resources 17 | ComPtr textFormat; 18 | DX::ThrowIfFailed( 19 | m_deviceResources->GetDWriteFactory()->CreateTextFormat( 20 | L"Segoe UI", 21 | nullptr, 22 | DWRITE_FONT_WEIGHT_LIGHT, 23 | DWRITE_FONT_STYLE_NORMAL, 24 | DWRITE_FONT_STRETCH_NORMAL, 25 | 32.0f, 26 | L"en-US", 27 | &textFormat 28 | ) 29 | ); 30 | 31 | DX::ThrowIfFailed( 32 | textFormat.As(&m_textFormat) 33 | ); 34 | 35 | DX::ThrowIfFailed( 36 | m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR) 37 | ); 38 | 39 | DX::ThrowIfFailed( 40 | m_deviceResources->GetD2DFactory()->CreateDrawingStateBlock(&m_stateBlock) 41 | ); 42 | 43 | CreateDeviceDependentResources(); 44 | } 45 | 46 | // Updates the text to be displayed. 47 | void SampleFpsTextRenderer::Update(DX::StepTimer const& timer) 48 | { 49 | // Update display text. 50 | uint32 fps = timer.GetFramesPerSecond(); 51 | 52 | m_text = (fps > 0) ? std::to_wstring(fps) + L" FPS" : L" - FPS"; 53 | 54 | ComPtr textLayout; 55 | DX::ThrowIfFailed( 56 | m_deviceResources->GetDWriteFactory()->CreateTextLayout( 57 | m_text.c_str(), 58 | (uint32) m_text.length(), 59 | m_textFormat.Get(), 60 | 240.0f, // Max width of the input text. 61 | 50.0f, // Max height of the input text. 62 | &textLayout 63 | ) 64 | ); 65 | 66 | DX::ThrowIfFailed( 67 | textLayout.As(&m_textLayout) 68 | ); 69 | 70 | DX::ThrowIfFailed( 71 | m_textLayout->GetMetrics(&m_textMetrics) 72 | ); 73 | } 74 | 75 | // Renders a frame to the screen. 76 | void SampleFpsTextRenderer::Render() 77 | { 78 | ID2D1DeviceContext* context = m_deviceResources->GetD2DDeviceContext(); 79 | Windows::Foundation::Size logicalSize = m_deviceResources->GetLogicalSize(); 80 | 81 | context->SaveDrawingState(m_stateBlock.Get()); 82 | context->BeginDraw(); 83 | 84 | // Position on the bottom right corner 85 | D2D1::Matrix3x2F screenTranslation = D2D1::Matrix3x2F::Translation( 86 | logicalSize.Width - m_textMetrics.layoutWidth, 87 | logicalSize.Height - m_textMetrics.height 88 | ); 89 | 90 | context->SetTransform(screenTranslation * m_deviceResources->GetOrientationTransform2D()); 91 | 92 | DX::ThrowIfFailed( 93 | m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING) 94 | ); 95 | 96 | context->DrawTextLayout( 97 | D2D1::Point2F(0.f, 0.f), 98 | m_textLayout.Get(), 99 | m_whiteBrush.Get() 100 | ); 101 | 102 | // Ignore D2DERR_RECREATE_TARGET here. This error indicates that the device 103 | // is lost. It will be handled during the next call to Present. 104 | HRESULT hr = context->EndDraw(); 105 | if (hr != D2DERR_RECREATE_TARGET) 106 | { 107 | DX::ThrowIfFailed(hr); 108 | } 109 | 110 | context->RestoreDrawingState(m_stateBlock.Get()); 111 | } 112 | 113 | void SampleFpsTextRenderer::CreateDeviceDependentResources() 114 | { 115 | DX::ThrowIfFailed( 116 | m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &m_whiteBrush) 117 | ); 118 | } 119 | void SampleFpsTextRenderer::ReleaseDeviceDependentResources() 120 | { 121 | m_whiteBrush.Reset(); 122 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/SampleFpsTextRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "..\Common\DeviceResources.h" 5 | #include "..\Common\StepTimer.h" 6 | 7 | namespace UWPHelpersCX 8 | { 9 | // Renders the current FPS value in the bottom right corner of the screen using Direct2D and DirectWrite. 10 | class SampleFpsTextRenderer 11 | { 12 | public: 13 | SampleFpsTextRenderer(const std::shared_ptr& deviceResources); 14 | void CreateDeviceDependentResources(); 15 | void ReleaseDeviceDependentResources(); 16 | void Update(DX::StepTimer const& timer); 17 | void Render(); 18 | 19 | private: 20 | // Cached pointer to device resources. 21 | std::shared_ptr m_deviceResources; 22 | 23 | // Resources related to text rendering. 24 | std::wstring m_text; 25 | DWRITE_TEXT_METRICS m_textMetrics; 26 | Microsoft::WRL::ComPtr m_whiteBrush; 27 | Microsoft::WRL::ComPtr m_stateBlock; 28 | Microsoft::WRL::ComPtr m_textLayout; 29 | Microsoft::WRL::ComPtr m_textFormat; 30 | }; 31 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/SamplePixelShader.hlsl: -------------------------------------------------------------------------------- 1 | struct PixelShaderInput 2 | { 3 | float4 pos : SV_POSITION; 4 | float3 color : COLOR0; 5 | }; 6 | 7 | float4 main(PixelShaderInput input) : SV_TARGET 8 | { 9 | return float4(input.color, 1.0f); 10 | } 11 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/SampleVertexShader.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer ModelViewProjectionConstantBuffer : register(b0) 2 | { 3 | matrix model; 4 | matrix view; 5 | matrix projection; 6 | }; 7 | 8 | struct VertexShaderInput 9 | { 10 | float3 pos : POSITION; 11 | float3 color : COLOR0; 12 | }; 13 | 14 | struct PixelShaderInput 15 | { 16 | float4 pos : SV_POSITION; 17 | float3 color : COLOR0; 18 | }; 19 | 20 | PixelShaderInput main(VertexShaderInput input) 21 | { 22 | PixelShaderInput output; 23 | float4 pos = float4(input.pos, 1.0f); 24 | 25 | pos = mul(pos, model); 26 | pos = mul(pos, view); 27 | pos = mul(pos, projection); 28 | output.pos = pos; 29 | 30 | output.color = input.color; 31 | 32 | return output; 33 | } 34 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Content/ShaderStructures.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace UWPHelpersCX 4 | { 5 | // Constant buffer used to send MVP matrices to the vertex shader. 6 | struct ModelViewProjectionConstantBuffer 7 | { 8 | DirectX::XMFLOAT4X4 model; 9 | DirectX::XMFLOAT4X4 view; 10 | DirectX::XMFLOAT4X4 projection; 11 | }; 12 | 13 | // Used to send per-vertex data to the vertex shader. 14 | struct VertexPositionColor 15 | { 16 | DirectX::XMFLOAT3 pos; 17 | DirectX::XMFLOAT3 color; 18 | }; 19 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | UWPHelpersCX 18 | Bashar Atifan 19 | Assets\StoreLogo.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/UWPHelpersCX.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 50ddbd34-2bcf-40e3-b0fe-a39090800249 6 | 7 | 8 | 09317fd7-d07a-46ae-b29e-1fe5699866de 9 | bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png 10 | 11 | 12 | 5d97f10d-c843-47fd-b505-8d9e93997f83 13 | 14 | 15 | Common 16 | 17 | 18 | Common 19 | 20 | 21 | Common 22 | 23 | 24 | Common 25 | 26 | 27 | Content 28 | 29 | 30 | Content 31 | 32 | 33 | Content 34 | 35 | 36 | Content 37 | 38 | 39 | Content 40 | 41 | 42 | Content 43 | 44 | 45 | Content 46 | 47 | 48 | Assets 49 | 50 | 51 | Assets 52 | 53 | 54 | Assets 55 | 56 | 57 | Assets 58 | 59 | 60 | Assets 61 | 62 | 63 | Assets 64 | 65 | 66 | {95f06108-0bcb-48f7-b4b4-00f33ecf7fb5} 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Source 75 | 76 | 77 | Source 78 | 79 | 80 | Source 81 | 82 | 83 | Source 84 | 85 | 86 | Source 87 | 88 | 89 | Source 90 | 91 | 92 | Source 93 | 94 | 95 | Source 96 | 97 | 98 | Source 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | Source 107 | 108 | 109 | Source 110 | 111 | 112 | Source 113 | 114 | 115 | Source 116 | 117 | 118 | Source 119 | 120 | 121 | Source 122 | 123 | 124 | Source 125 | 126 | 127 | Source 128 | 129 | 130 | Source 131 | 132 | 133 | Source 134 | 135 | 136 | Source 137 | 138 | 139 | Source 140 | 141 | 142 | Source 143 | 144 | 145 | Source 146 | 147 | 148 | Source 149 | 150 | 151 | 152 | 153 | Assets 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/UWPHelpersCXMain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UWPHelpersCXMain.h" 3 | #include "Common\DirectXHelper.h" 4 | 5 | using namespace UWPHelpersCX; 6 | using namespace Windows::Foundation; 7 | using namespace Windows::System::Threading; 8 | using namespace Concurrency; 9 | 10 | // Loads and initializes application assets when the application is loaded. 11 | UWPHelpersCXMain::UWPHelpersCXMain(const std::shared_ptr& deviceResources) : 12 | m_deviceResources(deviceResources) 13 | { 14 | // Register to be notified if the Device is lost or recreated 15 | m_deviceResources->RegisterDeviceNotify(this); 16 | 17 | // TODO: Replace this with your app's content initialization. 18 | m_sceneRenderer = std::unique_ptr(new Sample3DSceneRenderer(m_deviceResources)); 19 | 20 | m_fpsTextRenderer = std::unique_ptr(new SampleFpsTextRenderer(m_deviceResources)); 21 | 22 | // TODO: Change the timer settings if you want something other than the default variable timestep mode. 23 | // e.g. for 60 FPS fixed timestep update logic, call: 24 | /* 25 | m_timer.SetFixedTimeStep(true); 26 | m_timer.SetTargetElapsedSeconds(1.0 / 60); 27 | */ 28 | } 29 | 30 | UWPHelpersCXMain::~UWPHelpersCXMain() 31 | { 32 | // Deregister device notification 33 | m_deviceResources->RegisterDeviceNotify(nullptr); 34 | } 35 | 36 | // Updates application state when the window size changes (e.g. device orientation change) 37 | void UWPHelpersCXMain::CreateWindowSizeDependentResources() 38 | { 39 | // TODO: Replace this with the size-dependent initialization of your app's content. 40 | m_sceneRenderer->CreateWindowSizeDependentResources(); 41 | } 42 | 43 | // Updates the application state once per frame. 44 | void UWPHelpersCXMain::Update() 45 | { 46 | // Update scene objects. 47 | m_timer.Tick([&]() 48 | { 49 | // TODO: Replace this with your app's content update functions. 50 | m_sceneRenderer->Update(m_timer); 51 | m_fpsTextRenderer->Update(m_timer); 52 | }); 53 | } 54 | 55 | // Renders the current frame according to the current application state. 56 | // Returns true if the frame was rendered and is ready to be displayed. 57 | bool UWPHelpersCXMain::Render() 58 | { 59 | // Don't try to render anything before the first Update. 60 | if (m_timer.GetFrameCount() == 0) 61 | { 62 | return false; 63 | } 64 | 65 | auto context = m_deviceResources->GetD3DDeviceContext(); 66 | 67 | // Reset the viewport to target the whole screen. 68 | auto viewport = m_deviceResources->GetScreenViewport(); 69 | context->RSSetViewports(1, &viewport); 70 | 71 | // Reset render targets to the screen. 72 | ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() }; 73 | context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView()); 74 | 75 | // Clear the back buffer and depth stencil view. 76 | context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue); 77 | context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); 78 | 79 | // Render the scene objects. 80 | // TODO: Replace this with your app's content rendering functions. 81 | m_sceneRenderer->Render(); 82 | m_fpsTextRenderer->Render(); 83 | 84 | return true; 85 | } 86 | 87 | // Notifies renderers that device resources need to be released. 88 | void UWPHelpersCXMain::OnDeviceLost() 89 | { 90 | m_sceneRenderer->ReleaseDeviceDependentResources(); 91 | m_fpsTextRenderer->ReleaseDeviceDependentResources(); 92 | } 93 | 94 | // Notifies renderers that device resources may now be recreated. 95 | void UWPHelpersCXMain::OnDeviceRestored() 96 | { 97 | m_sceneRenderer->CreateDeviceDependentResources(); 98 | m_fpsTextRenderer->CreateDeviceDependentResources(); 99 | CreateWindowSizeDependentResources(); 100 | } 101 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/UWPHelpersCXMain.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Common\StepTimer.h" 4 | #include "Common\DeviceResources.h" 5 | #include "Content\Sample3DSceneRenderer.h" 6 | #include "Content\SampleFpsTextRenderer.h" 7 | 8 | // Renders Direct2D and 3D content on the screen. 9 | namespace UWPHelpersCX 10 | { 11 | class UWPHelpersCXMain : public DX::IDeviceNotify 12 | { 13 | public: 14 | UWPHelpersCXMain(const std::shared_ptr& deviceResources); 15 | ~UWPHelpersCXMain(); 16 | void CreateWindowSizeDependentResources(); 17 | void Update(); 18 | bool Render(); 19 | 20 | // IDeviceNotify 21 | virtual void OnDeviceLost(); 22 | virtual void OnDeviceRestored(); 23 | 24 | private: 25 | // Cached pointer to device resources. 26 | std::shared_ptr m_deviceResources; 27 | 28 | // TODO: Replace with your own content renderers. 29 | std::unique_ptr m_sceneRenderer; 30 | std::unique_ptr m_fpsTextRenderer; 31 | 32 | // Rendering loop timer. 33 | DX::StepTimer m_timer; 34 | }; 35 | } -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /UWPHelpers (CX)/UWPHelpersCX/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageAccess.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "StorageConfig.h" 8 | #include "StorageLog.h" 9 | #include "StorageExtensions.h" 10 | #include "StorageAsync.h" 11 | #include "StorageAccess.h" 12 | #include "StorageItemW.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace winrt::Windows::Storage; 25 | using namespace winrt::Windows::Foundation::Collections; 26 | using namespace winrt::Windows::Storage::AccessCache; 27 | using namespace winrt::Windows::ApplicationModel; 28 | using namespace winrt::Windows::UI::Core; 29 | 30 | // Main lookup list 31 | std::list FutureAccessItems; 32 | 33 | // Get value from app local settings 34 | winrt::hstring GetDataFromLocalSettings(winrt::hstring key) { 35 | ApplicationDataContainer localSettings{ ApplicationData::Current().LocalSettings() }; 36 | IPropertySet values{ localSettings.Values() }; 37 | if (!key.empty()) { 38 | auto tokenRetrive = values.Lookup(key); 39 | if (tokenRetrive != nullptr) { 40 | winrt::hstring ConvertedToken = tokenRetrive.as().GetString(); 41 | return ConvertedToken; 42 | } 43 | } 44 | return {}; 45 | } 46 | 47 | std::string GetDataFromLocalSettings(std::string key) { 48 | return convert(GetDataFromLocalSettings(convert(key))); 49 | } 50 | 51 | // Add or replace value in app local settings 52 | bool AddDataToLocalSettings(winrt::hstring key, winrt::hstring data, bool replace) { 53 | ApplicationDataContainer localSettings{ ApplicationData::Current().LocalSettings() }; 54 | IPropertySet values{ localSettings.Values() }; 55 | 56 | winrt::hstring testResult = GetDataFromLocalSettings(key); 57 | if (testResult.empty()) { 58 | values.Insert(key, winrt::Windows::Foundation::PropertyValue::CreateString(data)); 59 | return true; 60 | } 61 | else if (replace) { 62 | values.Remove(key); 63 | values.Insert(key, winrt::Windows::Foundation::PropertyValue::CreateString(data)); 64 | return true; 65 | } 66 | 67 | return false; 68 | } 69 | 70 | bool AddDataToLocalSettings(std::string key, std::string data, bool replace) { 71 | return AddDataToLocalSettings(convert(key), convert(data), replace); 72 | } 73 | 74 | // Add item to history list (FutureAccessItems) 75 | void AddToAccessibleItems(IStorageItem item) { 76 | bool isFolderAddedBefore = false; 77 | for (auto folderItem : FutureAccessItems) { 78 | if (folderItem.Equal(item)) { 79 | isFolderAddedBefore = true; 80 | break; 81 | } 82 | } 83 | 84 | if (!isFolderAddedBefore) { 85 | FutureAccessItems.push_back(StorageItemW(item)); 86 | } 87 | } 88 | 89 | 90 | // Add folder to future list (to avoid request picker again) 91 | void AddItemToFutureList(IStorageItem item) { 92 | try { 93 | if (item != nullptr) { 94 | winrt::hstring folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList().Add(item); 95 | AddToAccessibleItems(item); 96 | } 97 | } 98 | catch (...) { 99 | } 100 | } 101 | 102 | // Get item by key 103 | // This function can be used when you store token in LocalSettings as custom key 104 | IStorageItem GetItemByKey(winrt::hstring key) { 105 | IStorageItem item; 106 | winrt::hstring itemToken = GetDataFromLocalSettings(key); 107 | if (!itemToken.empty() && AccessCache::StorageApplicationPermissions::FutureAccessList().ContainsItem(itemToken)) { 108 | ExecuteTask(item, AccessCache::StorageApplicationPermissions::FutureAccessList().GetItemAsync(itemToken)); 109 | } 110 | 111 | return item; 112 | } 113 | 114 | // Append folder by token to (FutureAccessFolders) 115 | void AppendItemByToken(winrt::hstring token) { 116 | try { 117 | if (!token.empty() && AccessCache::StorageApplicationPermissions::FutureAccessList().ContainsItem(token)) { 118 | IStorageItem storageItem; 119 | ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList().GetItemAsync(token)); 120 | AddToAccessibleItems(storageItem); 121 | } 122 | } 123 | catch (...) { 124 | } 125 | } 126 | 127 | // Update the history list by the future list (to restore all the picked items) 128 | void UpdateItemsByFutureList() { 129 | auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList().Entries(); 130 | for (auto ListItem : AccessList) { 131 | winrt::hstring itemToken = ListItem.Token; 132 | AppendItemByToken(itemToken); 133 | } 134 | } 135 | 136 | bool fillListsCalled = false; 137 | bool fillListInProgress = false; 138 | void FillLookupList() { 139 | if (fillListsCalled) { 140 | // Should be called only once 141 | // but let's wait in case we got too calls at once 142 | CoreWindow corewindow = CoreWindow::GetForCurrentThread(); 143 | while (fillListInProgress) 144 | { 145 | try { 146 | if (corewindow) { 147 | corewindow.Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); 148 | } 149 | else { 150 | corewindow = CoreWindow::GetForCurrentThread(); 151 | } 152 | } 153 | catch (...) { 154 | 155 | } 156 | } 157 | return; 158 | } 159 | fillListsCalled = true; 160 | fillListInProgress = true; 161 | // Clean access list from any deleted/moved items 162 | for (auto listItem : AccessCache::StorageApplicationPermissions::FutureAccessList().Entries()) { 163 | try { 164 | IStorageItem test; 165 | ExecuteTask(test, AccessCache::StorageApplicationPermissions::FutureAccessList().GetItemAsync(listItem.Token)); 166 | if (test == nullptr) { 167 | // Access denied or file moved/deleted 168 | AccessCache::StorageApplicationPermissions::FutureAccessList().Remove(listItem.Token); 169 | } 170 | } 171 | catch (...) { 172 | // Access denied or file moved/deleted 173 | AccessCache::StorageApplicationPermissions::FutureAccessList().Remove(listItem.Token); 174 | } 175 | } 176 | 177 | // Get files/folders selected by the user 178 | UpdateItemsByFutureList(); 179 | 180 | // Append known folders 181 | #if APPEND_APP_LOCALDATA_LOCATION 182 | AddToAccessibleItems(ApplicationData::Current().LocalFolder()); 183 | AddToAccessibleItems(ApplicationData::Current().TemporaryFolder()); 184 | #endif 185 | 186 | #if APPEND_APP_INSTALLATION_LOCATION 187 | AddToAccessibleItems(Package::Current().InstalledLocation()); 188 | #endif 189 | 190 | #if APPEND_DOCUMENTS_LOCATION 191 | // >>>>DOCUMENTS (requires 'documentsLibrary' capability) 192 | AddToAccessibleItems(KnownFolders::DocumentsLibrary()); 193 | #endif 194 | 195 | #if APPEND_VIDEOS_LOCATION 196 | // >>>>VIDEOS (requires 'videosLibrary' capability) 197 | AddToAccessibleItems(KnownFolders::VideosLibrary()); 198 | #endif 199 | 200 | #if APPEND_PICTURES_LOCATION 201 | // >>>>VIDEOS (requires 'picturesLibrary' capability) 202 | AddToAccessibleItems(KnownFolders::PicturesLibrary()); 203 | #endif 204 | 205 | #if APPEND_MUSIC_LOCATION 206 | // >>>>MUSIC (requires 'musicLibrary' capability) 207 | AddToAccessibleItems(KnownFolders::MusicLibrary()); 208 | #endif 209 | 210 | // No need to append `RemovableDevices` 211 | // they will be allowed for access once you added the capability 212 | 213 | fillListInProgress = false; 214 | } 215 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageAccess.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | // Local settings 12 | std::string GetDataFromLocalSettings(std::string key); 13 | bool AddDataToLocalSettings(std::string key, std::string data, bool replace); 14 | 15 | // Lookup list 16 | void FillLookupList(); 17 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageAsync.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // Thanks to RetroArch/Libretro team for this idea 8 | // This is improved version of the original idea 9 | 10 | #include "StorageAsync.h" 11 | 12 | bool ActionPass(winrt::Windows::Foundation::IAsyncAction action) 13 | { 14 | try { 15 | WaitTask(action); 16 | return true; 17 | } 18 | catch (...) { 19 | return false; 20 | } 21 | } 22 | 23 | // Async action such as 'Delete' file 24 | // @action: async action 25 | // return false when action failed 26 | bool ExecuteTask(winrt::Windows::Foundation::IAsyncAction action) 27 | { 28 | return ActionPass(action); 29 | }; 30 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageAsync.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // WaitTask functions originally by Team Kodi 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "StorageLog.h" 29 | #include "StorageExtensions.h" 30 | 31 | using namespace winrt::Windows::UI::Core; 32 | 33 | #pragma region Async Handlers 34 | 35 | 36 | namespace winrt 37 | { 38 | using namespace Windows::Foundation; 39 | } 40 | 41 | inline void WaitTask(const winrt::IAsyncAction& asyncOp) 42 | { 43 | if (asyncOp.Status() == winrt::AsyncStatus::Completed) 44 | return; 45 | 46 | if (!winrt::impl::is_sta_thread()) 47 | return asyncOp.get(); 48 | 49 | auto __sync = std::make_shared(); 50 | asyncOp.Completed([&](auto&&, auto&&) { 51 | __sync->set(); 52 | }); 53 | __sync->wait(); 54 | } 55 | 56 | template inline 57 | TResult WaitTask(const winrt::IAsyncOperationWithProgress& asyncOp) 58 | { 59 | if (asyncOp.Status() == winrt::AsyncStatus::Completed) 60 | return asyncOp.GetResults(); 61 | 62 | if (!winrt::impl::is_sta_thread()) 63 | return asyncOp.get(); 64 | 65 | auto __sync = std::make_shared(); 66 | asyncOp.Completed([&](auto&&, auto&&) { 67 | __sync->set(); 68 | }); 69 | __sync->wait(); 70 | 71 | return asyncOp.GetResults(); 72 | } 73 | 74 | template inline 75 | TResult WaitTask(const winrt::IAsyncOperation& asyncOp) 76 | { 77 | if (asyncOp.Status() == winrt::AsyncStatus::Completed) 78 | return asyncOp.GetResults(); 79 | 80 | if (!winrt::impl::is_sta_thread()) 81 | return asyncOp.get(); 82 | 83 | auto __sync = std::make_shared(); 84 | asyncOp.Completed([&](auto&&, auto&&) 85 | { 86 | __sync->set(); 87 | }); 88 | __sync->wait(); 89 | 90 | return asyncOp.GetResults(); 91 | } 92 | 93 | template inline 94 | TResult WaitTask(const Concurrency::task& asyncOp) 95 | { 96 | if (asyncOp.is_done()) 97 | return asyncOp.get(); 98 | 99 | if (!winrt::impl::is_sta_thread()) // blocking suspend is allowed 100 | return asyncOp.get(); 101 | 102 | auto _sync = std::make_shared(); 103 | asyncOp.then([&](TResult result) 104 | { 105 | _sync->set(); 106 | }); 107 | _sync->wait(); 108 | 109 | return asyncOp.get(); 110 | } 111 | 112 | template 113 | T TaskPass(winrt::Windows::Foundation::IAsyncOperation task, T def) 114 | { 115 | try { 116 | return WaitTask(task); 117 | } 118 | catch (...) { 119 | return def; 120 | } 121 | } 122 | 123 | template 124 | T TaskPass(winrt::Windows::Foundation::IAsyncOperation task) 125 | { 126 | return WaitTask(task); 127 | } 128 | 129 | 130 | bool ActionPass(winrt::Windows::Foundation::IAsyncAction action); 131 | 132 | #pragma endregion 133 | 134 | // Now it's more simple to execute async task 135 | // @out: output variable 136 | // @task: async task 137 | template 138 | void ExecuteTask(T& out, winrt::Windows::Foundation::IAsyncOperation task) 139 | { 140 | out = TaskPass(task); 141 | }; 142 | 143 | // For specific return default value 144 | // @out: output variable 145 | // @task: async task 146 | // @def: default value when fail 147 | template 148 | void ExecuteTask(T& out, winrt::Windows::Foundation::IAsyncOperation task, T def) 149 | { 150 | out = TaskPass(task, def); 151 | }; 152 | 153 | 154 | // Async action such as 'Delete' file 155 | // @action: async action 156 | // return false when action failed 157 | bool ExecuteTask(winrt::Windows::Foundation::IAsyncAction action); 158 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageConfig.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | // Known locations 12 | // ACTIVATE BELOW ONLY IF YOU ADDED THE CAPABILITY 13 | #define APPEND_APP_LOCALDATA_LOCATION 1 // recommended to be always 1 14 | #define APPEND_APP_INSTALLATION_LOCATION 1 // recommended to be always 1 15 | #define APPEND_DOCUMENTS_LOCATION 0 // (requires 'documentsLibrary' capability) [Try to avoid docs very restricted] 16 | #define APPEND_VIDEOS_LOCATION 0 // (requires 'videosLibrary' capability) 17 | #define APPEND_MUSIC_LOCATION 0 // (requires musicLibrary' capability) 18 | #define APPEND_PICTURES_LOCATION 0 // (requires 'picturesLibrary' capability) 19 | 20 | // To force legacy APIs, define `UWP_LEGACY` (using header or project settings which is better) 21 | //#define UWP_LEGACY 1 22 | 23 | // Working folder 24 | // set this value by calling `SetWorkingFolder` from `StorageManager.h` 25 | static std::string AppWorkingFolder; 26 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageExtensions.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | typedef struct { 18 | DWORD dwDesiredAccess; 19 | DWORD dwShareMode; 20 | DWORD dwCreationDisposition; 21 | int flags; 22 | bool isWrite; 23 | bool isAppend; 24 | bool isCreate; 25 | } FILE_OPEN_UWP_MODE; 26 | 27 | bool replace(std::string& str, const std::string& from, const std::string& to); 28 | std::string replace2(const std::string str, const std::string& from, const std::string& to); 29 | std::vector split(const std::string s, char seperator); 30 | // Parent full path, child full path 31 | bool isChild(std::string parent, std::string child); 32 | // Parent full path, child full path, child name only 33 | bool isParent(std::string parent, std::string child, std::string childName); 34 | 35 | bool iequals(const std::string a, const std::string b); 36 | bool equals(const std::string a, const std::string b); 37 | bool ends_with(std::string const& value, std::string const& ending); 38 | bool starts_with(std::string str, std::string prefix); 39 | 40 | winrt::hstring convert(const std::string input); 41 | std::wstring convertToWString(const std::string input); 42 | std::string convert(winrt::hstring input); 43 | std::string convert(std::wstring input); 44 | std::string convert(const char* input); 45 | LPCWSTR convertToLPCWSTR(std::string input); 46 | LPCWSTR convertToLPCWSTR(winrt::hstring input); 47 | const char* convertToChar(winrt::hstring input); 48 | 49 | void tolower(std::string& input); 50 | void tolower(winrt::hstring& input); 51 | void toupper(std::string& input); 52 | void toupper(winrt::hstring& input); 53 | 54 | void windowsPath(std::string& path); 55 | void windowsPath(winrt::hstring& path); 56 | 57 | std::string merge(std::string targetFullPath, std::string subFullPath); 58 | 59 | std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v"); 60 | std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v"); 61 | std::string& trim(std::string& s, const char* t = " \t\n\r\f\v"); 62 | 63 | template 64 | bool findInList(std::list& inputList, T& str) { 65 | return (std::find(inputList.begin(), inputList.end(), str) != inputList.end()); 66 | }; 67 | 68 | FILE_OPEN_UWP_MODE* GetFileMode(const char* mode); 69 | 70 | // Parent and child full path 71 | std::string getSubRoot(std::string parent, std::string child); 72 | 73 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageFileW.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include "StorageLog.h" 13 | #include "StoragePath.h" 14 | #include "StorageExtensions.h" 15 | #include "StorageHandler.h" 16 | #include "StorageAsync.h" 17 | #include "StorageInfo.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace winrt::Windows::Storage; 28 | using namespace winrt::Windows::Storage::FileProperties; 29 | 30 | class StorageFileW { 31 | public: 32 | StorageFileW() : storageFile(nullptr), properties(nullptr), fileSize(0) { 33 | } 34 | StorageFileW(StorageFile file) : storageFile(file), properties(nullptr), fileSize(0) 35 | { 36 | 37 | } 38 | 39 | StorageFileW(IStorageItem file) : storageFile(file.as()), properties(nullptr), fileSize(0) { 40 | } 41 | 42 | ~StorageFileW() { 43 | } 44 | 45 | // Detect if main storage file is not null 46 | bool IsValid() { 47 | return (storageFile != nullptr); 48 | } 49 | 50 | // Delete file 51 | bool Delete() { 52 | bool state = ExecuteTask(storageFile.DeleteAsync()); 53 | if (state) { 54 | storageFile = nullptr; 55 | } 56 | return state; 57 | } 58 | 59 | // Rename file 60 | bool Rename(std::string name) { 61 | auto path = PathUWP(name); 62 | if (path.IsAbsolute()) { 63 | name = path.GetFilename(); 64 | } 65 | return ExecuteTask(storageFile.RenameAsync(convert(name))); 66 | } 67 | 68 | // Copy file 69 | bool Copy(StorageFolder folder, std::string name) { 70 | bool state = false; 71 | StorageFile newFile(nullptr); 72 | ExecuteTask(newFile, storageFile.CopyAsync(folder, convert(name), NameCollisionOption::ReplaceExisting)); 73 | if (newFile != nullptr) { 74 | state = true; 75 | } 76 | return state; 77 | } 78 | 79 | // Move file 80 | bool Move(StorageFolder folder, std::string name) { 81 | bool state = false; 82 | IStorageItem newFile; 83 | state = ExecuteTask(storageFile.MoveAsync(folder, convert(name), NameCollisionOption::GenerateUniqueName)); 84 | if (state) { 85 | ExecuteTask(newFile, folder.TryGetItemAsync(storageFile.Name())); 86 | if (newFile != nullptr) { 87 | storageFile = newFile.as(); 88 | } 89 | else { 90 | state = false; 91 | } 92 | } 93 | return state; 94 | } 95 | 96 | // Get file path 97 | std::string GetPath() { 98 | return convert(storageFile.Path()); 99 | } 100 | 101 | // Get file name 102 | std::string GetName() { 103 | return convert(storageFile.Name()); 104 | } 105 | 106 | // Compare file with std::string 107 | bool Equal(std::string path) { 108 | std::string filePath = GetPath(); 109 | 110 | // Fix slashs back from '/' to '\' 111 | windowsPath(path); 112 | return iequals(filePath, path); 113 | } 114 | 115 | // Compare file with Platform::String 116 | bool Equal(winrt::hstring path) { 117 | return storageFile.Path() == path; 118 | } 119 | 120 | // Compare file with Path 121 | bool Equal(PathUWP path) { 122 | return Equal(path.ToString()); 123 | } 124 | 125 | // Compare file with StorageFile 126 | bool Equal(StorageFile file) { 127 | return Equal(file.Path()); 128 | } 129 | 130 | // Get file size 131 | __int64 GetSize(bool updateCache = false) { 132 | if (fileSize == 0 || updateCache) { 133 | // Let's try getting size by handle first 134 | HANDLE handle; 135 | HRESULT hr = GetHandle(&handle); 136 | if (handle == INVALID_HANDLE_VALUE || hr != S_OK) { 137 | // We have no other option, fallback to UWP 138 | fileSize = FetchProperties().Size(); 139 | } 140 | else { 141 | LARGE_INTEGER size{ 0 }; 142 | if (FALSE == GetFileSizeEx(handle, &size)) { 143 | LARGE_INTEGER end_offset; 144 | const LARGE_INTEGER zero{}; 145 | if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) { 146 | CloseHandle(handle); 147 | } 148 | else { 149 | fileSize = end_offset.QuadPart; 150 | SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN); 151 | CloseHandle(handle); 152 | } 153 | } 154 | else { 155 | fileSize = size.QuadPart; 156 | CloseHandle(handle); 157 | } 158 | } 159 | } 160 | return fileSize; 161 | } 162 | 163 | // Get file handle 164 | HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) { 165 | return GetFileHandle(storageFile, handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 166 | } 167 | 168 | // Get file stream 169 | FILE* GetStream(const char* mode) { 170 | HANDLE handle; 171 | auto fileMode = GetFileMode(mode); 172 | if (fileMode && !fileMode->isAppend && fileMode->isCreate) { 173 | ExecuteTask(winrt::Windows::Storage::FileIO::WriteTextAsync(storageFile, L"")); 174 | } 175 | HRESULT hr = GetHandle(&handle, fileMode->dwDesiredAccess, fileMode->dwShareMode); 176 | FILE* file{}; 177 | if (hr == S_OK && handle != INVALID_HANDLE_VALUE) { 178 | UWP_ERROR_LOG(UWPSMT, "Opening file (%s) with flag:%d mode:%s", GetPath().c_str(), fileMode->flags, mode); 179 | file = _fdopen(_open_osfhandle((intptr_t)handle, fileMode->flags), mode); 180 | } 181 | return file; 182 | } 183 | 184 | // Get file handle from stream 185 | HANDLE GetHandle(FILE* file) { 186 | return (HANDLE)_get_osfhandle(_fileno(file)); 187 | } 188 | 189 | // Get file properties 190 | FILE_BASIC_INFO* GetProperties() { 191 | HANDLE handle; 192 | HRESULT hr = GetHandle(&handle); 193 | 194 | size_t size = sizeof(FILE_BASIC_INFO); 195 | FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size)); 196 | if (hr == S_OK && handle != INVALID_HANDLE_VALUE && information) { 197 | information->FileAttributes = (uint64_t)storageFile.Attributes(); 198 | 199 | if (FALSE == GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) { 200 | // Fallback to UWP method (Slow) 201 | auto props = FetchProperties(); 202 | information->ChangeTime.QuadPart = winrt::clock::to_file_time(props.DateModified()).value; 203 | information->CreationTime.QuadPart = winrt::clock::to_file_time(props.ItemDate()).value; 204 | information->LastAccessTime.QuadPart = winrt::clock::to_file_time(props.DateModified()).value; 205 | information->LastWriteTime.QuadPart = winrt::clock::to_file_time(props.DateModified()).value; 206 | } 207 | CloseHandle(handle); 208 | } 209 | 210 | return information; 211 | } 212 | 213 | // Get main storage file 214 | StorageFile GetStorageFile() { 215 | return storageFile; 216 | } 217 | 218 | time_t filetime_to_timet(LARGE_INTEGER ull) const { 219 | return ull.QuadPart / 10000000ULL - 11644473600ULL; 220 | } 221 | ItemInfoUWP GetFileInfo() { 222 | ItemInfoUWP info; 223 | info.name = GetName(); 224 | info.fullName = GetPath(); 225 | info.isDirectory = false; 226 | 227 | auto sProperties = GetProperties(); 228 | 229 | info.size = (uint64_t)GetSize(); 230 | info.lastAccessTime = (uint64_t)filetime_to_timet(sProperties->LastAccessTime); 231 | info.lastWriteTime = (uint64_t)filetime_to_timet(sProperties->LastWriteTime); 232 | info.changeTime = (uint64_t)filetime_to_timet(sProperties->ChangeTime); 233 | info.creationTime = (uint64_t)filetime_to_timet(sProperties->CreationTime); 234 | 235 | 236 | info.attributes = (uint64_t)sProperties->FileAttributes; 237 | 238 | return info; 239 | } 240 | 241 | private: 242 | StorageFile storageFile; 243 | BasicProperties properties; 244 | __int64 fileSize = 0; 245 | 246 | BasicProperties FetchProperties() { 247 | if (properties == nullptr) { 248 | // Very bad and slow way in UWP to get size and other properties 249 | // not preferred to be used on big list of files 250 | ExecuteTask(properties, storageFile.GetBasicPropertiesAsync()); 251 | } 252 | return properties; 253 | } 254 | }; 255 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageHandler.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #include "StorageHandler.h" 7 | #include "StorageExtensions.h" 8 | 9 | HRESULT GetFileHandle(winrt::Windows::Storage::StorageFile file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode) 10 | { 11 | if (file != nullptr) { 12 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(winrt::get_abi(file))); 13 | Microsoft::WRL::ComPtr handleAccess; 14 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 15 | { 16 | HANDLE hFile = INVALID_HANDLE_VALUE; 17 | 18 | if (SUCCEEDED(handleAccess->Create(accessMode, 19 | shareMode, 20 | HO_NONE, 21 | nullptr, 22 | &hFile))) 23 | { 24 | *handle = hFile; 25 | return S_OK; 26 | } 27 | } 28 | } 29 | return E_FAIL; 30 | } 31 | 32 | HRESULT GetFileHandleFromFolder(winrt::Windows::Storage::StorageFolder folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode) 33 | { 34 | if (folder != nullptr) { 35 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(winrt::get_abi(folder))); 36 | Microsoft::WRL::ComPtr handleAccess; 37 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 38 | { 39 | HANDLE hFolder = INVALID_HANDLE_VALUE; 40 | auto fn = convertToLPCWSTR(filename); 41 | if (SUCCEEDED(handleAccess->Create(fn, 42 | openMode, 43 | accessMode, 44 | shareMode, 45 | HO_NONE, 46 | nullptr, 47 | &hFolder))) 48 | { 49 | *handle = hFolder; 50 | return S_OK; 51 | } 52 | } 53 | } 54 | return E_FAIL; 55 | } 56 | 57 | HRESULT GetFolderHandle(winrt::Windows::Storage::StorageFolder folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode) 58 | { 59 | if (folder != nullptr) { 60 | Microsoft::WRL::ComPtr abiPointer(reinterpret_cast(winrt::get_abi(folder))); 61 | Microsoft::WRL::ComPtr handleAccess; 62 | if (SUCCEEDED(abiPointer.As(&handleAccess))) 63 | { 64 | HANDLE hFolder = INVALID_HANDLE_VALUE; 65 | 66 | if (SUCCEEDED(handleAccess->Create(accessMode, 67 | shareMode, 68 | HO_NONE, 69 | nullptr, 70 | &hFolder))) 71 | { 72 | *handle = hFolder; 73 | return S_OK; 74 | } 75 | } 76 | } 77 | return E_FAIL; 78 | } 79 | 80 | HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode) { 81 | switch (accessMode) { 82 | case GENERIC_READ: 83 | return HAO_READ | HAO_READ_ATTRIBUTES; 84 | case GENERIC_WRITE: 85 | return HAO_WRITE | HAO_READ; 86 | case GENERIC_ALL: 87 | return HAO_READ | HAO_READ_ATTRIBUTES | HAO_WRITE | HAO_DELETE; 88 | default: 89 | return HAO_READ; 90 | } 91 | } 92 | 93 | HANDLE_SHARING_OPTIONS GetShareMode(int shareMode) { 94 | switch (shareMode) 95 | { 96 | case FILE_SHARE_READ: 97 | return HSO_SHARE_READ; 98 | case FILE_SHARE_WRITE: 99 | return HSO_SHARE_READ | HSO_SHARE_WRITE; 100 | case FILE_SHARE_DELETE: 101 | return HSO_SHARE_DELETE; 102 | default: 103 | return HSO_SHARE_READ; 104 | } 105 | } 106 | 107 | HANDLE_CREATION_OPTIONS GetOpenMode(int openMode) { 108 | switch (openMode) 109 | { 110 | case CREATE_NEW: 111 | return HCO_CREATE_NEW; 112 | case CREATE_ALWAYS: 113 | return HCO_CREATE_ALWAYS; 114 | case OPEN_ALWAYS: 115 | return HCO_OPEN_ALWAYS; 116 | case OPEN_EXISTING: 117 | return HCO_OPEN_EXISTING; 118 | default: 119 | return HCO_OPEN_EXISTING; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageHandler.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #pragma region WindowsStorageCOM 17 | // These APIs have been accidentally placed inside the WINAPI_PARTITION_DESKTOP partition 18 | // (they're not desktop-specific; they're available to UWPs). 19 | // This will be addressed in future SDK updates. 20 | // These are copied from WindowsStorageCOM.h 21 | // You can remove this region once the real file has been updated 22 | // to fix the WINAPI_PARTITION_DESKTOP block 23 | // Source: https://stackoverflow.com/questions/42799235/how-can-i-get-a-win32-handle-for-a-storagefile-or-storagefolder-in-uwp 24 | 25 | typedef interface IOplockBreakingHandler IOplockBreakingHandler; 26 | typedef interface IStorageItemHandleAccess IStorageItemHandleAccess; 27 | typedef interface IStorageFolderHandleAccess IStorageFolderHandleAccess; 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | typedef 34 | enum HANDLE_OPTIONS 35 | { 36 | HO_NONE = 0, 37 | HO_OPEN_REQUIRING_OPLOCK = 0x40000, 38 | HO_DELETE_ON_CLOSE = 0x4000000, 39 | HO_SEQUENTIAL_SCAN = 0x8000000, 40 | HO_RANDOM_ACCESS = 0x10000000, 41 | HO_NO_BUFFERING = 0x20000000, 42 | HO_OVERLAPPED = 0x40000000, 43 | HO_WRITE_THROUGH = 0x80000000 44 | } HANDLE_OPTIONS; 45 | 46 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_OPTIONS); 47 | typedef 48 | enum HANDLE_ACCESS_OPTIONS 49 | { 50 | HAO_NONE = 0, 51 | HAO_READ_ATTRIBUTES = 0x80, 52 | HAO_READ = 0x120089, 53 | HAO_WRITE = 0x120116, 54 | HAO_DELETE = 0x10000 55 | } HANDLE_ACCESS_OPTIONS; 56 | 57 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_ACCESS_OPTIONS); 58 | typedef 59 | enum HANDLE_SHARING_OPTIONS 60 | { 61 | HSO_SHARE_NONE = 0, 62 | HSO_SHARE_READ = 0x1, 63 | HSO_SHARE_WRITE = 0x2, 64 | HSO_SHARE_DELETE = 0x4 65 | } HANDLE_SHARING_OPTIONS; 66 | 67 | DEFINE_ENUM_FLAG_OPERATORS(HANDLE_SHARING_OPTIONS); 68 | typedef 69 | enum HANDLE_CREATION_OPTIONS 70 | { 71 | HCO_CREATE_NEW = 0x1, 72 | HCO_CREATE_ALWAYS = 0x2, 73 | HCO_OPEN_EXISTING = 0x3, 74 | HCO_OPEN_ALWAYS = 0x4, 75 | HCO_TRUNCATE_EXISTING = 0x5 76 | } HANDLE_CREATION_OPTIONS; 77 | 78 | 79 | EXTERN_C const IID IID_IOplockBreakingHandler; 80 | MIDL_INTERFACE("826ABE3D-3ACD-47D3-84F2-88AAEDCF6304") 81 | IOplockBreakingHandler : public ::IUnknown 82 | { 83 | public: 84 | virtual HRESULT STDMETHODCALLTYPE OplockBreaking(void) = 0; 85 | 86 | }; 87 | 88 | EXTERN_C const IID IID_IStorageItemHandleAccess; 89 | MIDL_INTERFACE("5CA296B2-2C25-4D22-B785-B885C8201E6A") 90 | IStorageItemHandleAccess : public ::IUnknown 91 | { 92 | public: 93 | virtual HRESULT STDMETHODCALLTYPE Create( 94 | HANDLE_ACCESS_OPTIONS accessOptions, 95 | HANDLE_SHARING_OPTIONS sharingOptions, 96 | HANDLE_OPTIONS options, 97 | __RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler, 98 | __RPC__deref_out_opt HANDLE * interopHandle) = 0; 99 | 100 | }; 101 | 102 | EXTERN_C const IID IID_IStorageFolderHandleAccess; 103 | MIDL_INTERFACE("DF19938F-5462-48A0-BE65-D2A3271A08D6") 104 | IStorageFolderHandleAccess : public ::IUnknown 105 | { 106 | public: 107 | virtual HRESULT STDMETHODCALLTYPE Create( 108 | __RPC__in_string LPCWSTR fileName, 109 | HANDLE_CREATION_OPTIONS creationOptions, 110 | HANDLE_ACCESS_OPTIONS accessOptions, 111 | HANDLE_SHARING_OPTIONS sharingOptions, 112 | HANDLE_OPTIONS options, 113 | __RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler, 114 | __RPC__deref_out_opt HANDLE * interopHandle) = 0; 115 | 116 | }; 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | #pragma endregion 121 | 122 | HRESULT GetFileHandle(winrt::Windows::Storage::StorageFile file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode); 123 | HRESULT GetFileHandleFromFolder(winrt::Windows::Storage::StorageFolder folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode); 124 | HRESULT GetFolderHandle(winrt::Windows::Storage::StorageFolder folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode); 125 | 126 | HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode); 127 | HANDLE_SHARING_OPTIONS GetShareMode(int shareMode); 128 | HANDLE_CREATION_OPTIONS GetOpenMode(int openMode); 129 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageInfo.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // For updates check: https://github.com/basharast/UWP2Win32 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | struct ItemInfoUWP { 12 | std::string name; 13 | std::string fullName; 14 | 15 | bool isDirectory = false; 16 | 17 | uint64_t size = 0; 18 | uint64_t lastAccessTime = 0; 19 | uint64_t lastWriteTime = 0; 20 | uint64_t changeTime = 0; 21 | uint64_t creationTime = 0; 22 | 23 | uint64_t attributes = 0; 24 | }; 25 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageItemW.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include "StorageLog.h" 13 | #include "StoragePath.h" 14 | #include "StorageExtensions.h" 15 | #include "StorageHandler.h" 16 | #include "StorageAsync.h" 17 | #include "StorageFolderW.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace winrt::Windows::Storage; 24 | using namespace winrt::Windows::Storage::FileProperties; 25 | 26 | class StorageItemW { 27 | public: 28 | StorageItemW() { 29 | } 30 | 31 | StorageItemW(IStorageItem item) { 32 | storageItem = item; 33 | itemSize = 0; 34 | if (item != nullptr) { 35 | isDirectory = storageItem.IsOfType(StorageItemTypes::Folder); 36 | if (isDirectory) { 37 | storageFolderW = StorageFolderW(item); 38 | } 39 | else { 40 | storageFileW = StorageFileW(item); 41 | } 42 | } 43 | } 44 | // Delegate constructor for StorageFolderW 45 | StorageItemW(StorageFolderW folder) 46 | : StorageItemW(static_cast(folder.GetStorageFolder())) { } 47 | 48 | // Delegate constructor for StorageFileW 49 | StorageItemW(StorageFileW file) 50 | : StorageItemW(static_cast(file.GetStorageFile())) { } 51 | 52 | ~StorageItemW() { 53 | } 54 | 55 | bool IsDirectory() { 56 | return isDirectory; 57 | } 58 | 59 | // Detect if main storage item is not null 60 | bool IsValid() { 61 | return (storageItem != nullptr); 62 | } 63 | 64 | // Delete item 65 | bool Delete() { 66 | bool state = ExecuteTask(storageItem.DeleteAsync()); 67 | if (state) { 68 | storageItem = nullptr; 69 | } 70 | return state; 71 | } 72 | 73 | // Rename item 74 | bool Rename(std::string name) { 75 | auto path = PathUWP(name); 76 | if (path.IsAbsolute()) { 77 | name = path.GetFilename(); 78 | } 79 | return ExecuteTask(storageItem.RenameAsync(convert(name))); 80 | } 81 | 82 | // Copy item 83 | bool Copy(StorageFolder folder) { 84 | bool state = false; 85 | if (IsDirectory()) { 86 | state = storageFolderW.Copy(folder); 87 | } 88 | else { 89 | state = storageFileW.Copy(folder, storageFileW.GetName()); 90 | } 91 | return state; 92 | } 93 | 94 | 95 | // Copy item 96 | bool Copy(StorageItemW folder) { 97 | return Copy(folder.GetStorageFolder()); 98 | } 99 | 100 | bool Copy(StorageFolder folder, std::string name) { 101 | bool state = false; 102 | if (IsDirectory()) { 103 | state = storageFolderW.Copy(folder); 104 | } 105 | else { 106 | state = storageFileW.Copy(folder, name); 107 | } 108 | return state; 109 | } 110 | 111 | bool Copy(StorageItemW folder, std::string name) { 112 | return Copy(folder.GetStorageFolder(), name); 113 | } 114 | 115 | // Move item 116 | bool Move(StorageFolder folder) { 117 | bool state = false; 118 | if (IsDirectory()) { 119 | state = storageFolderW.Copy(folder, true); 120 | } 121 | else { 122 | state = storageFileW.Move(folder, storageFileW.GetName()); 123 | } 124 | return state; 125 | } 126 | 127 | bool Move(StorageItemW folder) { 128 | return Move(folder.GetStorageFolder()); 129 | } 130 | 131 | // Move item 132 | bool Move(StorageFolder folder, std::string name) { 133 | bool state = false; 134 | if (IsDirectory()) { 135 | state = storageFolderW.Copy(folder, true); 136 | } 137 | else { 138 | state = storageFileW.Move(folder, name); 139 | } 140 | return state; 141 | } 142 | 143 | bool Move(StorageItemW folder, std::string name) { 144 | return Move(folder.GetStorageFolder(), name); 145 | } 146 | 147 | // Get item path 148 | std::string GetPath() { 149 | return convert(storageItem.Path()); 150 | } 151 | 152 | // Get item name 153 | std::string GetName() { 154 | return convert(storageItem.Name()); 155 | } 156 | 157 | // Compare item with std::string 158 | bool Equal(std::string path) { 159 | std::string itemPath = GetPath(); 160 | 161 | // Fix slashs back from '/' to '\' 162 | windowsPath(path); 163 | return iequals(itemPath, path); 164 | } 165 | 166 | // Compare item with winrt::hstring 167 | bool Equal(winrt::hstring path) { 168 | return storageItem.Path() == path; 169 | } 170 | 171 | // Compare item with Path 172 | bool Equal(PathUWP path) { 173 | return Equal(path.ToString()); 174 | } 175 | 176 | // Compare item with StorageItem 177 | bool Equal(IStorageItem item) { 178 | return Equal(item.Path()); 179 | } 180 | 181 | // Get item size 182 | __int64 GetSize(bool updateCache = false) { 183 | if (itemSize == 0 || updateCache) { 184 | if (IsDirectory()) { 185 | itemSize = storageFolderW.GetSize(updateCache); 186 | } 187 | else { 188 | itemSize = storageFileW.GetSize(updateCache); 189 | } 190 | } 191 | return itemSize; 192 | } 193 | 194 | // Get item handle 195 | HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) { 196 | HRESULT hr = E_FAIL; 197 | if (IsDirectory()) { 198 | hr = GetFolderHandle(storageFolderW.GetStorageFolder(), handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 199 | } 200 | else { 201 | hr = GetFileHandle(storageFileW.GetStorageFile(), handle, GetAccessMode(accessMode), GetShareMode(shareMode)); 202 | } 203 | return hr; 204 | } 205 | 206 | // Get file stream 207 | FILE* GetStream(const char* mode) { 208 | FILE* file{}; 209 | if (!IsDirectory()) { 210 | file = storageFileW.GetStream(mode); 211 | } 212 | return file; 213 | } 214 | 215 | // Get files stream from folder 216 | FILE* GetFileStream(std::string name, const char* mode) { 217 | FILE* file{}; 218 | if (IsDirectory()) { 219 | file = storageFolderW.GetFileStream(name, mode); 220 | } 221 | return file; 222 | } 223 | 224 | // Get item handle from stream 225 | HANDLE GetHandleFromStream(FILE* file) { 226 | return (HANDLE)_get_osfhandle(_fileno(file)); 227 | } 228 | 229 | 230 | // Create or open folder if exists 231 | StorageFolderW CreateFolder(PathUWP path) { 232 | return StorageFolderW(storageFolderW.GetOrCreateFolder(path)); 233 | } 234 | 235 | // Create or open file if exists 236 | StorageFileW CreateFile(PathUWP path) { 237 | return StorageFileW(storageFolderW.GetOrCreateFile(path)); 238 | } 239 | 240 | // Create new folder 241 | bool CreateFolder(std::string name, bool replaceExisting = true) { 242 | return storageFolderW.CreateFolder(name, replaceExisting); 243 | } 244 | 245 | // Create new file 246 | bool CreateFile(std::string name, bool replaceExisting = true) { 247 | return storageFolderW.CreateFile(name, replaceExisting); 248 | } 249 | 250 | // Check if folder contains item by name or path 251 | bool Contains(PathUWP path, IStorageItem& storageItem) { 252 | return storageFolderW.Contains(path, storageItem); 253 | } 254 | 255 | // Get all sub folders (deep scan) 256 | std::list GetAllFolders(bool useWindowsIndexer = false) { 257 | return storageFolderW.GetAllFolders(useWindowsIndexer); 258 | } 259 | 260 | // Get all files including files in sub folders (deep scan) 261 | std::list GetAllFiles(bool useWindowsIndexer = false) { 262 | return storageFolderW.GetAllFiles(useWindowsIndexer); 263 | } 264 | 265 | std::list GetFolders() { 266 | return storageFolderW.GetFolders(); 267 | } 268 | 269 | std::list GetFiles() { 270 | return storageFolderW.GetFiles(); 271 | } 272 | 273 | // Get item properties 274 | FILE_BASIC_INFO* GetProperties() { 275 | if (IsDirectory()) { 276 | return storageFolderW.GetProperties(); 277 | } 278 | else { 279 | return storageFileW.GetProperties(); 280 | } 281 | } 282 | 283 | // Get main storage item 284 | IStorageItem GetStorageItem() { 285 | return storageItem; 286 | } 287 | 288 | // Get Wrapped StorageFolder 289 | StorageFolderW GetStorageFolderW() { 290 | return storageFolderW; 291 | } 292 | 293 | // Get Wrapped StorageFolder 294 | StorageFolder GetStorageFolder() { 295 | return storageFolderW.GetStorageFolder(); 296 | } 297 | 298 | // Get Wrapped StorageFile 299 | StorageFileW GetStorageFileW() { 300 | return storageFileW; 301 | } 302 | 303 | // Get StorageFile 304 | StorageFile GetStorageFile() { 305 | return storageFileW.GetStorageFile(); 306 | } 307 | 308 | ItemInfoUWP GetItemInfo() { 309 | ItemInfoUWP info; 310 | if (IsDirectory()) { 311 | info = storageFolderW.GetFolderInfo(); 312 | } 313 | else { 314 | info = storageFileW.GetFileInfo(); 315 | } 316 | return info; 317 | } 318 | 319 | private: 320 | IStorageItem storageItem; 321 | StorageFileW storageFileW; 322 | StorageFolderW storageFolderW; 323 | 324 | __int64 itemSize = 0; 325 | bool isDirectory = false; 326 | }; 327 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageLog.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #define UWPSMT = 4; // Change it based on your needs 10 | 11 | // Link your debug function below 12 | #define UWP_ERROR_LOG(t,...) do { } while (false) 13 | #define UWP_WARN_LOG(t,...) do { } while (false) 14 | #define UWP_NOTICE_LOG(t,...) do { } while (false) 15 | #define UWP_INFO_LOG(t,...) do { } while (false) 16 | #define UWP_DEBUG_LOG(t,...) do { } while (false) 17 | #define UWP_VERBOSE_LOG(t,...) do { } while (false) 18 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StorageManager.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "StoragePath.h" 17 | #include "StorageInfo.h" 18 | #include "StorageAccess.h" 19 | #include "StoragePickers.h" 20 | 21 | // Locations 22 | std::string GetWorkingFolder(); // Where main data is, default is app data 23 | void SetWorkingFolder(std::string location); // Change working location 24 | void SetWorkingFolder(std::wstring location); // Change working location 25 | std::string GetInstallationFolder(); 26 | std::string GetLocalFolder(); 27 | std::string GetTempFolder(); 28 | std::string GetTempFile(std::string name); 29 | std::string GetTempFile(std::wstring name); 30 | std::string GetPicturesFolder(); // Requires 'picturesLibrary' capability 31 | std::string GetVideosFolder(); // Requires 'videosLibrary' capability 32 | std::string GetDocumentsFolder(); // Requires 'documentsLibrary' capability 33 | std::string GetMusicFolder(); // Requires 'musicLibrary' capability 34 | std::string GetPreviewPath(std::string path); 35 | bool isLocalState(std::string path); 36 | bool isLocalState(std::wstring path); 37 | 38 | // Management 39 | HANDLE CreateFileUWP(std::string path, long accessMode = 0x80000000L, long shareMode = 0x00000001, long openMode = 3); 40 | HANDLE CreateFileUWP(std::wstring path, long accessMode = 0x80000000L, long shareMode = 0x00000001, long openMode = 3); 41 | FILE* GetFileStream(std::string path, const char* mode); 42 | FILE* GetFileStream(std::wstring path, const char* mode); 43 | // `GetFileStreamFromApp` Will use Windows UWP API, use it instead of fopen..etc 44 | FILE* GetFileStreamFromApp(std::string path, const char* mode); 45 | FILE* GetFileStreamFromApp(std::wstring path, const char* mode); 46 | 47 | // Validation 48 | bool IsValidUWP(std::string path, bool allowForAppData = false); 49 | bool IsValidUWP(std::wstring path, bool allowForAppData = false); 50 | bool IsExistsUWP(std::string path); 51 | bool IsExistsUWP(std::wstring path); 52 | bool IsDirectoryUWP(std::string path); 53 | bool IsDirectoryUWP(std::wstring path); 54 | 55 | // File Contents 56 | std::string GetFileContent(std::string path, const char* mode); 57 | std::string GetFileContent(std::wstring path, const char* mode); 58 | bool PutFileContents(std::string path, std::string content, const char* mode = "w+", bool backup = false); 59 | bool PutFileContents(std::wstring path, std::wstring content, const char* mode = "w+", bool backup = false); 60 | 61 | // Folder Contents 62 | std::list GetFolderContents(std::string path, bool deepScan = false); 63 | std::list GetFolderContents(std::wstring path, bool deepScan = false); 64 | ItemInfoUWP GetItemInfoUWP(std::string path); 65 | ItemInfoUWP GetItemInfoUWP(std::wstring path); 66 | 67 | // Basics 68 | int64_t GetSizeUWP(std::string path); 69 | int64_t GetSizeUWP(std::wstring path); 70 | bool DeleteUWP(std::string path); 71 | bool DeleteUWP(std::wstring path); 72 | bool CreateDirectoryUWP(std::string path, bool replaceExisting = true); 73 | bool CreateDirectoryUWP(std::wstring path, bool replaceExisting = true); 74 | // Both (old, new) full path 75 | bool RenameUWP(std::string oldname, std::string newname); 76 | bool RenameUWP(std::wstring oldname, std::wstring newname); 77 | // Add file name to destination path 78 | bool CopyUWP(std::string path, std::string dest); 79 | bool CopyUWP(std::wstring path, std::wstring dest); 80 | // Add file name to destination path 81 | bool MoveUWP(std::string path, std::string dest); 82 | bool MoveUWP(std::wstring path, std::wstring dest); 83 | 84 | // Helpers 85 | bool OpenFile(std::string path); 86 | bool OpenFile(std::wstring path); 87 | bool OpenFolder(std::string path); 88 | bool OpenFolder(std::wstring path); 89 | 90 | // More 91 | bool IsFirstStart(); 92 | std::string ResolvePathUWP(std::string path); 93 | bool IsContainsAccessibleItems(std::string path); 94 | bool IsContainsAccessibleItems(std::wstring path); 95 | bool IsRootForAccessibleItems(std::string path); 96 | bool IsRootForAccessibleItems(std::wstring path); 97 | // 'checkIfContainsFutureAccessItems' for listing purposes not real access, 'driveName' like C: 98 | bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessItems); 99 | bool CheckDriveAccess(std::wstring driveName, bool checkIfContainsFutureAccessItems); 100 | bool GetDriveFreeSpace(PathUWP path, int64_t& space); 101 | 102 | // Log helpers 103 | std::string GetLogFile(); 104 | bool SaveLogs(); // With picker 105 | void CleanupLogs(); 106 | 107 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StoragePath.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Based on 'Path' from PPSSPP 3 | // For updates check: https://github.com/basharast/UWP2Win32 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "StoragePath.h" 10 | #include "StorageLog.h" 11 | #include "StorageExtensions.h" 12 | 13 | PathUWP::PathUWP(const std::string& str) { 14 | Init(str); 15 | } 16 | 17 | PathUWP::PathUWP(const std::wstring& str) { 18 | type_ = PathTypeUWP::NATIVE; 19 | Init(convert(str)); 20 | } 21 | 22 | void PathUWP::Init(const std::string& str) { 23 | if (str.empty()) { 24 | type_ = PathTypeUWP::UNDEFINED; 25 | path_.clear(); 26 | } 27 | else if (starts_with(str, "http://") || starts_with(str, "https://")) { 28 | type_ = PathTypeUWP::HTTP; 29 | path_ = str; 30 | } 31 | else { 32 | type_ = PathTypeUWP::NATIVE; 33 | path_ = str; 34 | } 35 | 36 | replace(path_, "??\\", ""); 37 | replace(path_, "\\??\\", ""); 38 | replace(path_, "\\\\?\\", ""); 39 | replace(path_, "?\\", ""); 40 | 41 | // Flip all the slashes around. We flip them back on ToWString(). 42 | for (size_t i = 0; i < path_.size(); i++) { 43 | if (path_[i] == '\\') { 44 | path_[i] = '/'; 45 | } 46 | } 47 | 48 | // Don't pop_back if it's just "/". 49 | if (type_ == PathTypeUWP::NATIVE && path_.size() > 1 && path_.back() == '/') { 50 | path_.pop_back(); 51 | } 52 | } 53 | 54 | // We always use forward slashes internally, we convert to backslash only when 55 | // converted to a wstring. 56 | PathUWP PathUWP::operator /(const std::string& subdir) const { 57 | // Direct string manipulation. 58 | 59 | if (subdir.empty()) { 60 | return PathUWP(path_); 61 | } 62 | std::string fullPath = path_; 63 | if (subdir.front() != '/' && (fullPath.empty() || fullPath.back() != '/')) { 64 | fullPath += "/"; 65 | } 66 | fullPath += subdir; 67 | // Prevent adding extra slashes. 68 | if (fullPath.back() == '/') { 69 | fullPath.pop_back(); 70 | } 71 | return PathUWP(fullPath); 72 | } 73 | 74 | void PathUWP::operator /=(const std::string& subdir) { 75 | *this = *this / subdir; 76 | } 77 | 78 | PathUWP PathUWP::WithExtraExtension(const std::string& ext) const { 79 | return PathUWP(path_ + ext); 80 | } 81 | 82 | PathUWP PathUWP::WithReplacedExtension(const std::string& oldExtension, const std::string& newExtension) const { 83 | if (ends_with(path_, oldExtension)) { 84 | std::string newPath = path_.substr(0, path_.size() - oldExtension.size()); 85 | return PathUWP(newPath + newExtension); 86 | } 87 | else { 88 | return PathUWP(*this); 89 | } 90 | } 91 | 92 | PathUWP PathUWP::WithReplacedExtension(const std::string& newExtension) const { 93 | if (path_.empty()) { 94 | return PathUWP(*this); 95 | } 96 | std::string extension = GetFileExtension(); 97 | std::string newPath = path_.substr(0, path_.size() - extension.size()) + newExtension; 98 | return PathUWP(newPath); 99 | } 100 | 101 | std::string PathUWP::GetFilename() const { 102 | size_t pos = path_.rfind('/'); 103 | if (pos != std::string::npos) { 104 | return path_.substr(pos + 1); 105 | } 106 | return path_; 107 | } 108 | 109 | static std::string GetExtFromString(const std::string& str) { 110 | size_t pos = str.rfind("."); 111 | if (pos == std::string::npos) { 112 | return ""; 113 | } 114 | size_t slash_pos = str.rfind("/"); 115 | if (slash_pos != std::string::npos && slash_pos > pos) { 116 | // Don't want to detect "df/file" from "/as.df/file" 117 | return ""; 118 | } 119 | std::string ext = str.substr(pos); 120 | tolower(ext); 121 | 122 | return ext; 123 | } 124 | 125 | std::string PathUWP::GetFileExtension() const { 126 | return GetExtFromString(path_); 127 | } 128 | 129 | std::string PathUWP::GetDirectory() const { 130 | size_t pos = path_.rfind('/'); 131 | if (type_ == PathTypeUWP::HTTP) { 132 | // Things are a bit different for HTTP, because we probably ended with /. 133 | if (pos + 1 == path_.size()) { 134 | pos = path_.rfind('/', pos - 1); 135 | if (pos != path_.npos && pos > 8) { 136 | return path_.substr(0, pos + 1); 137 | } 138 | } 139 | } 140 | 141 | if (pos != std::string::npos) { 142 | if (pos == 0) { 143 | return "/"; // We're at the root. 144 | } 145 | return path_.substr(0, pos); 146 | } 147 | else if (path_.size() == 2 && path_[1] == ':') { 148 | // Windows fake-root. 149 | return "/"; 150 | } 151 | else { 152 | // There could be a ':', too. Unlike the slash, let's include that 153 | // in the returned directory. 154 | size_t c_pos = path_.rfind(':'); 155 | if (c_pos != std::string::npos) { 156 | return path_.substr(0, c_pos + 1); 157 | } 158 | } 159 | // No directory components, we're a relative path. 160 | return path_; 161 | } 162 | 163 | bool PathUWP::FilePathContainsNoCase(const std::string& needle) const { 164 | std::string haystack; 165 | 166 | haystack = path_; 167 | auto pred = [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }; 168 | auto found = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), pred); 169 | return found != haystack.end(); 170 | } 171 | 172 | bool PathUWP::StartsWith(const PathUWP& other) const { 173 | if (type_ != other.type_) { 174 | // Bad 175 | return false; 176 | } 177 | return starts_with(path_, other.path_); 178 | } 179 | 180 | const std::string& PathUWP::ToString() const { 181 | return path_; 182 | } 183 | 184 | std::wstring PathUWP::ToWString() const { 185 | std::wstring w = convertToWString(path_); 186 | for (size_t i = 0; i < w.size(); i++) { 187 | if (w[i] == '/') { 188 | w[i] = '\\'; 189 | } 190 | } 191 | return w; 192 | } 193 | 194 | std::string PathUWP::ToVisualString() const { 195 | if (type_ == PathTypeUWP::NATIVE) { 196 | return replace2(path_, "/", "\\"); 197 | } 198 | else { 199 | return path_; 200 | } 201 | } 202 | 203 | bool PathUWP::CanNavigateUp() const { 204 | if (path_ == "/" || path_.empty()) { 205 | return false; 206 | } 207 | if (type_ == PathTypeUWP::HTTP) { 208 | size_t rootSlash = path_.find_first_of('/', strlen("https://")); 209 | if (rootSlash == path_.npos || path_.size() < rootSlash + 1) { 210 | // This means, "http://server" or "http://server/". Can't go up. 211 | return false; 212 | } 213 | } 214 | return true; 215 | } 216 | 217 | PathUWP PathUWP::NavigateUp() const { 218 | std::string dir = GetDirectory(); 219 | return PathUWP(dir); 220 | } 221 | 222 | PathUWP PathUWP::GetRootVolume() const { 223 | if (!IsAbsolute()) { 224 | // Can't do anything 225 | return PathUWP(path_); 226 | } 227 | 228 | if (path_[1] == ':') { 229 | // Windows path with drive letter 230 | std::string path = path_.substr(0, 2); 231 | return PathUWP(path); 232 | } 233 | // Support UNC and device paths. 234 | if (path_[0] == '/' && path_[1] == '/') { 235 | size_t next = 2; 236 | if ((path_[2] == '.' || path_[2] == '?') && path_[3] == '/') { 237 | // Device path, or "\\.\UNC" path, skip the dot and consider the device the root. 238 | next = 4; 239 | } 240 | 241 | size_t len = path_.find_first_of('/', next); 242 | return PathUWP(path_.substr(0, len)); 243 | } 244 | return PathUWP("/"); 245 | } 246 | 247 | bool PathUWP::IsAbsolute() const { 248 | if (path_.empty()) 249 | return true; 250 | else if (path_.front() == '/') 251 | return true; 252 | else if (path_.size() > 3 && path_[1] == ':') 253 | return true; // Windows path with drive letter 254 | else 255 | return false; 256 | } 257 | 258 | bool PathUWP::ComputePathTo(const PathUWP& other, std::string& path) const { 259 | if (other == *this) { 260 | path.clear(); 261 | return true; 262 | } 263 | 264 | if (!other.StartsWith(*this)) { 265 | // Can't do this. Should return an error. 266 | return false; 267 | } 268 | 269 | if (*this == other) { 270 | // Equal, the path is empty. 271 | path.clear(); 272 | return true; 273 | } 274 | 275 | if (path_ == "/") { 276 | path = other.path_.substr(1); 277 | return true; 278 | } 279 | else { 280 | path = other.path_.substr(path_.size() + 1); 281 | return true; 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StoragePath.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Based on 'Path' from PPSSPP 3 | // For updates check: https://github.com/basharast/UWP2Win32 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #define HOST_IS_CASE_SENSITIVE 0 10 | 11 | enum class PathTypeUWP { 12 | UNDEFINED = 0, 13 | NATIVE = 1, // Can be relative. 14 | CONTENT_URI = 2, // Android only. Can only be absolute! 15 | HTTP = 3, // http://, https:// 16 | }; 17 | 18 | // Windows paths are always stored with '/' slashes in a Path. 19 | // On .ToWString(), they are flipped back to '\'. 20 | 21 | class PathUWP { 22 | private: 23 | void Init(const std::string& str); 24 | 25 | public: 26 | PathUWP() : type_(PathTypeUWP::UNDEFINED) {} 27 | explicit PathUWP(const std::string& str); 28 | 29 | explicit PathUWP(const std::wstring& str); 30 | 31 | PathTypeUWP Type() const { 32 | return type_; 33 | } 34 | 35 | bool Valid() const { return !path_.empty(); } 36 | bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash. 37 | 38 | // Some std::string emulation for simplicity. 39 | bool empty() const { return !Valid(); } 40 | void clear() { 41 | type_ = PathTypeUWP::UNDEFINED; 42 | path_.clear(); 43 | } 44 | size_t size() const { 45 | return path_.size(); 46 | } 47 | 48 | // WARNING: Potentially unsafe usage, if it's not NATIVE. 49 | const char* c_str() const { 50 | return path_.c_str(); 51 | } 52 | 53 | bool IsAbsolute() const; 54 | 55 | // Returns a path extended with a subdirectory. 56 | PathUWP operator /(const std::string& subdir) const; 57 | 58 | // Navigates down into a subdir. 59 | void operator /=(const std::string& subdir); 60 | 61 | // File extension manipulation. 62 | PathUWP WithExtraExtension(const std::string& ext) const; 63 | PathUWP WithReplacedExtension(const std::string& oldExtension, const std::string& newExtension) const; 64 | PathUWP WithReplacedExtension(const std::string& newExtension) const; 65 | 66 | // Removes the last component. 67 | std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension. 68 | std::string GetFileExtension() const; // Always lowercase return. Includes the dot. 69 | std::string GetDirectory() const; 70 | 71 | const std::string& ToString() const; 72 | 73 | std::wstring ToWString() const; 74 | 75 | std::string ToVisualString() const; 76 | 77 | bool CanNavigateUp() const; 78 | PathUWP NavigateUp() const; 79 | 80 | // Navigates as far up as possible from this path. If not possible to navigate upwards, returns the same path. 81 | // Not actually always the root of the volume, especially on systems like Mac and Linux where things are often mounted. 82 | // For Android directory trees, navigates to the root of the tree. 83 | PathUWP GetRootVolume() const; 84 | 85 | bool ComputePathTo(const PathUWP& other, std::string& path) const; 86 | 87 | bool operator ==(const PathUWP& other) const { 88 | return path_ == other.path_ && type_ == other.type_; 89 | } 90 | bool operator !=(const PathUWP& other) const { 91 | return path_ != other.path_ || type_ != other.type_; 92 | } 93 | 94 | bool FilePathContainsNoCase(const std::string& needle) const; 95 | 96 | bool StartsWith(const PathUWP& other) const; 97 | 98 | bool operator <(const PathUWP& other) const { 99 | return path_ < other.path_; 100 | } 101 | bool operator >(const PathUWP& other) const { 102 | return path_ > other.path_; 103 | } 104 | 105 | private: 106 | // The internal representation is currently always the plain string. 107 | // For CPU efficiency we could keep an AndroidStorageContentURI too, 108 | // but I don't think the encode/decode cost is significant. We simply create 109 | // those for processing instead. 110 | std::string path_; 111 | 112 | PathTypeUWP type_; 113 | }; 114 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StoragePickers.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #include "StorageLog.h" 7 | #include "StorageExtensions.h" 8 | #include "StorageAsync.h" 9 | #include "StorageAccess.h" 10 | #include "StoragePickers.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace winrt::Windows::Storage; 22 | 23 | extern void AddItemToFutureList(IStorageItem folder); 24 | 25 | // Call folder picker (the selected folder will be added to future list) 26 | winrt::hstring PickSingleFolder() 27 | { 28 | auto folderPicker{ Pickers::FolderPicker() }; 29 | folderPicker.SuggestedStartLocation(Pickers::PickerLocationId::Desktop); 30 | folderPicker.FileTypeFilter().Append(L"*"); 31 | 32 | auto folder = WaitTask(folderPicker.PickSingleFolderAsync()); 33 | winrt::hstring path = {}; 34 | if (folder != nullptr) 35 | { 36 | AddItemToFutureList(folder); 37 | path = folder.Path(); 38 | } 39 | return path; 40 | } 41 | 42 | // Call file picker (the selected file will be added to future list) 43 | winrt::hstring PickSingleFile(std::vector exts) 44 | { 45 | auto filePicker{ Pickers::FileOpenPicker() }; 46 | filePicker.SuggestedStartLocation(Pickers::PickerLocationId::Desktop); 47 | filePicker.ViewMode(Pickers::PickerViewMode::List); 48 | 49 | if (exts.size() > 0) { 50 | for (auto ext : exts) { 51 | filePicker.FileTypeFilter().Append(convert(ext)); 52 | } 53 | } 54 | else 55 | { 56 | filePicker.FileTypeFilter().Append(L"*"); 57 | } 58 | auto file = WaitTask(filePicker.PickSingleFileAsync()); 59 | 60 | winrt::hstring path = {}; 61 | if (file != nullptr) 62 | { 63 | AddItemToFutureList(file); 64 | path = file.Path(); 65 | } 66 | return path; 67 | } 68 | 69 | 70 | std::string ChooseFile(std::vector exts) { 71 | return convert(PickSingleFile(exts)); 72 | } 73 | 74 | std::string ChooseFolder() { 75 | return convert(PickSingleFolder()); 76 | } 77 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/StoragePickers.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | std::string ChooseFolder(); 14 | std::string ChooseFile(std::vector exts); 15 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UIHelpers.cpp: -------------------------------------------------------------------------------- 1 | // UWP UI HELPER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "UIHelpers.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace winrt::Windows::System; 18 | using namespace winrt::Windows::Foundation; 19 | using namespace winrt::Windows::UI::Core; 20 | using namespace winrt::Windows::UI::ViewManagement; 21 | using namespace winrt::Windows::ApplicationModel::Core; 22 | using namespace winrt::Windows::Data::Xml::Dom; 23 | using namespace winrt::Windows::UI::Notifications; 24 | 25 | #pragma region Input Keyboard 26 | void ShowInputKeyboard() { 27 | InputPane::GetForCurrentView().TryShow(); 28 | } 29 | 30 | void HideInputKeyboard() { 31 | InputPane::GetForCurrentView().TryHide(); 32 | } 33 | #pragma endregion 34 | 35 | #pragma region Keys Status 36 | bool IsCapsLockOn() { 37 | auto capsLockState = CoreApplication::MainView().CoreWindow().GetKeyState(VirtualKey::CapitalLock); 38 | return (capsLockState == CoreVirtualKeyStates::Locked); 39 | } 40 | bool IsShiftOnHold() { 41 | auto shiftState = CoreApplication::MainView().CoreWindow().GetKeyState(VirtualKey::Shift); 42 | return (shiftState == CoreVirtualKeyStates::Down); 43 | } 44 | bool IsCtrlOnHold() { 45 | auto ctrlState = CoreApplication::MainView().CoreWindow().GetKeyState(VirtualKey::Control); 46 | return (ctrlState == CoreVirtualKeyStates::Down); 47 | } 48 | #pragma endregion 49 | 50 | #pragma region Notifications 51 | void ShowToastNotification(std::string title, std::string message) { 52 | ToastNotifier toastNotifier = ToastNotificationManager::CreateToastNotifier(); 53 | XmlDocument toastXml = ToastNotificationManager::GetTemplateContent(ToastTemplateType::ToastText02); 54 | XmlNodeList toastNodeList = toastXml.GetElementsByTagName(L"text"); 55 | toastNodeList.Item(0).AppendChild(toastXml.CreateTextNode(convert(title))); 56 | toastNodeList.Item(1).AppendChild(toastXml.CreateTextNode(convert(message))); 57 | IXmlNode toastNode = toastXml.SelectSingleNode(L"/toast"); 58 | XmlElement audio = toastXml.CreateElement(L"audio"); 59 | audio.SetAttribute(L"src", L"ms-winsoundevent:Notification.SMS"); 60 | ToastNotification toast{ ToastNotification(toastXml) }; 61 | toastNotifier.Show(toast); 62 | } 63 | #pragma endregion 64 | 65 | 66 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UIHelpers.h: -------------------------------------------------------------------------------- 1 | // UWP UI HELPER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | #include "StorageExtensions.h" 8 | 9 | // Input Handler 10 | void ShowInputKeyboard(); 11 | void HideInputKeyboard(); 12 | 13 | 14 | // Keys Status 15 | bool IsCapsLockOn(); 16 | bool IsShiftOnHold(); 17 | bool IsCtrlOnHold(); 18 | 19 | // Notifications 20 | void ShowToastNotification(std::string title, std::string message); 21 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWP2C.cpp: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // This is small bridge to invoke UWP Storage manager 8 | 9 | #include "UWP2C.h" 10 | #include "StorageManager.h" 11 | #include "StorageExtensions.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode) { 17 | std::string fn = convert(path); 18 | 19 | return (void*)CreateFileUWP(fn, accessMode, shareMode, openMode); 20 | } 21 | 22 | int GetFileAttributesUWP(const void* name, void* lpFileInformation) { 23 | size_t size = sizeof(WIN32_FILE_ATTRIBUTE_DATA); 24 | WIN32_FILE_ATTRIBUTE_DATA* file_attributes = (WIN32_FILE_ATTRIBUTE_DATA*)(malloc(size)); 25 | 26 | std::string fn = convert((const char*)name); 27 | HANDLE handle = CreateFileUWP(fn); 28 | 29 | FILETIME createTime{}; 30 | FILETIME changeTime{}; 31 | 32 | DWORD fileSizeHigh = 0; 33 | DWORD fileSizeLow = 0; 34 | DWORD fileAttributes = 32; 35 | 36 | if (handle != INVALID_HANDLE_VALUE) { 37 | size_t size = sizeof(FILE_BASIC_INFO); 38 | FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size)); 39 | if (information) { 40 | if (FALSE != GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) { 41 | createTime.dwHighDateTime = information->CreationTime.HighPart; 42 | createTime.dwLowDateTime = information->CreationTime.LowPart; 43 | changeTime.dwHighDateTime = information->ChangeTime.HighPart; 44 | changeTime.dwLowDateTime = information->ChangeTime.LowPart; 45 | fileAttributes = information->FileAttributes; 46 | } 47 | } 48 | LARGE_INTEGER fsize{ 0 }; 49 | if (FALSE == GetFileSizeEx(handle, &fsize)) { 50 | LARGE_INTEGER end_offset; 51 | const LARGE_INTEGER zero{}; 52 | if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) { 53 | CloseHandle(handle); 54 | } 55 | else { 56 | fileSizeHigh = (DWORD)end_offset.HighPart; 57 | fileSizeLow = (DWORD)end_offset.LowPart; 58 | SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN); 59 | CloseHandle(handle); 60 | } 61 | } 62 | else { 63 | fileSizeHigh = (DWORD)fsize.HighPart; 64 | fileSizeLow = (DWORD)fsize.LowPart; 65 | 66 | CloseHandle(handle); 67 | } 68 | } 69 | 70 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftCreationTime = createTime; 71 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastAccessTime = changeTime; 72 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastWriteTime = changeTime; 73 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeHigh = fileSizeHigh; 74 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeLow = fileSizeLow; 75 | ((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->dwFileAttributes = fileAttributes; 76 | 77 | return 1; 78 | } 79 | 80 | int DeleteFileUWP(const void* name) { 81 | std::string fn = convert((const char*)name); 82 | bool state = DeleteUWP(fn); 83 | 84 | return state ? 1 : 0; 85 | } 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWP2C.h: -------------------------------------------------------------------------------- 1 | // UWP STORAGE MANAGER 2 | // Copyright (c) 2023-2024 Bashar Astifan. 3 | // Email: bashar@astifan.online 4 | // Telegram: @basharastifan 5 | // GitHub: https://github.com/basharast/UWP2Win32 6 | 7 | // This is small bridge to invoke UWP Storage manager 8 | 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode); 16 | int GetFileAttributesUWP(const void* name, void* lpFileInformation); 17 | int DeleteFileUWP(const void* name); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33829.357 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UWPHelpersRT", "UWPHelpersRT\UWPHelpersRT.vcxproj", "{BE33ED73-E741-47F5-BD8F-D71F737CB036}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM.Build.0 = Debug|ARM 22 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x64.ActiveCfg = Debug|x64 27 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x64.Build.0 = Debug|x64 28 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x64.Deploy.0 = Debug|x64 29 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x86.ActiveCfg = Debug|Win32 30 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x86.Build.0 = Debug|Win32 31 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Debug|x86.Deploy.0 = Debug|Win32 32 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM.ActiveCfg = Release|ARM 33 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM.Build.0 = Release|ARM 34 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM.Deploy.0 = Release|ARM 35 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM64.Build.0 = Release|ARM64 37 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x64.ActiveCfg = Release|x64 39 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x64.Build.0 = Release|x64 40 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x64.Deploy.0 = Release|x64 41 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x86.ActiveCfg = Release|Win32 42 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x86.Build.0 = Release|Win32 43 | {BE33ED73-E741-47F5-BD8F-D71F737CB036}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {A9641A66-145C-4586-A457-4753FE5FFBCF} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/StoreLogo.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basharast/UWP2Win32/fb3190f7bd28e69f57745d41eb4362197e74fd31/UWPHelpers (WinRT)/UWPHelpersRT/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 7 | 8 | 9 | UWPHelpersRT 10 | Bashar Astifan 11 | Assets\StoreLogo.png 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/UWPHelpersRT.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | sources 6 | 7 | 8 | sources 9 | 10 | 11 | sources 12 | 13 | 14 | imgui 15 | 16 | 17 | imgui 18 | 19 | 20 | imgui 21 | 22 | 23 | imgui 24 | 25 | 26 | imgui 27 | 28 | 29 | 30 | 31 | sources 32 | 33 | 34 | sources 35 | 36 | 37 | imgui 38 | 39 | 40 | imgui 41 | 42 | 43 | imgui 44 | 45 | 46 | 47 | 48 | Assets 49 | 50 | 51 | Assets 52 | 53 | 54 | Assets 55 | 56 | 57 | Assets 58 | 59 | 60 | Assets 61 | 62 | 63 | Assets 64 | 65 | 66 | Assets 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {db9086fe-bacc-4437-8272-1aa6642082db} 75 | 76 | 77 | {471c9fc1-b321-42c7-8019-9c5ba095670c} 78 | 79 | 80 | {11152085-f2a8-4cf7-af3c-43d65f2ac688} 81 | 82 | 83 | 84 | 85 | 86 | 87 | imgui 88 | 89 | 90 | imgui 91 | 92 | 93 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/UWPHelpersRT.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | true 6 | true 7 | true 8 | {be33ed73-e741-47f5-bd8f-d71f737cb036} 9 | UWPHelpersRT 10 | UWPHelpersRT 11 | en-US 12 | 15.0 13 | true 14 | Windows Store 15 | 10.0 16 | 10.0.19041.0 17 | 10.0.10240.0 18 | 19 | 20 | 21 | 22 | Debug 23 | ARM 24 | 25 | 26 | Debug 27 | ARM64 28 | 29 | 30 | Debug 31 | Win32 32 | 33 | 34 | Debug 35 | x64 36 | 37 | 38 | Release 39 | ARM 40 | 41 | 42 | Release 43 | ARM64 44 | 45 | 46 | Release 47 | Win32 48 | 49 | 50 | Release 51 | x64 52 | 53 | 54 | 55 | Application 56 | v143 57 | v142 58 | v141 59 | v140 60 | Unicode 61 | 62 | 63 | true 64 | true 65 | 66 | 67 | false 68 | true 69 | false 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 9F65A72F7B7496B7C77B690DE22E285EB35D102E 82 | True 83 | 84 | 85 | 86 | NotUsing 87 | pch.h 88 | $(IntDir)pch.pch 89 | Level4 90 | %(AdditionalOptions) /bigobj 91 | WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) 92 | $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) 93 | 94 | 95 | false 96 | 97 | 98 | 99 | 100 | _DEBUG;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions) 101 | 102 | 103 | 104 | 105 | NDEBUG;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions) 106 | 107 | 108 | true 109 | true 110 | 111 | 112 | 113 | 114 | Designer 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/UWPHelpersRT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Source 7 | 8 | 9 | Source 10 | 11 | 12 | Source 13 | 14 | 15 | Source 16 | 17 | 18 | Source 19 | 20 | 21 | Source 22 | 23 | 24 | Source 25 | 26 | 27 | Source 28 | 29 | 30 | Source 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {3914e9ab-525c-40dc-80ae-4283f0f813aa} 52 | 53 | 54 | 55 | 56 | Source 57 | 58 | 59 | Source 60 | 61 | 62 | Source 63 | 64 | 65 | Source 66 | 67 | 68 | Source 69 | 70 | 71 | Source 72 | 73 | 74 | Source 75 | 76 | 77 | Source 78 | 79 | 80 | Source 81 | 82 | 83 | Source 84 | 85 | 86 | Source 87 | 88 | 89 | Source 90 | 91 | 92 | Source 93 | 94 | 95 | Source 96 | 97 | 98 | Source 99 | 100 | 101 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using namespace winrt; 13 | 14 | using namespace Windows; 15 | using namespace Windows::ApplicationModel::Core; 16 | using namespace Windows::Foundation::Numerics; 17 | using namespace Windows::Graphics::Display; 18 | using namespace Windows::UI; 19 | using namespace Windows::UI::Core; 20 | 21 | struct App : implements 22 | { 23 | bool m_windowClosed = false; 24 | bool m_windowVisible = true; 25 | 26 | com_ptr m_pd3dDevice; 27 | com_ptr m_pd3dDeviceContext; 28 | com_ptr m_pSwapChain; 29 | com_ptr m_mainRenderTargetView; 30 | 31 | UINT m_ResizeWidth = 0, m_ResizeHeight = 0; 32 | Windows::Foundation::Size m_OldSize; 33 | 34 | IFrameworkView CreateView() 35 | { 36 | return *this; 37 | } 38 | 39 | void Initialize(CoreApplicationView const &) 40 | { 41 | } 42 | 43 | void Load(hstring const&) 44 | { 45 | } 46 | 47 | void Uninitialize() 48 | { 49 | } 50 | 51 | void Run() 52 | { 53 | CoreWindow window = CoreWindow::GetForCurrentThread(); 54 | CoreDispatcher dispatcher = window.Dispatcher(); 55 | window.Activate(); 56 | 57 | 58 | 59 | // High DPI scaling 60 | DisplayInformation currentDisplayInformation = DisplayInformation::GetForCurrentView(); 61 | float dpi = currentDisplayInformation.LogicalDpi() / 96.0f; 62 | 63 | 64 | while (!m_windowClosed) 65 | { 66 | if (m_windowVisible) 67 | { 68 | dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); 69 | 70 | // Handle window resize (we don't resize directly in the SizeChanged handler) 71 | if (m_ResizeWidth != 0 && m_ResizeHeight != 0) 72 | { 73 | CleanupRenderTarget(); 74 | HRESULT hr = m_pSwapChain->ResizeBuffers(2, lround(m_ResizeWidth), lround(m_ResizeHeight), DXGI_FORMAT_UNKNOWN, 0); 75 | m_ResizeWidth = m_ResizeHeight = 0; 76 | CreateRenderTarget(); 77 | } 78 | 79 | auto renderTargetView = m_mainRenderTargetView.get(); 80 | const float clear_color_with_alpha[4] = { 1, 1, 1, 1 }; 81 | 82 | m_pd3dDeviceContext->OMSetRenderTargets(1, &renderTargetView, nullptr); 83 | m_pd3dDeviceContext->ClearRenderTargetView(renderTargetView, clear_color_with_alpha); 84 | 85 | m_pSwapChain->Present(1, 0); 86 | } 87 | else 88 | { 89 | dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); 90 | } 91 | } 92 | } 93 | 94 | void SetWindow(CoreWindow const & window) 95 | { 96 | window.Closed({ this, &App::OnWindowClosed }); 97 | window.SizeChanged({ this, &App::OnSizeChanged }); 98 | window.VisibilityChanged({ this, &App::OnVisibiltyChanged }); 99 | 100 | D3D_FEATURE_LEVEL featureLevels[] = 101 | { 102 | D3D_FEATURE_LEVEL_12_1, 103 | D3D_FEATURE_LEVEL_12_0, 104 | D3D_FEATURE_LEVEL_11_1, 105 | D3D_FEATURE_LEVEL_11_0, 106 | D3D_FEATURE_LEVEL_10_1, 107 | D3D_FEATURE_LEVEL_10_0, 108 | D3D_FEATURE_LEVEL_9_3, 109 | D3D_FEATURE_LEVEL_9_2, 110 | D3D_FEATURE_LEVEL_9_1 111 | }; 112 | 113 | D3D_FEATURE_LEVEL featureLevel; 114 | 115 | HRESULT hr = D3D11CreateDevice( 116 | nullptr, 117 | D3D_DRIVER_TYPE_HARDWARE, 118 | 0, 119 | 0, 120 | featureLevels, 121 | ARRAYSIZE(featureLevels), 122 | D3D11_SDK_VERSION, 123 | m_pd3dDevice.put(), 124 | &featureLevel, 125 | m_pd3dDeviceContext.put() 126 | ); 127 | 128 | if (FAILED(hr)) 129 | { 130 | winrt::check_hresult( 131 | D3D11CreateDevice( 132 | nullptr, 133 | D3D_DRIVER_TYPE_WARP, 134 | 0, 135 | 0, 136 | featureLevels, 137 | ARRAYSIZE(featureLevels), 138 | D3D11_SDK_VERSION, 139 | m_pd3dDevice.put(), 140 | &featureLevel, 141 | m_pd3dDeviceContext.put() 142 | ) 143 | ); 144 | } 145 | 146 | DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; 147 | 148 | swapChainDesc.Width = 0; 149 | swapChainDesc.Height = 0; 150 | swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 151 | swapChainDesc.Stereo = false; 152 | swapChainDesc.SampleDesc.Count = 1; 153 | swapChainDesc.SampleDesc.Quality = 0; 154 | swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 155 | swapChainDesc.BufferCount = 2; 156 | swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; 157 | swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 158 | swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; 159 | 160 | // This sequence obtains the DXGI factory that was used to create the Direct3D device above. 161 | com_ptr dxgiDevice; 162 | m_pd3dDevice.as(dxgiDevice); 163 | 164 | com_ptr dxgiAdapter; 165 | winrt::check_hresult( 166 | dxgiDevice->GetAdapter(dxgiAdapter.put()) 167 | ); 168 | 169 | com_ptr dxgiFactory; 170 | winrt::check_hresult( 171 | dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)) 172 | ); 173 | 174 | winrt::check_hresult( 175 | dxgiFactory->CreateSwapChainForCoreWindow( 176 | m_pd3dDevice.get(), 177 | winrt::get_unknown(window), 178 | &swapChainDesc, 179 | nullptr, 180 | m_pSwapChain.put() 181 | ) 182 | ); 183 | 184 | winrt::check_hresult( 185 | dxgiDevice->SetMaximumFrameLatency(1) 186 | ); 187 | 188 | CreateRenderTarget(); 189 | } 190 | 191 | void OnSizeChanged(IInspectable const &, WindowSizeChangedEventArgs const & args) 192 | { 193 | auto size = args.Size(); 194 | 195 | // Prevent unnecessary resize 196 | if (size != m_OldSize) 197 | { 198 | m_ResizeWidth = size.Width; 199 | m_ResizeHeight = size.Height; 200 | } 201 | 202 | m_OldSize = size; 203 | } 204 | 205 | void OnVisibiltyChanged(IInspectable const&, VisibilityChangedEventArgs const& args) 206 | { 207 | m_windowVisible = args.Visible(); 208 | } 209 | 210 | void OnWindowClosed(IInspectable const&, CoreWindowEventArgs const& args) 211 | { 212 | m_windowClosed = true; 213 | } 214 | 215 | void CreateRenderTarget() 216 | { 217 | com_ptr pBackBuffer; 218 | m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(pBackBuffer.put())); 219 | m_pd3dDevice->CreateRenderTargetView(pBackBuffer.get(), nullptr, m_mainRenderTargetView.put()); 220 | } 221 | 222 | void CleanupRenderTarget() 223 | { 224 | m_mainRenderTargetView = nullptr; 225 | } 226 | }; 227 | 228 | int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) 229 | { 230 | CoreApplication::Run(make()); 231 | } 232 | -------------------------------------------------------------------------------- /UWPHelpers (WinRT)/UWPHelpersRT/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------