FindFirstFile returns INVALID_HANDLE_VALUE when lpFileName is volume - c++

There is a short example:
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(L"C:", &fd);
if (h == INVALID_HANDLE_VALUE)
{
wprintf(L"Err = %d\n", GetLastError());
return 1;
}
do {
std::wstring fullPath(fd.cFileName);
wprintf(L"FullPath = %s\n", fullPath.c_str());
} while (FindNextFile(h, &fd));
FindClose(h);
I'm confused since
HANDLE h = FindFirstFile(L"C:", &fd); // OK
HANDLE h = FindFirstFile(L"E:", &fd); // INVALID_HANDLE_VALUE
HANDLE h = FindFirstFile(L"F:", &fd); // INVALID_HANDLE_VALUE
But E and F are real, existing volumes.
I do so because I need all information from the WIN32_FIND_DATA structure which will be passed to the kernel mode.

This question seems to be based on a misunderstanding. You say:
I do not want to examine the files and directories in "E:*", I want to get information about this volume.
and
I need all information from the WIN32_FIND_DATA structure.
Well, the find data information is meaningful for file and directory objects, but not for volume objects.
You'll need to use some other means to obtain volume information. Perhaps GetVolumeInformation, WMI, or maybe something else depending on your needs.

I think you have to put "E:\\*" not only the volume. Or you want to find the volume entry? Also, it is good to clean fd structure memset( &fd, 0, sizeof fd ).

On my machine (Win7 x64) FindFirstFile(L"C:", &fd) returns -1 (C: is system disc), GetLastError() is 2 (i.e. "file not found").
I've checked how FindFirstFile is working. It converts winapi like path to nt path at some stage using RtlDosPathNameToRelativeNtPathName_U and then checks whether PartName is empty or not.
If it's empty it returns mentioned error code.
if it's a mask, it continues and enumerates entries that match: that's why FindFirstFile(L"C:\\*.*", &fd) returns valid handle. Thus if you need to enumerate all files in C: using form C:\\*.*.
In case if you need a volume information use special function GetVolumeInformation.

Related

RegOpenKeyEx Not finding an existing value

I am checking to see if the value "XXS" exists in the run registry
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\XXS", 0, KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_FILE_NOT_FOUND)
{
std::cout << "KEY NOT FOUND";
LONG createStatus = RegCreateKey(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hkey); //Creates a key
LONG status = RegSetValueEx(hkey, L"XXS", 0, REG_SZ, (LPBYTE)path, (size + 1) * sizeof(WCHAR));
}
I am not sure why this is happening and if I am using this function right. The key does exist but it says it does not. The program is 64 bit running on 64 bit pc
I think the issue here is that you do not differentiate between keys and values.
Registry keys are container objects similar to folders. Registry values are non-container objects similar to files. Keys may contain values and subkeys.
So you basically need to open/create a key and then handle the values in it.
In your case, i'd try something like this (but be aware, from the top of my head, not tested):
#define HKLM_BASE L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
HKEY hKey;
wchar_t buf[256] = { 0 };
LONG regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,HKLM_BASE,0, KEY_WOW64_64KEY | KEY_ALL_ACCESS,&hKey);
if (regError == ERROR_SUCCESS)
{
DWORD dwDataSize = sizeof(buf);
regError = RegQueryValueEx(hKey,L"XXS", NULL, NULL,(LPBYTE)&buf,&dwDataSize);
if ((regError != ERROR_SUCCESS) )
{
wchar_t *path =L"your value";
if (ERROR_SUCCESS != RegSetValueEx(hKey,L"XXS",NULL,REG_SZ,((const BYTE*)&path),wcslen (path)))
{
/* handle error */
}
} else {
/* current value in buf */
}
RegFlushKey( hKey );
RegCloseKey( hKey );
} else {
/* handle error */
}
Welcome to stack overflow! While typing this I see Morphine was just a little bit quicker. But he forgot to explain most of the the changes he made. So here are my 2 cents. The example of Morphine is fine , I won't provide another one.
I think XXS is a value (since you create a value, not a key, if it does not exist). This means you need to check if the value exist, right after you open the registry key. I also advise you to check on any error returning from the function RegOpenKeyEx, not only the ERROR_FILE_NOT_FOUND error.
Another thing I recommend is using RegCreateKeyEx instead of RegCreateKey, this since the documentation says the following:
Note This function is provided only for compatibility with 16-bit
versions of Windows. Applications should use the RegCreateKeyEx
function. However, applications that back up or restore system state
including system files and registry hives should use the Volume Shadow
Copy Service instead of the registry functions.
Last but not least, don't forget to close the keys once you do not need them anymore. You don't have to close values.

C++ Win32 - Getting App Name using PID and Executable Path

I'd like to get the name of an application on Windows.
Currently I'm using EnumProcesses() to enumerate all processes and receive a list of PIDs.
Then I'm looping through all PIDs, each iteration looks like this, when aProcess[i] is the current PID:
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
std::string processName = get_process_name(proc);
My get_process_name(proc) function uses GetModuleFileNameEx to get the executable path and GetProcessImageFileName in order to retrieve the name of the executable file.
What I want to retrieve is basically the App Name, as it is displayed in the Windows Task Manager.
I've looked throughout Win32 API's documentation and could not find a clue on how to achieve this.
I've tried looking for other ways such as Windows Shell tasklist but it outputs different things, for example- Google Chrome:
Image Name: chrome.exe PID: 84 Session Name: Console
I'd really appreciate any thought on the matter, whether it be the Win32 API or some other way I can implement through C++ code.
You can do this with GetFileVersionInfoA and VerQueryValueA.
You just need to follow the example given in the VerQueryValueA document.
Here is my sample:
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
int main()
{
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140); //Modify pid to the pid of your application
if (!handle) return 0;
wchar_t pszFile[MAX_PATH] = L"";
DWORD len = MAX_PATH;
QueryFullProcessImageName(handle, 0, pszFile, &len);
UINT dwBytes, cbTranslate;
DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes);
if (dwSize == 0) return 0;
LPVOID lpData = (LPVOID)malloc(dwSize);
ZeroMemory(lpData, dwSize);
if (GetFileVersionInfo(pszFile, 0, dwSize, lpData))
{
VerQueryValue(lpData,
L"\\VarFileInfo\\Translation",
(LPVOID*)&lpTranslate,
&cbTranslate);
wchar_t strSubBlock[MAX_PATH] = { 0 };
wchar_t* lpBuffer;
for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
StringCchPrintf(strSubBlock,50,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
VerQueryValue(lpData,
strSubBlock,
(void**)&lpBuffer,
&dwBytes);
std::wcout << lpBuffer << std::endl;
}
}
if(lpData) free(lpData);
if (handle) CloseHandle(handle);
return 0;
}
And it works for me:
I think what you want are the "version" resources embedded in the PE file (the executables.)
You seem to be familiar with using Win32 API, so I'm just going to give you some hints.
You have to use LoadLibraryEx to load the EXE file (the Ex suffix is to enable passing the LOAD_LIBRARY_AS_DATAFILE flag,) and then call EnumResourceTypes (also see EnumResourceNames) to enumerate all the resource types/resources in the file, and find what you are looking for and then extract the data with LoadResource. The resource type you want is RT_VERSION.
I'm sure I'm omitting a lot of details (as per usual for Win32 programming,) and there might not be a need for enumeration at all; in which case you may want to call FindResource or FindResourceEx directly (if there is a fixed name for this particular resource.)
As further clarification, this gives you the date you see if you right-click on the EXE file (not the shortcut) in Windows Explorer and select "Properties", then go to the "Details" tab. If that information is indeed what you want (e.g. the "File description" field) then the above method should give you the data.

Name of a named pipe given handle

I'm trying to find the name of a named pipe given it's handle. I found a solution where the named pipe handle is duplicated using NtDuplicateObject and then the name is extracted using NtQueryObject but it's unstable so that's out of the question.
Currently I'm attempting to do so with GetFinalPathNameByHandle but having no luck. I'm not even sure if it's possible to do this but it was mentioned as a potential solution so I'm going with it. The following is adapted from the example code at:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364962(v=vs.85).aspx
void __cdecl _tmain(int argc, TCHAR *argv[]){
TCHAR Path[BUFSIZE];
HANDLE pipe;
DWORD dwRet;
printf("\n");
if (argc != 2)
{
printf("ERROR:\tIncorrect number of arguments\n\n");
printf("%s <file_name>\n", argv[0]);
return;
}
pipe = CreateNamedPipe(argv[1], PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND, PIPE_WAIT, 1,
1024, 1024, 120 * 1000, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
printf("Could not open file (error %d\n)", GetLastError());
return;
}
dwRet = GetFinalPathNameByHandle(pipe, Path, BUFSIZE, VOLUME_NAME_NT);
if (dwRet < BUFSIZE)
{
_tprintf(TEXT("\nThe final path is: %s\n"), Path);
}
else printf("\nThe required buffer size is %d.\n", dwRet);
CloseHandle(pipe);}
The command line parameter is "\\\\.\\pipe\\mynamedpipe" or "\\.\pipe\mynamedpipe", I've tried both. The output is garbage but more importantly when debugging with Visual Studio 2013 Express while stepping through the program the path variable is garbage directly after the GetFinalPathNameByHandle call.
By garbage I mean:
Path 0x0036fab4 L"쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌쳌... wchar_t[100]
Console output is:
The final path is: ?????????????????????????????????????????????????????????????????????????????????????????????????????????6?╫☻
So I'm officially stuck. Alternatively and possibly a much better solution would be comparing two named pipe handles to each other to determine if they point to the same named pipe. If there is a way to do that it would solve my problem as well.
To answer my own question here. GetFileInformationByHandleEx does exactly this using FileNameInfo for the FileInformationClass parameter and a handle generated by CreateNamedPipe.

How to get Machine id using c++

am facing two problems one big problem and one small problem :)
problem # 1 : am unable to read Machine ID from below path ... i get my processor name like intel i7 #2.2ghz like that , i do not know why , i should get machine id , long integer string but i not get it , so please help
reg_path="SOFTWARE\\Microsoft\\Cryptography";
rvalue="MachineGuid"; // data value
my registery reading function
string read_reg_sz(char rpath[],char rdata[]) // read registery Loaction
{
REGSAM flag = KEY_WOW64_32KEY or KEY_WOW64_64KEY;
char buffer[MAX];
char Buffer[MAX];
DWORD BufSize = _MAX_PATH;
char dwMHz[MAX];
DWORD dataType = REG_SZ;
HKEY hKey;
long lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,rpath,NULL, KEY_READ | KEY_WRITE | flag,&hKey);
if(lError != ERROR_SUCCESS)
{// if the key is not found, tell the user why:
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
lError,
0,
Buffer,
_MAX_PATH,
0);
cout<<"\n reg erro : "<<Buffer;
return "N/A";
}
// query the key:
RegQueryValueEx(hKey,rdata,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
RegCloseKey(hKey); // close open handle ....
cout<<"\n reg data read: "<<dwMHz;
return dwMHz;
}
second problem :
currently i have function which can totally clean recycle bin :)
SHEmptyRecycleBin(NULL, NULL, SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND);
but i want to delete single file from recycle bin like passing filename
You should really post it as two different questions, but I'll try to answer both.
1. Get MachineGuid
I think your issue is in this line:
// query the key:
RegQueryValueEx(hKey,rdata,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
You should change it to:
// query the key:
RegQueryValueEx(hKey,rvalue,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
By the way, dhMHz does not sound like right variable name - change it to reflect reality.
Also, you should have this:
DWORD BufSize = sizeof(Buffer) - 1;
And, it would be nice to NOT have both buffer and Buffer variables.
2. Delete one file from recycle bin
According to Microsoft documentation on SHFileOperation, you should just use DeleteFile on filename like C:\$Recycle.Bin\file.txt:
When used to delete a file, SHFileOperation permanently deletes the file unless you set the FOF_ALLOWUNDO flag in the fFlags member of the SHFILEOPSTRUCT structure pointed to by lpFileOp. Setting that flag sends the file to the Recycle Bin. If you want to simply delete a file and guarantee that it is not placed in the Recycle Bin, use DeleteFile.
To delete a single file from the Recycle Bin, use SHGetSpecialFolderLocation(CSIDL_BITBUCKET) or SHGetKnownFolderIDList(FOLDERID_RecycleBinFolder) to get the absolute PIDL of the Recycle Bin, then use SHBindToObject() to get the IShellFolder interface for it and call its ParseDisplayName() method to convert the desired filename into a relative PIDL, then use SHBindToObject() to get the IContextMenu interface for the file and call its InvokeCommand() method to execute the file's "delete" verb.

How do you retrieve the original location of a mounted path?

In C++, how can I retrieve the location of a mounted drive?
for example, if I have mounted drive s: to c:\temp (using subst in the command line)
"subst c:\temp s:"
how can I get "c:\temp" by passing "s:"
I would also like to know how can it be done for a network drive.
(if s: is mounted to "\MyComputer\Hello", then I want to retrieve "\MyComputer\Hello" and then to retrieve "c:\Hello" from that)
It might be a very easy question but I just couldn't find information about it.
Thanks,
Adam
If you've used SUBST, the API you want is QueryDosDevice. You can SUBST things yourself by using DefineDosDevice.
You can probably use the GetVolumeInformation function. From the documentation:
Symbolic link behavior
If the path points to a symbolic link, the function returns volume information for the
target.
Haven't tested it myself, though.
To find the path of a mounted network share, you have to use the WNet APIs:
wstring ConvertToUNC(wstring sPath)
{
WCHAR temp;
UNIVERSAL_NAME_INFO * puni = NULL;
DWORD bufsize = 0;
wstring sRet = sPath;
//Call WNetGetUniversalName using UNIVERSAL_NAME_INFO_LEVEL option
if (WNetGetUniversalName(sPath.c_str(),
UNIVERSAL_NAME_INFO_LEVEL,
(LPVOID) &temp,
&bufsize) == ERROR_MORE_DATA)
{
// now we have the size required to hold the UNC path
WCHAR * buf = new WCHAR[bufsize+1];
puni = (UNIVERSAL_NAME_INFO *)buf;
if (WNetGetUniversalName(sPath.c_str(),
UNIVERSAL_NAME_INFO_LEVEL,
(LPVOID) puni,
&bufsize) == NO_ERROR)
{
sRet = wstring(puni->lpUniversalName);
}
delete [] buf;
}
return sRet;;
}