String in WinAPI and c++ I/O [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm teaching my self WinAPI in c++, but as I progress I notice that every functions in WinAPI returns either char*, DWORD, LPCSTR and etc. My concern is I like using string, so what am I doing is after I get the return value I convert it to string. Is it good or bad? or does it make any difference if I convert it every time? or will it make the process slow or any bad stuffs. And for the I/O in c++, what is better cout or printf considering the size of exe or performance/functionality issue?

Start by learning the various string types. For example char*, LPSTR, and LPCSTR are all related and store ANSI characters; the last is a pointer to a const string. Similarly wchar_t*, WCHAR*, LPWSTR, and LPCWSTR are all related and store Unicode characters; again the last is a pointer to a const string.
Then watch what you mean when you say something like "returns char*" as most Windows APIs do nothing of the sort. Instead they take a LPSTR (a pointer to a char buffer) or LPWSTR (a pointer to a WCHAR buffer), and write into the buffer. Those APIs again almost always either take a count of characters available in the buffer, or have a documented buffer size requirement such as MAX_PATH.
You can use this to your advantage. C++11 requires that a std::wstring or std::string store its characters contiguously, and all known implementations did so well before that. So given an API like GetEnvironmentVariable, you can use the string as the buffer directly and sidestep most conversions. Use code similar to this, but feel free to modify how it interacts with the rest of your code:
std::wstring GetEnvironmentVariable(const std::wstring& strName)
{
DWORD cchValue = MAX_PATH;
std::wstring strValue;
// call API once or twice, to get required buffer size
strValue.resize(cchValue);
cchValue = GetEnvironmentVariable(strName.c_str(), &strValue[0], cchValue);
if (cchValue > MAX_PATH)
{
strValue.resize(cchValue);
cchValue = GetEnvironmentVariable(strName.c_str(), &strValue[0], cchValue);
}
// process errors such as ERROR_ENVVAR_NOT_FOUND
if (0 == cchValue)
{
// throw exception? return empty string? (current code does latter)
}
// remove null character and any extra buffer
strValue.resize(cchValue);
return strValue;
}
There are a lot of further enhancements you can make to this approach.
If you need to support old Windows 9x era operating systems, you can use LPTSTR instead by creating a typedef tstring that maps to std::wstring or std::string per the definition of UNICODE (otherwise I'd suggest just doing wide strings like I showed above). You can do explicit A and W function calls that either overload in C++, or follow the Windows naming convention.
You might be able to refactor the double call into some helper, or at least factor out some of the steps it requires.
You can handle APIs that take an in-out parameter for the buffer size.
You can figure out a way to handle APIs such as GetWindowText that only return a success/failure but do not return their required buffer size, and hide that dance behind your new wrapper function. See the related question and answer for an example approach. (Also note that other approaches may be better for that specific case.)
As far as I/O, there isn't a clear winner. You'll find that it's fairly rare to use the console and console I/O in Windows, so perhaps the question isn't very interesting after all. Aside from that, there are significant tradeoffs when it comes to internationalization; namely it's a lot easier to translate full sentence format strings than to translate the fragments that tend to result from uses of iostream. But if translation isn't a concern for you, that won't influence your decision.

Nearly everything you asked is opinion based. Yes, converting every char* you get to an std::string will be slower, but no it won't make much of a difference. Of course that is completely up to how often you're doing that, and where you'll be running this program. There's absolutely no problem with converting things to std::string in this case, but be warned, you're not going to have a fun time fighting against any API( it's going to be a lot more tedious to convert to and from types all the time. ) In the end, it's completely up to you. Just remember, just because you converted a char* that you allocated with new or malloc into an std::string doesn't mean you don't have to free, or delete it.
I don't see a problem with either printf or std::cout. Once again that's completely opinion based. However, std::cout might be a little easier to use and is certainly more type-safe.

Related

How to convert a double into a char* [duplicate]

This question already has answers here:
Converting double to char* in C++ with high performance
(9 answers)
Closed 7 years ago.
I am heavily struggling with a question which should be very easy: how do I do a simple type conversion (from double into char*) in basic C.
I have found quite some solutions, but they are all based on conversions from double to char[x], but I am working here with char*, not with char[]. (I don't know how long the resulting string will be).
On top of that, I really can't believe that another type (be it stringstream, std::strings, ...) are needed for something that simple.
I admit, I'm a complete newbie in basic C, but I have worked in other languages (Visual Basic, Delphi, Java, ...) and I just can't understand why I can't find a simple function like "to_char_pointer(double d)" to do this.
Does anybody have an idea?
You can use sprintf() as you have done to convert a double to a string, but I would actually recommend using _snprintf() instead simply because sprintf() has no regard for the fact that strings are fixed length devices in memory and will overflow if you don't watch it. _snprintf() allows you to specify the length of the out string, just be sure to specify the size as one less than the actual allocated memory block, because _snprintf() does not store the terminating null character if it has to cut the output short.
An example us using _snprintf() is:
void ToString(char * outStr, int length, double val)
{
_snprintf(outStr,length,"%f",val);
}

Using, StringCchCat

I'm trying to use the StringCchCat function:
HRESULT X;
LPWSTR _strOutput = new wchar_t[100];
LPCWSTR Y =L"Sample Text";
X = StringCchCat(_strOutput, 100, Y);
But for some reason I keep getting the "E_INVALIDARG One or more arguments are invalid." error from X. _strOutput Is also full of some random characters.
This is actually part of a bigger program. So what I'm trying to do is to concatenated the "sample text" to the empty _strOutput variable. This is inside a loop so it is going to happen multiple times. For this particular example it will be as if I'm assigning the Text "Sample Text" to _strrOutput.
Any Ideas?
If it's part of a loop, a simple *_strOutput = 0; will fix your issue.
If you're instead trying to copy a string, not concatenate it, there's a special function that does this for you: StringCchCopy.
Edit: As an aside, if you're using the TCHAR version of the API (and you are), you should declare your strings as TCHAR arrays (ie LPTSTR instead of LPWSTR, and _T("") instead of L""). This would keep your code at least mildly portable.
String copy/concat functions look for null terminators to know where to copy/concat to. You need to initialize the first element of _strOutput to zero so the buffer is null terminated, then you can copy/concat values to it as needed:
LPWSTR _strOutput = new wchar_t[100];
_strOutput[0] = L'\0`; // <-- add this
X = StringCchCat(_strOutput, 100, Y);
I'm writing this answer to notify you (so you see the red 1 at the top of any Stack Overflow page) because you had the same bug yesterday (in your message box) and I now realize I neglected to say this in my answer yesterday.
Keep in mind that the new[] operator on a built-in type like WCHAR or int does NOT initialize the data at all. The memory you get will have whatever garbage was there before the call to new[], whatever that is. The same happens if you say WCHAR x[100]; as a local variable. You must be careful to initialize data before using it. Compilers are usually good at warning you about this. (I believe C++ objects have their constructors called for each element, so that won't give you an error... unless you forget to initialize something in the class, of course. It's been a while.)
In many cases you'll want everything to be zeroes. The '\0'/L'\0' character is also a zero. The Windows API has a function ZeroMemory() that's a shortcut for filling memory with zeroes:
ZeroMemory(array, size of array in bytes)
So to initialize a WCHAR str[100] you can say
ZeoMemory(str, 100 * sizeof (WCHAR))
where the sizeof (WCHAR) turns 100 WCHARs into its equivalent byte count.
As the other answers say, simply setting the first character of a string to zero will be sufficient for a string. Your choice.
Also just to make sure: have you read the other answers to your other question? They are more geared toward the task you were trying to do (and I'm not at all knowledgeable on the process APIs; I just checked the docs for my answer).

using wsprintf with malloc

Is there any mistake to write a code such:
char* sp=(char*)malloc(128);
int x=22;
wsprintf(sp,"%d",x);
cout<<sp;
I am asking specially about security mistakes?
There are a number of "potential" issues here, non of them is actually infinging anything but you may find things not behaving as you expect.
First: wsprintf, as a Win32 API (http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550(v=vs.85).aspx ) is prototyped as:
int __cdecl wsprintf(
_Out_ LPTSTR lpOut,
_In_ LPCTSTR lpFmt,
_In_ ...
);
where LPTSTR is defined as char* or wchar_t* depending on the definition or not of the UNICODE symbol (check your propject settings and / or build commands)
Now, in case you are on an ANSI build (no UNICODE) all types are coherent, but there is no check about wsprintf writing more than the 128 char you allocated. If you just write a decimal integer it will have no problem, but if you (of somebody else after you) modify later the "message" and no checks are made, some surprises may arise (like wsprintf(sp,"This is the number I've been told I was supposed to be expected to be: %d",x); will this still fits the 128 chars?!? )
In case you are on a UNICODE build, you allocate 128 char, and write a double-byte string on it. The number 22 will be written as \x32\x00\x32\x00\x00\x00 (3200 is the little-endian coding for 0x0032 that is the wchar_t correponding to the UNICODE 50 that stands for '2').
If you give that sequence to cout (that is char based, not wchar_t based) will see the first \x00 as a string terminator and will output ... just '2'.
To be coherent, you shold either:
use all char based types and function (OK malloc and cout, but wsprintfA instead of wsprintf)
use all wchar_t based types and function (malloc(128*sizeof(wchar_t)), wchar_t* and wsprintfW)
use all TCHAR based types (malloc(128*sizeof(TCHAR)), TCHAR* and wsprintf, but define tcout as cout or wcout depending on UNICODE).
There is no security mistake because it is never the case that an int converted to a C string will exceed the size you've allocated.
However this style of programming has the potential for security issues. And history has shown that this kind of code has caused real security issues time and time again. So maybe you should be learning a better style of coding?
This MSDN link lists some concerns over the use of wsprintf. They don't appear to apply to your example but they do give some alternatives that you might want to explore.
Ok given that you have stated you are using winapi, read this from their documentation:
Note Do not use. Consider using one of the following functions
instead: StringCbPrintf, StringCbPrintfEx, StringCchPrintf, or
StringCchPrintfEx. See Security Considerations.
Therefore do not use. I would ignore however what they tell you to do instead and either:
Write in C, and a function from the C standard library (sprintf, snprintf etc). In that case you cannot use cout.
Write in C++. Use std::string and there is even a new to_string, as well as boost::format and ostringstream to help you build formatted string. You can still use C standard library functions there if you want to as well when it really suits your purpose better, but leave the allocation stuff to the library.

When to use std::string vs char*? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ char* vs std::string
I'm new to C++ coming from C# but I really do like C++ much better.
I have an abstract class that defines two constant strings (not static). And I wondered if a const char* would be a better choice. I'm still getting the hang of the C++ standards, but I just figured that there really isn't any reason why I would need to use std::string in this particular case (no appending or editing the string, just writing to the console via printf).
Should I stick to std::string in every case?
Should I stick to std::string in every case?
Yes.
Except perhaps for a few edge cases where you writing a high performance multi-threaded logging lib and you really need to know when a memory allocation is going to take place, or perhaps in fiddling with individual bits in a packet header in some low level protocol/driver.
The problem is that you start with a simple char and then you need to print it, so you use printf(), then perhaps a sprintf() to parse it because std::stream would be a pain for just one int to string. And you end up with an unsafe and unmaintainable mix oc c/c++
I would stick to using std::string instead of const char*, simply because most of the built-in C++ libraries work with strings and not character arrays. std::string has a lot of built-in methods and facilities that give the programmer a lot of power when manipulating strings.
Should I stick to std::string in every case?
There are cases where std::string isn't needed and just a plain char const* will do. However you do get other functionality besides manipulation, you also get to do comparison with other strings and char arrays, and all the standard algorithms to operate on them.
I would say go with std::string by default (for members and variables), and then only change if you happen to see that is the cause of a performance drop (which it won't).
Use std::string when you need to store a value.
Use const char * when you want maximum flexibility, as almost everything can be easily converted to or from one.
This like comparing Apples to Oranges. std::string is a container class while char* is just a pointer to a character sequence.
It really all depends on what you want to do with the string.
Std::string on the other hand can give you a quick access for simple string calculation and manipulation function. Most of those are simple string manipulation functions, nothing fancy really.
So it basically depends on your needs and how your functions are declared. The only advantage for std::string over a char pointer is that it doesnt require a specific lenghth decleration.

Simple General Questions about C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Ive moved from autoit and am now learning C++ and some problems keep coming up.
The first one is storing character input. The problem is that I have no idea how many characters are in that line of the file (if you are reading a file) or how many letters a user is going to type (in a console application).
What is the best way to approach this problem?? I have heard about the string class, but I want to avoid it becuase I dont know how it works and that leads to vunerabilities etc.
Secondly...
In C you can load shellcode into memory, create a function pointer, and execute that code.
Is there any mechanism for this in C++???
Thirdly...
How does the interpreter iterate through char arrays for string output??? (char array[3];) Does the compiler keep track of the size of the array, or does it just keep reading from memory until it hits that \0 thing???
Lastly...
If Char * are just pointers to data in memory, then why does:
char * title = "Program Title";
this work??? where is the string literal stored in memory?? how is it referenced???
Thankyou very much. I greatly appreciate your help.
-Hyperzap
Investing your time in learning std::string is well worth the effort, as it takes care of a lot of hassle for you. If you don't want to take advantage of the features in C++, then why use C++ and not just C?
You can use the same code for this as you would in C.
Yes, iostream-output of C-style strings outputs until terminating zero. Once again, if you use std::string you do not have to care about such details.
Correct me if I'm wrong, but I think title would be a const char[] stored on the stack.
Example:
const char* hello = "Hello\0World";
cout << hello; // Prints only "Hello", i.e. up to terminating zero (\0)
The reason this works:
const char* hello = "Hello world";
cout << hello;
is because hello is really "Hello world\0"; - in other words, the compiler inserts a terminating zero.
Note that std::string doesn't do any magic. It too reads until the terminating zero:
string hello = "Hello\0World\n";
cout << hello; // Still only gives "Hello"
char* title = "String Literal" works because the compiler preallocates a memory location to store your string literal, thus you then get back a pointer to this memory location.
In c++, an array for which you know the size at compile time (as in your example: char array[3] is a type in itself, so the compiler does keep track of the size. However, if you do not know the size (ie. char array[]), it is just a pointer to char. However, you should be using std::vector in c++ (better safety and performance).
I'm not too sure about your other two questions (didn't quite understand them)