Skip to content

Commit e512237

Browse files
committed
Handle systems with multiple users
1 parent 1a5d018 commit e512237

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
@@ -18,6 +18,7 @@ using namespace NppShell::Installer;
1818
using namespace NppShell::Registry;
1919

2020
extern HMODULE thisModule;
21+
extern thread ensureRegistrationThread;
2122

2223
const wstring SparsePackageName = L"NotepadPlusPlus";
2324
constexpr int FirstWindows11BuildNumber = 22000;
@@ -178,6 +179,33 @@ void ResetAclPermissionsOnApplicationFolder()
178179
aclHelper.ResetAcl(applicationPath);
179180
}
180181

182+
Package GetSparsePackage()
183+
{
184+
PackageManager packageManager;
185+
IIterable<Package> packages;
186+
187+
try
188+
{
189+
packages = packageManager.FindPackagesForUser(L"");
190+
}
191+
catch (winrt::hresult_error)
192+
{
193+
return NULL;
194+
}
195+
196+
for (const Package& package : packages)
197+
{
198+
if (package.Id().Name() != SparsePackageName)
199+
{
200+
continue;
201+
}
202+
203+
return package;
204+
}
205+
206+
return NULL;
207+
}
208+
181209
HRESULT NppShell::Installer::RegisterSparsePackage()
182210
{
183211
PackageManager packageManager;
@@ -207,32 +235,20 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
207235
PackageManager packageManager;
208236
IIterable<Package> packages;
209237

210-
try
238+
Package package = GetSparsePackage();
239+
240+
if (package == NULL)
211241
{
212-
packages = packageManager.FindPackagesForUser(L"");
213-
}
214-
catch (winrt::hresult_error const& ex)
215-
{
216-
return ex.code();
242+
return S_FALSE;
217243
}
218244

219-
for (const Package& package : packages)
220-
{
221-
if (package.Id().Name() != SparsePackageName)
222-
{
223-
continue;
224-
}
225-
226-
winrt::hstring fullName = package.Id().FullName();
227-
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::None);
228-
auto deployResult = deploymentOperation.get();
229-
230-
if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
231-
{
232-
return deployResult.ExtendedErrorCode();
233-
}
245+
winrt::hstring fullName = package.Id().FullName();
246+
auto deploymentOperation = packageManager.RemovePackageAsync(fullName, RemovalOptions::None);
247+
auto deployResult = deploymentOperation.get();
234248

235-
break;
249+
if (!SUCCEEDED(deployResult.ExtendedErrorCode()))
250+
{
251+
return deployResult.ExtendedErrorCode();
236252
}
237253

238254
// After unregistering the sparse package, we reset the folder permissions of the folder where we are installed.
@@ -347,6 +363,41 @@ HRESULT NppShell::Installer::Uninstall()
347363
return S_OK;
348364
}
349365

366+
void EnsureRegistrationOnCurrentUserWorker()
367+
{
368+
// Initialize the WinRT apartment.
369+
winrt::init_apartment();
370+
371+
// Get the package to check if it is already installed for the current user.
372+
Package existingPackage = GetSparsePackage();
373+
374+
if (existingPackage == NULL)
375+
{
376+
// The package is not installed for the current user - but we know that Notepad++ is.
377+
// If it wasn't, this code wouldn't be running, so it is safe to just register the package.
378+
RegisterSparsePackage();
379+
380+
// Finally we notify the shell that we have made changes, so it reloads the right click menu items.
381+
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
382+
}
383+
}
384+
385+
void NppShell::Installer::EnsureRegistrationOnCurrentUser()
386+
{
387+
// First we find the name of the process the DLL is being loaded into.
388+
wstring moduleName = GetExecutingModuleName();
389+
390+
if (moduleName == L"explorer.exe")
391+
{
392+
// We are being loaded into explorer.exe, so we can continue.
393+
// Explorer.exe only loads the DLL on the first time a user right-clicks a file
394+
// after that it stays in memory for the rest of their session.
395+
// Since we are here, we spawn a thread and call the EnsureRegistrationOnCurrentUserWorker function.
396+
ensureRegistrationThread = thread(EnsureRegistrationOnCurrentUserWorker);
397+
ensureRegistrationThread.detach();
398+
}
399+
}
400+
350401
STDAPI CleanupDll()
351402
{
352403
// First we get the full path to this DLL.

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
@@ -29,4 +29,16 @@ const wstring NppShell::Helpers::GetContextMenuFullName()
2929
{
3030
path modulePath = GetThisModulePath();
3131
return modulePath.wstring();
32+
}
33+
34+
const wstring NppShell::Helpers::GetExecutingModuleName()
35+
{
36+
wchar_t pathBuffer[FILENAME_MAX] = { 0 };
37+
GetModuleFileNameW(NULL, pathBuffer, FILENAME_MAX);
38+
PathStripPathW(pathBuffer);
39+
40+
wstring moduleName(pathBuffer);
41+
transform(moduleName.begin(), moduleName.end(), moduleName.begin(), towlower);
42+
43+
return moduleName;
3244
}

PathHelper.h

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ namespace NppShell::Helpers
88
const wstring GetApplicationPath();
99
const wstring GetContextMenuPath();
1010
const wstring GetContextMenuFullName();
11+
const wstring GetExecutingModuleName();
1112
}

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)