Skip to content

Commit 0bfabe2

Browse files
committed
Handle systems with multiple users
1 parent 8f26080 commit 0bfabe2

File tree

5 files changed

+90
-22
lines changed

5 files changed

+90
-22
lines changed

Installer.cpp

+73-22
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using namespace NppShell::Helpers;
1616
using namespace NppShell::Installer;
1717

1818
extern HMODULE thisModule;
19+
extern thread ensureRegistrationThread;
1920

2021
const wstring SparsePackageName = L"NotepadPlusPlus";
2122
constexpr int FirstWindows11BuildNumber = 22000;
@@ -255,6 +256,33 @@ void ResetAclPermissionsOnApplicationFolder()
255256
aclHelper.ResetAcl(applicationPath);
256257
}
257258

259+
Package GetSparsePackage()
260+
{
261+
PackageManager packageManager;
262+
IIterable<Package> packages;
263+
264+
try
265+
{
266+
packages = packageManager.FindPackagesForUser(L"");
267+
}
268+
catch (winrt::hresult_error)
269+
{
270+
return NULL;
271+
}
272+
273+
for (const Package& package : packages)
274+
{
275+
if (package.Id().Name() != SparsePackageName)
276+
{
277+
continue;
278+
}
279+
280+
return package;
281+
}
282+
283+
return NULL;
284+
}
285+
258286
HRESULT NppShell::Installer::RegisterSparsePackage()
259287
{
260288
PackageManager packageManager;
@@ -284,32 +312,20 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
284312
PackageManager packageManager;
285313
IIterable<Package> packages;
286314

287-
try
288-
{
289-
packages = packageManager.FindPackagesForUser(L"");
290-
}
291-
catch (winrt::hresult_error const& ex)
315+
Package package = GetSparsePackage();
316+
317+
if (package == NULL)
292318
{
293-
return ex.code();
319+
return S_FALSE;
294320
}
295321

296-
for (const Package& package : packages)
297-
{
298-
if (package.Id().Name() != SparsePackageName)
299-
{
300-
continue;
301-
}
302-
303-
winrt::hstring fullName = package.Id().FullName();
304-
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::None);
305-
auto deployResult = deploymentOperation.get();
306-
307-
if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
308-
{
309-
return deployResult.ExtendedErrorCode();
310-
}
322+
winrt::hstring fullName = package.Id().FullName();
323+
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::None);
324+
auto deployResult = deploymentOperation.get();
311325

312-
break;
326+
if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
327+
{
328+
return deployResult.ExtendedErrorCode();
313329
}
314330

315331
// After unregistering the sparse package, we reset the folder permissions of the folder where we are installed.
@@ -409,6 +425,41 @@ HRESULT NppShell::Installer::Uninstall()
409425
return S_OK;
410426
}
411427

428+
void EnsureRegistrationOnCurrentUserWorker()
429+
{
430+
// Initialize the WinRT apartment.
431+
winrt::init_apartment();
432+
433+
// Get the package to check if it is already installed for the current user.
434+
Package existingPackage = GetSparsePackage();
435+
436+
if (existingPackage == NULL)
437+
{
438+
// The package is not installed for the current user - but we know that Notepad++ is.
439+
// If it wasn't, this code wouldn't be running, so it is safe to just register the package.
440+
RegisterSparsePackage();
441+
442+
// Finally we notify the shell that we have made changes, so it reloads the right click menu items.
443+
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
444+
}
445+
}
446+
447+
void NppShell::Installer::EnsureRegistrationOnCurrentUser()
448+
{
449+
// First we find the name of the process the DLL is being loaded into.
450+
wstring moduleName = GetExecutingModuleName();
451+
452+
if (moduleName == L"explorer.exe")
453+
{
454+
// We are being loaded into explorer.exe, so we can continue.
455+
// Explorer.exe only loads the DLL on the first time a user right-clicks a file
456+
// after that it stays in memory for the rest of their session.
457+
// Since we are here, we spawn a thread and call the EnsureRegistrationOnCurrentUserWorker function.
458+
ensureRegistrationThread = thread(EnsureRegistrationOnCurrentUserWorker);
459+
ensureRegistrationThread.detach();
460+
}
461+
}
462+
412463
STDAPI CleanupDll()
413464
{
414465
wstring currentFilePath(MAX_PATH, L'\0');

Installer.h

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ namespace NppShell::Installer
1111

1212
HRESULT Install();
1313
HRESULT Uninstall();
14+
15+
void EnsureRegistrationOnCurrentUser();
1416
}
1517

1618
STDAPI CleanupDll();

PathHelper.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,16 @@ const wstring NppShell::Helpers::GetContextMenuPath()
2323
{
2424
path modulePath = GetThisModulePath();
2525
return modulePath.parent_path().wstring();
26+
}
27+
28+
const wstring NppShell::Helpers::GetExecutingModuleName()
29+
{
30+
wchar_t pathBuffer[FILENAME_MAX] = { 0 };
31+
GetModuleFileNameW(NULL, pathBuffer, FILENAME_MAX);
32+
PathStripPathW(pathBuffer);
33+
34+
wstring moduleName(pathBuffer);
35+
transform(moduleName.begin(), moduleName.end(), moduleName.begin(), towlower);
36+
37+
return moduleName;
2638
}

PathHelper.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ namespace NppShell::Helpers
77
{
88
const wstring GetApplicationPath();
99
const wstring GetContextMenuPath();
10+
const wstring GetExecutingModuleName();
1011
}

dllmain.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using namespace NppShell::CommandHandlers;
99
using namespace NppShell::Factories;
1010

1111
HMODULE thisModule;
12+
thread ensureRegistrationThread;
1213

1314
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
1415
{
@@ -18,6 +19,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser
1819
{
1920
case DLL_PROCESS_ATTACH:
2021
thisModule = hModule;
22+
NppShell::Installer::EnsureRegistrationOnCurrentUser();
2123
break;
2224
case DLL_THREAD_ATTACH:
2325
case DLL_THREAD_DETACH:

0 commit comments

Comments
 (0)