WinAPI Named Pipe location - c

HANDLE pipe = CreateFile( L"\\\\.\\pipe\\my_pipe",
GENERIC_READ, // only need read access
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
I'm new to win api and i'd like to know where is the "my_pipe" file created on the hard disk?
I can't find it anywhere near the binary or sources

Windows doesn't follow the UNIX philosophy "everything is a file", so the named objects you create with the kernel APIs aren't files, but are objects in various NT objects namespaces. You can see them with tools like WinObj.
You may want to have a look at the article about the object manager in Windows.

Related

Kernel module check if file exists

I'm making some extensions to the kernel module nandsim, and I'm having trouble finding the correct way to test if a file exists before opening it. I've read this question, which covers how the basic open/read/write operations go, but I'm having trouble figuring out if and how the normal open(2) flags apply here.
I'm well aware that file reading and writing in kernel modules is bad practice; this code already exists in the kernel and is already reading and writing files. I am simply trying to make a few adjustments to what is already in place. At present, when the module is loaded and instructed to use a cache file (specified as a string path when invoking modprobe), it uses filp_open() to open the file or create it if it does not exist:
/* in nandsim.c */
...
module_param(cache_file, charp, 0400);
...
MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory");
...
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
You might ask, "what do you really want to do here?" I want to include a header for the cache file, such that it can be reused if the system needs to be reset. By including information about the nand page geometry and page count at the beginning of this file, I can more readily simulate a number of error conditions that otherwise would be impossible within the nandsim framework. If I can bring down the nandsim module during file operations, or modify the backing file to model a real-world fault mode, I can recreate the net effect of these error conditions.
This would allow me to bring the simulated device back online using nandsim, and assess how well a fault-tolerant file system is doing its job.
My thought process was to modify it as follows, such that it would fail trying to force creation of a file which already exists:
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if(IS_ERR(cfile)){
printk(KERN_INFO "File didn't exist: %ld", PTR_ERR(cfile));
/* Do header setup for first-time run of NAND simulation */
}
else{
/* Read header and validate against system parameters. Recover operations */
}
What I'm seeing is an error, but it is not the one I would have expected. It is reporting errno 14, EFAULT (bad address) instead of errno 17 EEXIST (File exists). I don't want to run with this because I would like this to be as idiomatic and correct as possible.
Is there some other way I should be doing this?
Do I need to somehow specify that the file path is in user address space? If so, why is that not the case in the code as it was?
EDIT: I was able to get a reliable error by trying to open with only O_RDWR and O_LARGEFILE, which resulted in ENOENT. It is still not clear why my original approach was incorrect, nor what the best way to accomplish my goal is. That said, if someone more experienced could comment on this, I can add it as a solution.
Indeed, filp_open expects a file path which is in kernel address space. Proof is the use of getname_kernel. You can mimic this for your use case with something like this:
struct filename *name = getname(cache_file);
struct file *cfile = ERR_CAST(name);
if (!IS_ERR(name)) {
cfile = file_open_name(name, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if (IS_ERR(cfile))
return PTR_ERR(cfile);
putname(name);
}
Note that getname expects a user-space address and is the equivalent of getname_kernel.

How to properly get contents of DLL file for PE parsing?

I'm trying to get the RVA of a function in kernel32.dll which means I need to use the offsets to find different structures in the file until I can get the IMAGE_EXPORT_DIRECTORY structure. However I know a lot of methods and ways of getting the contents of files interpret and leave certain characters and stuff out which would make this a nearly impossible task. So I want to know the best way to go about getting the contents of a dll file to copy into a character array.
Update: For anyone interested I created a function for mapping the dll into memory.
void* GetFileImage(char path[])
{
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if(hFile == INVALID_HANDLE_VALUE){return NULL;}
HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap");
if(file_map == INVALID_HANDLE_VALUE){return NULL;}
LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0);
if(file_image == 0){return NULL;}
return file_image;
}
There are multiple ways. Not that many multiple, though.
1.If you are trying to parse a system loaded file such as kernel32.dll which are loaded into memory on system startup, you can directly use GetModuleHandle to grab the loaded base address and start parsing through PE (assuming you are familiar with the PE structure and static/delay loading of dlls and its exports).
2.If the dll you are trying to parse is not one of the system loaded, you can load them using LoadLibrary, which will return you the loaded base address, thus enabling you to parse the PE.
3.You can also do CreatFileMapping/MapViewOfFile to map the dll in your own virtual memory to parse.
The msdn article suggested by #David Thomas will be of great help:: Peering Inside the PE

Check if a file is being written using Win32 API or C/C++. I do not have write access myself

Inside a Windows C/C++ programm, I need to process a text file. So I just need to open the file for reading. However, I do not want to do that while the file is still being written to by another process. I also know that this other process will eventually close the file and never write to it agin.
Looking at similar questions on stackoverflow, the typical answer is "try and open the file for writing - if that fails then try again later").
Now in this case, my process does not have write access to the file at all. So checking if the file can be opened for writing is not an option . It will always fail irrespective of any other process having write access or not.
As Hans Passant and Igor Tandetnik said you just need to pass the appropriate sharing flag to CreateFile. As the MSDN documentation for CreateFile says:
FILE_SHARE_WRITE 0x00000002
Enables subsequent open operations on a file or device to request write access.
Otherwise, other processes cannot open the file or device if they request write access.
If this flag is not specified, but the file or device has been opened for write access
or has a file mapping with write access, the function fails.
You'll want to use code like the following:
HANDLE handle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) {
DWORD errcode = GetLastError();
if (errcode == ERROR_SHARING_VIOLATION) {
printf("%s: sharing violation\n", name);
} else {
printf("%s: CreateFile failed, error code = %lu\n", name, errcode);
}
} else {
printf("%s: CreateFile succeeded\n", name);
}
This code in unable to tell if the ERROR_SHARING_VIOLATION occurred because the other process has the file open for writing or because the another process didn't use FILE_SHARE_READ when opening the file. In the later case any attempt to read from the file will fail with a sharing violation. The FILE_SHARE_READ flag is passed to prevent sharing violations in the case when the file already been opened and FILE_SHARE_READ was used. You could also add FILE_SHARE_DELETE but I assume you'd consider that the same as write access.

Execute a mapped file on Windows

Hello fellow developers,
I'm trying to map an executable binary file on Windows and then to execute the mapped file.
So far, I managed the mapping using CreateFileMapping and MapViewOfFile.
These functions gave me a HANDLE to the mapped file and a pointer to the mapped data but I have no clue how to execute the mapped binary.
I think I should use the CreateProcess function but what should it be given as parameters ?
char *binaryPath = "C:/MyExecutable.exe";
// Get the binary size
std::fstream stream(binaryPath, std::ios::in | std::ios::binary);
stream.seekg(0, std::ios::end);
unsigned int size = stream.tellg();
// Create a mapped file in the paging file system
HANDLE mappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READ, 0, size, NULL);
// Put the executable data into the mapped file
void* mappedData = MapViewOfFile(mappedFile, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, size);
stream.read((char*)mapping, size);
stream.close();
// What should I do now ?
There is no native way to run a raw executable image that resides in memory. CreateProcess() is the official way to run an executable image, but the image must reside on the file system instead. The OS loads the image into memory and then patches it as needed (resolves DLL references, etc) so it will actually run correctly.
With that said, I have seen third-party code floating around that duplicates what the OS does when it loads an executable image into memory. But I've only ever seen that used with DLLs (so code does not have to use LoadLibrary/Ex() to use a DLL in memory), not with EXEs.

Serial Port Communication Issues (C code)

I recently tried to get access to a serial communication using a Bluetooth usb dongle.
I used the C code below, and keep getting error 5, which is “Access denied”. I am the administrator for the system (which seemed to be the common solution to this problem on the forums) and no other application is accessing the same port I am using (also another common solution). I’m running on a Windows Vista Home Basic 32bit system. I was wondering if anyone had a solution for this
My C code is:
HANDLE hComm;
hComm = CreateFile( _T("\\.\COM3"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hComm == INVALID_HANDLE_VALUE)
printf("Error number: %ld\n", GetLastError());
else
printf("success\n");
I don't know if this is your problem or not, but I suspect you need to escape the backslashes in the path, like so: "\\\\.\\COM3"
That does look like you have to escape your backslashes again. You can also verify that the COM port you're targeting exists on your system by using an object viewer, such as WinObj (http://technet.microsoft.com/en-us/sysinternals/bb896657.aspx), although I don't know if WinObj runs on Vista.
In my experience the backslashes are not needed
hComm = CreateFile( _T("COM3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
Thanks for the tips but it turns out the bluetooth passkey was not set properly and therefore it was denying access to the serial port.
Just replace your COM# with \.\COM# in your code,
hComm = CreateFile("\\\\.\\COM15",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);

Resources