boost regex search fails with MFC CString - mfc

I having an issue in using Boost regex with a MFC CString.
The regex is very simple: it must check if the string ends with the name of a dll I am looking for.
In the code below the CString Path DOES contain the dll I am looking for, but I don't know why the regex is failing. Uisng ReleaseBuffer increases the buffer size so the Length of Path is set to MAX_PATH.
Do you know why is not correct?
I did a lot of attempts but always failing.
#include <boost/regex/mfc.hpp>
const CString ValuesDLLName = _T("MyDll.dll");
boost::tregex EndsWithRegex( _T(".+MyDll.dll\s*$") );
//boost::tregex EndsWithRegex1( _T("^.+Values\.dll\\s*$") ); // not working
//boost::tregex EndsWithRegex2( _T("^.+Values\.dll\s*$") ); // not working
//boost::tregex EndsWithRegex3( _T("^.+Values.dll\s*$") ); // not working
//boost::tregex EndsWithRegex4( _T("^.+Values.dll\\s*$") ); // not working
//boost::tregex EndsWithRegex5( _T("^.+Values\.dll\\s*$"),boost::regex::perl ); // not working
//boost::tregex EndsWithRegex6( _T("^.+Values\.dll\s*$"),boost::regex::perl ); // not working
//boost::tregex EndsWithRegex7( _T("^.+Values.dll\s*$"),boost::regex::perl ); // not working
//boost::tregex EndsWithRegex8( _T("^.+Values.dll\\s*$") ,boost::regex::perl); // not working
CString Path;
boost::tmatch What;
_tsearchenv(ValuesDLLName, _T("PATH"), Path.GetBufferSetLength(260));
Path.ReleaseBuffer(260);
bool endsWithDllName = boost::regex_search( Path, What, EndsWithRegex );

Your backslashes need to be doubled up, because C++ will swallow up the first one as an escape character. Try
boost::tregex EndsWithRegex( _T("^.+Values\\.dll\\s*$") );
Also I think you're using ReleaseBuffer incorrectly. The parameter should be the actual size of the string that was returned, otherwise the end of the string might contain garbage. If you can depend on the string being null terminated, you can always use -1 for the parameter, or leave it out since it's the default.

Related

ShellExecute ends up in error C2065 don't know how to fix

I have a timer, after which a local html file should be executed, but I hit some kind of error:
int delay = 120;
delay *= CLOCKS_PER_SEC;
clock_t now = clock();
while (clock() - now < delay);
string strWebPage = "file:///D:/project/site/scam.html";
strWebPage = "file:///" + strWebPage;
ShellExecute(NULL, NULL, NULL, strWebPage, NULL, SW_SHOWNORMAL);
return 0;
E0413 no suitable conversion function from "std::string" to "LPCWSTR" exists
I'm new to C++, so it might be an obvious solution.
Could anyone point me to how I can fix it?
You have two problems.
But first, you should always take the time to read the documentation. For Win32 functions, you can get to a known function by typing something like “msdn ShellExecute” into your favorite search engine and clicking the “Lucky” button.
Problem One
ShellExecute() is a C function. It does not take std::string as argument. It needs a pointer to characters. Hence:
std::string filename = "birds.html";
INT_PTR ok = ShellExecute(
NULL, // no window
NULL, // use default operation
filename.c_str(), // file to open
NULL, // no args to executable files
NULL, // no start directory
SW_SHOWNORMAL );
if (ok <= 32)
fooey();
Notice that we pass a const char * to the function as the file to <default verb>.
Problem Two
From your image it would appear that you have your application declared as a Unicode application. In other words, somewhere there is a #define UNICODE.
This makes ShellExecute() expect a WIDE character string (const wchar_t *)as argument, not a narrow string (const char *).
You can still use a narrow string by simply specifying that you want the narrow version:
INT_PTR ok = ShellExecuteA(
...
I recommend you look at how you set up your project to figure out how you got things to think you were using wide strings instead of narrow strings.

C++: Trying to create a Run key, All i get is Chinese characters in registry.

Please save me! I am new to this, trying to figure this out. I would like to have my program add a run key to run itself on startup . Here is "my" code:
HKEY hKey = 0;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0,
KEY_ALL_ACCESS,
&hKey );
const unsigned char Path[ MAX_PATH ] = "C:\\test.exe";
RegSetValueEx( hKey, L"Testing", 0, 1, Path, strlen("C:\\test.exe") );
RegCloseKey(hKey);
This "works" except they key added reads "㩃瑜獥⹴硥" under data . Took me a while to figure out that the key is going to WoW6432Node too, thought it complied but wasn't working for the first 5 hours, much head to wall action there...
I am sure this has something to do with the way my string is formatted, ANSII vs ASCII vs the other 10 types of strings C++ doesn't seem to be able to convert between... I've tried using (BYTE*)"C:\virus.exe" and anything else i could think of... If i set the length to 1, the first character shows fine. But if its any other length, Chinese starts to show again.
Please help! I am about ready to start choking kittens here!
The problem is this:
const unsigned char Path[ MAX_PATH ] = "C:\\test.exe";
You have defined an ANSI string and then attempted to use the Unicode (UTF-16) version of RegSetValueEx:
RegSetValueEx( hKey, L"Testing", 0, 1, Path, strlen("C:\\test.exe") );
Under the hood, RegSetValueEx is a macro that aliases to RegSetValueExW because you defined the macro UNICODE.
The correct solution is to use a Unicode string literal:
const wchar_t Path[] = L"C:\\test.exe";
RegSetValueEx( hKey, L"Testing", 0, 1, (const BYTE *) Path, sizeof(Path) );
Here I used sizeof because the string is an array of characters whose size is known at compile time. For dynamic strings, use (wcslen(Path) + 1) * sizeof(*Path) instead.
Note: There is no need to specify the length of a constant literal in the declaration because the compiler can automatically deduce that in this specific scenario. It's also bad idea to duplicate the string literal inside your strlen/wcslen because if it goes out of sync your code could be broken and trigger undefined behavior.

Double check my knowledge: Unicode

there is this method: SCardListReaders, http://msdn.microsoft.com/en-us/library/windows/desktop/aa379793(v=vs.85).aspx
On MSDN there is an example.
After this call:
LPTSTR pmszReaders = NULL;
LPTSTR pReader;
lReturn = SCardListReaders(hSC,
NULL,
(LPTSTR)&pmszReaders,
&cch );
Such code is present which extracts strings from a multi string pmszReaders (multistring is terminated with double null characters).
pReader = pmszReaders;
while ( '\0' != *pReader )
{
// Display the value.
printf("Reader: %S\n", pReader );
// Advance to the next value.
pReader = pReader + wcslen((wchar_t *)pReader) + 1;
}
Just my question is. I think above code only works for Unicode right? If I disable Unicode support in my project, I think above code snippet will not correctly extract reader names? Isn't it?
For instance when I checked wcslen returns 22 when Unicode is set and 24 when Unicode is not set.
If you want the function to work in either a Unicode or MBCS build, use Microsoft specific _tcslen instead of wcslen.
If you want a compile time error if someone tries to use the function without Unicode, change LPTSTR to LPWSTR.

How to use mciSendString("play path",0,0,0) with exe path?

I'm using mciSendString("play path repeat",0,0,0) to play music in my project
and I'm using it specially for playing multiple sounds in the same time.
The problem is that I want to put the sounds in the executable path
so I used a function to get the exe path
string ExePath() {
char buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );
string::size_type pos = string( buffer ).find_last_of( "\\/" );
return string( buffer ).substr( 0, pos);
}
but mciSendString() takes LPCSTR so I tried the following
string music_cmd="play "+ExePath()+"\\war1.mp3 repeat";
mciSendString(music_cmd.c_str(),0,0,0);
The program runs without Errors but it doesn't play the sound.
How can I fix this problem ?
the path should have no spaces, if you use a path like as
follows: C:\music\music 2.mp3 it will not work.
to make it work delete the space or create a new path without spaces like as follows: C:\music\music2.mp3
Other Observations: the path should have less than 255 characters, relative path will not work (it works when you compile, but when you run the program on another computer, it will not work), cannot have spaces, otherwise it will fail.
there is a workaround you can do which is simple, you will be able to play with dots and spaces on the path
mine is as follows:
path = Application.StartuPath & `\whateverMusic.mp3`
path = Chr(34) & path & Chr(34)
mciSendString("Open " & path & " alias " & oName, Nothing, 0, 0)
mciSendString("Play " & oName, Nothing, 0, 0)
Public Property Name As String
Set(value as String)
oName = value
End Set
Get
Return oName
End Get
End Property
From Here: https://www.youtube.com/watch?v=UWLTegpOuB0

GetCurrentDirectory() is breaking the code in C++

In the following code if I comment out the call to "GetCurrentDirectory" everything works fine, but if I don't then the code breaks after it, no child windows show up, but the program don't crash. The compiler doesn't give any error.
char *iniFilePath;
int lenWritten = GetCurrentDirectory( MAX_PATH, iniFilePath );
if( lenWritten )
{
lstrcat( iniFilePath, iniFileName.c_str() );
char *buffer;
GetPrivateProfileString( iniServerSectionName.c_str(), serverIp.c_str(), "", buffer, MAX_PATH, iniFilePath );// server ip
MessageBox( 0, buffer, 0, 0 );
}
else
{
MessageBox( 0,0,0,0 );
}
iniFilePath is an unintialised pointer which GetCurrentDirectory() is attempting to write to, causing undefined behaviour. GetCurrentDirectory() does not allocate a buffer for the caller: it must be provided.
Change to:
char iniFilePath[MAX_PATH]; // or similar.
Instead of using lstrcat(), which has Warning Do not use message on its reference page, construct the path use a std::string instead to avoid potential buffer overruns:
const std::string full_file_path(std::string(iniFilePath) + "/" + iniFileName);
Note similar issue with buffer, as pointed out by Wimmel.
I would do this in order to get the current directory -
int pathLength = GetCurrentDirectory(0, NULL);
std::vector<char> iniFilePath(pathLength);
GetCurrentDirectory(pathLength, iniFilePath.data());
Note however that this won't be thread safe as the directory could change from another thread between the two calls but as far as I know few programs change the current directory so it's unlikely to be an issue.