GetFileTime returns an old time - file

I want to download a file from a server if it´s newer then the one on my disc.
I wrote following code:
bool bDownload = true;
HANDLE hFile = CreateFile(strFileLocal, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME ftLocal = { 0 };
FILETIME ftWrite = { 0 }; // only for testing
GetFileTime(hFile, &ftLocal, NULL, &ftWrite);
FILETIME ftRemote = arrTimes[i]; //get size from server
if (ftLocal.dwLowDateTime >= ftRemote.dwLowDateTime && ftLocal.dwHighDateTime >= ftRemote.dwHighDateTime)
{
bDownload = false;
}
CloseHandle(hFile);
}
After this is done I download the file and set the filetime from server to the file:
//set file date
HANDLE hFile = CreateFile(strFileLocal, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME ftRemote = arrTimes[i];
SetFileTime(hFile, &ftRemote, NULL, &ftRemote);
CloseHandle(hFile);
}
Now my problem:
If I replace the file on disk with a new creation time, GetFileTime will read the time I had set. But in the file explorer in windows the file has the new creation time.
For testing I tried to read last writing time. But this is the same time as creation time.
Thanks a lot.
How can I fix this problem? Do I something wrong?

Related

writing in file using threads (WINAPI)

Just when I thought I finally understood threads, I got a problem.
In the main thread, I create a mutex using this:
Mutex = CreateMutex(NULL, FALSE, Mutex_Name);
Then, in one of the worker threads (the first one to reach), I have a function that returns a handle to a file by creating it like this:
file_h = CreateFile("The_File.txt",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
The other threads have functions that return a handle to the file by this:
file_h = CreateFile("The_File.txt",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
At the last part, both threads try to write to the file using this function:
int W_to_f(char* str_to_w, HANDLE file)
{
HANDLE mutex = NULL;
DWORD waitcode1;
DWORD dwBytesWrite;
char line[Line_Len];
mutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, LOCK);
if (mutex == NULL)
{
printf("Failed at opening LOCK in write file\n");
return -1;
}
waitcode1 = WaitForSingleObject(mutex, 15000);
if (WAIT_OBJECT_0 != waitcode1)
{
printf("Error when waiting for LOCK in file\n");
return -1;
}
strcpy(line, str_to_w);
while ((Line_Len - (strlen(line) + 1)) > 0)
{
strcat(line, "#");
}
SetFilePointer(file, 0, NULL, FILE_END); //problem?
WriteFile(file, line, strlen(line), &dwBytesWrite, NULL);
WriteFile(file, "\n", 2, &dwBytesWrite, NULL);
if(!ReleaseMutex(mutex))
{
printf("failed release mutex in write_file fun\n");
return -1;
}
return 0;
}
All I want them to do is to write to the file like this:
firststring############
secondstring###########
But, after checking with breakpoints, what I get is that the first one manages to write to file:
firststring###########
But then after the second one writes to the file, it becomes:
癡慩㩤㈱㐳䁀䁀䁀䁀䁀䁀䁀䁀䁀幀搀湩楤㩮㘵㠷䁀䁀䁀䁀䁀䁀䁀䁀䁀
Just one line, it doesn't even write the Chinese after the firststring####.
Should I somehow use SetFilePointer?
Should I CreateFile() in the function using OPEN_EXISTING for each thread?

Memory Mapped File changes not reflected in underlying file

I am learning MMF in win32 C.
I can't seem to see what I am missing...
Here is my code:
#include "stdafx.h"
#include <Windows.h>
int main()
{
wchar_t szfilename[] = L"c:\\temp\\mmf.txt";
HANDLE hFile = CreateFile(
szfilename,
GENERIC_READ | GENERIC_WRITE, //dwDesiredAccess
FILE_SHARE_READ | FILE_SHARE_WRITE, //dwShareMode
NULL, //lpSecurityAttributes
CREATE_NEW, //dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, //dwFlagsAndAttributes
NULL); //hTemplateFile
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD error = GetLastError();
if (error != ERROR_FILE_EXISTS)
exit(-1);
}
//Now create the file mapping
HANDLE hMap = CreateFileMapping(
hFile,
NULL, //LPSECURITY_ATTRIBUTES lpAttributes,
PAGE_READWRITE, //DWORD flProtect,
0, //DWORD dwMaximumSizeHigh,
1024, //DWORD dwMaximumSizeLow,
L"myMappingFile"); //LPCTSTR lpName
if (hMap == (HANDLE)ERROR_ALREADY_EXISTS || hMap == NULL)
{
DWORD error = GetLastError();
exit(-2);
}
LPCTSTR pBuf = (LPTSTR)MapViewOfFile(hMap, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
0);
if (pBuf == NULL)
{
printf("Could not map view of file (%d).\n",
GetLastError());
return -2;
}
wchar_t szMsg[] = L"Msg from first process";
CopyMemory((PVOID)pBuf, szMsg, wcslen(szMsg) * sizeof(wchar_t));
UnmapViewOfFile(pBuf);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}
I open a file, associate it with a memory mapping and create a view. Then I write data (copy) into the buffer (view) and close things down.
I am trying to figure out why my underlying file (c:\temp\mmf.txt) does not contain the msg after the routine executes. Am I missing something? The file size remains 0.
Here is a snippet of code that demonstrates memory mapping a file. In the end I think you will just benefit from reading the MSDN docs for each API call you are using a little more carefully.
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMapping = NULL;
LPVOID pBase = NULL;
__try
{
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hFile == INVALID_HANDLE_VALUE) __leave;
hFileMapping = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0, 0, NULL);
if(hFileMapping == NULL) __leave;
pFileBase = MapViewOfFile(hFileMapping,
FILE_MAP_READ,
0, 0, 0);
if(pBase == NULL) __leave;
}
__finally
{
if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if(hFileMapping != NULL) CloseHandle(hFileMapping);
}

How to use deviceiocontrol function properly

This is my code:
Code:
HANDLE HandelUsb= CreateFile(L"\\\\.\\G:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (HandelUsb == INVALID_HANDLE_VALUE)
{
printf("Terminal failure: Unable to open usb ERROR CODE:0x%x\n", GetLastError());
return 1;
}
DISK_GEOMETRY d = { 0 };
DWORD dwReturned = 0;
int gs =DeviceIoControl(HandelUsb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &d, sizeof(DISK_GEOMETRY),&dwReturned, NULL);
printf("%d\n", gs);
if (d.MediaType == RemovableMedia)
{
DWORD dwReturned2 = 0;
MEDIA_SERIAL_NUMBER_DATA data={ 0 };
if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
}
else {
printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());
}
}
CloseHandle(HandelUsb);
return 0;
Everything works well except for the function
Code:
DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)
It always fails (returns a value of 0), GetLastError returns the value 0X1 (problem function).
Maybe someone here can show me what I'm missing here?
Following the comment of #IInspectable ,i changed the code to it:
//volume handle to device handle
VOLUME_DISK_EXTENTS volumeToDevice = { 0 };
DWORD Returned = 0;
DeviceIoControl(HandelToUsb,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL,0,&volumeToDevice,sizeof(VOLUME_DISK_EXTENTS),&Returned,NULL);
WCHAR volume[150] ;
swprintf_s(volume, L"\\\\.\\PhysicalDrive%d", volumeToDevice.Extents[0].DiskNumber);
wprintf(L"%s\n", volume);
//handle to phisicalDrive
HANDLE HandelUsb = CreateFile(volume, 0, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
DWORD dwReturned2 = 0;
MEDIA_SERIAL_NUMBER_DATA data={ 0 };
if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
}
else {
printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());
}
I still get a failure 0X1 on function
DeviceIoControl (Handel Usb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, & data, sizeof (MEDIA_SERIAL_NUMBER_DATA), & dwReturned2, NULL)
I ran Windus 7
i tried to Change the permissions function CreateFile (Add GENERIC_EXECUTE , replace to GENERIC_ALL add FILE_ATTRIBUTE_NORMAL ), play with the parameters of the DeviceIoControl.

How to check if a file is being used by another application?

I am using the following code to check if a file is being used by another application:
HANDLE fh = CreateFile("D:\\1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "The file is in use", "Error", 0);
}
If the file is being used by another application, the message box is displayed. However, the message box is also displayed if the file does not exists!
So what should I do to solve this problem, should I also check if the file exists (using another function), or can the parameters of CreateFile() be changed to only return INVALID_HANDLE_VALUE if the file is in use and does exists?
If you wish to find out, which process has a file open, use the Restart Manager. The procedure consists of the following steps (as outlined in Raymond Chen's blog entry How do I find out which process has a file open?):
Create a Restart Manager session (RmStartSession).
Add a file resource to the session (RmRegisterResource).
Ask for a list of all processes affected by that resource (RmGetList).
Close the session (RmEndSession).
Sample code:
#include <Windows.h>
#include <RestartManager.h>
#pragma comment(lib, "Rstrtmgr.lib")
bool IsFileLocked( const wchar_t* PathName ) {
bool isFileLocked = false;
DWORD dwSession = 0x0;
wchar_t szSessionKey[CCH_RM_SESSION_KEY + 1] = { 0 };
if ( RmStartSession( &dwSession, 0x0, szSessionKey ) == ERROR_SUCCESS ) {
if ( RmRegisterResources( dwSession, 1, &PathName,
0, NULL, 0, NULL ) == ERROR_SUCCESS ) {
DWORD dwReason = 0x0;
UINT nProcInfoNeeded = 0;
UINT nProcInfo = 0;
if ( RmGetList( dwSession, &nProcInfoNeeded,
&nProcInfo, NULL, &dwReason ) == ERROR_MORE_DATA ) {
isFileLocked = ( nProcInfoNeeded != 0 );
}
}
RmEndSession( dwSession );
}
return isFileLocked;
}
You need to use GetLastError() to know why CreateFile() failed, eg:
// this is requesting exclusive access to the file, so it will
// fail if the file is already open for any reason. That condition
// is detected by a sharing violation error due to conflicting
// sharing rights...
HANDLE fh = CreateFile("D:\\1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE)
{
switch (GetLastError())
{
case ERROR_PATH_NOT_FOUND:
case ERROR_FILE_NOT_FOUND:
MessageBox(NULL, "The file does not exist", "Error", 0);
break;
case ERROR_SHARING_VIOLATION:
MessageBox(NULL, "The file is in use", "Error", 0);
break;
//...
default:
MessageBox(NULL, "Error opening the file", "Error", 0);
break;
}
}
else
{
// the file exists and was not in use.
// don't forget to close the handle...
CloseHandle(fh);
}

Win32 API - Trying to readfile, it's getting truncated -- why?

I am trying to read a file and then display the file in ASCII or HEX into hEdit. Eventually I will be running other computations on the file info but right now I just want to see it all.
Currently the code displays the first bit - "MZ" - but thats it. Somehow I am accidentally truncating the pszFileText variable, I want to be able to view the entire executable in my window.
BOOL ReadInEXEFile(HWND hEdit, LPCTSTR pszFileName)
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
DWORD dwFileSize;
dwFileSize = GetFileSize(hFile, NULL);
if(dwFileSize != 0xFFFFFFFF)
{
LPSTR pszFileText;
pszFileText = GlobalAlloc(GPTR, dwFileSize + 1);
if(pszFileText != NULL)
{
DWORD dwRead;
if(ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL))
{
pszFileText[dwFileSize] = 0; // Add null terminator
if(SetWindowText(hEdit, pszFileText))
{
bSuccess = TRUE; // It worked!
}
}
GlobalFree(pszFileText);
}
}
CloseHandle(hFile);
}
return bSuccess;
}
EXE files are binary, but you are you trying to display the raw binary data as-is, which will not work. You were on the right track thinking that you need to encode the binary data to hex before displaying it. Binary data is not displayable, but hex is.
Try this instead:
static const TCHAR Hex[] = TEXT("0123456789ABCDEF");
BOOL ReadInEXEFile(HWND hEdit, LPCTSTR pszFileName)
{
BOOL bSuccess = FALSE;
HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize != INVALID_FILE_SIZE)
{
LPTSTR pszFileText = (LPTSTR) LocalAlloc(LMEM_FIXED, ((dwFileSize * 3) + 1) * sizeof(TCHAR));
if (pszFileText != NULL)
{
BYTE buffer[1024];
DWORD dwOffset = 0;
DWORD dwRead;
for (DWORD dwFilePos = 0; dwFilePos < dwFileSize; dwFilePos += dwRead)
{
if (!ReadFile(hFile, buffer, sizeof(buffer), &dwRead, NULL))
{
CloseHandle(hFile);
return FALSE;
}
if (dwRead == 0)
break;
for (DWORD idx = 0; idx < dwRead; ++idx)
{
pszFileText[dwOffset++] = Hex[(buffer[idx] & 0xF0) >> 4];
pszFileText[dwOffset++] = Hex[buffer[idx] & 0x0F];
pszFileText[dwOffset++] = TEXT(' ');
}
}
pszFileText[dwOffset] = 0; // Add null terminator
bSuccess = SetWindowText(hEdit, pszFileText);
LocalFree(pszFileText);
}
}
CloseHandle(hFile);
}
return bSuccess;
}
Two reasons:
1) If you are reading an executable, the third byte is likely to be a zero, which might terminate the string, even though you are passing the length to SetWindowText.
2) This line is wrong: pszFileText[dwFileSize + 1] = 0;. It should be pszFileText[dwFileSize] = 0;. You are writing a zero byte some place wrong, there's no telling what that might be doing.
The way you are displaying it probably depends on the data being a NUL-terminated string, and binary data has embedded NULs in it, so you only display the data up to the first NUL.
You will need to print it by yourself and use the length of the data to know how much to print instead of depending on it being a NUL-terminated C-string.

Resources