Preventing WritePrivateProfileString going to the registry - windows

Is there any way to disable WritePrivateProfileString from writing to the registry and instead use the ini file that we provide to it? I see from the MSDN that you can disable file writes and exclusively use Registry, but not vice versa. I want to keep my program portable, at the same time, use standard win apis to store configuration data (instead of creating something new)..
Thanks

If your ini file is getting mapped to the registry, then you've apparently added it to
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping. Delete that entry and your ini file will end up where you expect it. Your line of code works as expected on my machine.
MSDN Link

I assume you're using MFC, since only that has its own versions of WritePrivateProfileString and similar functions. When you compile your code with newer Versions of MFC, you're automatically using the MFC equivalents of those APIs, and MFC simply uses the information you pass to the 'API's and writes/reads them from the registry.
To avoid this, don't write
WritePrivateProfileString
in your code but
::WritePrivateProfileString
instead.

Yes. Hook it (which you can do easily with a library such as Microsoft Detours).

Related

How to determine the version number of a registered OCX in Delphi XE2

I have an ActiveX component in XE2 that connects to a database to handle transaction processing, and it includes a check of its version against that of the database to determine if they are compatible.
Unlike C#, where the AssemblyVersion attribute can be obtained at runtime using the Application.ProductVersion property, Delphi XE2 has no such built-in property for getting the version information included in the project options, with the preferred method being to use GetFileVersionInfo, passing in the full path to the program, or in this case the OCX.
Originally the OCX was always installed to the Windows System path but we have changed our installation process so that the OCX is installed to the same folder as the executable that uses it, which is a location determined by the user.
What I need is a consistent method that I can use from within the OCX code to obtain the installation folder from the registry across the multitude of Windows environments. I assume it would have something to do with the GUID's defined in the _TLB.pas file.
You don't need to query the Registry at all. The OCX can retreive its own filename by passing Delphi's global HInstance variable as the module handle to the Win32 API GetModuleFileName() function, then it can pass that filename to GetFileVersionInfo().
Although, a better way for the OCX to access its own version, without resorting to GetFileVersionInfo(), is to use Find/Load/LockResource() to access its own version resource directly, then no filename is needed at all. You can copy the version resource data into a temp buffer and pass that to VerQueryValue() to retrieve the resource's VS_FIXEDFILEINFO structure (retrieving anything else from the resource gets a bit trickier because GetFileVersionInfo() prepares certain lookup data that VerQueryValue() then uses).
You certainly don't need to use the registry here. Not least because there could potentially be multiple versions of the DLL on the machine, because you are installing to the executable directory of any program that uses the DLL.
You could certainly read the version resource as Remy describes. But another alternative would be to include a constant in your program that encodes the database version compatibility.
const
DatabaseVersion = 1;
Check this constant against the value read from the database and fail if not compatible.
To me this makes a little more sense as it separates the version of the DLL from the version of the database. The two are not necessarily linked. You could, and probably do, update the DLL without changing the database structure.

how to overcome command line string limitation?

Command line has a string limitation as mentioned on msdn and here.
I tried the workaround suggested on msdn, writing the arguments to a file. But, I am unable to pass the arguments from a file.
Edit :
I need to run the bcp utility, in order to export (huge) data to flat files.
The executable you're running has to support this explicitly. For example, the C# compiler allows you to write
csc #foo
to load some options from a file called foo. I don't believe this can easily be "fixed" without support from the command you're running though... it's possible that you could write a small wrapper program which loaded the file and started the process itself. However, you'd have to be careful in terms of security handles, propagating console input and output etc. If you're in control of the application in question, you'd be much better off putting support in directly.

Send To Compressed (zipped) Folder from NSIS

Is there a way to programmatically Send (a single file) To Compressed (zipped) Folder from an NSIS script?
In my search, I found reference to opening such folder using:
rundll32.exe zipfldr.dll,RouteTheCall %filename%
But I haven't been able to find the opposite.
I also found references to creating a compressed (or zipped) folder by writing a fully fledged program in C++, VB, C#, or VJ# but that is not what I am interested in. I am interested in a simple call from an NSIS script.
Is this possible at all?
While it is possible to use the CompressedFolder feature to create zip files and NSIS can call native API's and COM interfaces, I can't really say that it would be a good idea. Some people don't like the CompressedFolder feature and disable it. It is probably better to include a command line zip tool in your installer and call that.
So to answer the question; yes it is possible, but calling COM from NSIS is a big pain and the code would break on machines where the CompressedFolder feature has been disabled.

Set directory permissions with inheritance during application installation?

I found a thread on the Microsoft Forums where the answer tells how to set directory permissions using the LockPermission table. I tried it, but it doesn't seem to set the inheritance for any of the subdirectories. I need to be able to set the permissions for a particular folder that I create and have those permissions be inherited by all of the files and directories within and beneath it. Is there a way to do this without having to add a line in the LockPermission table for each and every directory (and file) that I want to affect?
For anyone looking to know the joys and pains of using MsiLockPermissionsEx, here is a tutorial, some best practices and a helper script. The helper script extracts SDDL from existing system resources - so you just use Regedit and Windows Explorer to set permissions and the helper script extracts them for you.
The article also discusses the challenge of supporting XP and Windows 7 permissions with a single package.
You can check it out here: http://csi-windows.com/toolkit/csigetsddlfromobject
You can either see if the MsiLockPermissionsEx support in MSI 5 handles this (and is an acceptable dependency for you as currently it's only available on Windows 7), or you can implement custom support. The LockPermissions support available in earlier versions of Windows Installer has the limitation you describe (and others).

Can VS_VERSION_INFO be added to non-exe files?

My windows co-workers were asking me if I could modify my non-windows binary files such that when their "Properties" are examined under Windows, they could see a "Version" tab like that which would show for a Visual Studio compiled exe.
Specifically, I have some gzipped binary files and was wondering if I could modify them to satisfy this demand. If there's a better way, that would be fine, too.
Is there a way I could make my binaries appear to be exe files?
I tried simply appending the VS_VERSION_INFO block from notepad.exe to the end of one of my binaries in the hope that Windows scans for the block, but it didn't work.
I tried editing the other information regarding Author, Subject, Revision, etc. That doesn't modify the file, it just creates another data fork(what's the windows term?) for the file in NTFS.
It is not supported by windows, since each file type has their own file format. But that doesn't mean you can't accomplish it. The resources stored inside dlls and exes are part of the file format.
Display to the user:
If you wanted this information to be displayed to the user, this would probably be best accomplished with using a property page shell extension. You would create a similar looking page, but it wouldn't be using the exact same page. There is a really good multi part tutorial on shell extensions, including property pages starting with that link.
Where to actually store the resource:
Instead of appending a block to the file, you could store the resource into a separate alternate data stream on the same file. This would leave the original file stream non corrupted on disk and not cause its primary file size to change.
Alternate data streams allow more than one data stream to be associated with a filename. Each stream is identified by a colon : at the end of the filename and an identifier.
You can create them for example by doing:
notepad test.txt:adsname1
notepad test.txt:adsname2
notepad test.txt
Getting the normal Win32 APIs working:
If you wanted the normal API to work, you'd have to intercept the Win32 APIs: LoadLibraryEx, FindResource, LoadResource and LockResource. This is probably not worth the trouble though since you are already creating your own property page.
Can't think of any way to do this short of a shell extension. The approach I've taken in the past is a separate "census" program that knows how to read version information from any kind of file.
Zip files can be converted into exe files by using a program that turns a zip file into a self-extracting zip (I know that WinZip does this, there are most likely free utilities for this also; here's one that came up on a search but I haven't actually tried it). Once you've got an exe, you should be able to use a tool like Resource Hacker to change the version information.
It won't work. Either Windows would have to know every file format or no file format would be disturbed if version information were appended to it.
No, resource section is only expected inside PE (portable executable; exe, dll, sys).
It is more then just putting the data inside the file, you have a table that points to the data in the file header.
What you can do if you have NTFS drive, is to use NTFS stream to store custom properties this way the contact of the binary file will remain the same, but you will need to use a custom shell extension to show the content of the stream.

Resources