I was debugging some WinAPI application.
Right before the call to the function CreateFileMappingA the file's size was 0Kb. Immediately after the call to the function, the file got around 200Kb. I tried browsing the online Windows API documentation but didn't find anything (or not understand perhaps) whether a file write would occur after the function call. The flProtect parameter's value was PAGE_READWRITE.
I'd really like to know what the function really does, and especially why this write to the file.
After some research, I found out that the function CreateFileMappingA was being called like this:
CreateFileMappingA(fh, NULL, PAGE_READWRITE, 0, 0x336BC, "kll");
According to the documentation, if the file size would be lower than the length the mapping targets, the file would be extended to fit the size.
So in my case, the file was just created.
fh = CreateFileA("file2.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
So first, the file "file2.dat" would be created with write privileges. It would be 0Kb. Then, right after the call above to CreateFileMappingA, the file size would be 0x336BC bytes, or 206Kb.
Related
I am struggling to understand what may be causing the issue in my case.
I am using
ShellExecuteW('open', 'explorer.exe', '/select,[file_name]', None, win32con.SW_SHOW)
What I am trying to do is open the file in the OS, highlight it, and bring the File Explorer to the foreground. This works fine for most cases, but when I try to open a file that exceeds the MAX_PATH limit (260 characters), the file doesn't open, and instead it takes me to the "My Files" page.
I have tried prepending "\\?\" to the beginning of my file name, because that is what other Stack Overflow posts said to do with regards to overriding the MAX_PATH limit, but it has not changed the situation.
Does the ShellExecuteW function not allow for files that exceed MAX_PATH? And, if so, is there any workaround I could use?
I read some cases, about this issue. Find this article:Long Paths in .NET, Part 1 of 3 [Kim Hamilton]
If you prefix the file name with "\?\" and call the Unicode versions of the Windows APIs, then you can use file names up to 32K characters in length. In other words, the \?\ prefix is a way to enable long paths while working with the Windows file APIs.
and:
Long paths with the \?\ prefix can be used in most of the file-related Windows APIs, but not all Windows APIs.
I also test ShellExcuteW with \\?\,it failed.
Working well with SHOpenFolderAndSelectItems
CoInitialize(NULL);
LPCWSTR file_name ;//Change the path according to your needs
PIDLIST_ABSOLUTE pidl;
if (SUCCEEDED(SHParseDisplayName(file_name, 0, &pidl, 0, 0)))
{
ITEMIDLIST idNull = { 0 };
LPCITEMIDLIST pidlNull[1] = { &idNull };
SHOpenFolderAndSelectItems(pidl, 1, pidlNull, 0);
ILFree(pidl);
}
Note:CoInitialize or CoInitializeEx must be called before using SHOpenFolderAndSelectItems. Not doing so causes SHOpenFolderAndSelectItems to fail.
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.
:)
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.
The MSDN page on CreateFile says: The string "\\.\C:\" can be used to open the file system of the C: volume. However, the following code always returns an error : ERROR_PATH_NOT_FOUND.
HANDLE h = CreateFile(L"\\\\.\\C:\\", FILE_READ_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0);
How should I pass the arguments correctly?
If you wanted a volume handle (for use with I/O control codes) you would have needed to drop the trailing slash.
In order to get a handle to the root directory, you need to keep the trailing slash and pass the FILE_FLAG_BACKUP_SEMANTICS flag in the dwFlagsAndAttributes argument. This is documented on the MSDN page under the heading "Directories". For example, this is what you want to do if you're planning to call GetFileInformationByHandle or GetFileInformationByHandleEx.
Ordinarily, however, you wouldn't open a handle to the root directory in order to list the files. Instead, you would use FindFirstFile/FindNextFile or one of the related functions.
Try dropping the trailing slash:
L"\\\\.\\C:"
I'm trying to hide some values in the registry (such as serial numbers) with C++/windows
so I've been looking at this article http://www.codeproject.com/KB/system/NtRegistry.aspx
which says:
How is this possible? The answer is
that a name which is a counted as a
Unicode string can explicitly include
NULL characters (0) as part of the
name. For example, "Key\0". To include
the NULL at the end, the length of the
Unicode string is specified as 4.
There is absolutely no way to specify
this name using the Win32 API since if
"Key\0" is passed as a name, the API
will determine that the name is "Key"
(3 characters in length) because the
"\0" indicates the end of the name.
When a key (or any other object with a
name such as a named Event, Semaphore,
or Mutex) is created with such a name,
any application using the Win32 API
will be unable to open the name, even
though they might seem to see it.
so I tried doing something similar:
HKEY keyHandle;
PHKEY key;
unsigned long status = 0;
wchar_t *wKeyName = new wchar_t[m_keyLength];
MultiByteToWideChar(CP_ACP, 0, m_keyName, m_keyLength, wKeyName, m_keyLength);
wKeyName[18] = '\0';
long result = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
wKeyName,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&keyHandle,
&status);
where m_keyName is the ASCII text and wKeyName is the wide char text, but in regedit I see that it is treated the same and the key is just cut where I put the '\0'.
what is wrong with it?
The problem is that you are using the Win32 API and not the NT Native API. There is a table about 1/2 way through the article that you referenced that contains the list of Native APIs. For example, you would use NtCreateKey or ZwCreateKey instead of RegCreateKeyExW. The Win32 API assumes that alls strings are terminated by a NUL character whereas the Native API counterparts use a UNICODE_STRING structure for the name.
I'll take a stab in the dark, as I have never tried to do this.
It appears that you are using the wrong function to create your registry key. You should be using the NtCreateKey method because RegCreateKeyEx[AW] will notice your '\0' and chop off past it.
Why not use the class provided in the example? It provides a method called CreateHiddenKey. To use it, simply call SetKey before it. It would be much cleaner.