Initialize a wchar_t[] using a string - c++

Currently, I'm dealing with WMI for collecting the log files from a remote machine.
I have the username of the remote machine initialized as given below.
wchar_t pszName[]=L"My username";
pszName[] is a wchar_t array. The trouble I face is that when I pass my username as a parameter of string datatype, I need to initialize wchar_t array using a string.
I cannot use a wchar_t* pointer because it gives me an error on the later part of the program. I need to initialize something like
string username = "My username";
wchar_t pszName[] = .....?.....;

#include <string>
#include <vector>
#include <windows.h>
std::wstring str_to_wstr(std::string const & str)
{
int length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 0, 0);
if (!length)
return L"utf-8 to utf-16 conversion error!";
std::vector<wchar_t> buffer(length + 1);
if (!MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), buffer.data(), length))
return L"utf-8 to utf-16 conversion error!";
return std::wstring(buffer.data(), length);
}
// ...
std::string username{ "My username" };
std::wstring utf_16_username{ str_to_wstr(username) };
// ... use:
utf_16_username.data(); // wherever you would have used pszName

You can use the std::mbstowcs function to convert your string into wchar_t*:
std::string username = "My username"; //set your username
wchar_t pszName[] = L"My username"; //initialize pszName with a certain length wide string
std::mbstowcs(pszName, name.c_str(), std::wcslen(pszName)); //copy and convert name from username to pszName
And you need to include:
#include <string>
#include <cstdlib>
Be aware, that you have to give a maximum length for pszName, and that this value actually has to have allocated at least this length in memory! Otherwise you get runtime crashes!
With the current implementation, you can just insert a dummy name of the right length into pszName and get the right length with the std::wcslen function.

Related

Can "const char[18]* be changed to an entity of type LPCWSTR(C++)? [duplicate]

After getting a struct from C# to C++ using C++/CLI:
public value struct SampleObject
{
LPWSTR a;
};
I want to print its instance:
printf(sampleObject->a);
but I got this error:
Error 1 error C2664: 'printf' : cannot convert parameter 1 from
'LPWSTR' to 'const char *'
How can I convert from LPWSTR to char*?
Thanks in advance.
Use the wcstombs() function, which is located in <stdlib.h>. Here's how to use it:
LPWSTR wideStr = L"Some message";
char buffer[500];
// First arg is the pointer to destination char, second arg is
// the pointer to source wchar_t, last arg is the size of char buffer
wcstombs(buffer, wideStr, 500);
printf("%s", buffer);
Hope this helped someone! This function saved me from a lot of frustration.
Just use printf("%ls", sampleObject->a). The use of l in %ls means that you can pass a wchar_t[] such as L"Wide String".
(No, I don't know why the L and w prefixes are mixed all the time)
int length = WideCharToMultiByte(cp, 0, sampleObject->a, -1, 0, 0, NULL, NULL);
char* output = new char[length];
WideCharToMultiByte(cp, 0, sampleObject->a, -1, output , length, NULL, NULL);
printf(output);
delete[] output;
use WideCharToMultiByte() method to convert multi-byte character.
Here is example of converting from LPWSTR to char*
or wide character to character.
/*LPWSTR to char* example.c */
#include <stdio.h>
#include <windows.h>
void LPWSTR_2_CHAR(LPWSTR,LPSTR,size_t);
int main(void)
{
wchar_t w_char_str[] = {L"This is wide character string test!"};
size_t w_len = wcslen(w_char_str);
char char_str[w_len + 1];
memset(char_str,'\0',w_len * sizeof(char));
LPWSTR_2_CHAR(w_char_str,char_str,w_len);
puts(char_str);
return 0;
}
void LPWSTR_2_CHAR(LPWSTR in_char,LPSTR out_char,size_t str_len)
{
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,in_char,-1,out_char,str_len,NULL,NULL);
}
Here is a Simple Solution. Check wsprintf
LPWSTR wideStr = "some text";
char* resultStr = new char [wcslen(wideStr) + 1];
wsprintfA ( resultStr, "%S", wideStr);
The "%S" will implicitly convert UNICODE to ANSI.
Don't convert.
Use wprintf instead of printf:
wprintf
See the examples which explains how to use it.
Alternatively, you can use std::wcout as:
wchar_t *wstr1= L"string";
LPWSTR wstr2= L"string"; //same as above
std::wcout << wstr1 << L", " << wstr2;
Similarly, use functions which are designed for wide-char, and forget the idea of converting wchar_t to char, as it may loss data.
Have a look at the functions which deal with wide-char here:
Unicode in Visual C++

Why a smiley is displayed instead of a username?

Why a smiley is displayed instead of a username?
Changing console properties did not help...
#include "pch.h"
#include <windows.h>
#include <Lmcons.h>
#include <string>
#include <iostream>
std::string UserName() {
TCHAR username[UNLEN + 1];
DWORD size = UNLEN + 1;
std::string UserName1;
UserName1 = GetUserName((TCHAR*)username, &size);
std::cout << UserName1 << std::endl;
return UserName1;
}
int main()
{
UserName();
}
Conclusion: ☺
Have a look at the MSDN documentation of that function. The signature is
BOOL GetUserNameA(
LPSTR lpBuffer,
LPDWORD pcbBuffer
);
The function's return value is a BOOL, which is non-zero if the function succeeded. It does not return a string. The username buffer you pass to the lpBuffer parameter will contain the username:
std::string UserName() {
char username[UNLEN + 1];
DWORD size = UNLEN + 1;
std::string UserName1;
if (GetUserNameA(username, &size))
UserName1.assign(username, size-1);
std::cout << UserName1 << std::endl;
return UserName1;
}
As to why it displays a smiley, the reason is quite simple: the function happens to return TRUE, which is a 1 on your platform. A BOOL is an int, and this can be coerced to a char. Thus, the compiler calls the operator=(char) method on your std::string, writing char 0x01 to the std::string and setting its length to 1:
The string value is set to a single copy of this character (the string length becomes 1).
To recap, you're assigning character code 0x01 to your std::string. I assume you're running your code in a Windows Command Prompt, which uses an encoding derived from DOS' codepage 437. Here is its character map:
The upper left corner is code 0. What do you see right next to it? (tip: after 0 comes 1).
P.S.: On Windows, you can type any character of CP437 by holding down Alt and typing the character code. Alt + 1 will give you the smiley you got by running your program.

Replace wchar_t error return memory address

I want to replace a specific character wchar_t. as a result it return memory address. is there a way to return replaced wchar_t?
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
using namespace std;
int main()
{
wchar_t processPath[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 3820);
GetProcessImageFileName(hProcess, processPath, MAX_PATH);
CloseHandle(hProcess);
wchar_t * pwc;
pwc = wcsstr(processPath, L"\\Device\\HardiskVolume1");
wcscpy_s(pwc, 100, L"C:", 100);
wcout << processPath;
return 0;
}
Thank you
I suggest that you use std::wstring, and then .replace, there isn't really a good 'replace' function when using c-strings:
LPCWSTR pwszReplace = L"string-of-interest";
std::size_t len = wcslen(pwszReplace);
std::wstring path(processPath),
std::size_t ndx = path.find(pwszReplace);
if(std::wstring::npos!=ndx)
{
path.replace(ndx, len, L"new-string");
}
std::wcout << L"path is now: " << path << std::endl;
Use GetModuleFileNameEx Windows XP and higher. Or QueryFullProcessImageName for Vista and higher.
Otherwise, you can't assume "\\Device\\HardiskVolume1" is always "C:"
See also this SO Q&A: Convert HarddiskVolume path to normal path
Start by changing "\Device" to "\\?":
`"\\Device\\HardiskVolume1\\path.exe"` //to
`"\\\\?\\HardiskVolume1\\path.exe"`
wchar_t buf[MAX_PATH];
wchar_t *ptr = wcsstr(processPath, L"\\Device");
if(ptr)
{
wcscpy_s(buf, L"\\\\?");
wcscat_s(buf, ptr + wcslen(L"\\Device"));
}
Now you can open buf in CreateFile, then use GetFinalPathNameByHandle to get
`"\\\\?\\C:\\path.exe"`
Note that wcsstr returns NULL if search string is not found. If search string was found and copy was successful, you end up overwriting processPath the way you have done that. Moreover, wcscpy_s is the secure version of wcscpy. If you don't want to use wcscpy_s correctly then just use wcscpy without using a random number like 100 as the argument.

How do I assign a value to TCHAR* without using a string literal with TEXT()?

I need to assign a value to a TCHAR* variable in C++ and I have been told that this is accomplished using the TEXT() macro. However, I have found that I am only able to do this when using string literals.
//This assignment uses a string literal and works
TCHAR* name = TEXT("example");
//This assignment uses a local variable and causes an error
char* example = "example";
TCHAR* otherName = TEXT(example);
This wouldn't be a problem if it wasn't for the fact that the value of the TEXT() quote parameter will be determined by the user at runtime. Therefore, I need to store the value in some kind of local variable and pass it to the TEXT() macro. How am I able to use a local variable with TEXT() instead of a string literal? Or is there another way that I can assign the value to the TCHAR* varible?
The TEXT() macro only works for literals at compile-time. For non-literal data, you have to perform a runtime conversion instead.
If UNICODE is defined for the project, TCHAR will map to wchar_t, and you will have to use MultiByteToWideChar() (or equivalent) to convert your char* value to a wchar_t buffer:
char* example = "example";
int example_len = strlen(example);
int otherName_len = MultiByteToWideChar(CP_ACP, 0, example, example_len, NULL, 0);
TCHAR* otherName = new TCHAR[otherName_len+1];
MultiByteToWideChar(CP_ACP, 0, example, example_len, otherName, otherName_len);
otherName[otherName_len] = 0;
// use otherName as needed ...
delete[] otherName;
If UNICODE is not defined, TCHAR will map to char instead, and you can just assign your char* directly:
char* example = "example";
TCHAR* otherName = example;
I would suggest using C++ strings to help you:
std::basic_string<TCHAR> toTCHAR(const std::string &s)
{
#ifdef UNICODE
std::basic_string<TCHAR> result;
int len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), s.length(), NULL, 0);
if (len > 0)
{
result.resize(len);
MultiByteToWideChar(CP_ACP, 0, s.c_str(), s.length(), &result[0], len);
}
return result;
#else
return s;
#endif
}
char* example = "example";
std::basic_string<TCHAR> otherName = toTCHAR(example);

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.