diff --git a/.github/workflows/p4vfs-verify.yml b/.github/workflows/p4vfs-verify.yml
index 0c8681a..24d5f07 100644
--- a/.github/workflows/p4vfs-verify.yml
+++ b/.github/workflows/p4vfs-verify.yml
@@ -38,7 +38,7 @@ jobs:
Write-Output "ImageVersion=$env:ImageVersion" >> $env:GITHUB_ENV
- name: Checkout the repo
- uses: actions/checkout@v4.1.7
+ uses: actions/checkout@v4.2.2
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
@@ -46,7 +46,7 @@ jobs:
msbuild-architecture: x64
- name: Cache OpenSSL ${{env.ImageOS}} ${{env.ImageVersion}}
- uses: actions/cache@v4.0.2
+ uses: actions/cache@v4.2.0
with:
path: |
external/OpenSSL
diff --git a/README.md b/README.md
index fe9776d..fbd044a 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ For example, you can use the P4VFS to perform a "virtual sync" to a Perforce fil
# Installation
You can install the latest signed release of P4VFS from here:
-> [P4VFS.Setup](https://github.com/microsoft/p4vfs/releases/download/v1.28.0.0/P4VFS.Setup-1.28.0.0.exe)
+> [P4VFS.Setup](https://github.com/microsoft/p4vfs/releases/download/v1.28.3.0/P4VFS.Setup-1.28.3.0.exe)
The entire history of release notes is included with the installer.
> [Release Notes](https://github.com/microsoft/p4vfs/blob/main/source/P4VFS.Console/P4VFS.Notes.txt)
@@ -49,8 +49,8 @@ The tool respects P4CONFIG file usage, as well as supports typical configuration
### Build Requirments:
1. Visual Studio 2022 version 17.5.0 or later
-1. Windows SDK version 10.0.22621.0 (22H2)
-1. Windows WDK version 10.0.22621.382 (22H2)
+1. Windows SDK version 10.0.26100.1742
+1. Windows WDK version 10.0.26100.2454
Details for installing Visual Studio 2022, the Windows Software Development Kit (SDK), and the Windows Driver Kit (WDK) can be found here:
> [Download the Windows Driver Kit](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)
diff --git a/source/P4VFS.Console/P4VFS.Notes.txt b/source/P4VFS.Console/P4VFS.Notes.txt
index fcfea58..4991160 100644
--- a/source/P4VFS.Console/P4VFS.Notes.txt
+++ b/source/P4VFS.Console/P4VFS.Notes.txt
@@ -1,5 +1,11 @@
Microsoft P4VFS Release Notes
+Version [1.28.3.0]
+* Fixing service initialization error if registry ImagePath value contains quotes
+ under key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\P4VFS.Service".
+ Including a new unit test to verify handling of user settings paths.
+* Updating driver WDK to 10.0.26100
+
Version [1.28.2.0]
* Fixing support for specifying a value for P4TICKETS from within a P4CONFIG file,
and correctly used from working directory of p4vfs.exe, or placeholder file folder
diff --git a/source/P4VFS.Driver/Include/DriverVersion.h b/source/P4VFS.Driver/Include/DriverVersion.h
index 7a62b84..61b7acb 100644
--- a/source/P4VFS.Driver/Include/DriverVersion.h
+++ b/source/P4VFS.Driver/Include/DriverVersion.h
@@ -4,7 +4,7 @@
#define P4VFS_VER_MAJOR 1 // Increment this number almost never
#define P4VFS_VER_MINOR 28 // Increment this number whenever the driver changes
-#define P4VFS_VER_BUILD 2 // Increment this number when a major user mode change has been made
+#define P4VFS_VER_BUILD 3 // Increment this number when a major user mode change has been made
#define P4VFS_VER_REVISION 0 // Increment this number when we rebuild with any change
#define P4VFS_VER_STRINGIZE_EX(v) L#v
diff --git a/source/P4VFS.Driver/P4VFS.Driver.vcxproj b/source/P4VFS.Driver/P4VFS.Driver.vcxproj
index 75f92f9..23ad7cd 100644
--- a/source/P4VFS.Driver/P4VFS.Driver.vcxproj
+++ b/source/P4VFS.Driver/P4VFS.Driver.vcxproj
@@ -19,7 +19,7 @@
x64
Microsoft::P4VFS::Driver
/msft
- 10.0.22621.0
+ 10.0.26100.0
diff --git a/source/P4VFS.Extensions/Source/Common/VirtualFileSystem.cs b/source/P4VFS.Extensions/Source/Common/VirtualFileSystem.cs
index b80c43b..29e350c 100644
--- a/source/P4VFS.Extensions/Source/Common/VirtualFileSystem.cs
+++ b/source/P4VFS.Extensions/Source/Common/VirtualFileSystem.cs
@@ -231,7 +231,7 @@ public static string PublicSettingsFilePath
{
get
{
- string publicProfile = Environment.GetEnvironmentVariable("PUBLIC");
+ string publicProfile = Environment.GetEnvironmentVariable("PUBLIC")?.Trim('"');
return String.IsNullOrEmpty(publicProfile) ? String.Empty : Path.GetFullPath(String.Format("{0}\\{1}", publicProfile, SettingsFile));
}
}
@@ -247,6 +247,7 @@ public static string InstalledSettingsFilePath
{
string serviceFilePath = null;
RegistryInfo.GetTypedValue(Microsoft.Win32.Registry.LocalMachine, ServiceRegistryKey, "ImagePath", ref serviceFilePath);
+ serviceFilePath = serviceFilePath?.Trim('"');
return String.IsNullOrEmpty(serviceFilePath) ? String.Empty : Path.GetFullPath(String.Format("{0}\\{1}", Path.GetDirectoryName(serviceFilePath), SettingsFile));
}
}
diff --git a/source/P4VFS.Extensions/Source/Utilities/RegistryInfo.cs b/source/P4VFS.Extensions/Source/Utilities/RegistryInfo.cs
index b9ddc9c..c9e9ef7 100644
--- a/source/P4VFS.Extensions/Source/Utilities/RegistryInfo.cs
+++ b/source/P4VFS.Extensions/Source/Utilities/RegistryInfo.cs
@@ -1,20 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
-using System.Security.Permissions;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.P4VFS.Extensions.Utilities
{
///
- /// Class to help with the nitty-gritty details of accessing the two registries (32 and 64 bit)
- /// from managed code.
+ /// Class to help with the nitty-gritty details of accessing the two registries (32 and 64 bit) from managed code.
///
public static class RegistryInfo
{
@@ -34,19 +30,6 @@ public static string StrRegError
/// Retrieves the specified key/value and casts to type T, where possible. Expected errors (such as could not open key)
/// stored in StrRegError. Use GetValueType() or T=object if uncertain what type of value the key stores.
///
- /// The type to cast the key value to.
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "ifFaceName".
- /// Stores the casted value if RegistryCmd access succeeded.
- /// Success true/false.
- /// A null argument was passed in.
- /// sub_key or name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
- /// The key value could not be cast to requested type.
public static bool GetTypedValue(RegistryKey hive_key, string sub_key, string name, ref T value)
{
return RegistryInfo.GetTypedValueWithOptions(hive_key, sub_key, name, RegistryValueOptions.None, ref value);
@@ -56,20 +39,6 @@ public static bool GetTypedValue(RegistryKey hive_key, string sub_key, string
/// Retrieves the specified key/value and casts to type T, where possible. Expected errors (such as could not open key)
/// stored in StrRegError. Use GetValueType() or T=object if uncertain what type of value the key stores.
///
- /// The type to cast the key value to.
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "ifFaceName".
- /// The options to use when querying the registry.
- /// Stores the casted value if RegistryCmd access succeeded.
- /// Success true/false.
- /// A null argument was passed in.
- /// sub_key or name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
- /// The key value could not be cast to requested type.
public static bool GetTypedValueWithOptions(RegistryKey hive_key, string sub_key, string name, RegistryValueOptions options, ref T value)
{
object obj_data = RegistryInfo.GetValue(hive_key, sub_key, name, options);
@@ -85,16 +54,6 @@ public static bool GetTypedValueWithOptions(RegistryKey hive_key, string sub_
///
/// Sets/creates the specified String value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "ifFaceName".
- /// String data value to write.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetStringValue(RegistryKey hive_key, string sub_key, string name, string value)
{
RegistryInfo.SetValue(hive_key, sub_key, name, value, RegistryValueKind.String);
@@ -103,16 +62,6 @@ public static void SetStringValue(RegistryKey hive_key, string sub_key, string n
///
/// Sets/creates the specified ExpandString value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "ifFaceName".
- /// String data value to write.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetStringExpandValue(RegistryKey hive_key, string sub_key, string name, string value)
{
RegistryInfo.SetValue(hive_key, sub_key, name, value, RegistryValueKind.ExpandString);
@@ -121,16 +70,6 @@ public static void SetStringExpandValue(RegistryKey hive_key, string sub_key, st
///
/// Sets/creates the specified DWORD value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize".
- /// DWORD data value to write.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetDWORDValue(RegistryKey hive_key, string sub_key, string name, int value)
{
RegistryInfo.SetValue(hive_key, sub_key, name, value, RegistryValueKind.DWord);
@@ -139,16 +78,6 @@ public static void SetDWORDValue(RegistryKey hive_key, string sub_key, string na
///
/// Sets/creates the specified Binary value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize" sic.
- /// Binary data value to write.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetBinaryValue(RegistryKey hive_key, string sub_key, string name, byte[] value)
{
RegistryInfo.SetValue(hive_key, sub_key, name, value, RegistryValueKind.Binary);
@@ -157,16 +86,6 @@ public static void SetBinaryValue(RegistryKey hive_key, string sub_key, string n
///
/// Sets/creates the specified String Array value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize" sic.
- /// String Array value to write.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetStringArrayValue(RegistryKey hive_key, string sub_key, string name, string[] value)
{
RegistryInfo.SetValue(hive_key, sub_key, name, value, RegistryValueKind.MultiString);
@@ -175,17 +94,6 @@ public static void SetStringArrayValue(RegistryKey hive_key, string sub_key, str
///
/// Sets/creates the specified value. Casts where able to RegistryValueKind. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize" sic.
- /// Binary data value to write.
- /// Microsoft.Win32.RegistryValueKind to store the value as.
- /// A null argument was passed in.
- /// value is an unsupported data type. -or- name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void SetValue(RegistryKey hive_key, string sub_key, string name, object value, RegistryValueKind kind)
{
StrRegError = null;
@@ -204,15 +112,6 @@ public static void SetValue(RegistryKey hive_key, string sub_key, string name, o
///
/// Creates a new subkey or opens an existing subkey. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// A null argument was passed in.
- /// sub_key is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
- /// The Microsoft.Win32.RegistryKey created from hive_key and sub_key.
public static RegistryKey CreateSubKey(RegistryKey hive_key, string sub_key)
{
StrRegError = null;
@@ -228,13 +127,6 @@ public static RegistryKey CreateSubKey(RegistryKey hive_key, string sub_key)
///
/// Deletes a subkey and any child subkeys recursively. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// A null argument was passed in.
- /// Deletion of a root hive is attempted. -or- subkey does not specify a valid registry subkey.
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The user does not have the necessary registry rights.
public static void DeleteSubKeyTree(RegistryKey hive_key, string sub_key)
{
StrRegError = null;
@@ -244,15 +136,6 @@ public static void DeleteSubKeyTree(RegistryKey hive_key, string sub_key)
///
/// Deletes the specified value from this (current) key. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize".
- /// A null argument was passed in.
- /// name is not a valid reference to a value.
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static void DeleteValue(RegistryKey hive_key, string sub_key, string name)
{
StrRegError = null;
@@ -277,34 +160,40 @@ public static void DeleteValue(RegistryKey hive_key, string sub_key, string name
///
/// Retrieves the type of the specified RegistryCmd value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize".
- /// System.Type. Exceptions/errors stored in StrRegError.
- /// A null argument was passed in.
- /// sub_key or name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static Type GetValueType(RegistryKey hive_key, string sub_key, string name)
{
return RegistryInfo.GetValue(hive_key, sub_key, name, RegistryValueOptions.None).GetType();
}
+ ///
+ /// Retrieves the RegistryValueKind of the specified RegistryCmd value. Exceptions/errors stored in StrRegError.
+ ///
+ public static RegistryValueKind GetValueKind(RegistryKey hive_key, string sub_key, string name)
+ {
+ StrRegError = null;
+ using (RegistryKey subKey = hive_key.OpenSubKey(sub_key))
+ {
+ if (subKey == null)
+ {
+ StrRegError = "Cannot open the specified sub-key";
+ return RegistryValueKind.Unknown;
+ }
+
+ try
+ {
+ return subKey.GetValueKind(name);
+ }
+ catch (Exception ex)
+ {
+ StrRegError = ex.Message;
+ return RegistryValueKind.Unknown;
+ }
+ }
+ }
+
///
/// Determines the existence of a value. Exceptions/errors stored in StrRegError.
///
- /// Identifies which hive to look in, such as Microsoft.Win32.Registry.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize".
- /// Whether the value exists by boolean. Exceptions/errors stored in StrRegError.
- /// A null argument was passed in.
- /// sub_key or name is longer than the maximum length allowed (255 characters).
- /// The Microsoft.Win32.RegistryKey is closed (closed keys cannot be accessed).
- /// The user does not have the permissions required to read the registry key.
- /// The Microsoft.Win32.RegistryKey that contains the specified key has been marked for deletion.
- /// The user does not have the necessary registry rights.
public static bool ValueExists(RegistryKey hive_key, string sub_key, string name)
{
StrRegError = null;
@@ -333,10 +222,6 @@ public static bool ValueExists(RegistryKey hive_key, string sub_key, string name
/// Wraps up the Win32 RegistryCmd access to a single line. OpenSubKey and GetValue can throw several exceptions,
/// but for now we will let those hit the user (exceptions listed on public accessors to this function).
///
- /// Identifies which hive to look in, such as Microsoft.Win32.RegistryCmd.LocalMachine.
- /// Path from hive key to target node. Such as "SOFTWARE\\MICROSOFT\\Notepad\DefaultFonts.
- /// The key to act on. Such as "iPointSize".
- /// Object from RegistryKey.OpenSubKey.
private static object GetValue(RegistryKey hive_key, string sub_key, string name, RegistryValueOptions options)
{
object objData = null;
@@ -657,14 +542,8 @@ public static bool GetDWORDValueFromRegistryHandle(SafeRegistryHandle safe_handl
///
- /// Horrible stuff to be able to access the 64-bit registry from a managed app, regardless of
- /// the app's bitness.
+ /// Horrible stuff to be able to access the 64-bit registry from a managed app, regardless of the app's bitness.
///
- /// The hive to read from (HKLM, HKCU, etc).
- /// The key itself.
- /// The value to query.
- /// Additional flags to pass directly to the Win32 API.
- /// String value stored in the registry, or empty string if not available.
public static string GetStringValueFromRegistryWithFlags(RegistryHive reg_hive, string key, string value, int flags)
{
string return_value = String.Empty;
@@ -684,26 +563,16 @@ public static string GetStringValueFromRegistryWithFlags(RegistryHive reg_hive,
}
///
- /// Horrible stuff to be able to access the 32-bit registry from a managed app, regardless of
- /// the app's bitness.
+ /// Horrible stuff to be able to access the 32-bit registry from a managed app, regardless of the app's bitness.
///
- /// The hive to read from (HKLM, HKCU, etc).
- /// The key itself.
- /// The value to query.
- /// String value stored in the 32-bit registry, or empty string if not available.
public string GetStringValueFrom32BitRegistry(RegistryHive reg_hive, string key, string value)
{
return GetStringValueFromRegistryWithFlags(reg_hive, key, value, KEY_WOW64_32KEY);
}
///
- /// Horrible stuff to be able to access the 64-bit registry from a managed app, regardless of
- /// the app's bitness.
+ /// Horrible stuff to be able to access the 64-bit registry from a managed app, regardless of the app's bitness.
///
- /// The hive to read from (HKLM, HKCU, etc).
- /// The key itself.
- /// The value to query.
- /// String value stored in the 64-bit registry, or empty string if not available.
public string GetStringValueFrom64BitRegistry(RegistryHive reg_hive, string key, string value)
{
return GetStringValueFromRegistryWithFlags(reg_hive, key, value, KEY_WOW64_64KEY);
diff --git a/source/P4VFS.UnitTest/Source/UnitTestInstall.cs b/source/P4VFS.UnitTest/Source/UnitTestInstall.cs
index fd64459..2bbe034 100644
--- a/source/P4VFS.UnitTest/Source/UnitTestInstall.cs
+++ b/source/P4VFS.UnitTest/Source/UnitTestInstall.cs
@@ -334,6 +334,43 @@ public void DriverOperationsTest()
Assert(VirtualFileSystem.IsVirtualFileSystemAvailable());
}
+ [TestMethod, Priority(9)]
+ public void InstalledSettingsFilePathTest()
+ {
+ // Verifications of the simple settings file path
+ Assert(String.IsNullOrEmpty(VirtualFileSystem.UserSettingsFilePath) == false);
+ Assert(String.IsNullOrEmpty(VirtualFileSystem.AssemblySettingsFilePath) == false);
+
+ // Verifications of the public settings file path given differences in the PUBLIC environment variable
+ string originalPublicSettingsFilePath = VirtualFileSystem.PublicSettingsFilePath;
+ Assert(String.IsNullOrEmpty(VirtualFileSystem.PublicSettingsFilePath) == false);
+ using (new SetEnvironmentVariableScope("PUBLIC", ""))
+ Assert(String.IsNullOrEmpty(VirtualFileSystem.PublicSettingsFilePath));
+ using (new SetEnvironmentVariableScope("PUBLIC", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)))
+ Assert(String.Equals(VirtualFileSystem.PublicSettingsFilePath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), VirtualFileSystem.SettingsFile), StringComparison.InvariantCultureIgnoreCase));
+ using (new SetEnvironmentVariableScope("PUBLIC", $"\"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\""))
+ Assert(String.Equals(VirtualFileSystem.PublicSettingsFilePath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), VirtualFileSystem.SettingsFile), StringComparison.InvariantCultureIgnoreCase));
+ Assert(originalPublicSettingsFilePath == VirtualFileSystem.PublicSettingsFilePath);
+
+ // Verifications of the installed settings file path given the service registry key
+ string originalInstalledSettingsFilePath = VirtualFileSystem.InstalledSettingsFilePath;
+ Assert(String.IsNullOrEmpty(VirtualFileSystem.InstalledSettingsFilePath) == false);
+ Assert(String.Equals(VirtualFileSystem.InstalledSettingsFilePath, Path.Combine(Path.GetDirectoryName(InstalledP4vfsExe), VirtualFileSystem.SettingsFile), StringComparison.InvariantCultureIgnoreCase));
+ Assert(RegistryInfo.GetValueKind(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath") == Microsoft.Win32.RegistryValueKind.ExpandString);
+ string installedImagePath = null;
+ Assert(RegistryInfo.GetTypedValue(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath", ref installedImagePath));
+ Assert(Directory.Exists(Path.GetDirectoryName(installedImagePath)));
+ Assert(String.Equals(Path.GetDirectoryName(installedImagePath), Path.GetDirectoryName(InstalledP4vfsExe), StringComparison.InvariantCultureIgnoreCase));
+ AssertLambda(() => RegistryInfo.SetValue(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath", $"\"{installedImagePath}\"", Win32.RegistryValueKind.ExpandString));
+ string quotedInstalledImagePath = null;
+ Assert(RegistryInfo.GetTypedValue(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath", ref quotedInstalledImagePath));
+ Assert(quotedInstalledImagePath == $"\"{installedImagePath}\"");
+ Assert(originalInstalledSettingsFilePath == VirtualFileSystem.InstalledSettingsFilePath);
+ AssertLambda(() => RegistryInfo.SetValue(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath", installedImagePath, Win32.RegistryValueKind.ExpandString));
+ Assert(RegistryInfo.GetValueKind(Microsoft.Win32.Registry.LocalMachine, VirtualFileSystem.ServiceRegistryKey, "ImagePath") == Microsoft.Win32.RegistryValueKind.ExpandString);
+ Assert(originalInstalledSettingsFilePath == VirtualFileSystem.InstalledSettingsFilePath);
+ }
+
public bool IsInstallationSigned()
{
string p4vfsExe = InstalledP4vfsExe;
diff --git a/source/P4VFS.UnitTest/Source/UnitTestUtilities.cs b/source/P4VFS.UnitTest/Source/UnitTestUtilities.cs
index 52a7c10..ed2101c 100644
--- a/source/P4VFS.UnitTest/Source/UnitTestUtilities.cs
+++ b/source/P4VFS.UnitTest/Source/UnitTestUtilities.cs
@@ -53,7 +53,7 @@ public void FileAttributeTest()
Assert(ReconcilePreview(clientFolder).Any() == false);
Assert(IsPlaceholderFile(clientFile) == false);
- Assert(getAttr(clientFile) == FileAttributes.ReadOnly);
+ Assert(getAttr(clientFile).HasFlag(FileAttributes.ReadOnly));
File.SetAttributes(clientFile, FileAttributes.Normal);
Assert(getAttr(clientFile) == FileAttributes.Normal);