Set timestamp of a file to a custom time - c

I wanted to change timestamp a file to a custom date, I have find out the following code that must change time stamp a file to the current time but it doesn't work, however. How can I implement a function which it can change timestamp a file to a custom time (specified by user).
bool SetFileToCurrentTime(const char* arg_path, const char* arg_file_name)
{
HANDLE h_File;
FILETIME ft_FileTime;
SYSTEMTIME st_SystemTime;
char l_c_Path[MAX_PATH];
strcpy(l_c_Path, arg_path);
strcat(l_c_Path, arg_file_name);
h_File = CreateFile(l_c_Path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetSystemTime(&st_SystemTime); // Gets the current system time
SystemTimeToFileTime(&st_SystemTime, &ft_FileTime); // Converts the current system time to file time format
if (SetFileTime(h_File, (LPFILETIME)NULL, (LPFILETIME)NULL, &ft_FileTime))
return true;
else
return false;
}

I have find out the following code that must change time stamp a file to the current time but it doesn't work
I don't know what's going wrong, I don't have a Windows compiler to check, but here's some possibilities.
Check the return value of SystemTimeToFileTime and CreateFile.
Use GetLastError to find out why they failed.
l_c_Path is not putting a path separator between the path and file name. If the caller does not supply one the path will be incorrect. Print out l_c_Path.
Rather than using strcpy and strlcat, consider using _makepath_s to concatenate paths.
char l_c_Path[_MAX_PATH];
errno_t errorCode = _makepath_s(l_c_Path, _MAX_PATH, NULL, arg_path, arg_file_name, NULL);
if( errorCode ) {
// check the errorCode
}
How can I implement a function which it can change timestamp a file to a custom time (specified by user).
Instead of calling GetSystemTime and converting it with SystemTimeToFileTime, have the caller pass in a FILETIME.

Related

How do I get the disk drive serial number in filter driver?

I write a driver in windows, and I need disk drive serial number, for user mode I found this ansver.
My question is it possible to translate the above code to kernel mode, and how? Is WMI query available in filter driver? Sample code can greatly help.
EDIT:
I found here this code, but how I rewrite him for get serial number?
void GetSmbios()
{
NTSTATUS status;
GUID smbiosGUID = SMBIOS_DATA_GUID; // defined in wmiguid.h
PVOID wmiObject = NULL;
PWNODE_ALL_DATA dataBuffer;
ULONG bufferSize;
int TAG_SMBIOS = 'smbi';
//
// Get a WMI block handle to the SMBIOS_DATA_GUID
//
status = IoWMIOpenBlock((GUID *)&smbiosGUID, WMIGUID_QUERY,
&wmiObject);
if (!NT_SUCCESS(status))
{
return status;
}
//
// Determine how much space is required for the data
//
status = IoWMIQueryAllData(wmiObject, &bufferSize, NULL);
if (status != STATUS_BUFFER_TOO_SMALL)
{
ObDereferenceObject(wmiObject);
return status;
}
//
// Allocate the necessary storage. This space must come out of NP-pool
//
dataBuffer = ExAllocatePoolWithTag(
NonPagedPool,
bufferSize,
TAG_SMBIOS);
if (dataBuffer == NULL)
{
ObDereferenceObject(wmiObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
After allocating memory, I believe you need to call IoWMIQueryAllData() again, this time passing dataBuffer.
SMBIOS doesn't seem related to disk drives, so you'll want a different GUID to pass to IoWMIOpenBlock(). Perhaps this one ({BF253431-1E4D-4F57-00E7-64B2CACC801E}), since your user-mode example and others query Win32_PhysicalMedia to get SerialNumber.
However, this references a (presumably user-mode) DLL that is the provider for Win32_PhysicalMedia. So this may not be accessible in kernel-mode.
But it also gives a hint how to get the information from kernel-mode: IOCTLs. It mentions IOCTL_SMART_GET_VERSION, which should be just SMART_GET_VERSION, and here's an example:
(in user-mode, but you should be able to do similar from kernel-mode using ZwDeviceIoControlFile()). Note it follows up with another ioctl command, SMART_RCV_DRIVE_DATA, to get the serial number.
Another ioctl that sounds promising (and more general) is IOCTL_STORAGE_QUERY_PROPERTY, with the input STORAGE_PROPERTY_QUERY.PropertyId set to StorageDeviceProperty, so the output will be a STORAGE_DEVICE_DESCRIPTOR structure, which has field SerialNumberOffset:
Specifies the byte offset from the beginning of the structure to a null-terminated ASCII string that contains the device's serial number. If the device has no serial number, this member is zero.
FILE_FS_VOLUME_INFORMATION contains field VolumeSerialNumber. This data structure might be retrieved with ZwQueryVolumeInformationFile(... FileFsVolumeInformation).
That requires a handle to the volume or a file/directory in the volume. If that's not feasible, but you have a DEVICE_OBJECT, you might try building your own IRP with IRP_MJ_QUERY_VOLUME_INFORMATION and sending it with IoCallDriver(), though I don't know if that's sanctioned -- the docs say such a "request is sent by the I/O Manager."

Opening symbolic link in kernel Windows8.1+

i'm trying to open symbolic link as a file using ZwOpenProcess in kernel space. Using code below all is ok on XP-7. But using Windows 8.1 ZwOpenProcess fails with different NTSTATUS codes, like 0xC0000001, 0xC000000D
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
InitializeObjectAttributes ( &ObjectAttributes,
SymLinkOrDeviceName, // <--- \Device\CEDRIVER60
OBJ_KERNEL_HANDLE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL );
Status = ZwOpenFile ( &FileHandle,
FILE_READ_ACCESS,
&ObjectAttributes,
&IoStatus,
0,
FILE_NON_DIRECTORY_FILE );
if ( !NT_SUCCESS ( Status ) )
{
DbgPrint("TEST: ERROR %p ", Status); // <--- 0xC0000001, 0xC000000D
goto Exit;
}
I checked, using WinObj - symbolic link present in system, code works fine on XP-7.
I also trind to change Access to - FILE_ANY_ACCESS - the same result.
ZwOpenProcess
I suppose you meant ZwOpenFile.
\Device\CEDRIVER60
Did you really looked into the \Device directory? This directory usually contains device objects created by drivers. Symbolic links are usually placed into directories like \DosDevices. You should also include the OBJ_CASE_INSENSITIVE flag.
FILE_READ_ACCESS
This flag determines access right(s) required to successfully deliver an IOCTL message to a target device object. Specify a true file access right constant like FILE_READ_ATTRIBUTES, FILE_READ_DATA (its value is actually the same as FILE_READ_ACCESS) or GENERIC_READ. MSDN page on ZwOpenFile (and ZwCreateFile) is also worth of reading. You may need to include the SYNCHRONIZE flag too.
%p
NTSTATUS is defined as long (32-bit signed integer). %x is more appropriate.

Unique String generator

I want to make a program (network server-client).
One of the specification for this program is next:
The server will receive the sent packages and save it into a file, with a unique name (generated by the server at the moment the transfer starts.
Ex __tf_"unique_random_string".txt
I made a function that returns a pointer to a "unique" string created.
The problem is: If i stop the server and then start it again it will generate the same names.
Ex:this file names were generated and then i stopped the server.
__ft_apqfwk.txt
__ft_arzowk.txt
__ft_cdyggx.txt
I start it again and i try to generate 3 file names. Them will be the same.
Sorry for my english. I'm still learning it.
My function to generate this "unique string" is:
char *create_random_name(void)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
char *file_name;
int i=0;
int key;
if((file_name = malloc(16 * sizeof ( char )) ) == NULL)
{
printf("Failed to alloc memory space\n");
return NULL;
}
strcpy(file_name,"__ft_");
for(i=5 ; i<11 ; i++)
{
key = rand() % (int)(sizeof(charset)-1);
file_name[i]=charset[key];
}
strcat(file_name,".txt");
file_name[15] = '\0';
return file_name;
}
One option is saving to a file the names that have been used, and using them as a checklist. You also want to seed rand with something like srand(time(NULL)).
another is ignoring the randomisation, and just going in order, e.g. aaa, aab aac...aba ,abb etc. Again, save where your cycle is up to on a file.
Your question seems a little bit unclear but if you want to generate a unique string there are a couple of things you can consider:
Get System timestamp ( yyyy-MM-dd-HH-mm-ss-fff-tt)
Use Random function to generate a random number
Combine this with your function and I am sure you will get a unique string.
Hope it helps !
If it's available, you could avoid manually generating random names that might collide and let the system do it for you (and handle collision resolution by creating a new name) by using mkstemps. This is also safer because it opens the file for you, removing the risk of a random name being generated, verified to be unique, then trying to open it and discovering another thread/process raced in and created it.
char name[] = "/path/to/put/files/in/__ft_XXXXXX.txt";
int fd = mkstemps(name, strlen(".txt"));
if (fd == -1) { ... handle error ... }
After mkstemps succeeds, name will hold the path to the file (it's mutated in place, replacing the XXXXXX string), and fd will be an open file descriptor to that newly created file; if you need a FILE*, use fdopen to convert to a stdio type.
Before calling rand(),--- once and only once---, call srand(time()) to initialize the random number generator.
Before settling on any specific file name, call stat() to assure that file name does not already exist.

Time doesn't update in C

I've encountered a very weird problem. My time isn't changing at all, and it's always printing the same time to log file. Here is a function that overwrites the last time, and should return the new one:
char * update_time(char *date)
{
time_t timer;
timer = time(&timer);
struct tm* time_real;
time_real = localtime(&timer);
date = asctime(time_real);
strftime(date, 26, "%Y.%m.%d %H:%M:%S", time_real);
return date;
}
Here is how i call the function to get new time:
date = update_time(date);
In main function i declare a pointer to char like this:
char *date = NULL;
and call the function everytime i need to get new data. What's more interesting is the fact, that when i debug my program line-by-line, i see that debugger "see" the new value of char *data, but it cannot be seen (printed) in the result file.
FIY here is the output txt file:
2015.04.16 20:09:49:09S Program starts
2015.04.16 20:09:49:09S Opening file: a.txt
2015.04.16 20:09:49:09S New data retrieved
2015.04.16 20:09:49:09S Closing file: a.txt
2015.04.16 20:09:49:09S End of program
Thanks for help in advance
EDIT
Gave my program a nap with Sleep(5000), and #nos and #Weather Vane were right, its all about elapsed time (what's more funny in the context of my question :D). We can close this ticket, thanks everyone for help.
Note: asctime is noted in a MSVC example to be deprecated since it uses an internal static array.
Consider using asctime_s instead, which takes a buffer argument for its output.
If you use asctime, you must copy its result before you use it again. It's no use remembering the returned pointer beyond its immediate use.
UPDATE
I can see a bug:
date = asctime(time_real); // overwrites the pointer you passed
trftimse(date, 26, "%Y.%m.%d %H:%M:%S", time_real); // passes the pointer provided by asctime
return date; // that's NOT the arg you passed
So the function uses the pointer to the static internal string returned by asctime, not the one you provided.
Your question shows this
char *date = NULL;
date = update_time(date);
So you are passing a NULL pointer to strftime. It worked before, because the irrelevant call to asctime replaced the NULL pointer with its internal static pointer.
But even when it's all correct, if the program runs and completes in a short time span, the granularity of time means that small time differences cannot be reported.

How to get metadata from Libextractor into a struct

I want to use Libextractor to get keywords/metadata for files.
The basic example for it is -
struct EXTRACTOR_PluginList *plugins
= EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&EXTRACTOR_meta_data_print, stdout);
EXTRACTOR_plugin_remove_all (plugins);
However, this calls the function EXTRACTOR_meta_data_print which "prints" it to "stdout"
I'm looking at a way to get this information to another function - i.e. pass or store this in memory for further working. The documentation was not clear to me. Any help or experience regarding this?
I've tried to install libextractor and failed to get it working (it always returns a NULL plugin pointer upon call to EXTRACTOR_plugin_add_defaults()), so what I will write next is NOT TESTED:
from : http://www.gnu.org/software/libextractor/manual/libextractor.html#Extracting
Function Pointer: int
(*EXTRACTOR_MetaDataProcessor)(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
and
Type of a function that libextractor calls for each meta data item found.
cls
closure (user-defined)
plugin_name
name of the plugin that produced this value;
special values can be used (i.e. '<zlib>' for
zlib being used in the main libextractor library
and yielding meta data);
type
libextractor-type describing the meta data;
format basic
format information about data
data_mime_type
mime-type of data (not of the original file);
can be NULL (if mime-type is not known);
data
actual meta-data found
data_len
number of bytes in data
Return 0 to continue extracting, 1 to abort.
So you would just have to write your own function called whatever you want, and have this declaration be like:
int whateveryouwant(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
{
// Do your stuff here
if(stop)
return 1; // Stops
else
return 0; // Continues
}
and call it via:
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&whateveryouwant,
NULL/* here be dragons */);
Like described in http://www.gnu.org/software/libextractor/manual/libextractor.html#Generalities "3.3 Introduction to the libextractor library"
[here be dragons]: That is a parameter left for the user's use (even if it's redundant to say so). As defined in the doc: "For each meta data item found, GNU libextractor will call the ‘proc’ function, passing ‘proc_cls’ as the first argument to ‘proc’."
Where "the proc function" being the function you added (whateveryouwant() here) and proc_cls being an arbitrary pointer (can be anything) for you to pass data to the function. Like a pointer to stdout in the example, in order to print to stdout. That being said, I suspect that the function writes to a FILE* and not inevitably to stdout; so if you open a file for writing, and pass its "file decriptor" as last EXTRACTOR_extract()'s parameter you would probably end with a file filled with the information you can currently read on your screen. That wouldn't be a proper way to access the information, but if you're looking into a quick and dirty way to test some behavior or some feature; that could do it, until you write a proper function.
Good luck with your code!

Resources