I want to get the version info of a dll or exe. To do this I call the function VerQueryValue.
Here is my code:
UINT dwBytes;
DWORD dwSize = GetFileVersionInfoSizeA(pszFile, (DWORD*)&dwBytes);
if( dwSize == 0)
return;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
UINT cbTranslate;
LPVOID lpData = (LPVOID)malloc(dwSize);
ZeroMemory(lpData, dwSize);
if(GetFileVersionInfoA(pszFile, 0, dwSize, lpData) )
{
VerQueryValueA(lpData,
"\\VarFileInfo\\Translation",
(LPVOID*)&lpTranslate,
&cbTranslate);
// Read the file description for each language and code page.
char strSubBlock[MAX_PATH] = {0};
char* lpBuffer;
for(int i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++ )
{
sprintf(strSubBlock,
"\\StringFileInfo\\%04x%04x\\FileDescription",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
// Retrieve file description for language and code page "i".
VerQueryValueA(lpData,
strSubBlock,
(void**)&lpBuffer,
&dwBytes);
}
}
free( lpData );
I got a 1813 error when calling VerQueryValueA. This code is almost same with with url http://msdn.microsoft.com/zh-cn/library/ms647464%28v=vs.85%29 .
I have tested the code under vc++6 and vc++2005 and got the same error. My windows is win7.
How should I fix it? Thanks in advanced.
According to MSDN, this error code maps to ERROR_RESOURCE_TYPE_NOT_FOUND. Thus I would conclude that the Resource you are looking for (FileDescription) does not exist in the image file.
Related
I am building upon the Cloud Mirror Sample and having a similar issue to this one
Here is the test code involved:
// When the client needs to fetch data from the cloud, this method will be called.
// The FakeMirrorDataMover class does the actual work of copying files from
// the "cloud" to the "client" and updating the transfer status along the way.
void CALLBACK FakeCloudProvider::OnFetchData(
_In_ CONST CF_CALLBACK_INFO* callbackInfo,
_In_ CONST CF_CALLBACK_PARAMETERS* callbackParameters)
{
//FileCopierWithProgress::CopyFromServerToClient(callbackInfo, callbackParameters, ProviderFolderLocations::GetServerFolder());
const UINT CHUNKSIZE = 48 * 1024 * 1024;
UINT len;
LONG64 offset = callbackParameters->FetchData.RequiredFileOffset.QuadPart;
LONG64 requiredLength = callbackParameters->FetchData.RequiredLength.QuadPart;
byte *buffer = new byte[CHUNKSIZE];
FillMemory(buffer, CHUNKSIZE, (byte)0xA5);
while (0 < requiredLength)
{
len = requiredLength < CHUNKSIZE ? requiredLength : CHUNKSIZE;
if (0 != len % 4096)
len = 4096 * (len / 4096 + 1);
Placeholders::TransferData(callbackInfo->TransferKey.QuadPart, buffer, offset, len, 0);
requiredLength -= len;
offset += len;
}
delete[] buffer;
}
HRESULT Placeholders::TransferData(
//_In_ CF_CONNECTION_KEY connectionKey,
_In_ LONG64 transferKey,
_In_reads_bytes_opt_(length.QuadPart) LPCVOID transferData,
_In_ LONG64 startingOffset,
_In_ LONG64 length,
_In_ NTSTATUS completionStatus)
{
CF_OPERATION_INFO opInfo = { 0 };
CF_OPERATION_PARAMETERS opParams = { 0 };
opInfo.StructSize = sizeof(opInfo);
opInfo.Type = CF_OPERATION_TYPE_TRANSFER_DATA;
opInfo.ConnectionKey = FakeCloudProvider::GetConnectionKey();
opInfo.TransferKey.QuadPart = transferKey;
opParams.ParamSize = CF_SIZE_OF_OP_PARAM(TransferData);
opParams.TransferData.CompletionStatus = completionStatus;
opParams.TransferData.Buffer = transferData;
opParams.TransferData.Offset.QuadPart = startingOffset;
opParams.TransferData.Length.QuadPart = length;
winrt::check_hresult(CfExecute(&opInfo, &opParams));
return S_OK;
}
There is only one placeholder file created inside the sync root folder of ~ 9.3 GB size. After I create this I either double click it or right click and "always keep on this device" - same result.
The result being that after the last call to TransferData the Windows Explorer file progress gets stuck. It will eventually time out, I click on "try again", my breakpoints inside OnFetchData() get hit and file progress remains stuck. If I cancel the transfer then onCancelFetchData() gets called once as it should. Subsequent attempts to download the rest of the file will no longer call onFetchData()
If I comment out the if (0 != len % 4096) len = 4096 * (len / 4096 + 1); part then I am getting the dreaded 0x8007017c the cloud operation is invalid with the rest of the symptoms as above.
I have tried with a smaller ~ 9.3 MB file and it went fine... what else to try?
edit
The ~100MB and ~1GB sizes also working fine
Result of CfExecute calls:
//[...] same output for all previous offsets except for the last call
TransferData method - offset: 1298137088, length: 50331648, syncStatBeforeCall: null, syncStatAfterCall: null, hresult: 0
TransferData method - offset: 1348468736, length: 50331648, syncStatBeforeCall: null, syncStatAfterCall: null, hresult: 0
TransferData method - offset: 1398800384, length: 11265024, syncStatBeforeCall: null, syncStatAfterCall: null, hresult: 8007017c
As far as I can tell null is fine for SyncStatus:
SyncStatus
Note This member is new for Windows 10, version 1803.
The current sync status of the platform.
The platform queries this information upon any failed operations on a
cloud file placeholder. If a structure is available, the platform will
use the information provided to construct a more meaningful and
actionable message to the user. The platform will keep this
information on the file until the last handle on it goes away. If
null, the platform will clear the previously set sync status, if there
is one.
--edit--
HRESULT Placeholders::Create(_In_ PCWSTR destPath,
_In_ PCWSTR fileName,
_In_ CF_PLACEHOLDER_CREATE_FLAGS flags,
_In_ LONG64 fileSize,
_In_ DWORD fileAttributes,
_In_ LONG64 ftCreationTime,
_In_ LONG64 ftLastWriteTime,
_In_ LONG64 ftLastAccessTime,
_In_ LONG64 ftChangeTime)
{
CF_PLACEHOLDER_CREATE_INFO cloudEntry;
cloudEntry.FileIdentity = fileName;
cloudEntry.FileIdentityLength = (DWORD)((wcslen(fileName)+1) * sizeof(WCHAR));
cloudEntry.RelativeFileName = fileName;
cloudEntry.Flags = flags;
cloudEntry.FsMetadata.FileSize.QuadPart = fileSize;
cloudEntry.FsMetadata.BasicInfo.FileAttributes = fileAttributes;
cloudEntry.FsMetadata.BasicInfo.CreationTime.QuadPart = ftCreationTime;
cloudEntry.FsMetadata.BasicInfo.LastWriteTime.QuadPart = ftLastWriteTime;
cloudEntry.FsMetadata.BasicInfo.LastAccessTime.QuadPart = ftLastAccessTime;
cloudEntry.FsMetadata.BasicInfo.ChangeTime.QuadPart = ftChangeTime;
if ((fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
cloudEntry.Flags |= CF_PLACEHOLDER_CREATE_FLAG_DISABLE_ON_DEMAND_POPULATION;
cloudEntry.FsMetadata.FileSize.QuadPart = 0;
cloudEntry.FileIdentity = nullptr;
}
try
{
wprintf(L"Creating placeholder for %s\n", fileName);
winrt::check_hresult(CfCreatePlaceholders(destPath, &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL));
}
catch (...)
{
// winrt::to_hresult() will eat the exception if it is a result of winrt::check_hresult,
// otherwise the exception will get rethrown and this method will crash out as it should
wprintf(L"Failed to create placeholder for %s with %08x\n", fileName, static_cast<HRESULT>(winrt::to_hresult()));
// Eating it here lets other files still get a chance. Not worth crashing the sample, but
// certainly noteworthy for production code
return static_cast<HRESULT>(winrt::to_hresult());
}
return S_OK;
}
Create(_T("C:\\SyncRootDT"), _T("file1"), CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC,
10000000000, FILE_ATTRIBUTE_NORMAL, 532657415, 532657415, 532657415, 532657415));
I observe similar behaviour. The hydration of files up to 4Gb works fine, but files over 4Gb always stuck and failed with the 'Cloud operation is invalid' exception. I was able to overcome it with this fix but instead of the CF_CALLBACK_PARAMETERS.FETCHDATA.RequiredLength and OptionalLength, I used a complete file length from CF_CALLBACK_INFO.FileSize. It looks like after a recent Windows update the OptionalLength is always zero.
My code is in .NET, but I guess you can easily translate it into C++:
// Use a complete file size in case the file is over 4Gb
if (callbackInfo.FileSize > 0x100000000)
{
requiredLength = callbackInfo.FileSize;
}
I'm trying to use SymGetLineFromAddr64 to get the source file name of symbols loaded from a PDB. I load the PDB module and enumerate on the types/symbols, but the Address field from the SYMBOL_INFO pointer I get in the enumeration callback is always 0 so I can't use it to get the source file information. (SymGetLineFromAddr64 fails with error code 126
"The specified module could not be found.")
I also tried using the TI_GET_ADDRESS property from the SymInfo->Index but it's 0 too.
Here's my main:
int main(char **Argv, int Argc)
{
HANDLE Process = GetCurrentProcess();
DWORD ProcessId = GetProcessId(Process);
DWORD Options = SymGetOptions();
Options |= SYMOPT_DEBUG;
Options |= SYMOPT_LOAD_LINES;
Options |= SYMOPT_LOAD_ANYTHING; // Wanted to test if this would do anything at all, didn't do much
SymSetOptions(Options);
if (SymInitialize(Process, 0, 0) == TRUE)
{
char *FilePath = "C:\\Users\\pc\\Documents\\Saedo\\VSProjects\\x64\\Debug\\PDBReflector.pdb";
DWORD64 BaseAddress = 0x10000000;
DWORD FileSize = GetFileSize(FilePath);
DWORD64 Module = SymLoadModuleEx(Process, 0, FilePath, 0, BaseAddress, FileSize, 0, 0);
if (Module)
{
Reflector.Process = Process; //Reflector is just a global struct that contains the process and module base for use later
Reflector.ModuleBase = Module;
SymEnumTypes(Process, Module, EnumTypesProc, 0);
}
}
SymCleanup(Process);
return(0);
}
And here's the enumerator:
BOOL CALLBACK EnumTypesProc(SYMBOL_INFO *SymInfo, ULONG SymbolSize, VOID *UserContext)
{
if (SymInfo)
{
ULONG64 Address = SymInfo->Address; // Address is 0
//SymGetTypeInfo(Reflector.Process, Reflector.ModuleBase, SymInfo->Index, TI_GET_ADDRESS, &Address); // Address is 0 as well
IMAGEHLP_LINE64 LineInfo = {};
LineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD LineDisplacement = 0;
if (SymGetLineFromAddr64(Reflector.Process, Address, &LineDisplacement, &LineInfo))
{
Log("FILE: %s\n", LineInfo.FileName);
}
}
return(TRUE);
}
Compiling using VS2015 Community Edition, X64 Debug mode with /Zi for the Debug Information Format and "Optimize for debugging" (/DEBUG).
Note that I'm loading the PDB for the same executable that's running. I didn't think that would be the issue because I could load other type information just fine. And I also tried inspecting another PDB, the addresses were 0 as well.
Question: Why am I getting 0 in the Address field and how to actually get the right address so that I could retrieve the source file of a particular type/tag?
Pretty sure I'm missing something obvious here.
Thanks for any help.
GetWindowThreadProcessId(hwndFoundWindow, &dwTrayProcessID);
HANDLE hTrayProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwTrayProcessID);
int iButtonsCount = SendMessage(hwndFoundWindow, TB_BUTTONCOUNT, 0, 0);
LPVOID lpData = VirtualAllocEx(hTrayProc, NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE);
int iButton;
DWORD dwBytesRead;
TBBUTTON buttonData;
dwBytesRead = -1;
int chk_data = (int)SendMessage(hwndFoundWindow, TB_GETBUTTON, iButton, (LPARAM)lpData);
ReadProcessMemory(hTrayProc, lpData, &buttonData, sizeof(TBBUTTON), &dwBytesRead);
int len_text = (int)SendMessage(hwndFoundWindow, TB_GETBUTTONTEXTW, buttonData.idCommand, (LPARAM)lpData);
till now, i know the length of button's text but i also need to get the text to display on console.
my problem is i do not really know how to get that text from the button. please kindly help.
what i am trying is ... trying to access to lpData to get the string inside, but could not do that.
My first comment is that you need to add error checking to your code. As far as I can see, you perform no checking of return values. Any of the API functions you call could fail. If you don't check return values for errors then you have no way of diagnosing where you went wrong.
For instance, starting with GetWindowThreadProcessId, you need to write it like this:
if (GetWindowThreadProcessId(hwndFoundWindow, &dwTrayProcessID) == 0)
{
// handle error
}
And so on for all the other functions. Consult MSDN carefully to understand how each function signals failure.
Now to the main part of the question. I believe that it is the TB_GETBUTTONTEXTW message that is giving you trouble. You need to write it like this:
LRESULT len = SendMessage(hwndFoundWindow, TB_GETBUTTONTEXTW,
buttonData.idCommand, NULL);
if (len == -1)
{
// handle error
}
size_t size = sizeof(wchar_t)*(len+1);
LPVOID lpData = VirtualAllocEx(hTrayProc, NULL, size, MEM_COMMIT, PAGE_READWRITE);
if (lpData == NULL)
{
// handle error
}
len = SendMessage(hwndFoundWindow, TB_GETBUTTONTEXTW,
buttonData.idCommand, (LPARAM)lpData);
if (len == -1)
{
// handle error
}
wchar_t* str = new wchar_t[len+1];
if (!ReadProcessMemory(hTrayProc, lpData, (LPVOID)str, size, NULL))
{
// handle error
}
// the text is now in str, as a null-terminated UTF-16 string
delete[] str;
You need this: (see documentation of TB_GETBUTTONTEXTW).
WCHAR *buffer ;
int len_text = (int)SendMessage(hwndFoundWindow, TB_GETBUTTONTEXTW,
buttonData.idCommand, (LPARAM)NULL);
buffer = (WCHAR*)malloc(sizeof(WCHAR) * (len_text + 1)) ;
SendMessage(hwndFoundWindow, TB_GETBUTTONTEXTW,
buttonData.idCommand, (LPARAM)buffer);
....
free(buffer) ;
HKEY hKey = 0;
DWORD dwType = REG_SZ;
TCHAR buf[255] = {0};
DWORD dwBufSize = sizeof(buf);
DWORD ret;
CComboBox m_portCombo;
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
{
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
m_portCombo.AddString(str);
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial1"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial2"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial3"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
}
First problem: i want to change the TEXT("\\Device\\Serial3") with something like TEXT("\\Device\\Serial",%i), so i can resume all that lines of code to a for loop.Is tehre a way to accomplish this?
Second problem: if i use the m_portCombo.AddString(str); i get an Debug Assertion Failed! error, and, of course, the combobox is not populated with that registry value. Why could that happen?
First Problem: Use the CString Format() function using %d for integer.
for (int i =0 ; i<10; i++)
{
CString szPath;
szPath.Format(TEXT("\\Device\\Serial%d"),i);
// ...
}
Second Problem:
There could be many reasons this would fail. Most likely of which would be having not created the combo box yet.(It needs a window handle before it can add strings) To figure out the cause of the debug assertion, click the "retry" button on the Debug Assertion Failed window and it should jump to the code which caused the assertion. For example it might be something like:
ASSERT(GetSafeHwnd()!=NULL);
Your combo box class won't be 'subclassed' until after the first DoDataExchange is called (and any attempt to use it before that happens will ASSERT). Either wait until the base class has run OnInitDialog or do something like this:
CComboBox * pcombo = static_cast<CComboBox*>(GetDlgItem( IDC_MYCOMBO ));
pcombo->AddString( szPath );
See #TheSteve's answer for string problem.
I am trying to print out the name of the first entry (which I suppose is user32.dll) in the imports table of a PE file, but the program terminates unexpectedly saying "cannot read memory", can someone please explain me why??
#include<iostream>
#include<Windows.h>
#include<stdio.h>
#include<WinNT.h>
int main()
{
HANDLE hFile,hFileMapping;
LPVOID lpFileBase;
LPVOID lp;
if((hFile = CreateFile(TEXT("c:\\linked list.exe"),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0)) == INVALID_HANDLE_VALUE)
std::cout<<"unable to open";
if((hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL)) == 0)
{
CloseHandle(hFile);
std::cout<<"unable to open for mapping";
}
if((lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0))== 0)
{
CloseHandle(hFile);
CloseHandle(hFileMapping);
std::cout<<"couldn't map view of file";
}
PIMAGE_DOS_HEADER pimdh;
pimdh = (PIMAGE_DOS_HEADER)lpFileBase;
PIMAGE_NT_HEADERS pimnth;
pimnth = (PIMAGE_NT_HEADERS)((char *)pimdh + pimdh->e_lfanew);
PIMAGE_SECTION_HEADER pimsh;
pimsh = (PIMAGE_SECTION_HEADER)(pimnth + 1);
int i;
for(i = 0; i<pimnth->FileHeader.NumberOfSections; i++)
{
if(!strcmp((char *)pimsh->Name,".idata"))
{
char *p;
PIMAGE_IMPORT_DESCRIPTOR pimid;
pimid = (PIMAGE_IMPORT_DESCRIPTOR)(pimnth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (char *)lpFileBase);
p = (char *)((char *)lpFileBase + pimid->Name);
printf("%s",p);
};
pimsh++;
}
}
You asked a similar question a couple of days ago and looking at your code you've read two-thirds of my answer.
The other third says that pimid->Name is not a file offset, it's a Relative Virtual Address (or RVA), which you need to convert to a file offset. That's why you're getting an error. To understand RVAs read the MSDN article. For sample code to do the conversion have a look at pedump, which is referenced in the article.