diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index 933fe1f1d81c..46e7ac64ac2d 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.3.0 +* Replaces `win32` dependency with direct FFI usage. * Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. ## 2.2.1 diff --git a/packages/path_provider/path_provider_windows/lib/src/folders.dart b/packages/path_provider/path_provider_windows/lib/src/folders.dart index 55def29df2d7..022aba45d602 100644 --- a/packages/path_provider/path_provider_windows/lib/src/folders.dart +++ b/packages/path_provider/path_provider_windows/lib/src/folders.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:win32/win32.dart'; - // ignore_for_file: non_constant_identifier_names // ignore: avoid_classes_with_only_static_members @@ -11,122 +9,127 @@ import 'package:win32/win32.dart'; /// known folders. A property of this class may be passed to the `getPath` /// method in the [PathProvidersWindows] class to retrieve a known folder from /// Windows. +// These constants come from +// https://learn.microsoft.com/windows/win32/shell/knownfolderid class WindowsKnownFolder { /// The file system directory that is used to store administrative tools for /// an individual user. The MMC will save customized consoles to this /// directory, and it will roam with the user. - static String get AdminTools => FOLDERID_AdminTools; + static String get AdminTools => '{724EF170-A42D-4FEF-9F26-B60E846FBA4F}'; /// The file system directory that acts as a staging area for files waiting to /// be written to a CD. A typical path is C:\Documents and /// Settings\username\Local Settings\Application Data\Microsoft\CD Burning. - static String get CDBurning => FOLDERID_CDBurning; + static String get CDBurning => '{9E52AB10-F80D-49DF-ACB8-4330F5687855}'; /// The file system directory that contains administrative tools for all users /// of the computer. - static String get CommonAdminTools => FOLDERID_CommonAdminTools; + static String get CommonAdminTools => + '{D0384E7D-BAC3-4797-8F14-CBA229B392B5}'; /// The file system directory that contains the directories for the common /// program groups that appear on the Start menu for all users. A typical path /// is C:\Documents and Settings\All Users\Start Menu\Programs. - static String get CommonPrograms => FOLDERID_CommonPrograms; + static String get CommonPrograms => '{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}'; /// The file system directory that contains the programs and folders that /// appear on the Start menu for all users. A typical path is C:\Documents and /// Settings\All Users\Start Menu. - static String get CommonStartMenu => FOLDERID_CommonStartMenu; + static String get CommonStartMenu => '{A4115719-D62E-491D-AA7C-E74B8BE3B067}'; /// The file system directory that contains the programs that appear in the /// Startup folder for all users. A typical path is C:\Documents and /// Settings\All Users\Start Menu\Programs\Startup. - static String get CommonStartup => FOLDERID_CommonStartup; + static String get CommonStartup => '{82A5EA35-D9CD-47C5-9629-E15D2F714E6E}'; /// The file system directory that contains the templates that are available /// to all users. A typical path is C:\Documents and Settings\All /// Users\Templates. - static String get CommonTemplates => FOLDERID_CommonTemplates; + static String get CommonTemplates => '{B94237E7-57AC-4347-9151-B08C6C32D1F7}'; /// The virtual folder that represents My Computer, containing everything on /// the local computer: storage devices, printers, and Control Panel. The /// folder can also contain mapped network drives. - static String get ComputerFolder => FOLDERID_ComputerFolder; + static String get ComputerFolder => '{0AC0837C-BBF8-452A-850D-79D08E667CA7}'; /// The virtual folder that represents Network Connections, that contains /// network and dial-up connections. - static String get ConnectionsFolder => FOLDERID_ConnectionsFolder; + static String get ConnectionsFolder => + '{6F0CD92B-2E97-45D1-88FF-B0D186B8DEDD}'; /// The virtual folder that contains icons for the Control Panel applications. - static String get ControlPanelFolder => FOLDERID_ControlPanelFolder; + static String get ControlPanelFolder => + '{82A74AEB-AEB4-465C-A014-D097EE346D63}'; /// The file system directory that serves as a common repository for Internet /// cookies. A typical path is C:\Documents and Settings\username\Cookies. - static String get Cookies => FOLDERID_Cookies; + static String get Cookies => '{2B0F765D-C0E9-4171-908E-08A611B84FF6}'; /// The virtual folder that represents the Windows desktop, the root of the /// namespace. - static String get Desktop => FOLDERID_Desktop; + static String get Desktop => '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}'; /// The virtual folder that represents the My Documents desktop item. - static String get Documents => FOLDERID_Documents; + static String get Documents => '{FDD39AD0-238F-46AF-ADB4-6C85480369C7}'; /// The file system directory that serves as a repository for Internet /// downloads. - static String get Downloads => FOLDERID_Downloads; + static String get Downloads => '{374DE290-123F-4565-9164-39C4925E467B}'; /// The file system directory that serves as a common repository for the /// user's favorite items. A typical path is C:\Documents and /// Settings\username\Favorites. - static String get Favorites => FOLDERID_Favorites; + static String get Favorites => '{1777F761-68AD-4D8A-87BD-30B759FA33DD}'; /// A virtual folder that contains fonts. A typical path is C:\Windows\Fonts. - static String get Fonts => FOLDERID_Fonts; + static String get Fonts => '{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}'; /// The file system directory that serves as a common repository for Internet /// history items. - static String get History => FOLDERID_History; + static String get History => '{D9DC8A3B-B784-432E-A781-5A1130A75963}'; /// The file system directory that serves as a common repository for temporary /// Internet files. A typical path is C:\Documents and Settings\username\Local /// Settings\Temporary Internet Files. - static String get InternetCache => FOLDERID_InternetCache; + static String get InternetCache => '{352481E8-33BE-4251-BA85-6007CAEDCF9D}'; /// A virtual folder for Internet Explorer. - static String get InternetFolder => FOLDERID_InternetFolder; + static String get InternetFolder => '{4D9F7874-4E0C-4904-967B-40B0D20C3E4B}'; /// The file system directory that serves as a data repository for local /// (nonroaming) applications. A typical path is C:\Documents and /// Settings\username\Local Settings\Application Data. - static String get LocalAppData => FOLDERID_LocalAppData; + static String get LocalAppData => '{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}'; /// The file system directory that serves as a common repository for music /// files. A typical path is C:\Documents and Settings\User\My Documents\My /// Music. - static String get Music => FOLDERID_Music; + static String get Music => '{4BD8D571-6D19-48D3-BE97-422220080E43}'; /// A file system directory that contains the link objects that may exist in /// the My Network Places virtual folder. A typical path is C:\Documents and /// Settings\username\NetHood. - static String get NetHood => FOLDERID_NetHood; + static String get NetHood => '{C5ABBF53-E17F-4121-8900-86626FC2C973}'; /// The folder that represents other computers in your workgroup. - static String get NetworkFolder => FOLDERID_NetworkFolder; + static String get NetworkFolder => '{D20BEEC4-5CA8-4905-AE3B-BF251EA09B53}'; /// The file system directory that serves as a common repository for image /// files. A typical path is C:\Documents and Settings\username\My /// Documents\My Pictures. - static String get Pictures => FOLDERID_Pictures; + static String get Pictures => '{33E28130-4E1E-4676-835A-98395C3BC3BB}'; /// The file system directory that contains the link objects that can exist in /// the Printers virtual folder. A typical path is C:\Documents and /// Settings\username\PrintHood. - static String get PrintHood => FOLDERID_PrintHood; + static String get PrintHood => '{9274BD8D-CFD1-41C3-B35E-B13F55A758F4}'; /// The virtual folder that contains installed printers. - static String get PrintersFolder => FOLDERID_PrintersFolder; + static String get PrintersFolder => '{76FC4E2D-D6AD-4519-A663-37BD56068185}'; /// The user's profile folder. A typical path is C:\Users\username. /// Applications should not create files or folders at this level. - static String get Profile => FOLDERID_Profile; + static String get Profile => '{5E6C858F-0E22-4760-9AFE-EA3317B67173}'; /// The file system directory that contains application data for all users. A /// typical path is C:\Documents and Settings\All Users\Application Data. This @@ -134,110 +137,114 @@ class WindowsKnownFolder { /// example, an application can store a spell-check dictionary, a database of /// clip art, or a log file in the CSIDL_COMMON_APPDATA folder. This /// information will not roam and is available to anyone using the computer. - static String get ProgramData => FOLDERID_ProgramData; + static String get ProgramData => '{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}'; /// The Program Files folder. A typical path is C:\Program Files. - static String get ProgramFiles => FOLDERID_ProgramFiles; + static String get ProgramFiles => '{905e63b6-c1bf-494e-b29c-65b732d3d21a}'; /// The common Program Files folder. A typical path is C:\Program /// Files\Common. - static String get ProgramFilesCommon => FOLDERID_ProgramFilesCommon; + static String get ProgramFilesCommon => + '{F7F1ED05-9F6D-47A2-AAAE-29D317C6F066}'; /// On 64-bit systems, a link to the common Program Files folder. A typical path is /// C:\Program Files\Common Files. - static String get ProgramFilesCommonX64 => FOLDERID_ProgramFilesCommonX64; + static String get ProgramFilesCommonX64 => + '{6365D5A7-0F0D-45e5-87F6-0DA56B6A4F7D}'; /// On 64-bit systems, a link to the 32-bit common Program Files folder. A /// typical path is C:\Program Files (x86)\Common Files. On 32-bit systems, a /// link to the Common Program Files folder. - static String get ProgramFilesCommonX86 => FOLDERID_ProgramFilesCommonX86; + static String get ProgramFilesCommonX86 => + '{DE974D24-D9C6-4D3E-BF91-F4455120B917}'; /// On 64-bit systems, a link to the Program Files folder. A typical path is /// C:\Program Files. - static String get ProgramFilesX64 => FOLDERID_ProgramFilesX64; + static String get ProgramFilesX64 => '{6D809377-6AF0-444b-8957-A3773F02200E}'; /// On 64-bit systems, a link to the 32-bit Program Files folder. A typical /// path is C:\Program Files (x86). On 32-bit systems, a link to the Common /// Program Files folder. - static String get ProgramFilesX86 => FOLDERID_ProgramFilesX86; + static String get ProgramFilesX86 => '{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}'; /// The file system directory that contains the user's program groups (which /// are themselves file system directories). - static String get Programs => FOLDERID_Programs; + static String get Programs => '{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}'; /// The file system directory that contains files and folders that appear on /// the desktop for all users. A typical path is C:\Documents and Settings\All /// Users\Desktop. - static String get PublicDesktop => FOLDERID_PublicDesktop; + static String get PublicDesktop => '{C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}'; /// The file system directory that contains documents that are common to all /// users. A typical path is C:\Documents and Settings\All Users\Documents. - static String get PublicDocuments => FOLDERID_PublicDocuments; + static String get PublicDocuments => '{ED4824AF-DCE4-45A8-81E2-FC7965083634}'; /// The file system directory that serves as a repository for music files /// common to all users. A typical path is C:\Documents and Settings\All /// Users\Documents\My Music. - static String get PublicMusic => FOLDERID_PublicMusic; + static String get PublicMusic => '{3214FAB5-9757-4298-BB61-92A9DEAA44FF}'; /// The file system directory that serves as a repository for image files /// common to all users. A typical path is C:\Documents and Settings\All /// Users\Documents\My Pictures. - static String get PublicPictures => FOLDERID_PublicPictures; + static String get PublicPictures => '{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}'; /// The file system directory that serves as a repository for video files /// common to all users. A typical path is C:\Documents and Settings\All /// Users\Documents\My Videos. - static String get PublicVideos => FOLDERID_PublicVideos; + static String get PublicVideos => '{2400183A-6185-49FB-A2D8-4A392A602BA3}'; /// The file system directory that contains shortcuts to the user's most /// recently used documents. A typical path is C:\Documents and /// Settings\username\My Recent Documents. - static String get Recent => FOLDERID_Recent; + static String get Recent => '{AE50C081-EBD2-438A-8655-8A092E34987A}'; /// The virtual folder that contains the objects in the user's Recycle Bin. - static String get RecycleBinFolder => FOLDERID_RecycleBinFolder; + static String get RecycleBinFolder => + '{B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC}'; /// The file system directory that contains resource data. A typical path is /// C:\Windows\Resources. - static String get ResourceDir => FOLDERID_ResourceDir; + static String get ResourceDir => '{8AD10C31-2ADB-4296-A8F7-E4701232C972}'; /// The file system directory that serves as a common repository for /// application-specific data. A typical path is C:\Documents and /// Settings\username\Application Data. - static String get RoamingAppData => FOLDERID_RoamingAppData; + static String get RoamingAppData => '{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}'; /// The file system directory that contains Send To menu items. A typical path /// is C:\Documents and Settings\username\SendTo. - static String get SendTo => FOLDERID_SendTo; + static String get SendTo => '{8983036C-27C0-404B-8F08-102D10DCFD74}'; /// The file system directory that contains Start menu items. A typical path /// is C:\Documents and Settings\username\Start Menu. - static String get StartMenu => FOLDERID_StartMenu; + static String get StartMenu => '{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}'; /// The file system directory that corresponds to the user's Startup program /// group. The system starts these programs whenever the associated user logs /// on. A typical path is C:\Documents and Settings\username\Start /// Menu\Programs\Startup. - static String get Startup => FOLDERID_Startup; + static String get Startup => '{B97D20BB-F46A-4C97-BA10-5E3608430854}'; /// The Windows System folder. A typical path is C:\Windows\System32. - static String get System => FOLDERID_System; + static String get System => '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}'; /// The 32-bit Windows System folder. On 32-bit systems, this is typically /// C:\Windows\system32. On 64-bit systems, this is typically /// C:\Windows\syswow64. - static String get SystemX86 => FOLDERID_SystemX86; + static String get SystemX86 => '{D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}'; /// The file system directory that serves as a common repository for document /// templates. A typical path is C:\Documents and Settings\username\Templates. - static String get Templates => FOLDERID_Templates; + static String get Templates => '{A63293E8-664E-48DB-A079-DF759E0509F7}'; /// The file system directory that serves as a common repository for video /// files. A typical path is C:\Documents and Settings\username\My /// Documents\My Videos. - static String get Videos => FOLDERID_Videos; + static String get Videos => '{18989B1D-99B5-455B-841C-AB7C74E4DDFC}'; /// The Windows directory or SYSROOT. This corresponds to the %windir% or /// %SYSTEMROOT% environment variables. A typical path is C:\Windows. - static String get Windows => FOLDERID_Windows; + static String get Windows => '{F38BF404-1D43-42F2-9305-67DE0B28FC23}'; } diff --git a/packages/path_provider/path_provider_windows/lib/src/guid.dart b/packages/path_provider/path_provider_windows/lib/src/guid.dart new file mode 100644 index 000000000000..84daffe6bed7 --- /dev/null +++ b/packages/path_provider/path_provider_windows/lib/src/guid.dart @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:typed_data'; + +/// Representation of the Win32 GUID struct. +// For the layout of this struct, see +// https://learn.microsoft.com/windows/win32/api/guiddef/ns-guiddef-guid +@Packed(4) +base class GUID extends Struct { + /// Native Data1 field. + @Uint32() + external int data1; + + /// Native Data2 field. + @Uint16() + external int data2; + + /// Native Data3 field. + @Uint16() + external int data3; + + /// Native Data4 field. + // This should be an eight-element byte array, but there's no such annotation. + @Uint64() + external int data4; + + /// Parses a GUID string, with optional enclosing "{}"s and optional "-"s, + /// into data. + void parse(String guid) { + final String hexOnly = guid.replaceAll(RegExp(r'[{}-]'), ''); + if (hexOnly.length != 32) { + throw ArgumentError.value(guid, 'guid', 'Invalid GUID string'); + } + final ByteData bytes = ByteData(16); + for (int i = 0; i < 16; ++i) { + bytes.setUint8( + i, int.parse(hexOnly.substring(i * 2, i * 2 + 2), radix: 16)); + } + data1 = bytes.getInt32(0); + data2 = bytes.getInt16(4); + data3 = bytes.getInt16(6); + // [bytes] is big endian, but the host is little endian, so a default + // big-endian read would reverse the bytes. Since data4 is supposed to be + // a byte array, the order should be preserved, so do a little-endian read. + // https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding + data4 = bytes.getInt64(8, Endian.little); + } +} diff --git a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart index 2faa599a5341..50f010ba56f2 100644 --- a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart +++ b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart @@ -7,11 +7,13 @@ import 'dart:io'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart' show visibleForTesting; +import 'package:flutter/services.dart'; import 'package:path/path.dart' as path; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; -import 'package:win32/win32.dart'; import 'folders.dart'; +import 'guid.dart'; +import 'win32_wrappers.dart'; /// Constant for en-US language used in VersionInfo keys. @visibleForTesting @@ -35,7 +37,7 @@ class VersionInfoQuerier { /// language and encoding, or null if there is no such entry, /// or if versionInfo is null. /// - /// See https://docs.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + /// See https://docs.microsoft.com/windows/win32/menurc/versioninfo-resource /// for list of possible language and encoding values. String? getStringValue( Pointer? versionInfo, @@ -49,7 +51,7 @@ class VersionInfoQuerier { return null; } final Pointer keyPath = - TEXT('\\StringFileInfo\\$language$encoding\\$key'); + '\\StringFileInfo\\$language$encoding\\$key'.toNativeUtf16(); final Pointer length = calloc(); final Pointer> valueAddress = calloc>(); try { @@ -89,7 +91,7 @@ class PathProviderWindows extends PathProviderPlatform { if (length == 0) { final int error = GetLastError(); - throw WindowsException(error); + throw _createWin32Exception(error); } else { path = buffer.toDartString(); @@ -134,7 +136,7 @@ class PathProviderWindows extends PathProviderPlatform { /// [WindowsKnownFolder]. Future getPath(String folderID) { final Pointer> pathPtrPtr = calloc>(); - final Pointer knownFolderID = calloc()..ref.setGUID(folderID); + final Pointer knownFolderID = calloc()..ref.parse(folderID); try { final int hr = SHGetKnownFolderPath( @@ -146,7 +148,7 @@ class PathProviderWindows extends PathProviderPlatform { if (FAILED(hr)) { if (hr == E_INVALIDARG || hr == E_FAIL) { - throw WindowsException(hr); + throw _createWin32Exception(hr); } return Future.value(); } @@ -179,7 +181,8 @@ class PathProviderWindows extends PathProviderPlatform { String? companyName; String? productName; - final Pointer moduleNameBuffer = wsalloc(MAX_PATH + 1); + final Pointer moduleNameBuffer = + calloc(MAX_PATH + 1).cast(); final Pointer unused = calloc(); Pointer? infoBuffer; try { @@ -188,7 +191,7 @@ class PathProviderWindows extends PathProviderPlatform { GetModuleFileName(0, moduleNameBuffer, MAX_PATH); if (moduleNameLength == 0) { final int error = GetLastError(); - throw WindowsException(error); + throw _createWin32Exception(error); } // From that, load the VERSIONINFO resource @@ -223,7 +226,7 @@ class PathProviderWindows extends PathProviderPlatform { } /// Makes [rawString] safe as a directory component. See - /// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions + /// https://docs.microsoft.com/windows/win32/fileio/naming-a-file#naming-conventions /// /// If after sanitizing the string is empty, returns null. String? _sanitizedDirectoryName(String? rawString) { @@ -263,3 +266,15 @@ class PathProviderWindows extends PathProviderPlatform { return directory.path; } } + +Exception _createWin32Exception(int errorCode) { + return PlatformException( + code: 'Win32 Error', + // TODO(stuartmorgan): Consider getting the system error message via + // FormatMessage if it turns out to be necessary for debugging issues. + // Plugin-client-level usability isn't a major consideration since per + // https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#platform-exception-handling + // any case that comes up in practice should be handled and returned + // via a plugin-specific exception, not this fallback. + message: 'Error code 0x${errorCode.toRadixString(16)}'); +} diff --git a/packages/path_provider/path_provider_windows/lib/src/win32_wrappers.dart b/packages/path_provider/path_provider_windows/lib/src/win32_wrappers.dart new file mode 100644 index 000000000000..a39488eb0a08 --- /dev/null +++ b/packages/path_provider/path_provider_windows/lib/src/win32_wrappers.dart @@ -0,0 +1,112 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The types and functions here correspond directly to corresponding Windows +// types and functions, so the Windows docs are the definitive source of +// documentation. +// ignore_for_file: public_member_api_docs + +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import 'guid.dart'; + +typedef BOOL = Int32; +typedef BYTE = Uint8; +typedef DWORD = Uint32; +typedef UINT = Uint32; +typedef HANDLE = IntPtr; +typedef HMODULE = HANDLE; +typedef HRESULT = Int32; +typedef LPCVOID = Pointer; +typedef LPCWSTR = Pointer; +typedef LPDWORD = Pointer; +typedef LPWSTR = Pointer; +typedef LPVOID = Pointer; +typedef PUINT = Pointer; +typedef PWSTR = Pointer>; +typedef WCHAR = Uint16; + +const int NULL = 0; + +// https://learn.microsoft.com/windows/win32/fileio/maximum-file-path-limitation?tabs=registry +const int MAX_PATH = 260; + +// https://learn.microsoft.com/windows/win32/seccrypto/common-hresult-values +// ignore: non_constant_identifier_names +final int E_FAIL = 0x80004005.toSigned(32); +// ignore: non_constant_identifier_names +final int E_INVALIDARG = 0x80070057.toSigned(32); + +// https://learn.microsoft.com/windows/win32/api/winerror/nf-winerror-failed#remarks +// ignore: non_constant_identifier_names +bool FAILED(int hr) => hr < 0; + +// https://learn.microsoft.com/windows/win32/api/shlobj_core/ne-shlobj_core-known_folder_flag +const int KF_FLAG_DEFAULT = 0x00000000; + +final DynamicLibrary _dllKernel32 = DynamicLibrary.open('kernel32.dll'); +final DynamicLibrary _dllVersion = DynamicLibrary.open('version.dll'); +final DynamicLibrary _dllShell32 = DynamicLibrary.open('shell32.dll'); + +// https://learn.microsoft.com/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath +typedef _FFITypeSHGetKnownFolderPath = HRESULT Function( + Pointer, DWORD, HANDLE, PWSTR); +typedef FFITypeSHGetKnownFolderPathDart = int Function( + Pointer, int, int, Pointer>); +// ignore: non_constant_identifier_names +final FFITypeSHGetKnownFolderPathDart SHGetKnownFolderPath = + _dllShell32.lookupFunction<_FFITypeSHGetKnownFolderPath, + FFITypeSHGetKnownFolderPathDart>('SHGetKnownFolderPath'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-getfileversioninfow +typedef _FFITypeGetFileVersionInfoW = BOOL Function( + LPCWSTR, DWORD, DWORD, LPVOID); +typedef FFITypeGetFileVersionInfoW = int Function( + Pointer, int, int, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetFileVersionInfoW GetFileVersionInfo = _dllVersion + .lookupFunction<_FFITypeGetFileVersionInfoW, FFITypeGetFileVersionInfoW>( + 'GetFileVersionInfoW'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-getfileversioninfosizew +typedef _FFITypeGetFileVersionInfoSizeW = DWORD Function(LPCWSTR, LPDWORD); +typedef FFITypeGetFileVersionInfoSizeW = int Function( + Pointer, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetFileVersionInfoSizeW GetFileVersionInfoSize = + _dllVersion.lookupFunction<_FFITypeGetFileVersionInfoSizeW, + FFITypeGetFileVersionInfoSizeW>('GetFileVersionInfoSizeW'); + +// https://learn.microsoft.com/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror +typedef _FFITypeGetLastError = DWORD Function(); +typedef FFITypeGetLastError = int Function(); +// ignore: non_constant_identifier_names +final FFITypeGetLastError GetLastError = _dllKernel32 + .lookupFunction<_FFITypeGetLastError, FFITypeGetLastError>('GetLastError'); + +// https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew +typedef _FFITypeGetModuleFileNameW = DWORD Function(HMODULE, LPWSTR, DWORD); +typedef FFITypeGetModuleFileNameW = int Function(int, Pointer, int); +// ignore: non_constant_identifier_names +final FFITypeGetModuleFileNameW GetModuleFileName = _dllKernel32.lookupFunction< + _FFITypeGetModuleFileNameW, + FFITypeGetModuleFileNameW>('GetModuleFileNameW'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-verqueryvaluew +typedef _FFITypeVerQueryValueW = BOOL Function(LPCVOID, LPCWSTR, LPVOID, PUINT); +typedef FFITypeVerQueryValueW = int Function( + Pointer, Pointer, Pointer, Pointer); +// ignore: non_constant_identifier_names +final FFITypeVerQueryValueW VerQueryValue = + _dllVersion.lookupFunction<_FFITypeVerQueryValueW, FFITypeVerQueryValueW>( + 'VerQueryValueW'); + +// https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-gettemppathw +typedef _FFITypeGetTempPathW = DWORD Function(DWORD, LPWSTR); +typedef FFITypeGetTempPathW = int Function(int, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetTempPathW GetTempPath = _dllKernel32 + .lookupFunction<_FFITypeGetTempPathW, FFITypeGetTempPathW>('GetTempPathW'); diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index c3211cf3c474..cb84e14accc6 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_windows issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.2.1 +version: 2.3.0 environment: sdk: ^3.2.0 @@ -21,7 +21,6 @@ dependencies: sdk: flutter path: ^1.8.0 path_provider_platform_interface: ^2.1.0 - win32: ">=2.1.0 <6.0.0" dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_windows/test/guid_test.dart b/packages/path_provider/path_provider_windows/test/guid_test.dart new file mode 100644 index 000000000000..561ad3b87d62 --- /dev/null +++ b/packages/path_provider/path_provider_windows/test/guid_test.dart @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_windows/src/guid.dart'; + +void main() { + test('has correct byte representation', () async { + final Pointer guid = calloc() + ..ref.parse('{00112233-4455-6677-8899-aabbccddeeff}'); + final ByteData data = ByteData(16) + ..setInt32(0, guid.ref.data1, Endian.little) + ..setInt16(4, guid.ref.data2, Endian.little) + ..setInt16(6, guid.ref.data3, Endian.little) + ..setInt64(8, guid.ref.data4, Endian.little); + expect(data.getUint8(0), 0x33); + expect(data.getUint8(1), 0x22); + expect(data.getUint8(2), 0x11); + expect(data.getUint8(3), 0x00); + expect(data.getUint8(4), 0x55); + expect(data.getUint8(5), 0x44); + expect(data.getUint8(6), 0x77); + expect(data.getUint8(7), 0x66); + expect(data.getUint8(8), 0x88); + expect(data.getUint8(9), 0x99); + expect(data.getUint8(10), 0xAA); + expect(data.getUint8(11), 0xBB); + expect(data.getUint8(12), 0xCC); + expect(data.getUint8(13), 0xDD); + expect(data.getUint8(14), 0xEE); + expect(data.getUint8(15), 0xFF); + + calloc.free(guid); + }); + + test('handles alternate forms', () async { + final Pointer guid1 = calloc() + ..ref.parse('{00112233-4455-6677-8899-aabbccddeeff}'); + final Pointer guid2 = calloc() + ..ref.parse('00112233445566778899AABBCCDDEEFF'); + + expect(guid1.ref.data1, guid2.ref.data1); + expect(guid1.ref.data2, guid2.ref.data2); + expect(guid1.ref.data3, guid2.ref.data3); + expect(guid1.ref.data4, guid2.ref.data4); + + calloc.free(guid1); + calloc.free(guid2); + }); + + test('throws for bad data', () async { + final Pointer guid = calloc(); + + expect(() => guid.ref.parse('{00112233-4455-6677-88'), throwsArgumentError); + + calloc.free(guid); + }); +} diff --git a/script/configs/allowed_unpinned_deps.yaml b/script/configs/allowed_unpinned_deps.yaml index 974385ac1465..fa23bb48c910 100644 --- a/script/configs/allowed_unpinned_deps.yaml +++ b/script/configs/allowed_unpinned_deps.yaml @@ -13,7 +13,6 @@ # cautious about adding to this list. - build_verify - google_maps -- win32 ## Allowed by default