Why a smiley is displayed instead of a username? - c++

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.

Related

How can I solve the problem when reading a registry entry?

i want to get the value from an registry entry. Here is my code:
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
#define BUFFER 8192
int main()
{
char value[255];
DWORD BufferSize = BUFFER;
RegGetValue(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", RRF_RT_REG_SZ, NULL, (PVOID)&value, &BufferSize);
std::cout << value << std::endl;
}
My Computer name is: DESKTOP-IGW3F.
But if i run my program my output is: D
I have no idea how to fix it...i hope you can help me.
The Win32 function RegGetValue() does not exist. It is only a preprocessor macro that will resolve to either RegGetValueA() or RegGetValueW() depending on your project settings. In your case, the macro resolves to RegGetValueW(), therefore it treats the registry value as a Unicode string (2 bytes per character). But you are using a char (1 byte per character) buffer to receive the Unicode data.
To make your code work, you need to either explicitly call RegGetValueA() instead, or change your buffer type from char to wchar_t. Either way, you should also check the return value of the function.
A working example could look like this:
#include <windows.h>
#include <iostream>
int main()
{
WCHAR value[255];
DWORD bufferSize = 255 * sizeof(WCHAR);
if (!RegGetValueW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", RRF_RT_REG_SZ, NULL, value, &bufferSize))
{
std::wcout << value << std::endl;
}
}

Initialize a wchar_t[] using a string

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.

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.

Display an int variable in a MessageBox

I am working on an old app written in Visual C++ 6.0. I am trying to display an int variable in a MessageBox for debugging reasons. Here is my code, I thought this would be a simple process, but I am just learning C++. The two lines that are commented I have tried as well with similar errors. Below is the error I am getting.
int index1 = 1;
char test1 = index1;
// char var1[] = index1;
// char *varGo1 = index1;
MessageBox(NULL, test1, "testx", MB_OK);
error C2664: 'MessageBoxA' : cannot convert parameter 2 from 'char' to 'const char *'
Why bother with C-style strings if you tagged C++?
Although Mark Ransom provided MFC solution (which is perfectly valid), here is a Standard C++ one:
int index1 = 1;
std::string test1 = std::to_string(index1);
MessageBoxA(NULL, test1.c_str(), "testx", MB_OK);
References:
std::to_string();
Arrays are evil
Use boost::format for more sophisticated formatting.
int index1 = 1;
char buf[10];
itoa(index1,buf,10);
MessageBox(NULL,buf,"Caption",MB_OK);
Can try this
CString str1;
str1.Format(_T("%d"), index1);
MessageBox(NULL, str1, "testx", MB_OK);
CString's Format works just like printf to populate the string with the parameter list.
The second parameter of MessageBox needs to be a pointer to a string of chars, terminated with NULL. Passing a char will not work.
But, learning to use a debugger is an integral part to learning a language. Why not build a debug build and set a breakpoint on char test1 = index1; instead? You do that by pressing F9 when the cursor is on that line.
For what it's worth, I prefer to use a manipulator for this:
#include <sstream>
#include <iostream>
#include <windows.h>
using std::ostringstream;
using std::ostream;
ostream &msg_box(ostream &s) {
ostringstream &os = dynamic_cast<ostringstream &>(s);
MessageBox(NULL, os.str().c_str(), "testx", MB_OK);
return s;
}
int main() {
ostringstream msg;
msg << "The number is: " << 10 << msg_box;
return 0;
}
This maintains (mostly) the same interface nearly everybody's already accustomed to with iostreams, avoids the type-unsafe CString::Format, and avoids having several lines of distraction everywhere you're going to display a little information for debugging. The other obvious good point is that if you've overloaded operator<< for your own type, that overload will work with this as well.
Acording to your error, you should declare a const pointer on the second parameter.
Like this,
const char * test1= new char();
or use
std::string test1= "";
MessageBox(NULL, test1.c_str(), "testx", MB_OK);
Also using just "Text" will work.
Here is the pure C solution using sprintf method to store all input in buffer and passing that buffer to MessageBox.
#include <stdio.h>
#include <windows.h>
int main(void)
{
int intVal = 50;
float fltVal = 5.5;
char *str = "Test String";
char buf[1024] = {'\0'};//buffer to store formatted input.
//convert formatted input into buffer.
sprintf(buf,"Int value : %d\nFloat value : %f\nString : %s\n",intVal,fltVal,str);
//display whole buffer.
MessageBox(NULL,buf,"INFO",MB_ICONINFORMATION);
return 0;
}

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.