use SetupGetInfDriverStoreLocation function - c++

BOOL SetupGetInfDriverStoreLocation(
_In_ PCTSTR FileName,
_In_opt_ PSP_ALTPLATFORM_INFO AlternatePlatformInfo,
_In_opt_ PCTSTR LocaleName,
_Out_ PTSTR ReturnBuffer,
_In_ DWORD ReturnBufferSize,
_Out_opt_ PDWORD RequiredSize
);
How can I call this function if I have FileName as:
TCHAR FileName[MAX_VALUE_NAME];
where #define MAX_VALUE_NAME 16383

This is a very common pattern in the Windows API; you give the function a buffer and the size of the buffer (often as a character count) and the call will fail if the buffer is too small.
#define MAX_VALUE_NAME 16383
TCHAR fullpath[MAX_VALUE_NAME];
BOOL result = SetupGetInfDriverStoreLocation(TEXT("NameOfMyFile.inf"), 0, 0, fullpath, MAX_VALUE_NAME, 0);
if (result) MessageBox(0, fullpath, 0, 0);
Your buffer is very large (MSDN says "The maximum supported path size is MAX_PATH") so it should be able to hold any .inf path but the function is designed so you can first call it with a NULL buffer:
To determine the size of the return buffer that is required to contain
the fully qualified file name of the specified INF file in the driver
store, call SetupGetInfDriverStoreLocation and set ReturnBuffer to
NULL, ReturnBufferSize to zero, and supply RequiredSize.
SetupGetInfDriverStoreLocation will return the required buffer size in
RequiredSize.
I'd call this the "peek, allocate, get" pattern. If there is a chance the data might actually change then you should call it in a loop until the "get" call succeeds.

Related

C++ how to find last (offset - adress) used in processmemory with use readprocessmemory

i use this code to readprocessmemory :
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead
);
char value[5];
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, 6500);
{
ReadProcessMemory(hProcess, (LPVOID)105477, value, 5, 0);
}
its work 100%
but i want to know how know last Offset used in processmemory - before i read it
see the picture : enter image description here
the last offset in this processmemory is 7FFE0FFF - but how can i get it before i read the processmemory
Well it MAY work if you are absolutely sure that you CAN read the memory of the other process... anyway it is a quite dangerous method, there are much better IPC APIs to do these things!
Unless you are writing a debugger yourself... in fact ReadProcessMemory is cited here "Process Functions for Debugging" https://msdn.microsoft.com/it-it/library/windows/desktop/ms680549(v=vs.85).aspx

How to copy a file but touch the timestamp on the new copy?

I am using ::CopyFile() to make a copy of a file. It appears the original file's timestamp is being preserved and I would like the copy to set the current timestamp on the copy, i.e. 'touching' it.
Is there a WinAPI way to do this easily?
If you read the MSDN documentation for CopyFile(), there are comments at the bottom that say the following:
File times semantics
This article should document semantics with respect to file creation/modification/access times.
Creation time: if the target file already exists, its' creation time is preserved, otherwise it is set to the current system time.
Last Modification time: always copied from modification time of the source file.
Last Access time: always set to the current system time.
and
Mod-time not always preserved
The modification time is not guaranteed to be set. CopyFileEx does try to set the modification time, but it does NO error checking on it. This means if setting modification time fails internally in CopyFileEx (e.g. with access denied), latter will still returns successful!
So if modification time is important for your scenario (it is for my synchronization program), you have to explicitly call SetFileTime() and check it's return value to be sure.
You should use SetFileTime() to update the copied file's timestamp(s) yourself to make sure they are set to what you want them to be set to. There is an example on MSDN:
Changing a File Time to the Current Time
#include <windows.h>
// SetFileToCurrentTime - sets last write time to current system time
// Return value - TRUE if successful, FALSE otherwise
// hFile - must be a valid file handle
BOOL SetFileToCurrentTime(HANDLE hFile)
{
FILETIME ft;
SYSTEMTIME st;
BOOL f;
GetSystemTime(&st); // Gets the current system time
SystemTimeToFileTime(&st, &ft); // Converts the current system time to file time format
f = SetFileTime(hFile, // Sets last-write time of the file
(LPFILETIME) NULL, // to the converted current system time
(LPFILETIME) NULL,
&ft);
return f;
}
::CopyFile is actually part of windows:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29.aspx
It is a convenience function that does copy metadata. There is another way, though less convenient, to copy files using windows. Check out these functions:
ReadFile:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
CreateFile:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
WriteFile:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx
HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
BOOL WINAPI ReadFile(
_In_ HANDLE hFile,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfBytesToRead,
_Out_opt_ LPDWORD lpNumberOfBytesRead,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
So you would open the file with something like this:
CreateFile(<File>, GENERIC_READ, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
Check for a invalid return handle,
Create the new file with something like this:
CreateFile(<File>, GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)
Check for a invalid return handle,
read the file into a buffer:
ReadFile(handle for file 1, buffer, Buffer size, Destination file,OUT for Bytes Read, NULL)
Then write out the Buffer:
WriteFile(outfile handle,buffer,number of bytes,NULL)
Close your handles.
Make sure to read CreateFiles details, it can be used to open files too.

Visual C++ RegGetValue() fails in program where it shouldn't

I'm making a C++ program using Visual C++ 2008 Express that gets the paths to specific apps from the registry, display a list of those that are installed, allows the user to pick one to configure, then launch the selected app.
This program is supposed to retrieve the paths to (currently) three apps by using RegGetValue (from windows.h).
While it works with Apps n°1 and 3, it fails with app n°2.
The part of the source that handles the registry is available on Pastebin: http://pastebin.com/9X2hjGqh.
I get error n°234 (ERROR_MORE_DATA) when I add a cout to get the function's return.
RegGetValue syntax:
LONG WINAPI RegGetValue(
_In_ HKEY hkey,
_In_opt_ LPCTSTR lpSubKey,
_In_opt_ LPCTSTR lpValue,
_In_opt_ DWORD dwFlags,
_Out_opt_ LPDWORD pdwType,
_Out_opt_ PVOID pvData,
_Inout_opt_ LPDWORD pcbData
);
Full reference here: http://msdn.microsoft.com/en-us/library/ms724875(v=VS.85).aspx
One thing that stands out are all the calls where you do this:
RegGetValue(hKey, NULL, "PATH", RRF_RT_ANY, NULL, (PVOID)&ValueBuffer, &BufferSize);
Notice the last parameter is &BufferSize. This is an [in, out] parameter. You set it to the size of your buffer before going in and it changes the value to the number of characters read into the buffer on the way out. This is what the docs say about RegGetValue (and other similar Reg) functions:
pcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the pvData parameter, in bytes. When the function returns, this variable contains the size of the data copied to pvData.
So when you call RegGetValue it started at 8192 (BUFFER) but after the first call it was overwritten by the the number of characters read.
Before each RegGetValue call where you pass a &BufferSize you should do this:
BufferSize = BUFFER
As well I notice you have:
#define BUFFER 8192
char ValueBuffer[255];
DWORD BufferSize = BUFFER;
Shouldn't you be setting ValueBuffer to be at least ValueBuffer[BUFFER] instead of ValueBuffer[255]?
As well your code as it is only supports an 8192 byte buffer. If the Value key from the registry is longer than that then it would return ERROR_MORE_DATA. I assume that your code is not anticipating anything beyond 8192. You can determine the size up front for a Value key by using RegQueryInfoKey and dynamically allocating enough space ahead of time.
ERROR_MORE_DATA means that one of the buffers you passed to RegGetValue is not large enough to store the data you asked RegGetValue to give you. You need to loop and reallocate the buffers supplied here when you get this exit code.
For example:
LONG result = ERROR_MORE_DATA;
DWORD dataLength = /* some reasonable default size */ 255;
unique_ptr<char[]> buffer;
while (result == ERROR_MORE_DATA)
{
buffer.reset(new char[dataLength]);
result = RegGetValueW(
hKey,
L"Subkey",
L"Value",
0,
nullptr,
buffer.get(),
&dataLength
);
}
if (result != ERROR_SUCCESS)
{
// Handle the error
}

RegQueryInfoKey not giving registry key name text

Using the RegQueryInfoKey as in the example available on http://msdn.microsoft.com/en-us/library/windows/desktop/ms724256(v=vs.85).aspx, doesn't give me the registry folder name in the output parameter achClass. I always receive an empty string.
My question is: Do I have to call any other function after to get the text of the key name? Or can I use this, but I am missing something?
Side note: machine is Windows 7, 64 bit.
Thanks in advance
UPDATE: code
//Calling site:
HKEY hKey;
LSTATUS status= RegOpenKeyEx(HKEY_CURRENT_USER, InstanceFullName, 0, KEY_ALL_ACCESS, &hKey);
if ( status != ERROR_SUCCESS)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
this->MessageBox( (LPCTSTR)lpMsgBuf, GetProgramTitle(), MB_OK | MB_ICONERROR );
LocalFree( lpMsgBuf );
return;
}
status= MyRegSaveKey(hKey, sTempRegFilePath, NULL);
//Called function
LSTATUS MyRegSaveKey(_In_ HKEY hKey, _In_ LPCTSTR lpFile, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
CXmlWriter xmlWriter;
if(!xmlWriter.Begin(lpFile))
return ERROR_CANNOT_MAKE;
LSTATUS retCode= _MyRegSaveKey(hKey, lpFile, lpSecurityAttributes, xmlWriter);
xmlWriter.Finish();
return retCode;
}
//Inner called function
LSTATUS _MyRegSaveKey(_In_ HKEY hKey, _In_ LPCTSTR lpFile, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, CXmlWriter& writer)
{
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms724256(v=vs.85).aspx
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
achClass[0] = '\0';
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
DWORD i, retCode;
TCHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;
DWORD type;
BYTE* pData= NULL;
DWORD size;
// Get the class name and the value count.
retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime // last write time
);
if(retCode != ERROR_SUCCESS)
return retCode;
//... the rest does not make any difference
return ERROR_SUCCESS;
}
Now that I can see the code, it looks like you expect to get the name of the opened key.
You cannot use the lpClass parameter of RegQueryInfoKey() for this -- see this SO answer; it looks like the example you mentioned uses only the cSubKeys and cValues from the RegQueryInfoKey() call.
From this SO answer [even though the question was for Perl], it doesn't look like the Win32 Registry API has a function will let you take the handle and return the key name.
From the same article, the only two practical solutions are
Maintain a list of returned objects from Open and the path to them yourself
extend the Win32::Registry API to call the NtQueryKey exported function in ntdll.dll and do what's shown in this stackoverflow answer

EnumResourceNames Function C++

So I try to read resource types and names from given file (in my case, .msstyle on my desktop) using C++
But somehow the resinfo result is sort of weird and not accurate. It doesnt write what actually was found. For example, the msstyle gives a result of: http://pastebin.com/ZhnkPmUe
#include <windows.h>
#include <strsafe.h>
#include <stdio.h>
HANDLE g_hFile;
BOOL EnumTypesFunc(HMODULE hModule, LPTSTR lpType, LONG lParam);
BOOL EnumNamesFunc(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam);
BOOL EnumLangsFunc(HMODULE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wLang, LONG lParam);
void main(void)
{
HMODULE hExe;
TCHAR szBuffer[80];
DWORD cbWritten;
size_t cbString;
HRESULT hResult;
// Load the .EXE whose resources you want to list.
hExe = LoadLibrary(TEXT("C:\\Users\\Kala\\Desktop\\776.msstyles"));
g_hFile = CreateFile(TEXT("C:\\Users\\Kala\\Desktop\\resinfo.txt"), GENERIC_READ | GENERIC_WRITE, 0, (LPSECURITY_ATTRIBUTES) NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
// Find all of the loaded file's resources.
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR),TEXT("The file contains the following resources:\r\n\r\n"));
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
//Calls the function to find types
EnumResourceTypes(hExe, (ENUMRESTYPEPROC)EnumTypesFunc, 0);
// Unload the executable file whose resources were
FreeLibrary(hExe);
CloseHandle(g_hFile);
}
// FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG)
//
// PURPOSE: Resource type callback
BOOL EnumTypesFunc(HMODULE hModule, LPTSTR lpType, LONG lParam)
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource type to a resource information file.
// The type may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpType))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %s\r\n"), lpType);
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %u\r\n"), (USHORT)lpType);
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
// Find the names of all resources of type lpType.
EnumResourceNames(hModule, lpType, (ENUMRESNAMEPROC)EnumNamesFunc, 0);
return TRUE;
}
// FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG)
//
// PURPOSE: Resource name callback
BOOL EnumNamesFunc(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam)
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource name to a resource information file.
// The name may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpName))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %s\r\n"), lpName);
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %u\r\n"), (USHORT)lpName);
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
return TRUE;
}
I think I must be missing something because I dont seem to get a proper strings I wanted from it, so if anyone could point me to right direction I would be very thankful
Your file is UTF-16 encoded because you are using the Unicode version of the Win32 API. Your text editor is interpreting the file as being 8 bit encoded. So you simply need to get your text editor to interpret the file as UTF-16. Probably the easiest way to do that is to put the UTF-16LE BOM at the beginning of the file.
As an aside I would advise you to stop coding to support MBCS character sets, stop using TCHAR and so on. Just write your program assuming that you will be targeting the Unicode version of the Win32 API. It will make your code much easier to read if you write L"..." rather than TEXT("...") and so on. Of course, if you need to support Windows 9x then forget I said this and carry on writing code that will compile in both MBCS and Unicode modes.