Deleting a bitmap resource in Visual C++ - c++

I am trying to delete a resource bitmap through code and am having trouble doing it. Went through several hours of headbanging with google. Here is the code:
int result;
HANDLE h;
h = BeginUpdateResource(L"C:\\Users\\Steve\\Desktop\\stub.exe", FALSE);
result = UpdateResource(h, RT_BITMAP, MAKEINTRESOURCE(IDB_BITMAP2), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
EndUpdateResource(h, FALSE);
When I debug, variable "result" ends up being NULL which means that the update didn't go through. Is there something incredibly basic that I'm missing?

Ok, I figured out what went wrong. First off, I used the "GetLastError()" command to help widdle down the possibilities. It gave me an error 0x57 which means ERROR_INVALID_PARAMETER.
When I experimented more, it seems that in the language paramters, I listed "MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)" instead of "MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)". Apparently, resources care about the language you are using even if it's something like a bitmap which doesn't use language.
Once I put in LANG_ENGLISH paramters, it worked. You can find out what language you are using by inspecting the text of the .rc that the resource is using to build.,

Related

rollback function or design pattern in C++

Right now, I am facing a new problem that I can't figure out how to fix. I have two files. One is a video file and other is a thumbnail. They have same name. I want to rename these two files using C++. I am using the rename function and it works. This is what I've written:
if(rename(videoFile) == 0)
{
if(rename(thumbnail) != 0)
{
printf("Fail rename \n");
}
}
The problem occurs when the video file is renamed successfully but for some reason the thumbnail can't be renamed. When this happens, I would like to rollback the renaming of the video file because the video file name and the thumbnail file name should be the same in my program. What I want to do is to rename after both files are okay to rename. Please guide me, any design pattern for function like rollback or third party software.
There is no absolutely foolproof way to do this.
Fundamental rule of disk I/O: The filesystem can change at any time. You can't check whether a rename would succeed; your answer is already wrong. You can't be certain that undoing the rename will succeed; somebody else might have taken the name while you briefly weren't using it.
On systems that support hard links, you can use them to get about 90% of the way there, assuming you're not moving between filesystems. Suppose you're renaming A to B and C to D. Then do these things:
Create hard link B which links to A. This is written as link("A", "B") in C, using the Unix link(2) system call. Windows users should call CreateHardLink() instead.
If (1) succeeded, create hard link D which links to C. Otherwise, return failure now.
If (2) succeeded, delete A and C and return success. Otherwise, delete B and return failure. If the deletions fail, there is no obvious means of recovery. In practice, you can probably ignore failed deletions assuming the reason for failure was "file not found" or equivalent for your platform.
This is still vulnerable to race conditions if someone deletes one of the files out from under you at the wrong time, but that is arguably not an issue since it is largely equivalent to the rename failing (or succeeding) and then the person deleting the file afterwards.
Technically, you should also be opening the containing directory (in O_RDONLY mode) and fsync(2)'ing it after each operation, at least under Unix. If moving between directories, that's both the source and the destination directories. In practice, nobody does this, particularly since it will lead to degraded performance under ext3. Linus takes the position that the filesystem ought to DTRT without this call, but it is formally required under POSIX. As for Windows, I've been unable to find any authoritative reference on this issue on MSDN or elsewhere. So far as I'm aware, Windows does not provide an API for synchronizing directory entries (you can't open() a directory, so you can't get a file descriptor suitable to pass to fsync()).
Nitpick: To some extent, this sort of thing can be done perfectly on transactional filesystems, but just about the only one in common use right now is NTFS, and Microsoft specifically tells developers not to use that feature. If/when btrfs hits stable, transactions might become genuinely useful.
On Windows platform starting from Vista, you can use code such as the following.
#include "KtmW32.h"
bool RenameFileTransact( LPCTSTR lpctszOldVideoFile, LPCTSTR lpctszNewVideoFile, LPCTSTR lpctszOldThumbnailFile, LPCTSTR lpctszNewThumbnailFile )
{
bool bReturn = false;
HANDLE hRnameTransaction = CreateTransaction(NULL, NULL, 0, 0, 0, 0, NULL);
if (MoveFileTransacted(lpctszOldVideoFile, lpctszNewVideoFile, NULL, NULL, 0, hRnameTransaction) &&
MoveFileTransacted(lpctszOldThumbnailFile, lpctszNewThumbnailFile, NULL, NULL, 0, hRnameTransaction))
{
if ( CommitTransaction(hRnameTransaction))
{
bReturn = true;
}
}
CloseHandle( hRnameTransaction );
return bReturn;
}
But as #Kevin pointed out above, Microsoft discourages the usage of this good feature.

Playing mp3 files with mciSendString (MCIERR_CANNOT_LOAD_DRIVER)

I am trying to write some code that can play an .mp3 file. I thought I could use the mciSendString call, but I am getting a strange error.
So, when I have this code:
int rc=mciSendString(L"open songname.mp3 alias song1", NULL, 0, 0);
rc returns with the number 266, and the error string returned with GetErrorString was:
"Unknown problem while loading the specified device driver."
Error 266 is MCIERR_CANNOT_LOAD_DRIVER
I have also tried:
int rc=mciSendString(L"open songname.mp3 type mpegvideo alias song1", NULL, 0, 0);
and received the same error.
I thought it may be the mp3 file, but I tried a few different ones and kept getting the same error.
My code is in C++ and is running on Windows 7. Is my code missing something?
Try surrounding songname.mp3 with an extra pair of quotes (be sure to escape them with backslashes).
It looks like I didn't have an mp3 codec for MCI. (Actually answered by #LightnessRacesinOrbit in comments to the question.)

Deleting registry keys - error in MSDN sample

This MSDN article is supposed to demonstrate how to delete a registry key which has subkeys, but the code is flawed.
The line that says
StringCchCopy (lpEnd, MAX_PATH*2, szName);
causes an exception, which is due to trying to copy to beyond the buffer of lpEnd. I tried correcting the solution by replacing that line with the following
size_t subKeyLen = lstrlen(lpSubKey);
size_t bufLen = subKeyLen + lstrlen(szName)+1;
LPTSTR buf = new WCHAR[bufLen];
StringCchCopy(buf,bufLen,lpSubKey);
StringCchCopy(buf+subKeyLen,lstrlen(szName)+1,szName);
buf[bufLen-1]='\0';
I'm unable to step through the code as the target platform and dev platform are different, but from the logging I've put in the code it looks like it just freezes up, but doesn't throw an exception.
It's frustrating that MSDN articles are wrong...you'd think they would be checked.
Any ideas on how to correct this?
Thanks.
If you don't mind having Shlwapi.dll as an additional dependency, it may be easier for you just to use SHDeleteKey. If you're only targetting Vista+, RegDeleteTree (which lives in Advapi32.dll) is another alternative.
That change by itself would not be sufficient. The line of code following it:
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
break;
would also need to change. lpSubKey would need to be replaced with buf since that now contains the full key.
And it probably goes without saying, but be sure to free (delete) buf as part of the cleanup.
However, for correctness, it seems as if it would be better just to fix the original line of code by changing it to pass the correct length (which should be okay since I believe the maximum key length in the registry is 255):
StringCchCopy (lpEnd, MAX_PATH*2 - lstrlen(lpSubKey), szName);

C++ CopyFile() does not works on c:\

hello guys i have one simple program which copying itself. Its work great when i copying in D disk. But when im trying to copy it on c disk nothing happens.
This is code :
int main()
{
string appDir = "";
appDir = std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
CopyFile(appDir.c_str(), "C:\\SelfCopyingApp.exe", 1);
system("PAUSE");
return 0;
}
Does anyone have an idea?
Thanks...
By default, the system drive has locked down permissions which prevent anyone from copying things there who are not administrators. Generally, one should not be messing with the root of the drive. If you need to do something like an installer, then you should
Ask for Admin rights
Install yourself in the correct location, namely %PROGRAMFILES%\CompanyName\ProductName
Messing with the root of the drive is asking for trouble; that's not where programs go.
Other notes on this code not related to your question:
system("pause") is wrong. Use std::cin.get() if you really want a portable way to get that behavior.
You should probably be using Unicode.
If GetModuleFileName fails you're going to be copying some random garbage to that location, not yourself. You need to check the return codes and GetLastError codes of every Win32 function.

Decrypting data files with wincrypt. Having trouble. Example shows CBase64Utils?

I need to decrypt some data files with wincrypt and examples are few and far between online. The most solid example I've found is here. However, this is using all sorts of types I cannot seem to find information about (CBase64Utils, CString, etc).
I am reading the final solution, trying to understand the process, and have come to this:
// 5. Determine the LENGTH of the BUFFER to hold the corresponding cyphertext.
CBase64Utils bu;
int ipszSourceLen = strlen(pszSource);
char *pszSource2 = bu.Decode(pszSource, &ipszSourceLen);
DWORD dwSourceLen = strlen(pszSource2); // Get the length of the input string.
DWORD dwDataLen = dwSourceLen;
BYTE* pTarget = NULL;
DWORD dwCryptDataLen = dwDataLen;
CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwCryptDataLen, dwDataLen);
This is pure chinese to me. Can anybody make sense of it and hopefully clear some muddy waters? Thanks
The code you linked is horrible. It appears the fellow wrote his encrypt method, and then subsequently wrote his decrypt method simply by copying and pasting the first method and making a few changes (yet leaving a ton of code left over from the encryption process). I wouldn't be surprised if it works, it's just that it wastes time and space doing useless work left over from encryption (plus the comments are all backwards).
As wincrypt is a Microsoft library, there are plenty of examples over at the MSDN. As MSDN samples are (usually) well-written and well-commented, they should be much easier to understand, so I would recommend you look at them instead.