Volume changes without creating notification for IAudioEndpointVolume - c++

I'm have written a C++ application that is running as a Windows service to limit the volume of a Windows 7 computer. The user can specify different rules for different days and times and the service will smoothly change the volume. To implement this I use the IAudioEndpointVolume interface. In general it works like intended...
However, there exists a strange behavior I cannot explain yet. When switching users the volume suddenly drops but it does not generate a notification as one would expect. What is also strange is that the sliders in the SndVol.exe show the correct value for the volume.
Because of the missing notification my program cannot react to this change and as a result it cannot perform its intend anymore.
I have discovered that the volume will switch back to its correct volume again if I move the volume slider a bit. Of course this generates a notification that will be handled by my service. My service will then force the correct volume.
I don't understand why the volume changes without being visible in SndVol.exe and without creating a notification. Switching back to the first user account does not solve the problem. Even after logging out the volume is still at the wrong level.
As far as I have seen the documentation about the IAudioEndpointVolume interface does not mention anything about different user session.
Any ideas on what might cause this problem or what I could try to fix it?

Your service runs in session 0, the isolated session that prevents malware from exercising shatter attacks. The user's desktop runs in another session, there can be multiple. The WASAPI documentation is silent about exactly how an audio session gets mapped across Windows sessions. You have a very strong hint that it doesn't from the way it behaves.
There are ominous words in the section that talks about grouping parameters. A construct that primarily exists to allow Sndvol to identify processes that share the same volume control. It quotes Explorer as an example, a process that can be started more than once but still has a single volume control. A process that doesn't want to share uses session identifier GUID_NULL to select the default session in IAudioSessionControl::SetGroupingParam() or simply omits the call altogether since that's the default.
And the behavior of Sndvol, it only displays volume controls for the processes that run in the desktop session. You can't see the processes in another desktop session. Giving a very strong hint that audio session GUID_NULL is specific to the session in which it got created.
So quite unlikely that you can find a workaround for it as long as you do this with a service.
Instead, consider running your program as a normal windowless process that runs in the user's desktop session. Getting started by the Run registry key or a Startup folder shortcut or the task scheduler.

Well, after some time I am now quite confident that the volume change is caused by the 3rd party driver we are using. This driver has it's own volume control mechanism. I do not experience the change anymore after just starting the drivers' control GUI. Even after a restart the problem seems to be fixed. However, after some time it gets broken again for a reason I cannot figure out. But this only happened because some security settings prevented the drivers' control GUI to start when logged in as non admin. I fixed this now and expect everything to work now.
Furthermore it looks like that all user sessions share the same volume control. That means if I change the volume with SndVol in one user session the same change happens in the other user session. My service receives notifications for all these changes. So it looks like that I did not receive a notification when switching between users because the change was caused by the driver's control GUI starting when logging in as administrator. But this change happened in the driver, a lower layer, so that Windows is not aware of the change.
The driver we are using is the kX Audio Driver.

Related

C++ way of detecting powerstate changes in Windows for a desktop app

I've been looking everywhere for some information as to how one might go about registering for power state changes in a C++ application. I don't have a window handle and the program does not always run in as a service. I see that there are powerstate broadcasts available to register for but I cant seem to find anyway to get to them. Any one have any idea?
Once I've received a power state change, I plan on informing all connected users to that machine.

ETW how to survive a reboot

Using C++/Win32 API I create myself an event trace session. My application must supported NT5 thus I can't newer the newer APIs.
I am using the circular mode flags and real time flags.
I have everything working apart from one snag, when I reboot the machine the ETW session isn't persisted, my service starts up and recreates the ETW session (as the reboot has wiped it) which then causes the log file to be overwritten.
According to MSDN I must use the "global" logger on NT5 of which there can only be one, or an "AutoLogger" on NT6 of which there can be many. However MSDN says:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363687(v=vs.85).aspx
The AutoLogger sessions increase the system boot time and should be
used sparingly. Services that want to capture information during the
boot process should consider adding controller logic to itself instead
of using the AutoLogger session.
Sounds like overkill for what I'm trying to do. Indeed my service does contain the "controller" logic itself.
So how do I get ETW to keep my trace session for the next reboot? Or alternatively how do I re-create my ETW session on the next reboot without overwriting the ETW file if its already there?

How to tell that the logon screen is currently displayed?

I am writing a service application that will run with local system credentials. I will need to know from my service if the Windows logon screen is displayed at any particular time. Is there any way to do this?
PS. The screens that can be brought up by locking the workstation:
Or by trying to switch the user:
Or after a Ctrl+Alt+Del:
PS. I need this to run on Windows XP and up.
EDIT: The only viable solution that I came up with so far is to see if LogonUI.exe process is running. The issue with this approach is how to distinguish between the actual system logon process and any other process that has that image name?
As described in the comments you are trying to detect whether or not a process in an interactive desktop session should show a message box. There being no point doing so if the interactive session is not active.
In which case I believe that your proposed solution is the wrong one. Instead you should register for session change notifications by calling WTSRegisterSessionNotification. When you do this you'll get sent WM_WTSSESSION_CHANGE messages that allow you to keep track of the current state.
Note that you do this in your desktop app rather than the service. The service still sends its messages to the desktop app. But the desktop app now knows whether or not it is worth showing them.
Update
Remy suggests a better way in the comments:
And if a separate app is being used, there is no reason to detect session changes at all, that app can simply check if its currently assigned workstation/desktop is the currently interactive workstation/desktop instead, comparing GetThreadDesktop() to OpenInputDesktop(), for instance.
All such screens are presented on a separate desktop. You may try to enumerate the user's desktops and compare it with the current (I am not sure the service in session 0 - Vista and up - can do that; if not, spawn a helper process in the user session). This however may give a false positive if an UAC desktop is up. Another corner case is a userless situation (right after boot before any user looged on).
There are several states in the windows.
Logged-Off State
When Winlogon is in the logged-off state, users are prompted to identify themselves and provide authentication information. If a user provides correct user account information and no restrictions prevent it, the user is logged on and a shell program (such as Windows Explorer) is executed in the application desktop. Winlogon changes to the logged-on state.
Logged-On State
When Winlogon is in the logged-on state, users can interact with the shell, activate additional applications, and do their work. From the logged-on state, users can either stop all work and log off, or lock their workstations (leaving all work in place). If the user decides to log off, Winlogon will terminate all processes associated with that logon session and the workstation will be available for another user. If, instead, the user decides to lock the workstation, Winlogon changes to the workstation-locked state.
Workstation-Locked State
When Winlogon is in the workstation-locked state, a secure desktop is displayed until the user unlocks the workstation by providing the same identification and authentication information as the user who originally logged on, or until an administrator forces a logoff. If the workstation is unlocked, the application desktop is displayed, and work can resume.
reference: https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa380547(v=vs.85).aspx
p.s. registering a secure attention sequence (SAS, CTRL+ALT+Delete) is included in Workstation-Locked state
Similarly, there are several desktop types on windows.
Winlogon desktop
Application desktop(=Default desktop)
Screensaver desktop
Secure desktop
I recommend you read this:
https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa375994(v=vs.85).aspx
I don't know my answers are what you want... but I hope it helps in some ways.

Send images when app is tombstoned/closed?

The app I'm currently developing needs to send images and text to a webservice, and so far so good. The app works fine, but the next step is to make it keep sending when the user exits the app or changes to another app.
How do I achieve this?
I've looked at the background agent function, but that doesn't seem to be what I want. I do not want to wait every 30 minutes and then try to send for 25 sec with the periodic agent, and the users will almost never be in the very limiting state that the resource-intensive agent requires (over 90% battery life, must be on wi-fi etc).
Am I missing something obvious here? Only sending pictures and text when the user has the app active is a big down side.
I'm afraid it is not possible to do what you require with the current WP7 OS. The Windows Phone 7 OS has been designed to restrict applications in such as way that the user's security is protected, battery life is prolonged and they have a consistent experience. Allowing any application to execute arbitrary code in the background, without imposing constraints on execution time or duration would allow people to write applications that are extremely resource intensive. This is not good for the end user!
The "periodic" or "resource-intensive" agents, as described on MSDN, are your only options.

Windows Service with GUI monitor?

I have a C++ Win32 application that was written as a Windows GUI project, and now I'm trying to figure out to make it into a Service / GUI hybrid. I understand that a Windows Service cannot / should not have a user interface. But allow me to explain what I have so far and what I'm shooting for.
WHAT I HAVE NOW is a windows application. When it is run it places an icon in the system tray that you can double-click on to open up the GUI. The purpose of this application is to process files located in a specified directory on a nightly schedule. The GUI consists of the following:
A button to start an unscheduled scan/process manually.
A button to open a dialog for modifying settings.
A List Box for displaying status messages sent from the processing thread.
A custom drawn window for displaying image data (the file processing includes the creation and saving of images).
A status bar - while a process is not running, it shows a countdown to the next scheduled scan. During a scan it also provides some status feedback, including a progress bar.
WHAT I'M SHOOTING FOR is a service that will run on boot-up and not require a user to login. This would consist of the scheduled file processing. However, when a user logs in I would still like the tray icon to be loaded and allow them to open up a GUI as I described above to monitor the current state of the service, change settings, start a scan manually, and monitor the progress of a scan.
I'm sure that I have seen applications like this - that function as a service even when I'm not logged in, but still give me a user interface to work with once I do log in.
I'm thinking that instead of having a single multi-threaded application that sends messages to the GUI thread from the processing thread, I need two applications - a Service to perform the processing and a GUI application to provide visual feedback from the Service and also send messages to the Service (for example, to start a scan manually). But I am new to Windows Services and have no idea how this is done.
It is also possible that I'm completely off base and a Service is not what I'm looking for at all.
Any help / ideas / suggestions would be greatly appreciated! Thank you.
You can't do this as a service.
You'll need to make your Windows Service as a normal service application. This will startup on system startup, and run the entire time the system is up.
You'd then make a completely separate GUI application, which "talks" to the service. This can be set to run when a user logs in, in the user's account.
In order to make them "talk" to each other, you'll need to use some form of IPC. Since these run on the same system (but in different accounts, typically), named pipes or sockets both work quite well.
There is a simple way of doing it.
You can’t have the service access any user’s session (session 1,2,3..) since services are isolated and can access session 0 only. This is a change from 2011.
You should write a win32 program to be launched by your service per each user who logs in using https://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx
The service can continue performing any task that isn’t user specific.