Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WORK IN PROGRESS - Install for all users #55

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 73 additions & 14 deletions Installer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,33 @@ HRESULT MoveFileToTempAndScheduleDeletion(const wstring& filePath, bool moveToTe
return S_OK;
}

void ResetAclPermissionsOnApplicationFolder()
void ResetAclPermissionsOnContextMenuFolder()
{
// First we get the path where Notepad++ is installed.
const wstring applicationPath = GetApplicationPath();
// First we get the path where Notepad++ context menu is installed.
const wstring contextMenuPath = GetContextMenuPath();

// Create a new AclHelper
AclHelper aclHelper;

// Reset the ACL of the folder where Notepad++ is installed.
aclHelper.ResetAcl(applicationPath);
// Reset the ACL of the folder where Notepad++ context menu is installed.
aclHelper.ResetAcl(contextMenuPath);
}

Package GetSparsePackage()
Package GetSparsePackage(bool allUsers)
{
PackageManager packageManager;
IIterable<Package> packages;

try
{
packages = packageManager.FindPackagesForUser(L"");
if (allUsers)
{
packages = packageManager.FindPackages();
}
else
{
packages = packageManager.FindPackagesForUser(L"");
}
}
catch (winrt::hresult_error)
{
Expand All @@ -206,10 +213,57 @@ Package GetSparsePackage()
return NULL;
}

HRESULT NppShell::Installer::RegisterSparsePackage()
HRESULT NppShell::Installer::RegisterSparsePackageAllUsers()
{
if (::GetSystemMetrics(SM_CLEANBOOT) > 0)
{
return S_FALSE; // Otherwise we will get an unhandled exception later due to HRESULT 0x8007043c (ERROR_NOT_SAFEBOOT_SERVICE).
}

PackageManager packageManager;
StagePackageOptions options;

const wstring externalLocation = GetContextMenuPath();
const wstring sparsePkgPath = externalLocation + L"\\NppShell.msix";

Uri externalUri(externalLocation);
Uri packageUri(sparsePkgPath);

options.ExternalLocationUri(externalUri);

auto deploymentOperation = packageManager.StagePackageByUriAsync(packageUri, options);
auto deployResult = deploymentOperation.get();

if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
{
return deployResult.ExtendedErrorCode();
}

Package package = GetSparsePackage(true);
if (package == NULL)
{
return S_FALSE;
}

winrt::hstring familyName = package.Id().FamilyName();

deploymentOperation = packageManager.ProvisionPackageForAllUsersAsync(familyName);
deployResult = deploymentOperation.get();

if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
{
return deployResult.ExtendedErrorCode();
}

return S_OK;
}

HRESULT NppShell::Installer::RegisterSparsePackageCurrentUser()
{
if (::GetSystemMetrics(SM_CLEANBOOT) > 0)
{
return S_FALSE; // Otherwise we will get an unhandled exception later due to HRESULT 0x8007043c (ERROR_NOT_SAFEBOOT_SERVICE).
}

PackageManager packageManager;
AddPackageOptions options;
Expand All @@ -236,20 +290,22 @@ HRESULT NppShell::Installer::RegisterSparsePackage()
HRESULT NppShell::Installer::UnregisterSparsePackage()
{
if (::GetSystemMetrics(SM_CLEANBOOT) > 0)
{
return S_FALSE; // Only to speed up things a bit here. (code in the following GetSparsePackage() is safe against the ERROR_NOT_SAFEBOOT_SERVICE)
}

PackageManager packageManager;
IIterable<Package> packages;

Package package = GetSparsePackage();
Package package = GetSparsePackage(true);

if (package == NULL)
{
return S_FALSE;
}

winrt::hstring fullName = package.Id().FullName();
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::None);
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::RemoveForAllUsers);
auto deployResult = deploymentOperation.get();

if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
Expand All @@ -258,7 +314,7 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
}

// After unregistering the sparse package, we reset the folder permissions of the folder where we are installed.
ResetAclPermissionsOnApplicationFolder();
ResetAclPermissionsOnContextMenuFolder();

return S_OK;
}
Expand Down Expand Up @@ -298,15 +354,18 @@ HRESULT NppShell::Installer::UnregisterOldContextMenu()
void ReRegisterSparsePackage()
{
if (::GetSystemMetrics(SM_CLEANBOOT) > 0)
{
return; // Sparse package reg/unreg cannot be done in the Windows OS SafeMode.
}

winrt::init_apartment();

// Since we are on Windows 11, we unregister the sparse package as well.
UnregisterSparsePackage();

// And then we register it again.
RegisterSparsePackage();
RegisterSparsePackageAllUsers();
RegisterSparsePackageCurrentUser();
}

HRESULT NppShell::Installer::Install()
Expand Down Expand Up @@ -387,13 +446,13 @@ void EnsureRegistrationOnCurrentUserWorker()
winrt::init_apartment();

// Get the package to check if it is already installed for the current user.
Package existingPackage = GetSparsePackage();
Package existingPackage = GetSparsePackage(false);

if (existingPackage == NULL)
{
// The package is not installed for the current user - but we know that Notepad++ is.
// If it wasn't, this code wouldn't be running, so it is safe to just register the package.
RegisterSparsePackage();
RegisterSparsePackageCurrentUser();

// Finally we notify the shell that we have made changes, so it reloads the right click menu items.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
Expand Down
3 changes: 2 additions & 1 deletion Installer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ namespace NppShell::Installer
HRESULT RegisterOldContextMenu();
HRESULT UnregisterOldContextMenu();

HRESULT RegisterSparsePackage();
HRESULT RegisterSparsePackageAllUsers();
HRESULT RegisterSparsePackageCurrentUser();
HRESULT UnregisterSparsePackage();

HRESULT Install();
Expand Down
Loading