To get the volume GUID i tried the code like below
int len = wcslen( pDetData->DevicePath);
pDetData->DevicePath[len] = '\\';
pDetData->DevicePath[len+1] = 0;
#define BUFFER_SIZE MAX_PATH
WCHAR volume[BUFFER_SIZE];
BOOL bFlag;
bFlag = GetVolumeNameForVolumeMountPoint( pDetData->DevicePath, volume, BUFFER_SIZE );
int loginErrCode = GetLastError();
printf("loginErrCode: %d\n", loginErrCode);
printf("BFLAG: %d\n", bFlag);
the GetLastError() also prints it as 1 . it means ERROR_INVALID_FUNCTION. The bFlag always returns zero it means false.
what is the problem in my code...
This requires some crystal-ball consulting. The DevicePath string looks like it comes from SP_DEVICE_INTERFACE_DETAIL_DATA. That's a string that you don't own, modifying it corrupts the internal setupapi database at best, the heap at worst. You'll have to copy the string into your own buffer before turning it into the root directory name.
This is just a theory, especially "loginErrCode" is a very strange name for what the code seems to do. Verify that the string you end up with at least looks similar to "F:\".
Related
bool sendMessageToGraphics(char* msg)
{
//char ea[] = "SSS";
char* chRequest = msg; // Client -> Server
DWORD cbBytesWritten, cbRequestBytes;
// Send one message to the pipe.
cbRequestBytes = sizeof(TCHAR) * (lstrlen(chRequest) + 1);
if (*msg - '8' == 0)
{
char new_msg[1024] = { 0 };
string answer = "0" + '\0';
copy(answer.begin(), answer.end(), new_msg);
char *request = new_msg;
WriteFile(hPipe, request, cbRequestBytes, &cbRequestBytes, NULL);
}
BOOL bResult = WriteFile( // Write to the pipe.
hPipe, // Handle of the pipe
chRequest, // Message to be written
cbRequestBytes, // Number of bytes to writ
&cbBytesWritten, // Number of bytes written
NULL); // Not overlapped
if (!bResult/*Failed*/ || cbRequestBytes != cbBytesWritten/*Failed*/)
{
_tprintf(_T("WriteFile failed w/err 0x%08lx\n"), GetLastError());
return false;
}
_tprintf(_T("Sends %ld bytes; Message: \"%s\"\n"),
cbBytesWritten, chRequest);
return true;
}
after the first writefile in running (In case of '8') the other writefile function doesn't work right, can someone understand why ?
the function sendMessageToGraphics need to send move to chess board
There are 2 problems in your code:
First of all, there's a (minor) problem where you initialize a string in your conditional statement. You initialize it as so:
string answer = "0" + '\0';
This does not do what you think it does. It will invoke the operator+ using const char* and char as its argument types. This will perform pointer addition, adding the value of '\0' to where your constant is stored. Since '\0' will be converted to the integer value of 0, it will not add anything to the constant. But your string ends up not having a '\0' terminator. You could solve this by changing the statement to:
string answer = std::string("0") + '\0';
But the real problem lies in the way you use your size variables. You first initialize the size variable to the string length of your input variable (including the terminating '\0' character). Then in your conditional statement you create a new string which you pass to WriteFile, yet you still use the original size. This may cause a buffer overrun, which is undefined behavior. You also set your size variable to however many bytes you wrote to the file. Then later on you use this same value again in the next call. You never actually check this value, so this could cause problems.
The easiest way to change this, is to make sure your sizes are set up correctly. For example, instead of the first call, you could do this:
WriteFile(hPipe, request, answer.size(), &cbBytesWritten, NULL);
Then check the return value WriteFile and the value of cbBytesWritten before you make the next call to WriteFile, that way you know your first call succeeded too.
Also, do not forget to remove your sizeof(TCHAR) part in your size calculation. You are never using TCHAR in your code. Your input is a regular char* and so is the string you use in your conditional. I would also advice replacing WriteFile by WriteFileA to show you are using such characters.
Last of all, make sure your server is actually reading bytes from the handle you write to. If your server does not read from the handle, the WriteFile function will freeze until it can write to the handle again.
void fn(HINTERNET hfile,...){
char *url=new char[3000];
DWORD *len = new DWORD;
if(InternetQueryOption(hFile, INTERNET_OPTION_URL, url, len)==FALSE){
char* tmp=new char[3000];
sprintf(temp, "InternetQueryOption failed!\nError: %d\nRequired bytes: %d\n", GetLastError(),*len);
MessageBox(NULL, tmp, _T("myBHO !!!"), MB_OK | MB_ICONINFORMATION);
delete [] tmp;
}
//....
delete [] url;
delete len;
}
In this function I am using InternetQueryOption() with option INTERNET_OPTION_URL to find URL of handle hfile. Result would be returned in url[] and length in len.
But the function always fails and GetLastError() always returns 122 (ERROR_INSUFFICIENT_BUFFER).
According to this, maximum URL length possible in IE is 2083 while I am using buffer of length 3000. So how is this error possible? I even made url[] global, still the same error.
Now, according to IntenetQueryOption() documentation, if GetLastError() returns ERROR_INSUFFICIENT_BUFFER, then variable len points to the number of bytes required to hold the requested information (in this case the information is URL). And this value is always less than 100. So how can the URL not fit in ulr[]?
What could be the reason for this strange behaviour?
Please help.
According to this, maximum URL length possible in IE is 2083 while I am using buffer of length 3000. So how is this error possible? I even made url[] global, still the same error.
Browse your code, you declare a buffer big enough but you do not communicate to InternetQueryOption its size, that's why it always returns ERROR_INSUFFICIENT_BUFFER.
And this value is always less than 100.
After you call that function, check its value BEFORE.
With this line:
DWORD *len = new DWORD;
You allocate a pointer to DWORD but value in the pointed memory is uninitialized (may be 0, may be 338, may be 1234567, may crash your app). You may keep this code but you need to initialize memory to right value:
DWORD *len = new DWORD;
*len = sizeof(url);
IMO here you don't need any dynamic allocation and you may simply change it to:
DWORD len = sizeof(url);
Now you can pass its address to InternetQueryOption, like this:
if (InternetQueryOption(hFile, INTERNET_OPTION_URL, url, &len) == FALSE) {
Don't forget to remove delete len;.
I am trying to use GetComputerName() to retrieve the box's name. The code works great on windows 7, however, when i test on windows xp the code does not work (result is UNKNOWN). Any idea why?
int GetBoxName(BoxInfo &box_info)
{
int Ret;
DWORD dwLen;
const char* szUnk = "UNKNOWN\0";
// Get the size of the box name then allocate memory.
Ret = GetComputerName(NULL, &dwLen);
box_info.BoxName = new char[dwLen];
// Attempt to retrieve the box name.
if((Ret = GetComputerName(box_info.BoxName, &dwLen) == 0))
{
delete[] box_info.BoxName;
box_info.BoxName = new char[strlen(szUnk)];
box_info.BoxName = (char*)szUnk;
return 1;
}
return 0;
}
#Ben has given a good account of errors that you made. I'd like to show you how you would typically call GetComputerName. You are making it harder than it needs to be. The key information is the excerpt from the documentation:
The buffer size should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.
You have a hard upper bound on the size of the buffer. You can therefore use a fixed size buffer, and only make a single call to GetComputerName.
std::string getComputerName()
{
char buffer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerName(buffer, &len))
return std::string(buffer, len);
return "UNKNOWN";
}
Were you compiling for Unicode it would be:
std::wstring getComputerName()
{
wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerName(buffer, &len))
return std::wstring(buffer, len);
return L"UNKNOWN";
}
If you want to cater for the possibility of the computer name being longer than MAX_COMPUTERNAME_LENGTH then you can write it like this:
std::string getComputerName()
{
char buffer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerName(buffer, &len))
{
return std::string(buffer, len);
}
if (GetLastError() == ERROR_BUFFER_OVERFLOW)
{
std::vector<char> name(len);
if (GetComputerName(&name[0], &len))
{
return std::string(&name[0], len);
}
}
return "UNKNOWN";
}
I don't know whether or not this can even happen. The docs hint that it can, although if it does happen then it renders MAX_COMPUTERNAME_LENGTH somewhat of a misnomer. If we pass a value of len that is less than MAX_COMPUTERNAME_LENGTH+1 then the function succeeds if the name fits. It does not automatically fail with ERROR_BUFFER_OVERFLOW. Of course, if the name returned by this function can never exceed MAX_COMPUTERNAME_LENGTH then the second version is rather paranoid.
FWIW, the code in your updated answer is still badly broken. You simply must not pass NULL for the first parameter to GetComputerName. The documentation could not be much clearer.
This makes no sense at all:
box_info.BoxName = new char[strlen(szUnk)];
box_info.BoxName = (char*)szUnk;
You allocate memory, then immediately lose track of it. And you are directing a non-const pointer to a string literal. And the amount of memory allocated here doesn't include space for the terminating NUL byte, so you would overrun the buffer.
Perhaps you wanted the second line to be
strcpy(box_info.BoxName, szUnk);
And why aren't you using a smart pointer to automatically deallocate the memory when needed, for example std::string or std::unique_ptr<char[]> ?
Finally, the documentation says
The buffer size should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.
That is a pretty plain requirement. Makes you wonder the point of
If the buffer is too small, the function fails and GetLastError returns ERROR_BUFFER_OVERFLOW. The lpnSize parameter specifies the size of the buffer required, including the terminating null character.
This latter behavior appears to only be true for the Unicode version. Stanly Roark left a comment on the MSDN page that:
The ANSI version does not return the required length
I have to maintain an old application that uses ANSI.
I have noticed that, while the Unicode version returns the required buffer length, the ANSI version does not.
I want to get the install date of product:
DWORD max = 255;
WCHAR buffer[255];
std::wstring guidWString = S::WstrToStr(subKeys[i]); //from array of std::string
LPCWSTR guid = guidWString.c_str();
int err = MsiGetProductInfo(guid, INSTALLPROPERTY_INSTALLDATE, buffer, &max);
if(err == ERROR_SUCCESS){ //never success :(
info.date = S::WstrToStr(std::wstring(buffer));
}
But I always get the error code 87 (*ERROR_INVALID_PARAMETER*).
I don't see anything "invalid" here, according to the documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa370130%28v=vs.85%29.aspx
I have checked that:
All variables are of good types, buffer size (DWORD max) is not null, equal to the size of my buffer.
I use a function to convert std::string (I have my GUID in std::string) to std::wstring (under debugger, all looks good, conversion works in many other places in code that use WinAPI and std::wstring).
I have tried with different GUID, all of them exists and works for asking register "manually". MsiGetProductInfo() returns that error ALWAYS.
I have also tried to just write GUID in code (L"{GUID-GO-EXACTLY-HERE}"), with the same result.
I just don't know where the problem is?
I write filtering system and use Winsock2 LSP.
In WSPConnect I need to compare executable filename of process with harcoded Unicode String.
I do:
LPWSTR moduleName = {0};
GetModuleFileNameEx (GetCurrentProcess(),0,moduleName,_MAX_FNAME );
LPWSTR mn = L"redirect.exe";
if (lstrcmp (moduleName, mn) == 0){ ...some code there...}
What I am doing wrong?
You should compare "case-insensitive": lstrcmpi
You need to pass a correct char array...
Also you should always check the result values of function calls!
Also you should not use the TCHAR version of GetModuleFileNameEx if you explicit use wchar_t => GetModuleFileNameExW!
Also you should use the method GetModuleFileNameW if you want to get the name of the current process! This is more reliable!
ALso you should use MAX_PATH instead of _MAX_FNAME, because the method might also return the full path!
Also be sure that your string is correctly NUL-terminated!
Also you must be aware that the returned path might contain the full path, so comparing with the process name does never match...
Also you must be aware that the path might contion the short file name! (not in your case, because the name is not longer than 8 characters; but if you compare it with "MyExecutable.exe" you also must compare with the short file name; see GetShortPathName
The code part should now look like:
WCHAR moduleName[MAX_PATH+1];
if (GetModuleFileNameW (NULL, moduleName, MAX_PATH) != 0)
{
moduleName[MAX_PATH] = 0;
LPWSTR mn = L"redirect.exe";
int len = lstrlen(moduleName);
int lenmn = lstrlen(mn);
if (len > lenmn)
{
if (lstrcmpi (&moduleName[len-lenmn], mn) == 0){ ...some code there...}
}
}
You need to declare storage space, just a pointer is not enough
LPWSTR moduleName = {0};
GetModuleFileNameEx (GetCurrentProcess(),0,moduleName,_MAX_FNAME );
should be
TCHAR moduleName[_MAX_PATH];
GetModuleFileNameEx(GetCurrentProcess(), 0, moduleName, _countof(moduleName));
and use case-insensitive lstrcmpi().