How to get file MFT entry/inode using Java or C++ - windows

I've written a duplicate finder in Java, but I need to include hard link support for it. Unfortunately, there seems to be no way to dig out a file's MFT entry in Java.
Although there is a method called fileKey() in the BasicFileAttributeView class, it won't work on the NTFS file system (I haven't tested it on ext yet).
I also found the method isSameFile() (in java.nio.file.Path). Does anyone know how this method works? It seems to be doing the right thing, but it returns a Boolean value, so it is worthless for me (I wish to put the results into a map and group them by their MFT entries).
I can always compare the creation times, modification times, etc. for each file, but this is just giving up.
Is there any way to accomplish what I am trying to do in either C++ or Java? I care more about making it work on NTFS than ext.

You would need to use the FILE_ID_FULL_DIRECTORY_INFORMATION structure along with the NtQueryDirectoryFile function (or the FILE_INTERNAL_INFORMATION structure along with the NtQueryInformationFile, if you already have a handle) inside ntdll.dll (available since Windows XP, if not earlier) to get the 8-byte file IDs and check if they are the same.
This will tell you if they are the same file, but not if they are the same stream of the same file.
I'm not sure how to detect if two files are the same stream from user-mode -- there is a structure named FILE_STREAM_INFORMATION which can return all the streams associated with a file, but it doesn't tell you which stream you have currently opened.

Detecting hard links is usually accomplished by calling FindFirstFileNameW. But there is a lower level way.
To get the NTFS equivalent to inodes, try the FSCTL_GET_OBJECT_ID ioctl code.
There's a unique (until the file is deleted) identifier in the BY_HANDLE_FILE_INFORMATION structure as well.
If the volume has an enabled USN Change Journal, you can issue the FSCTL_READ_FILE_USN_DATA ioctl code. Check the FileReferenceNumber member in the USN_RECORD structure

In Java you can use sun.nio.ch.FileKey which is a non-transparent enclosure for NTFS Inode. All the hard links share the same Inode.
Therefore, if you need to collect hard links, you can create FileKey from each suspect and compare them (e.g. by putting pairs of FileKey -> File into a Multimap)

I find fileKey is always null. Here is some code that can actually read the NTFS inode number. There remain many aspects I'm not happy with, not least, it relies on reflection.
import sun.nio.ch.FileKey;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Path;
class NTFS {
static long inodeFromPath(Path path) throws IOException, NoSuchFieldException, IllegalAccessException {
try (FileInputStream fi = new FileInputStream(path.toFile())) {
FileDescriptor fd = fi.getFD();
FileKey fk = FileKey.create(fd);
Field privateField = FileKey.class.getDeclaredField("nFileIndexHigh");
privateField.setAccessible(true);
long high = (long) privateField.get(fk);
privateField = FileKey.class.getDeclaredField("nFileIndexLow");
privateField.setAccessible(true);
long low = (long) privateField.get(fk);
long power = (long) 1 << 32;
long inode = high * power + low;
return inode;
}
}
}

Related

check if read operation is for spesific file in filter driver

Hello im new at filter driver programming, i took windows swapBuffer example and i try to modify it to pritn me the file name for each read/write operation
and print the data tryed to read/ write.
i tried to do it like this:
FLT_PREOP_CALLBACK_STATUS SwapPreWriteBuffers(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext)
{
/* here we do some logic that check that we want to write more the
0 bytes and get volume context and allocate aligned nonPaged memory
for the "swapping memory" , build a MDL and then if all succeed i try this:
*/
WCHAR filename[300] = {0};
wfprintf(filename, "%wZ\0", Data->Iopb->TargetFileObject->FileName);
if (NULL != wcstr(filename, L"try_me.txt"))
{
DbgPrint("Fname %S try to write %S\n", filename, Data->Iopb->Parameters.Write.WriteBuffe);
}
}
my main problem (i think) Data->Iopb->TargetFileObject->FileName is unicode and i dont know how to make the compae betwine this and a string of the file name
my outher problem is how do i print the buffer curretly to the dbg string without risking at getting blue screen? (i got alot from them laytly...) sometimes i get to this function without writing a string , how do i recognize the different and printing it saftely?
last question , are there any way to nake try except in drivers or all the faults are continue directly to blue screen?
thank you
p.s.
here is the link to the entire code (Without the additions I wrote (which I listed in this post above))
https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/miniFilter/swapBuffers/swapBuffers.c
File name are the concepts at IRP_MJ_CREATE. you can't rely on the name at irp_mj_write or read. so better to do it in create. also try to get the name from FltObject->FileObject->FileName it may give you the desired name of your file aling with other names too.
For printing the written data you need to check for Irp flag in minifilter it is from Data->Iopb->IrpFlags, IRP_PAGING_IO if its true then print the buffer using
KdPrint((".... "));
Yes, you can use try, except in driver too.
Hope this may help.
:)

Get the file type of a file using the Windows API

I am trying to identify when a file is PNG or JPG to apply it as a wallpaper. I am using the SHGetFileInfo to get the type name with the .szTypeName variable, but I just realized that it changes if the OS is in another language.
This is my code:
SHFILEINFOW fileInfo;
UINT sizeFile = sizeof(fileInfo);
UINT Flags = SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES;
// Getting file info to find out if it has JPG or PNG format
SHGetFileInfoW(argv[1], 0, &fileInfo, sizeFile, Flags);
This is how I am validating:
if (wcscmp(fileInfo.szTypeName, L"JPG File") == 0)
{
//Code here
}
When the OS is in spanish, the value changes to "Archivo JPG" so I would have to validate against all language, and does not make sense.
Any idea what other function I can use?
This API is meant to be used to produce a user-facing string representation for known file types1). It is not meant to be used to implement code logic.
More importantly, it doesn't try to parse the file contents. It works off of the file extension alone. If you rename an Excel workbook MySpreadsheet.xlsx to MySpreadsheet.png, it will happily report, that this is a "PNG File".
The solution to your problem is simple: You don't have to do anything, other than filtering on the file extension. Use PathFindExtension (or PathCchFindExtension for Windows 8 and above) to get the file extension from a fully qualified path name.
This can fail, in case the user appended the wrong file extension. Arguably, this isn't something your application should fix, though.
As an aside, you pass SHGFI_USEFILEATTRIBUTES to SHGetFileInfoW but decided to not pass any file attributes (second argument) to the call. This is a bug. See What does SHGFI_USEFILEATTRIBUTES mean? for details.
1) It is the moral equivalent of SHGFI_DISPLAYNAME. The only thing you can do with display names is display them.

Write data to sdcard zedboard

I want to write data to zedboard's sdcard. I am able to write data to DRAM. Now I want to read DRAM's data and write it Sdcard. I have followed this (http://elm-chan.org/fsw/ff/00index_e.html) but it does not fulfill my requirement. I am not able to find any tutorial any example etc for this.
Please any tutorial link or any example. Thanks.
If you're using Vivado SDK, which I assume you are, it is really straightforward to use the SD Card.
To include the Fat File System, inside Xilinx SDK, open your Board Support Package (system.mss file) an select Modify this BSP's Settings. Under Overview, you can select xilffs.
Next, you must write the software to access the SD Card. This library offers a wide variety of functions. You can either look at here_1, in here_2 or in here_3. In this second reference is provided a wide variety of complex functions.
Aside from this, in order to use the SD Card, what you should basically do is written below. Note that this is just an overview, and you should refer to the references I gave you.
# Flush the cache
Xil_DCacheFlush();
Xil_DCacheDisable();
# Initialize the SD Card
f_mount(0, 0);
f_mount(0, <FATFS *>)
# Open a file using f_open
# Read and Write Operations
# Either use f_write or f_read
# Close your file with f_close
# Unmount the SD with f_mount(0,0)
Note that experience teaches me that you need to write to the file in blocks that are multiples of the block size of the file system, which for the FAT files syste, is typically 512 bytes. Writing less that 512 bytes and closing the file will make it zero bytes in length.
In new version of Xilffs (Fatfs) lib syntax is little changed.
New syntax is:
static FATFS FS_instance; // File System instance
const char *path = "0:/"; // string pointer to the logical drive number
static FIL file1; // File instance
FRESULT result; // FRESULT variable
static char fileName[24] = "FIL"; // name of the log
result = f_mount(&FS_instance, path, 0); //f_mount
result = f_open(&file1, (char *)fileName, FA_OPEN_ALWAYS | FA_WRITE); //f_open
May be this can help you.

SHFileOperation FOF_ALLOWUNDO fails on long filenames

I'm using the following function to delete a file to the recycle bin: (C++, MFC, Unicode)
bool DeleteFileToPaperbasket (CString filename)
{
TCHAR Buffer[2048+4];
_tcsncpy_s (Buffer, 2048+4, filename, 2048);
Buffer[_tcslen(Buffer)+1]=0; //Double-Null-Termination
SHFILEOPSTRUCT s;
s.hwnd = NULL;
s.wFunc = FO_DELETE;
s.pFrom = Buffer;
s.pTo = NULL;
s.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOERRORUI;
s.fAnyOperationsAborted = false;
s.hNameMappings = NULL;
s.lpszProgressTitle = NULL;
int rc = SHFileOperation(&s);
return (rc==0);
}
This works nicely for most files. But if path+filename exceed 255 characters (and still much shorter that 2048 characters), SHFileOperation returns 124. Which is DE_INVALIDFILES.
But what's wrong? I checked everything a million times. The path is double-null terminated, I'm not using \\?\ and it works for short filenames.
I'm totally out of ideas...
I think backwards comparability is biting you in the --- in several ways, and I'd need to actually see the paths your using and implement some error checking code to help. But here are some hints.
You would not get a DE_INVALIDFILES 0x7C "The path in the source or destination or both was invalid." for a max path violation, you'd get a DE_PATHTOODEEP 0x79 "The source or destination path exceeded or would exceed MAX_PATH."
These error codes(return value) do, can, and have changed over time, to be sure what your specific error code means, you need to check it with GetLastError function(msdn)
Also, taken from the SHFileOperation function documentation: "If you do not check fAnyOperationsAborted as well as the return value, you cannot know that the function accomplished the full task you asked of it and you might proceed under incorrect assumptions."
You should not be using this API for extremely long path names, it has been replaced in vista+ by IFileOperation interface
The explanation for why it may work in explorer and not thru this LEGACY api is - Taken from the msdn page on Naming Files, Paths, and Namespaces
The shell and the file system have different requirements. It is
possible to create a path with the Windows API that the shell user
interface is not able to interpret properly.
Hope this was helpful
The recycle bin doesn't support files whose paths exceed MAX_PATH in length. You can verify this for yourself by trying to recycle such a file in Explorer - you will get an error message about the path being too long.

Why are LoadResource/LockResource sometimes returning concatenated resource data?

I'm working with a Visual Studio C++ project that contains a number of HTML resources. They are loaded by a method that looks like this:
LPCTSTR loadHTML(HMODULE hModule, LPCTSTR sResourceName)
{
HRSRC hResource = FindResource(hModule, sResourceName, RT_HTML);
if(!hResource)
return 0;
HGLOBAL hResourceData = LoadResource(hModule, hResource);
if(!hResourceData)
return 0;
return reinterpret_cast<LPCTSTR>(LockResource(hResourceData));
}
Most of the time, this works fine. Some times, though, it returns a resource concatenated with another resource. When this happens, it is a persistent problem in that build. I can "fix" it by adding a few blank lines to the resource in question and then rebuilding the project. It happens periodically, even when the resources haven't changed.
I am keen to get to the bottom of why it is happening. Has anyone else come across it? Could there be something peculiar about my resources that is causing the problem? Is my code wrong?
Sadly, I'm reluctant to post an example resource here; they're pretty long and this is proprietary software.
Whats peculiar about your resources is you are expecting them to be zero terminated. iirc resource sections are aligned on 16 byte boundries, which means that whenever a "blob" is a multiple of 16 bytes long there won't be any separating byte's between the resource and the next.
Either ensure that the resources are saved with a terminating zero character, or use SizeofResource to determine where the resource ends.
How do you determine the end of a resource? Do your resource files end in a (double for unicode) NULL? I don't think there is any guarantee that a resource is NULL terminated in the PE file and you seem to be treating it as a string.

Resources