CopyFile to a custom location, with string conversion problem - c++

I am trying to make this application copy itself to appdata, which requires the USERNAME, which I already have.
But, for some reason, the file doesn't copy to this place. I tried a lot of string conversion to char, but none of them worked for the strcat() and CopyFile() functions.
Here is the code:
char user[UNLEN + 1];
char Original[MAX_PATH];
DWORD User_len = UNLEN + 1;
GetUserName(user, & User_len);
std::string Path("C:\\Users\\");
Path += user;
Path += ("\\AppData\\Other Stuff");
GetModuleFileName(NULL, OriginalFile, sizeof(OriginalFile))
char *PathChr = new char(Path.length() + 1); // Might be wrong but continue...
strcat(PathChr, "something.exe");
CopyFile(OriginalFile, PathChr, NULL);
The question is now solved!

You are not allocating enough memory for PathChr. You are allocating only 1 char, not Path.length() number of chars. You need to use [] instead of () when calling new, eg:
char *PathChr = new char[Path.length() + 1];
...
delete[] PathChr;
Alternatively, forget using new[], just use the std::string you already created, eg:
std::string Path = "C:\\Users\\";
Path += user;
Path += "\\AppData\\Other Stuff\\";
Path += "something.exe";
...
CopyFileA(OriginalFile, Path.c_str(), NULL);
But, since you already know the maximum array length up front (UNLEN + 43), you don't need a dynamically allocated string at all, a fixed array will suffice:
char user[UNLEN + 1];
char Path[UNLEN + 46];
char Original[MAX_PATH];
DWORD User_len = UNLEN + 1;
GetUserName(user, &User_len);
strcpy(Path, "C:\\Users\\");
strcat(Path, user);
strcat(Path, "\\AppData\\Other Stuff\\something.exe");
GetModuleFileName(NULL, OriginalFile, sizeof(OriginalFile));
CopyFileA(OriginalFile, Path, NULL);
That being said, the location of the AppData folder is user-customizable, so do not hard-code it. The correct way to get the actual AppData path is to use SHGetFolderPath() with CSIDL_(LOCAL_)APPDATA, or SHGetKnownFolderPath() with FOLDERID_(Roaming|Local)AppData, eg:
char AppData[MAX_PATH];
char Path[MAX_PATH];
char Original[MAX_PATH];
SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, AppData);
LPSTR pDest = PathCombineA(Path, AppData, "Other Stuff\\something.exe");
GetModuleFileName(NULL, OriginalFile, sizeof(OriginalFile));
CopyFileA(OriginalFile, pDest, NULL);

Related

memcpy CString to char*

I'm trying to copy a CString to a char* using memcpy() and I have difficulties doing it. In fact, only the first character is copied. Here is my code:
CString str = _T("something");
char* buff = new char();
memcpy(buff, str, str.GetLength() + 1);
After this, all that buff contains is the letter s.
You probably are mixing ASCII and Unicode strings. If compiling with Unicode setting, then CString stores a Unicode string (two bytes per character, in your case each second byte is 0 and thus looks like an ASCII string terminator).
If you want all ASCII:
CStringA str = "something";
char* buff = new char[str.GetLength()+1];
memcpy(buff, (LPCSTR)str, str.GetLength() + 1);
If you want all Unicode:
CStringW str = L"something";
wchar_t* buff = new wchar_t[str.GetLength()+1];
memcpy(buff, (LPCWSTR)str, sizeof(wchar_t)*(str.GetLength() + 1));
If you want it working on both settings:
CString str = _T("something");
TCHAR* buff = new TCHAR[str.GetLength()+1];
memcpy(buff, (LPCTSTR)str, sizeof(TCHAR) * (str.GetLength() + 1));
If you want to convert a Unicode string to an ASCII string:
CString str = _T("something");
char* buff = new char[str.GetLength()+1];
memcpy(buff, (LPCSTR)CT2A(str), str.GetLength() + 1);
Please also recognize the casts from str to LPCSTR, LPCWSTR or LPCTSTR and the corrected buffer allocation (need multiple characters and not only one).
Also, I am not quite sure if this is really what you need. A strdup for example looks much simpler than a new + memcpy.
You have only allocated memory to hold a char variable. To do what you intend, you need to allocate enough memory to hold the complete string.
CString str = _T("something");
LPTSTR buff = new TCHAR[(str.GetLength()+1) * sizeof(TCHAR)]; //allocate sufficient memory
memcpy(buff, str, str.GetLength() + 1);
You are
Only allocating one char, which won't be enough unless the CString is empty, and
copying the CString instance instead of the string it represents.
Try
CString str = _T("something");
int size = str.GetLength() + 1;
char* buff = new char[size];
memcpy(buff, str.GetBuffer(), size);

C++ WCHAR manipulations

I'm developing a tiny Win32 app in C++.
I've studied C++ fundamentals long time ago, so now I completely confused because of character strings in C++. There were no WCHAR or TCHAR only char and String.
After a little investigation I've decided not to use TCHAR.
My issue is very simple I think, but I can't find clear guide how to manipulate strings in C++. Affected by PHP coding last few years I've expected something simple with strings manipulations and was wrong!
Simply, all I need is to put new data to a character string.
WCHAR* cs = L"\0";
swprintf( cs, "NEW DATA" );
This was my first attempt. When debugging my app I've investigated that swprintf puts only first 2 chars to my cs var. I've resolved my problem this way:
WCHAR cs[1000];
swprintf( cs, "NEW DATA" );
But generally this trick could fail, because in my case new data is not constant value but another variable, that could potentialy be wider, than 1000 chars long. And my code is looks like this:
WCHAR cs[1000];
WCHAR* nd1;
WCHAR* nd2;
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, "The paths are %s and %s", nd1, nd2);
In this case there is possibility than nd1 and nd2 total character count could be greater than 1000 chars so critical data will be lost.
The question is how can I copy all data I need to WCHAR string declared this way WCHAR* wchar_var; without losing anything?
P.S. Since I'm Russian the question may be unclear. Let me now about that, and I'll try to explain my issue more clear and complex.
In modern Windows programming, it's OK to just ignore TCHAR and instead use wchar_t (WCHAR) and Unicode UTF-16.
(TCHAR is a model of the past, when you wanted to have a single code base, and produce both ANSI/MBCS and Unicode builds changing some preprocessor switches like _UNICODE and UNICODE.)
In any case, you should use C++ and convenient string classes to simplify your code. You can use ATL::CString (which corresponds to CStringW in Unicode builds, which are the default since VS2005), or STL's std::wstring.
Using CString, you can do:
CString str1 = L"Some value";
CString str2 = L"Another value";
CString cs;
cs.Format(L"The paths are %s and %s", str1.GetString(), str2.GetString());
CString also provides proper overloads of operator+ to concatenate strings (so you don't have to calculate the total length of the resulting string, dynamically allocate a buffer for the destination string or check existing buffer size, call wcscpy, wcscat, don't forget to release the buffer, etc.)
And you can simply pass instances of CString to Win32 APIs expecting const wchar_t* (LPCWSTR/PCWSTR) parameters, since CString offers an implicit conversion operator to const wchar_t*.
When you're using a WCHAR*, you are invoking undefined behavior because you have a pointer but have not made it point to anything valid. You need to find out how long the resulting string will be and dynamically allocate space for the string. For example:
WCHAR* cs;
WCHAR* nd1;
WCHAR* nd2;
nd1 = new WCHAR[lstrlen(L"Some value") + 1]; // +1 for the null terminator
nd2 = new WCHAR[lstrlen(L"Another value") + 1];
cs = new WCHAR[lstrlen(L"The paths are and ") + lstrlen(nd1) + lstrlen(nd2) + 1];
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, L"The paths are %s and %s", nd1, nd2);
delete[] nd1;
delete[] nd2;
delete[] cs;
But this is very ugly and error-prone. As noted, you should be using std::wstring instead, something like this:
std::wstring cs;
std::wstring nd1;
std::wstring nd2;
nd1 = L"Some value";
nd2 = L"Another value";
cs = std::wstring(L"The paths are ") + nd1 + L" and " + nd2;
Suggest to use ATL CStringW class instead of raw WCHAR, it's much more handy. CString is wrapper for dynamically allocated C-string. It will manage string length & allocated memory buffer appropriately after each operation so you wouldn't care on it.
Typical usage:
#include <atlstr.h>
CStringW s;
s.Format(L"The paths are %s and %s", L"Some value", L"Another value");
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
or
#include <atlstr.h>
CStringW s(L"The paths are ");
s += L"Some value";
s += L" and ";
s += L"Another value";
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR

WIN32_FIND_DATA - Get the absolute path

I'm using something like this:
std::string tempDirectory = "./test/*";
WIN32_FIND_DATA directoryHandle;
memset(&directoryHandle, 0, sizeof(WIN32_FIND_DATA));//perhaps redundant???
std::wstring wideString = std::wstring(tempDirectory.begin(), tempDirectory.end());
LPCWSTR directoryPath = wideString.c_str();
//iterate over all files
HANDLE handle = FindFirstFile(directoryPath, &directoryHandle);
while(INVALID_HANDLE_VALUE != handle)
{
//skip non-files
if (!(directoryHandle.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
//convert from WCHAR to std::string
size_t size = wcslen(directoryHandle.cFileName);
char * buffer = new char [2 * size + 2];
wcstombs(buffer, directoryHandle.cFileName, 2 * size + 2);
std::string file(buffer);
delete [] buffer;
std::cout << file;
}
if(FALSE == FindNextFile(handle, &directoryHandle)) break;
}
//close the handle
FindClose(handle);
which prints the names of each file in the relative directory ./test/*.
Is there any way to determine the absolute path of this directory, just like realpath() does on Linux without involving any 3rd party libraries like BOOST? I'd like to print the absolute path to each file.
See the GetFullPathName function.
You can try GetFullPathName
Or you can use SetCurrentDirectory and GetCurrentDirectory. You might want to save the current directory before doing this so you can go back to it afterwards.
In both cases, you only need to get the full path of your search directory. API calls are slow. Inside the loop you just combine strings.

Why is the following C++ code printing only the first character?

I am trying to convert a char string to a wchar string.
In more detail: I am trying to convert a char[] to a wchar[] first and then append " 1" to that string and the print it.
char src[256] = "c:\\user";
wchar_t temp_src[256];
mbtowc(temp_src, src, 256);
wchar_t path[256];
StringCbPrintf(path, 256, _T("%s 1"), temp_src);
wcout << path;
But it prints just c
Is this the right way to convert from char to wchar? I have come to know of another way since. But I'd like to know why the above code works the way it does?
mbtowc converts only a single character. Did you mean to use mbstowcs?
Typically you call this function twice; the first to obtain the required buffer size, and the second to actually convert it:
#include <cstdlib> // for mbstowcs
const char* mbs = "c:\\user";
size_t requiredSize = ::mbstowcs(NULL, mbs, 0);
wchar_t* wcs = new wchar_t[requiredSize + 1];
if(::mbstowcs(wcs, mbs, requiredSize + 1) != (size_t)(-1))
{
// Do what's needed with the wcs string
}
delete[] wcs;
If you rather use mbstowcs_s (because of deprecation warnings), then do this:
#include <cstdlib> // also for mbstowcs_s
const char* mbs = "c:\\user";
size_t requiredSize = 0;
::mbstowcs_s(&requiredSize, NULL, 0, mbs, 0);
wchar_t* wcs = new wchar_t[requiredSize + 1];
::mbstowcs_s(&requiredSize, wcs, requiredSize + 1, mbs, requiredSize);
if(requiredSize != 0)
{
// Do what's needed with the wcs string
}
delete[] wcs;
Make sure you take care of locale issues via setlocale() or using the versions of mbstowcs() (such as mbstowcs_l() or mbstowcs_s_l()) that takes a locale argument.
why are you using C code, and why not write it in a more portable way, for example what I would do here is use the STL!
std::string src = std::string("C:\\user") +
std::string(" 1");
std::wstring dne = std::wstring(src.begin(), src.end());
wcout << dne;
it's so simple it's easy :D
L"Hello World"
the prefix L in front of the string makes it a wide char string.

How do you convert from a nsACString to a LPCWSTR?

I'm making a firefox extension (nsACString is from mozilla) but LoadLibrary expects a LPCWSTR. I googled a few options but nothing worked. Sort of out of my depth with strings so any references would also be appreciated.
It depends whether your nsACString (which I'll call str) holds ASCII or UTF-8 data:
ASCII
std::vector<WCHAR> wide(str.Length()+1);
std::copy(str.beginReading(), str.endReading(), wide.begin());
// I don't know whether nsACString has a terminating NUL, best to be sure
wide[str.Length()] = 0;
LPCWSTR newstr = &wide[0];
UTF-8
// get length, including nul terminator
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
str.BeginReading(), str.Length(), 0, 0);
if (len == 0) panic(); // happens if input data is invalid UTF-8
// allocate enough space
std::vector<WCHAR> wide(len);
// convert string
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
str.BeginReading(), str.Length(), &wide[0], len)
LPCWSTR newstr = &wide[0];
This allocates only as much space as is needed - if you want faster code that potentially uses more memory than necessary, you can replace the first two lines with:
int len = str.Length() + 1;
This works because a conversion from UTF-8 to WCHAR never results in more characters than there were bytes of input.
Firstly note: LoadLibrary need not accept a LPWSTR. Only LoadLibraryW does. You may call LoadLibraryA directly (passing a narrow LPCSTR) and it will perform the translation for you.
If you choose to do it yourself however, below is one possible example.
nsACString sFoo = ...; // Some string.
size_t len = sFoo.Length() + 1;
WCHAR *swFoo = new WCHAR[len];
MultiByteToWideChar(CP_ACP, 0, sFoo.BeginReading(), len - 1, swFoo, len);
swFoo[len - 1] = 0; // Null-terminate it.
...
delete [] swFoo;
nsACString a;
const char* pData;
PRUint32 iLen = NS_CStringGetData(a, &pData);