Getting the service name from the executable that the service starts - c++

I have written an application and using a service to start it. All in C++, on Windows 7. My query is similar to How can a Windows Service determine its ServiceName?
Is there a way to determine (in C++) in an executable at run time, the name of the service that started that executable.
Just need a pointer in the right direction.
Thanks

You could use EnumServicesStatus to get a list of all services then filter those, I guess the best way is to compare the binary name. Then call QueryServiceConfig to get the service configuration including the service name.
I hope this is what you're looking for.
Of course to do this your application must be run as an administrator in Windows Vista and 7 or the call to OpenSCManager will definitely fail.
Edit:
Another quick way is to either have the service name hard-coded in a def file shared between the service and the executable or in a separate configuration file, hence eliminating all the fuss of the SCManager

Related

Windows 8: Application is not able write to C:\ProgramData\

I'm porting my application on Windows 8. Program uses path
C:\ProgramData\MyProgramName\
for storing backups.
It works good on Windows 7, but it got "Access Denied" when I run it on Windows 8.
What is the proper way and place to store my program's backups (not related to any particular user) ?
I see many programs storing their non-user related application data in the common application folder. Ok, actually what they do is create a folder inside the common application folder to store their data.
To get the path to the common application folder, you can call the SHGetFolderPath function with CSIDL_COMMON_APPDATA as the folder id. If don't have to support anything earlier than Windows Vista then you can call the SHGetKnownFolderPath function instead, and pass FOLDERID_ProgramData as the known folder id.
Ah! I did not know that the common application folder is not-writeable by normal users. Luckily there appears to be a recommended solution. See this article on MSDN, Data and Settings Management which states the following "If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup. The modified security must be documented in the Vendor Questionnaire."
C:\ProgramData has security settings that prevent standard user from writing there. This is not new in Windows 8, Windows 7 was the same, and the equivalent folder on Vista is also secured in this way. Perhaps your Windows 7 environment has UAC disabled, or perhaps you have secured C:\ProgramData or C:\ProgramData\MyProgramName to permit write access to standard user.
There are a couple of approaches to the use of this folder. Some applications write there only during installation whilst the installer process is running elevated. Then the application itself, which runs as standard user, can read, but never attempts to write.
Another approach is for the installer to create a sub folder of C:\ProgramData that is secured to allow write access for standard user, or whatever user/group that you the developer deem appropriate.

How can I retrieve the Windows profiles directory path remotely?

I'm trying to retrieve the path of the profiles directory across various versions of Windows. In older versions that might be [drive]:\Documents and Settings, on newer ones it's [drive]:\Users. There are several ways to do this locally without a problem, however I need to find the path on a remote machine that I've connected to.
Remote Registry is enabled.
I have an impersonation token and can successfully gather information from the remote host via the Net API, etc.
I have access to the administrative share, and therefore all the files on the remote drive.
Here's a list of other important caveats.
It's a C++ project.
It doesn't seem to be possible for GetProfilesDirectory or GetUserProfileDirectory to operate in a remote context. If I'm wrong about this please let me know but in all my experiments the function has returned something from the local machine.
I can't use WMI, we tried many times to integrate WMI functionality into our project and it just didn't work.
I would prefer to do as little "screen scraping" as possible. If you have an idea that doesn't involve reading from some text file and parsing the result, I'd love to hear it. But I'd appreciate any useful answer really.
The profile directory information in the registry don't seem to be useful because it contains environment variables, and like GetProfilesDirectory, the environment variable expansion function does not seem designed for work with remote hosts. This means that the solution wouldn't work if I was making the call from a newer Windows machine to an older Windows machine or vice versa.
The solution should be general enough to work between hosts that might be running any version of Windows from Windows Server 2003 to Windows 7.
Thanks in advance for whatever ideas you might have. Ideally I'd just like to be able to force GetProfilesDirectory to operate on the remote host so if you know how to do that I'll love you forever.
If you have access to the remote registry, you should be able to look at the key where the profile directory and the profile list is kept:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

service and registry

I have a problem in understanding the relationship between services and registry.
I have the task of taking my windows C++ program and transform it from simple application to a service.
I read that I need to produce some more functions as: start stop resume install.
The problem is:
Why I need the regisrty ?
how I enter the new program ?
Beside those method what I need to do with the registry? how I enter inside it ?
Do I need to write a script for entering the service ?
I read but I just didn't understand, any answear and or some good links to explanation will be appreciated.
Thanks,
I'm not aware of any documented relationship between services and the registry. Services can use the registry to store their settings, just like any other application, but they're not required to.
Formally, you don't need the registry. You simply need to install the service using the relevant API functions. As part of their implementation, the API functions create registry entries that the OS uses later to know when and how to start your service, but I don't think those keys are documented with any expectation that developers would modify them manually, so don't worry about them.
If your program uses the registry to store settings, though, you'll need to understand what account your service runs as, because that affects what areas of the registry your program has access to.
Install your service by calling CreateService. Do that in your program's installer. You can also make your service install itself when it detects itself being run with a certain command-line switch, such as -i. To uninstall your service, call OpenService and then DeleteService. In either case, you'll need to call OpenSCManager first. See MSDN for more on how to call those functions.
Alternatively, you can use the sc command to create and delete your service.
As I mentioned above, you don't need to do anything with the registry. Just install and uninstall your service with the API and let the OS take care of the rest.
You don't need to write any scripts to start your service. The OS already knows how to start it (because it's installed). If your service is something that users would want to start and stop frequently, then rather than use the service control panel then they can use the net or sc commands.
We use the registry to store command line parameters. The executable is passed a special parameter saying "you are a service, and here is your service name", and then the program knows to look in the registry and read the rest of the command line parameters from there. Honestly, I don't know why it was done this way, but I suspect that there's a limit on the length of service command line.
As Rob said however, services don't have to use the registry at all.

Windows Limited User Installation

I have a Win32 application that includes an EXE, an ActiveX control (DLL) and a COM server (EXE) and I am using Inno Setup 5 to build my installer. Many of our customers use limited user accounts where the user has no admin rights and because the COM components require to be registered (which writes to HKEY_CLASSES_ROOT), my setup file must run with elevated (admin) privileges. I think this in unavoidable (sadly, I can't use registration-free COM because of the EXE COM server I have). However, I would like to create an update installer that can be ran as a limited user and am looking for some advice.
What I am thinking is the following:
The initial setup (first time installation) installs the application into %ALLUSERSPROFILE%\Application Data\CompanyName\AppName instead of %PROGRAMFILES%. The COM components are registered as normal (as they won't already exist).
Subsequent updates (using a different Inno Setup script) will simply copy the new files into %ALLUSERSPROFILE%\Application Data\CompanyName\AppName. Hopefully even a limited user will have write access to this folder and as the COM components have already been registered, admin access won't be required.
This would mean that my customers could upgrade to the latest and greatest version without the hassle of using an Administrator account. Is this acceptable or is this likely to bite me on the backside? I'm pretty sure Google Chrome does something similar but as it has no COM components (as far as I can tell) even the initial setup can be as a limited user.
Any advice from others who have faced this issue would be very welcome indeed.
OK, I found a way to create a limited-user installation script with both my COM server and COM objects being registered per-user.
I am using the latest version of ATL (v9) that ships with MSVC 2008 to create my COM server and COM objects. Turns out that you can register the COM server per-user via the new /RegServerPerUser switch. I tested this with limited user accounts on XP, Vista and Windows 7 and it works perfectly.
Next, the COM controls. Again, ATL9 to the rescue. You can register a control per-user by ensuring that RegSvr32 calls your control's DllInstall function, passing it a command-line parameter of user. So, to register a control in this way you simply do:
regsvr32.exe /i:user /n MyControl.DLL
Again, I tested this on XP, Vista and Windows 7 and it works fine.
I then made the following changes to my Inno Setup script:
The default installation folder will be {pf} (i.e. C:\Program Files) if the user has Admin rights. If not, then it defaults to {commonappdata} (i.e. C:\Documents and Settings\All Users).
Register my COM server using the new /RegServerPerUser switch.
I removed the regserver flags from my COM objects and instead added support to call regsvr32 using the new 'user' switch.
All of these changes are easy to do using the Inno Setup {code} feature.
Thanks to Kim for setting me down the per-user COM install path.
I don't know for sure, but I seem to recall COM servers support per-user installation, and maybe that goes for EXE servers as well.
If so, change your registration code to write information to HKEY_CURRENT_USER\Software\Classes instead of HKEY_CLASSES_ROOT.
The COM infrastructure should do the lookup first per-user and then per-machine.
It's worth an experiment anyway.
If you dumped inno-setup and used MSIs - MSI files support the idea of limited user installation of patches. An administrator must authorize the initial install, thereafter, digital signatures in patch msi files are processed by the elevated msi service without requiring user elevation.
You can duplicate this basic idea yourself - during an initial administrative install, install a service component that has the necessary access. When processing patches, ask the service process to process the EXE COM server registrations.
You need to rethink your approache ... write access to a folder than can also allow for program execution by the same user is the cause for 99% of all virus/malware functionality. Please learn a little about Software Restriction Policy and the new App Locker behavior built into Windows 7 so that the computing infrastructure can move forward not backward.

Installing Root CA Cert via code on Win32

We've just set up a new remote access solution using Microsoft's TS Gateway, which requires a couple of somewhat fiddly steps on the end users behalf in order to get it working (installing our root ca cert, requirement of RDP 6.1 client etc).
In order to make this setup process as easy as possible (a lot of these users aren't technically minded), I'm looking to create a program to perform all these tasks automatically. I have most of it working, however I'm not entirely sure how to go about importing the Root CA cert into the Windows certificate store.
Because this can potentially be run on a wide range of computers with varying levels of patches and updates, I'm steering well clear of .NET and anything that isn't native - the tool should 'just run' without the user having to install anything extra (well, I will say windows XP, no service packs, is the bare minimum required version of windows). In saying that, I don't mind using something third party if it can be bundled in with the tool, as long as it's not huge, and doesn't introduce any interactive steps. Ideally something in the windows API would be best, however I can't seem to track down anything relevant.
Currently the tool is a C++ application, so I don't mind if it's quite low level stuff.
First you need to open the root certificate store...
HCERTSTORE hRootCertStore = CertOpenSystemStore(NULL,"ROOT");
Then add the certificate using one of the CertAdd functions, such as CertAddEncodedCertificateToStore.
CertAddEncodedCertificateToStore(hRootCertStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,pCertData,cbCertData,CERT_STORE_ADD_USE_EXISTING,NULL);
pCertData and cbCertData would likely point to the certificate data that you read from a file (not sure if the certificate will be in a file, or how you will include it in your application).
Then close the store with...
CertCloseStore(hRootCertStore,0);
NOTE: This code if run as the user, installs the certificate to the user's root store, not the computer's. It also results in a warning dialog that the user must understand and select "Yes" to authorize the import. If your setup program can run this code in a system account, the import will affect the computer's root store and not warning dialog will be shown.
Have you looked at CertAddEncodedCertificateToStore ?
you could also check out CertAddEncodedCertificateToSystemStore