I'm getting used to win32 API shenanigans but it's tiresome, the problem I face this time regards the assignemt of a name of a named pipe, this is what I'm doing:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
This is verbatim from MSDN webpages, and surprise, surprise, this doesn't compile and issues the following error:
E0144 a value of type "const wchar_t *" cannot be used to initialize an entity of type "LPTSTR"
Now a cast will solve the assignment but then I get a 109 error, which is, you guessed it, ERROR_BROKEN_PIPE.
How should I solve this?
The problem is that, despite claims to the contrary, the examples given in the WinAPI documentation are written in (mostly) C, not C++. Also, the use of string literals to initialize non-const character pointers is no longer allowed in C++ (since C++11).
So, replace:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
with:
TCHAR lpszPipename[] = TEXT("\\\\.\\pipe\\mynamedpipe");
(Whether or not that will fix your ERROR_BROKEN_PIPE is another matter, though!)
LPTSTR is the non-const version. You're trying to acquire a non-const pointer to a string literal.
This used to be valid C++ (it still is valid C, hence the sample), but it was very dangerous, so they made illegal in C++11. You either want:
wchar_t const* lpszPipename = L"\\\\.\\pipe\\mynamedpipe";
or
wchar_t pipename[] = L"\\\\.\\pipe\\mynamedpipe";
CreateNamedPipe take pointer to constant string ( LPCSTR or LPCWSTR) in place pipe name. so and do direct
CreateNamedPipe(TEXT("\\\\.\\pipe\\mynamedpipe"), ..)
i not view any reason for
LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
CreateNamedPipe(lpszPipename , ..)
however if by some reason use lpszPipename - it must be declared as pointer to constant string. LPCTSTR lpszPipename instead LPTSTR lpszPipename
possible and next solution - declare in global scope
static const WCHAR gPipename[] = L"\\\\.\\pipe\\mynamedpipe";
and use it, on binary level CreateNamedPipeW(L"\\\\.\\pipe\\mynamedpipe"), ..) and CreateNamedPipeW(gPipename, ..) produce the same code
Related
I'm trying to pass a process name as a TCHAR to the following void:
void GetBaseAddressByName(DWORD pID, TCHAR *pN)
By doing it like this:
GetBaseAddressByName(aProcs[i], (TCHAR*)"Process.exe");
So my question is: is what I am doing correct? Because I have tried both TEXT("Process.exe") and _T("Process.exe") with my project's Character Set both on Multi-Bite and Unicode and it just tells me that
argument of type "const char*" is incompatible with parameter of type "TCHAR*"
The short answer is no. TCHAR maps to either char or wchar_t depending on your project's Unicode/Multi-byte setting. So, in general, a cast like that is either unnecessary or incorrect. The correct way, as you said, is to use either the TEXT or _T macro. The reason you're getting an error is that you're trying to pass a const character string to a function that expects a mutable character string. The safeset way to get around the error is to copy your constant string into a local TCHAR buffer and then pass that to GetBaseAddressByName.
It is better to have a TCHAR array first, then copy into it.
#include "atlstr.h"
char const * procName = "processName.exe";
TCHAR szName [128];
_tcscpy(szName, A2T(procName));
GetBaseAddressByName(aProcs[i], szName);
As suggested by #Remy Lebeau in the comments, procName can be defined as TCHAR const * procName = TEXT("processName.exe");.
(TCHAR*)"Process.exe" is not a valid type-cast. It will "work" when the project charset is set to ANSI/MBCS, but it will produce garbage if the charset is set to Unicode.
Using TEXT("Process.exe") is the correct way to make a string literal use TCHAR characters.
GetBaseAddressByName(aProcs[i], TEXT("Process.exe"));
However, you need to change your pN parameter to const TCHAR * (or LPCTSTR) instead:
void GetBaseAddressByName(DWORD pID, const TCHAR *pN);
void GetBaseAddressByName(DWORD pID, LPCTSTR pN);
A string literal is const data, and you cannot pass a pointer-to-const-data where a pointer-to-non-const-data is expected (without casting the const away with const_cast). That is why you were still getting errors when trying to use the TEXT()/_T() macros.
You need a L, like L"Process.exe". Unicode strings are specified with L"".
That said, there is no reason to use TCHAR. Use unicode all the time, if doing Windows work only.
As I clould not pass LPCSTR from one function to another (Data get changed) I tried passing it as a string.
But later I need to again convert it back to LPSTR. While trying the conversion I am getting the above error:
cannot convert from 'std::string' to 'LPSTR'
How can I resolve this?
That's just because you should use std::string::c_str() method.
But this involves const_cast in given case because const char * returned by c_str() can not be assigned to a non-constant LPSTR.
std::string str = "something";
LPSTR s = const_cast<char *>(str.c_str());
But you must be sure that lifetime of str will be longer that that of LPTSTR variable.
Another mention, if code compiles as Unicode-conformant, then types LPTSTR and std::string are incompatible. You should use std::wstring instead.
Important note: If you pass the resulting pointer s from above to a function which tries to modify the data it is pointing to this will result in undefined behaviour. The only way to properly deal with it is to duplicate the string into a non-const buffer (e.g. via strdup)
If you need an LPSTR, that means the string will/may be modified. std::string::c_str() returns a const pointer, and you can't just const_cast it away and hope all is good in the world, because it isn't. The string may be changed in all sorts of nasty ways, and your original std::string will be oblivious to all of them.
Try this instead:
// myFunction takes an LPSTR
std::string cppString = "something";
LPSTR cString = strdup( cppString.c_str() );
try {
myFunction( cString );
cppString = cString;
} catch(...) {
free( cString );
}
Wrap the string in a smart pointer and get rid of the try...catch for bonus points (don't forget the custom deleter).
There is a function on std::string c_str() . However I doubt that you could not use a std::string in your case.
Are you running somestringvariablename.c_str()?
That should work.
An LPSTR can be substituted with by using a TCHAR (i.e. found in tchar.h). So if you have a std::string, you can use the method std::string::c_str().
If the function, you are calling does not write to string, but only reads it, then you can simply use string::c_str method. If it is going to write something, then you probably should ensure that your string has enough space by calling string::reserve().
I tried to use this code:
USES_CONVERSION;
LPWSTR temp = A2W(selectedFileName);
but when I check the temp variable, just get the first character
thanks in advance
If I recall correctly, CString is typedef'd to either CStringA or CStringW, depending on whether you're building Unicode or not.
LPWSTR is a "Long Pointer to a Wide STRing" -- aka: wchar_t*
If you want to pass a CString to a function that takes LPWSTR, you can do:
some_function(LPWSTR str);
// if building in unicode:
some_function(selectedFileName);
// if building in ansi:
some_function(CA2W(selectedFileName));
// The better way, especially if you're building in both string types:
some_function(CT2W(selectedFileName));
HOWEVER LPWSTR is non-const access to a string. Are you using a function that tries to modify the string? If so, you want to use an actual buffer, not a CString.
Also, when you "check" temp -- what do you mean? did you try cout << temp? Because that won't work (it will display just the first character):
char uses one byte per character. wchar_t uses two bytes per character. For plain english, when you convert it to wide strings, it uses the same bytes as the original string, but each character gets padded with a zero. Since the NULL terminator is also a zero, if you use a poor debugger or cout (which is uses ANSI text), you will only see the first character.
If you want to print a wide string to standard out, use wcout.
In short: You cannot. If you need a non-const pointer to the underlying character buffer of a CString object you need to call GetBuffer.
If you need a const pointer you can simply use static_cast<LPCWSTR>(selectedFilename).
I know this is a decently old question, but I had this same question and none of the previous answers worked for me.
This, however, did work for my unicode build:
LPWSTR temp = (LPWSTR)(LPCWSTR)selectedFileName;
LPWSTR is a "Long Pointer to a Wide String". It is like wchar*.
CString strTmp = "temp";
wchar* szTmp;
szTmp = new WCHAR[wcslen(strTmp) + 1];
wcscpy_s(szTmp, wcslen(strTmp) + 1, strTmp);
HRESULT UrlCanonicalize(
_In_ PCTSTR pszUrl,
_Out_ PTSTR pszCanonicalized,
_Inout_ DWORD *pcchCanonicalized,
DWORD dwFlags
);
Example:
LPCTSTR pszURL = URL.c_str();
LPSTR pszOutPut = new CHAR[ strUrl.length ];
DWORD* dwCount = new DWORD[ strUrl.length ];
hRes = UrlCanonicalize( pszURL, pszOutPut,dwCount, URL_ESCAPE_UNSAFE );
Output:
E_INVALIDARG
This API fails and returns E_INVALIDARG every time I try to call it. Please give me a working code snippet to call the UrlCanonicalize function.
If you know the C++ language, the SDK documentation for the function pretty much tells you everything that you need to know:
You pass it a C-style nul-terminated string that contains your URL.
You pass it pointer to a buffer to receive the output string.
You pass it one or more flags that customize the function's behavior.
And finally, it returns to you an HRESULT value, which is an error code. If it succeeds, that value will be S_OK. If it fails, it will be some other error code.
It works like this:
std::wstring originalURL(L"http://www.example.com/hello/cruel/../world/");
// Allocate a buffer of the appropriate length.
// It needs to be at least as long as the input string.
std::wstring canonicalURL(originalURL.length() + 1, L'\0');
DWORD length = originalURL.length() + 1;
// Call the function to modify the string.
HRESULT hr = UrlCanonicalize(originalURL.c_str(), // input string
&canonicalURL[0], // buffer
&length, // pointer to a DWORD that contains the length of the buffer
URL_UNESCAPE | URL_ESCAPE_UNSAFE);
if (SUCCEEDED(hr))
{
// The function succeeded.
// Your canonicalized URL is in the canonicalURL string.
MessageBox(nullptr, canonicalURL.c_str(), L"The URL is:", MB_OK);
}
else
{
// The function failed.
// The hr variable contains the error code.
throw std::runtime_error("The UrlCanonicalize function failed.");
}
If you want to make sure that the buffer is sufficiently long (and avoid having to handle that error), use the constant INTERNET_MAX_URL_LENGTH (declared in WinInet.h) when allocating it:
std::wstring canonicalURL(INTERNET_MAX_URL_LENGTH, L'\0');
DWORD length = INTERNET_MAX_URL_LENGTH;
The code you tried has a couple of problems:
You've incorrectly initialized the dwCount variable. The function wants a pointer, but that doesn't mean you should declare the variable as a pointer. Nor do you want an array; this is a single DWORD value. So you need to declare it as a regular DWORD, and then use the address-of operator (&) to pass the function a pointer to that variable. Right now, you're passing the function garbage, so it's failing.
You're using C-style strings, which you should avoid in C++ code. Use the C++ string class (std::wstring for Windows code), which is exception safe and manages memory for you. As you already know, the c_str() member function gives you easy access to a C-style nul-terminated string like all C APIs want. This works fine, you do not need to use raw character arrays yourself. Avoid new whenever possible.
Potentially, a third problem is that you're trying to use the C++ string type std::string instead of std::wstring. The former is an 8-bit string type and doesn't support Unicode in a Windows environment. You want std::wstring, which is a wide string with Unicode support. It's what all the Windows API functions expect if you have the UNICODE symbol defined for your project (which it is by default).
Here you go:
LPCTSTR pszURL = URL.c_str();
DWORD nOutputLength = strUrl.length * 2 + 32;
LPTSTR pszOutPut = new TCHAR[nOutputLength];
hRes = UrlCanonicalize( pszURL, pszOutPut, &nOutputLength, URL_ESCAPE_UNSAFE);
On the third parameter you provided garbage instead of pointer to initialized value, so you had API failure back. MSDN has it all for you:
A pointer to a value that, on entry, is set to the number of characters in the pszCanonicalized buffer.
As I clould not pass LPCSTR from one function to another (Data get changed) I tried passing it as a string.
But later I need to again convert it back to LPSTR. While trying the conversion I am getting the above error:
cannot convert from 'std::string' to 'LPSTR'
How can I resolve this?
That's just because you should use std::string::c_str() method.
But this involves const_cast in given case because const char * returned by c_str() can not be assigned to a non-constant LPSTR.
std::string str = "something";
LPSTR s = const_cast<char *>(str.c_str());
But you must be sure that lifetime of str will be longer that that of LPTSTR variable.
Another mention, if code compiles as Unicode-conformant, then types LPTSTR and std::string are incompatible. You should use std::wstring instead.
Important note: If you pass the resulting pointer s from above to a function which tries to modify the data it is pointing to this will result in undefined behaviour. The only way to properly deal with it is to duplicate the string into a non-const buffer (e.g. via strdup)
If you need an LPSTR, that means the string will/may be modified. std::string::c_str() returns a const pointer, and you can't just const_cast it away and hope all is good in the world, because it isn't. The string may be changed in all sorts of nasty ways, and your original std::string will be oblivious to all of them.
Try this instead:
// myFunction takes an LPSTR
std::string cppString = "something";
LPSTR cString = strdup( cppString.c_str() );
try {
myFunction( cString );
cppString = cString;
} catch(...) {
free( cString );
}
Wrap the string in a smart pointer and get rid of the try...catch for bonus points (don't forget the custom deleter).
There is a function on std::string c_str() . However I doubt that you could not use a std::string in your case.
Are you running somestringvariablename.c_str()?
That should work.
An LPSTR can be substituted with by using a TCHAR (i.e. found in tchar.h). So if you have a std::string, you can use the method std::string::c_str().
If the function, you are calling does not write to string, but only reads it, then you can simply use string::c_str method. If it is going to write something, then you probably should ensure that your string has enough space by calling string::reserve().