Skip to content

Commit 7edcea8

Browse files
committed
Migrate from C# to C++ and update docs
Replaces the original C# implementation with a new C++ version.
1 parent ee50ba4 commit 7edcea8

15 files changed

+286
-919
lines changed

DisableStartupDelay.reg

-324 Bytes
Binary file not shown.

HideSoundEvents.reg

-866 Bytes
Binary file not shown.

README.md

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,28 @@
11
# System Sound Player
2-
**A small C# program that will restore the logon, logoff, system start, and system exit program events in Windows 10.**
2+
**A tiny program to restore logon, logoff, system start, and system exit sounds in modern versions of Windows.**
33

4-
In Windows 10, Microsoft removed the ability for the operating system to play a sound when locking or unlocking a session, as well as when logging on or logging off. This program will help you get these features back, because like everything the Shell Team at Microsoft does, the removal was only half-assed.
4+
Microsoft removed the ability for the operating system to play a sound when locking or unlocking a session, as well as when logging on or logging off. This program will help you get these features back, because like everything the Windows Shell Team at Microsoft does, the removal was only half-assed.
55

6-
What was removed in Windows 10 was the ability for the operating system to actually play back a configured sound file. This was supposedly because they had optimized startup and shutdown so much that they couldn't get the sounds to play reliably anymore. However, the ability to set a sound file via the control panel still exists and has just been hidden.
6+
What was actually removed was the ability for the operating system to play a configured sound file. This was supposedly because they had optimized startup and shutdown so much that they couldn't get the sounds to play reliably anymore. However, the ability to set a sound file via the Control Panel still exists and was just hidden.
77

88
## How to Use
9-
1. Put `soundrestore.exe` in a central location, like your Windows directory
10-
1. Put a shortcut to `soundrestore.exe` in your Startup folder
9+
1. Put `soundrestore.exe` in `C:\Windows\`
10+
1. Use the `SetTaskman.reg` to start the program as early as possible after signing in to Windows
1111
1. Use the `RestoreSoundEvents.reg` file to unhide the program events for "Windows Logon", "Windows Logoff", "Exit Windows" and "Start Windows" (you need to do this once for every user if you have multiple user accounts)
12-
1. Optional: use the `DisableStartupDelay.reg` to make the sound play as early as possible after logging on (you need to do this once for every user if you have multiple user accounts)
13-
1. Configure the sounds that you want to play using the Control Panel
14-
1. Launch the shortcut manually once (or reboot)
15-
16-
The All Users Startup folder is located at `C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup`, and the current user's Startup folder is located at `C:\Users\[User Name]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`.
17-
18-
You can use the `HideSoundEvents.reg` file if you want to hide the abovementioned program events again. You can use the `RestoreStartupDelay.reg` file to restore the default Windows 10 startup delay.
19-
20-
## When Program Events are Played
21-
|Event|When Played|
22-
|---|---|
23-
|Windows Logon|Session is unlocked|
24-
|Windows Logoff|Session is locked (Win+L) or "Switch user" command|
25-
|Exit Windows|Shut down, restart, sign out (anything that ends your session)|
26-
|Start Windows|When `soundrestore.exe` is launched, so if you put it in the Startup folder it will play when starting your session|
27-
28-
It is absolutely pathetic that you need to use a third-party program like this one to do such a simple thing but here we are...
29-
30-
# Why?
31-
## Windows 10 Has No Soul
32-
![](https://i.ibb.co/Cbw576Y/W10-Laptop-Start-Mini-Start-16x9-en-US-042315.png)
33-
34-
After you install Windows 10, you're greeted by a dark and cold environment along with a start menu that is basically a giant advertisement board. It feels very much like a dark and lonely subway station. It isn't welcoming at all and makes you want to leave as quickly as possible.
35-
36-
My solution for this was to run some custom-made scripts that remove essentially all safely removable modern apps. I also use Windows 10 Enterprise so that I can apply a few hundred Group Policies that make the operating system largely stop spying on me. They also make it a whole lot less annoying to use.
37-
38-
But it still feels dark and cold.
39-
40-
## Windows Used to be Fun
41-
![](https://i.ibb.co/D19Gr94/Annotation-2020-10-16-150202.jpg)
42-
43-
Remember Windows 98? Yes, it wasn't exactly what people would consider a technological marvel. It would crash daily due to bad drivers and badly written software, and when it crashed, it showed no mercy and usually took down everything with it.
44-
45-
Putting the daily crashes aside for a moment, Windows 98 did at least feel a little bit like it had a *soul*. Call me nostalgic, but I think it tried hard to be friendly and welcoming operating system that you could take seriously. It tried to help you get things done as good as it could.
46-
47-
I tried to extract some Plus! 98 themes and apply them to Windows 10. If you put the effort in, you can actually still customize everything from the wallpaper and colors right down to the desktop icons, mouse pointers and sounds. That's part of what made the themes fun back in the day. But since Microsoft's Shell Team decided that Windows 10 isn't supposed to be fun, I had to resort to writing this small program to get some of the fun back.
12+
1. Configure the sounds that you want to play using the Control Panel (hint: Press <kbd>Windows</kbd> + <kbd>R</kbd> on your keyboard, type `control mmsys.cpl`, and press Enter)
13+
1. Reboot
14+
15+
> [!CAUTION]
16+
> The [Taskman registry key](https://www.geoffchappell.com/notes/windows/shell/explorer/taskman.htm) is fairly obscure. Some anti-virus programs may flag setting it as suspicious. You can verify that `SetTaskman.reg` is not doing anything malicious by examining its contents with a text editor.
17+
>
18+
> Likewise, `soundrestore.exe` is a tiny program that lacks a digital signature, doesn't have an icon, and doesn't include any file version information. This makes it look scary to "AI-powered" or "cloud-enhanced" security software. If you don't trust me, grab a copy of Visual Studio and compile the code yourself.
19+
20+
## When Program Events Are Played
21+
| Event | When Played |
22+
|-------|-------------|
23+
| Windows Logon | Session is unlocked (e.g., after entering password) |
24+
| Windows Logoff | Session is locked (<kbd>Windows</kbd> + <kbd>L</kbd>) or "Switch user" is selected |
25+
| Exit Windows | System shuts down, restarts, or user signs out |
26+
| Start Windows | At session startup, triggered by the Task Scheduler task |
27+
28+
It is absolutely pathetic that you need to use a third-party program like this one to do such a simple thing, but alas, such is the state of modern Windows.

RestoreStartupDelay.reg

-298 Bytes
Binary file not shown.

SetTaskman.reg

324 Bytes
Binary file not shown.

src/soundrestore.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include <windows.h>
2+
#include <mmsystem.h>
3+
#include <wtsapi32.h>
4+
5+
#pragma comment(lib, "kernel32.lib")
6+
#pragma comment(lib, "user32.lib")
7+
#pragma comment(lib, "winmm.lib")
8+
#pragma comment(lib, "wtsapi32.lib")
9+
10+
/* Microsoft:
11+
*
12+
* ----------------------------------------------------------------------
13+
*
14+
* As part of speeding up logon, logoff, shutdown, we experiment a lot
15+
* with what process is in control of the startup and shutdown sounds.
16+
* In an interim build of Windows 8 we were able to speed things up
17+
* considerably by moving the shutdown sound from Explorer.exe (which
18+
* is running while you’re still logged on) to logonui.exe (which
19+
* is the thing that shows the “Shutting down” circle.)
20+
*
21+
* However moving the shutdown sound this late started running into
22+
* other problems. The code we use to play the sound (PlaySound) needs
23+
* to read from the registry (to see what the preferences for this
24+
* sound were) and from the disk (to read the .wav file), and we ran
25+
* into issues where the sound was unable to play (or got cutoff
26+
* halfway) because we had shut down the registry or the disk already!
27+
*
28+
* We could have spent time rewriting the API but we decided the safest
29+
* and most performant thing to do was to eliminate the sound altogether.
30+
*
31+
* ----------------------------------------------------------------------
32+
*
33+
* TLDR: We could have kept the sounds, but weren't competent enough to
34+
* do it, so we decided to just kill the feature.
35+
*
36+
* Putting aside the fact that the WAV file could've been loaded into
37+
* memory earlier, and that the registry settings could've been cached,
38+
* just keeping all of the existing and working code to play the sound
39+
* inside Explorer would have cost nothing.
40+
*/
41+
42+
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
43+
switch (uMsg) {
44+
case WM_WTSSESSION_CHANGE:
45+
if (wParam == WTS_SESSION_LOCK)
46+
PlaySoundW(L"WindowsLogoff", NULL, SND_ALIAS | SND_SYSTEM | SND_ASYNC);
47+
else if (wParam == WTS_SESSION_UNLOCK)
48+
PlaySoundW(L"WindowsLogon", NULL, SND_ALIAS | SND_SYSTEM | SND_ASYNC);
49+
return 0;
50+
case WM_QUERYENDSESSION:
51+
return TRUE;
52+
case WM_ENDSESSION:
53+
if (wParam) {
54+
ShutdownBlockReasonCreate(hWnd, L"Playing shutdown sound");
55+
// We do not use SND_ASYNC here to block the thread
56+
PlaySoundW(L"SystemExit", NULL, SND_ALIAS | SND_SYSTEM | SND_SYNC);
57+
ShutdownBlockReasonDestroy(hWnd);
58+
PostQuitMessage(0);
59+
}
60+
return 0;
61+
case WM_DESTROY:
62+
PostQuitMessage(0);
63+
return 0;
64+
default:
65+
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
66+
}
67+
}
68+
69+
extern "C" void __cdecl Entry() {
70+
HANDLE hMutex = CreateMutexW(NULL, TRUE, L"sndrst_d3f9ae65");
71+
if (GetLastError() == ERROR_ALREADY_EXISTS) {
72+
if (hMutex) CloseHandle(hMutex);
73+
ExitProcess(0);
74+
}
75+
76+
WNDCLASSEXW wc;
77+
wc.cbSize = sizeof(WNDCLASSEXW);
78+
wc.style = 0;
79+
wc.lpfnWndProc = WindowProc;
80+
wc.cbClsExtra = 0;
81+
wc.cbWndExtra = 0;
82+
wc.hInstance = GetModuleHandleW(NULL);
83+
wc.hIcon = NULL;
84+
wc.hCursor = NULL;
85+
wc.hbrBackground = NULL;
86+
wc.lpszMenuName = NULL;
87+
wc.lpszClassName = L"DummyForm";
88+
wc.hIconSm = NULL;
89+
RegisterClassExW(&wc);
90+
91+
HWND hWnd = CreateWindowExW(WS_EX_NOACTIVATE, L"DummyForm", L"System Sound Player", 0, 0, 0, 0, 0, NULL, NULL, wc.hInstance, NULL);
92+
if (!hWnd) {
93+
if (hMutex) CloseHandle(hMutex);
94+
ExitProcess(0);
95+
}
96+
97+
ShowWindow(hWnd, SW_HIDE);
98+
WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
99+
PlaySoundW(L"SystemStart", NULL, SND_ALIAS | SND_ASYNC);
100+
101+
MSG msg;
102+
while (GetMessageW(&msg, NULL, 0, 0)) {
103+
TranslateMessage(&msg);
104+
DispatchMessageW(&msg);
105+
}
106+
107+
WTSUnRegisterSessionNotification(hWnd);
108+
if (hMutex) CloseHandle(hMutex);
109+
ExitProcess(0);
110+
}

src/soundrestore.sln

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11

2-
Microsoft Visual Studio Solution File, Format Version 11.00
3-
# Visual Studio 2010
4-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "soundrestore", "soundrestore\soundrestore.csproj", "{C83D7D14-48EE-47B9-A07E-E9CD4F0FFA96}"
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36518.9
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soundrestore", "soundrestore.vcxproj", "{9B3AD05F-3AEC-46F5-A7F8-463DD25D8586}"
57
EndProject
68
Global
79
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8-
Debug|Any CPU = Debug|Any CPU
9-
Release|Any CPU = Release|Any CPU
10+
Release|x86 = Release|x86
1011
EndGlobalSection
1112
GlobalSection(ProjectConfigurationPlatforms) = postSolution
12-
{C83D7D14-48EE-47B9-A07E-E9CD4F0FFA96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13-
{C83D7D14-48EE-47B9-A07E-E9CD4F0FFA96}.Debug|Any CPU.Build.0 = Debug|Any CPU
14-
{C83D7D14-48EE-47B9-A07E-E9CD4F0FFA96}.Release|Any CPU.ActiveCfg = Release|Any CPU
15-
{C83D7D14-48EE-47B9-A07E-E9CD4F0FFA96}.Release|Any CPU.Build.0 = Release|Any CPU
13+
{9B3AD05F-3AEC-46F5-A7F8-463DD25D8586}.Release|x86.ActiveCfg = Release|Win32
14+
{9B3AD05F-3AEC-46F5-A7F8-463DD25D8586}.Release|x86.Build.0 = Release|Win32
1615
EndGlobalSection
1716
GlobalSection(SolutionProperties) = preSolution
1817
HideSolutionNode = FALSE
1918
EndGlobalSection
19+
GlobalSection(ExtensibilityGlobals) = postSolution
20+
SolutionGuid = {9B774D9E-418F-47E9-8209-A2F69FF4A859}
21+
EndGlobalSection
2022
EndGlobal

src/soundrestore.vcxproj

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Debug|Win32">
5+
<Configuration>Debug</Configuration>
6+
<Platform>Win32</Platform>
7+
</ProjectConfiguration>
8+
<ProjectConfiguration Include="Release|Win32">
9+
<Configuration>Release</Configuration>
10+
<Platform>Win32</Platform>
11+
</ProjectConfiguration>
12+
<ProjectConfiguration Include="Debug|x64">
13+
<Configuration>Debug</Configuration>
14+
<Platform>x64</Platform>
15+
</ProjectConfiguration>
16+
<ProjectConfiguration Include="Release|x64">
17+
<Configuration>Release</Configuration>
18+
<Platform>x64</Platform>
19+
</ProjectConfiguration>
20+
</ItemGroup>
21+
<PropertyGroup Label="Globals">
22+
<VCProjectVersion>17.0</VCProjectVersion>
23+
<Keyword>Win32Proj</Keyword>
24+
<ProjectGuid>{9b3ad05f-3aec-46f5-a7f8-463dd25d8586}</ProjectGuid>
25+
<RootNamespace>soundrestore</RootNamespace>
26+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
27+
</PropertyGroup>
28+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
29+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
30+
<ConfigurationType>Application</ConfigurationType>
31+
<UseDebugLibraries>true</UseDebugLibraries>
32+
<PlatformToolset>v143</PlatformToolset>
33+
<CharacterSet>Unicode</CharacterSet>
34+
</PropertyGroup>
35+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
36+
<ConfigurationType>Application</ConfigurationType>
37+
<UseDebugLibraries>false</UseDebugLibraries>
38+
<PlatformToolset>v143</PlatformToolset>
39+
<WholeProgramOptimization>true</WholeProgramOptimization>
40+
<CharacterSet>Unicode</CharacterSet>
41+
</PropertyGroup>
42+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
43+
<ConfigurationType>Application</ConfigurationType>
44+
<UseDebugLibraries>true</UseDebugLibraries>
45+
<PlatformToolset>v143</PlatformToolset>
46+
<CharacterSet>Unicode</CharacterSet>
47+
</PropertyGroup>
48+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
49+
<ConfigurationType>Application</ConfigurationType>
50+
<UseDebugLibraries>false</UseDebugLibraries>
51+
<PlatformToolset>v143</PlatformToolset>
52+
<WholeProgramOptimization>true</WholeProgramOptimization>
53+
<CharacterSet>Unicode</CharacterSet>
54+
</PropertyGroup>
55+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
56+
<ImportGroup Label="ExtensionSettings">
57+
</ImportGroup>
58+
<ImportGroup Label="Shared">
59+
</ImportGroup>
60+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
61+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
62+
</ImportGroup>
63+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
64+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
65+
</ImportGroup>
66+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
67+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
68+
</ImportGroup>
69+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
70+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
71+
</ImportGroup>
72+
<PropertyGroup Label="UserMacros" />
73+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
74+
<ClCompile>
75+
<WarningLevel>Level3</WarningLevel>
76+
<SDLCheck>true</SDLCheck>
77+
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
78+
<ConformanceMode>true</ConformanceMode>
79+
</ClCompile>
80+
<Link>
81+
<SubSystem>Windows</SubSystem>
82+
<GenerateDebugInformation>true</GenerateDebugInformation>
83+
</Link>
84+
</ItemDefinitionGroup>
85+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
86+
<ClCompile>
87+
<WarningLevel>Level3</WarningLevel>
88+
<FunctionLevelLinking>true</FunctionLevelLinking>
89+
<IntrinsicFunctions>true</IntrinsicFunctions>
90+
<SDLCheck>false</SDLCheck>
91+
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
92+
<ConformanceMode>true</ConformanceMode>
93+
<Optimization>Custom</Optimization>
94+
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
95+
<OmitFramePointers>true</OmitFramePointers>
96+
<StringPooling>false</StringPooling>
97+
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
98+
<BufferSecurityCheck>false</BufferSecurityCheck>
99+
<CompileAs>CompileAsCpp</CompileAs>
100+
<LanguageStandard_C>stdc17</LanguageStandard_C>
101+
<DebugInformationFormat>None</DebugInformationFormat>
102+
</ClCompile>
103+
<Link>
104+
<SubSystem>Windows</SubSystem>
105+
<GenerateDebugInformation>true</GenerateDebugInformation>
106+
<AdditionalDependencies>kernel32.lib;user32.lib;winmm.lib;wtsapi32.lib</AdditionalDependencies>
107+
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
108+
<EntryPointSymbol>Entry</EntryPointSymbol>
109+
</Link>
110+
</ItemDefinitionGroup>
111+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
112+
<ClCompile>
113+
<WarningLevel>Level3</WarningLevel>
114+
<SDLCheck>true</SDLCheck>
115+
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
116+
<ConformanceMode>true</ConformanceMode>
117+
</ClCompile>
118+
<Link>
119+
<SubSystem>Windows</SubSystem>
120+
<GenerateDebugInformation>true</GenerateDebugInformation>
121+
</Link>
122+
</ItemDefinitionGroup>
123+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
124+
<ClCompile>
125+
<WarningLevel>Level3</WarningLevel>
126+
<FunctionLevelLinking>true</FunctionLevelLinking>
127+
<IntrinsicFunctions>true</IntrinsicFunctions>
128+
<SDLCheck>true</SDLCheck>
129+
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
130+
<ConformanceMode>true</ConformanceMode>
131+
</ClCompile>
132+
<Link>
133+
<SubSystem>Windows</SubSystem>
134+
<GenerateDebugInformation>true</GenerateDebugInformation>
135+
</Link>
136+
</ItemDefinitionGroup>
137+
<ItemGroup>
138+
<ClCompile Include="soundrestore.cpp" />
139+
</ItemGroup>
140+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
141+
<ImportGroup Label="ExtensionTargets">
142+
</ImportGroup>
143+
</Project>

src/soundrestore/AssemblyInfo.cs

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)