Editing file information from driver

I tried all means of editing file creation and modified date by using ZwQueryInformationFile and ZwSetInformationFile by using FILE_BASIC_INFORMATION Class and modifying the CreationTime.LowPart,CreationTime.HighPart and even the CreationTime.QuadPart.
But whenever I see the file attributes from windows explorer by right clicking on file and properties the date and time remains the same.
Why is that so?Should I use any other method?
The date and time appears in proper format but here it is large negative or a positive integer.How does the conversion takes place internally? or it uses some other information table etc.
Please tell me how to modify this time of creation, modification etc.It was far easier in general VC++ programming.

FILE_BASIC_INFORMATION are working fine.How to change attributes of FILE_NAME_INFORMATION and FILE_RENAME_INFORMATION?
It doesnot take FileNameInformation.Name=L"\??\c:\hello.txt"
It says left operand must be lvalue.What does that mean?
I never faced a problem with this
WCHAR *sourcestring=L"\??\C:\hello.txt"

In FILE_NAME_INFORMATION, FileName is defined as:
WCHAR FileName[1];
not
WCHAR *FileName;

xxxxx@hotmail.com wrote:

FILE_BASIC_INFORMATION are working fine.How to change attributes of FILE_NAME_INFORMATION and FILE_RENAME_INFORMATION?
It doesnot take FileNameInformation.Name=L"\??\c:\hello.txt"
It says left operand must be lvalue.What does that mean?
I never faced a problem with this
WCHAR *sourcestring=L"\??\C:\hello.txt"

arjames correctly pointed out the issue:

In FILE_NAME_INFORMATION, FileName is defined as:
WCHAR FileName[1];
not
WCHAR *FileName;

Just in case it isn’t obvious, the file name is considered part of the
structure here. Instead of having a pointer to a separate string, the
characters are stored at the end of the structure. That means that the
structure is variable sized. You can’t just allocate a
FILE_NAME_INFORMATION and fill in the fields, because there would only
be room for one character. Instead you have to allocate
sizeof(FILE_NAME_INFORMATION)+sizeof(string)-2, then copy the characters
starting at FileName.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

How to copy?Will wcsncpy work?as
wchar *string=L"\??\c:\hello.txt"
wcsncpy(FileNameInformation.FileName,string,sizeof(string));
I used previously without the increase in size as
sizeof(FILE_NAME_INFORMATION)+sizeof(string)-2
you have said and the system crashed.

I noticed one more problem?Many at times compiler denies to convert FILE_NAME_INFORMATION to FILE_INFORMATION_CLASS but compiles otherwise.I really dont understand why?
Even though after compilation when I run it ZwQueryInformationFile and ZwSetInformationFile fail to retrieve/set name information.It doesnot return STATUS_SUCCESS.
Is there any other way to do it?

> wcsncpy(FileNameInformation.FileName,string,sizeof(string));

The last arg of wcsncpy is *count of characters*, not sizeof.

http://msdn.microsoft.com/en-us/library/xdsywd25(VS.80).aspx

–pa

/* But IMHO it is good that they don’t teach C in schools any longer */

one thing .whenever property is checked of any file or folder…call goes to querydirectory (IRP_MJ_Querydirectory) and from there buffer is filled.
It seems pretty strange to me but i encountered same problem with excel.
in query dir , there is a flag “return_single_entry” this flag is set and the corresponding file name is send to query dir function

“compiler denies to convert FILE_NAME_INFORMATION to FILE_INFORMATION_CLASS”, I’m a bit confused here. Who’s trying to convert FILE_NAME_INFORMATION, a struct defined in Ntddk.h, to FILE_INFORMATION_CLASS, an enum defined in wdm.h?

Also an alternative to wcsncpy is RtlCopyMemory, see the WDK for documentation.

Posts like this make me despair. I want to be patient and helpful, but
you have some basic misunderstandings of fundamental C concepts. I
don’t know how much C programming you have done, but you need to have
done a fair amount before you start dabbling in kernel-mode extensions.

xxxxx@hotmail.com wrote:

How to copy?Will wcsncpy work?as
wchar *string=L"\??\c:\hello.txt"
wcsncpy(FileNameInformation.FileName,string,sizeof(string));

Do you know what sizeof(string) is here? It is 4, because that’s the
size of a pointer. If you were using an array, this would work, but
when you use wchar*, it doesn’t. However, that’s not the right
parameter anyway. The final parameter to wcsncpy is supposed to be the
size of the DESTINATION, not the size of the source. That puts an upper
limit on the number of characters copied. It can figure out the size of
the source string by counting up to the zero terminator. You need to
tell it how much room you provided when you allocated the
FileNameInformation structure.

For purity, you should probably be using RtlStringCchCopyW or
RtlStringCbCopyW here, although in this case the net effect is the same.

I noticed one more problem?Many at times compiler denies to convert FILE_NAME_INFORMATION to FILE_INFORMATION_CLASS but compiles otherwise.I really dont understand why?

Really? You didn’t notice that FILE_NAME_INFORMATION is a structure
that is passed as a pointer, while FILE_INFORMATION_CLASS is an
enumeration that gets passed as an integer? They have two entirely
different uses.

Is there any other way to do it?

Yes – you can use these APIs as they are supposed to be used.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks for all suggestions its working now.I had just overlooked some minor errors.
I am able to retrieve both the filename and its length but when I print it it shows something like this
\DriverCode\config.txt???
Where do these marks come from?
and when I covert them to character string using wcstombs() and print it soemthing like this occurs
\DriverCode\confi???
some characters are missing and there are stray “?”.
What should I do now?

Most likely it’s because you are working with FILE_NAME_INFORMATION and it’s probably not guaranteed that FileName is NULL-terminated string. You need to use FileNameLength to build either NULL-terminated string or UNICODE_STRING (it depends on how you’re going to use it later).

Kris

This is not my thing, but are these strings null terminated? I have no
idea, but as they are also passing around the length, it might be the case
that they are not null terminated. In either case, have you tried printing
them using the length to limit the output?

How about you show us your code.

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Thursday, November 18, 2010 8:14 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Editing file information from driver

Thanks for all suggestions its working now.I had just overlooked some minor
errors.
I am able to retrieve both the filename and its length but when I print it
it shows something like this
\DriverCode\config.txt???
Where do these marks come from?
and when I covert them to character string using wcstombs() and print it
soemthing like this occurs
\DriverCode\confi???
some characters are missing and there are stray “?”.
What should I do now?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>>Where do these marks come from? and when I covert them to character string using wcstombs() and print it soemthing like this occurs \DriverCode\confi??? some characters are missing and there are stray “?”.

What should I do now? >>

Go and read some books on C programming and stop asking here simple questions. Sorry for being rude, but most of your questions here are because you don’t pay attention to small bugs you make because of lack of knowledge of basic C.

xxxxx@hotmail.com wrote:

Thanks for all suggestions its working now.I had just overlooked some minor errors.
I am able to retrieve both the filename and its length but when I print it it shows something like this
\DriverCode\config.txt???
Where do these marks come from?
and when I covert them to character string using wcstombs() and print it soemthing like this occurs
\DriverCode\confi???
some characters are missing and there are stray “?”.
What should I do now?

Show us your code. You have bugs, but surely you must realize that none
of us can read your mind.

You must remember that the strings in a UNICODE_STRING (or ANSI_STRING)
are not zero-terminated. They aren’t like a char * constant. You can’t
pass the string to printf or KdPrint and expect it to know where the
string ends. There is a special KdPrint descriptor that CAN handle a
UNICODE_STRING (%wZ), but I’m guessing you’re not using that.

You shouldn’t ever need wcstombs in a kernel driver. Are you calling
that from an application?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

xxxxx@hotmail.com wrote:

Thanks for all suggestions its working now.I had just overlooked some minor errors.
I am able to retrieve both the filename and its length but when I print it it shows something like this
\DriverCode\config.txt???
Where do these marks come from?
and when I covert them to character string using wcstombs() and print it soemthing like this occurs
\DriverCode\confi???
some characters are missing and there are stray “?”.
What should I do now?

Read and understand

http://www.catb.org/~esr/faqs/smart-questions.html

then ask again.

I am familiar with general ansi strings but I am new to wide character strings.I am have come up with a solution to the above problem.
I converted FileNameInfo->FileName to unicode string and then to ansi string using RtlInitUnicodeString and RtlUnicodeStringToAnsiString and everything is working fine.The FileName is printed without any stray characters.
Thanks!
One more doubt !What I am supposed to do to print the full path along with file name as
C:\DriverCode\config.txt instead of just
\DriverCode\config.txt as it doesnot mention the root directory which may be C:\ or D:\ etc.
I have seen in “system information” that it prints the full path like c:\ windows\system32\drivers\acpi.sys
or ??\c:\windows\system32\drivers\devsim.sys

FILE_RENAME_INFORMATION FileRenameInfo;
PFILE_RENAME_INFORMATION PFileRenameInfo;
PFileNameInfo=&FileNameInfo;

WCHAR *DestString=L"config.txt";

status=ZwOpenFile(&FileHandle, SYNCHRONIZE | GENERIC_ALL | DELETE | FILE_READ_ATTRIBUTES |FILE_WRITE_ATTRIBUTES ,pObjectAttributes,&IoStatusBlock,FILE_SHARE_READ | FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT);
if(status==STATUS_SUCCESS)
{
RtlStringCchLengthW(DestString,200,&size);
KdPrint((“InfoFile:size is %d”,size));
RtlStringCchCopyW(PFileRenameInfo->FileName, size+1 ,DestString);
KdPrint((“InfoFile:filename is %ws”,PFileRenameInfo->FileName));
PFileRenameInfo->FileNameLength=size + 1;
PFileRenameInfo->RootDirectory=‘\0’;
PFileRenameInfo->ReplaceIfExists=TRUE;
status=ZwSetInformationFile(FileHandle,&IoStatusBlock,PFileRenameInfo,sizeof(FileRenameInfo),FileRenameInformation);
if(status!=STATUS_SUCCESS)
{
KdPrint((“InfoFile:renaming failed”));
_snprintf( string, 255, “status = %0x, statusblock = %0x\n”,status,IoStatusBlock.Status );
DbgPrint( string );
}
}

sometimes the renaming fails with
status=c000000d statusblock=0

and sometimes it does work but file is renamed only “conf”

The same happens if I use

WCHAR *DestString=L"\??\C:\DriverCode\config.txt";

many at times it fails with same errors and if it does work then file file moves to c:\ directory and renamed “Drive”.
Is there any other way to do so?

Most obvious thing here is that RtlStringCchLengthW(DestString,200,&size) returns size in characters.
Then you are using this value (size) to set PFileRenameInfo->FileNameLength. However FileNameLength should be given in bytes not characters!
You really need to start reading documentation and pay much more attention to details. Those are the basics.

Anyway this is not the only problem you have with your code.

Kris

xxxxx@hotmail.com wrote:

FILE_RENAME_INFORMATION FileRenameInfo;
PFILE_RENAME_INFORMATION PFileRenameInfo;
PFileNameInfo=&FileNameInfo;

WCHAR *DestString=L"config.txt";

status=ZwOpenFile(&FileHandle, SYNCHRONIZE | GENERIC_ALL | DELETE | FILE_READ_ATTRIBUTES |FILE_WRITE_ATTRIBUTES ,pObjectAttributes,&IoStatusBlock,FILE_SHARE_READ | FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT);
if(status==STATUS_SUCCESS)
{
RtlStringCchLengthW(DestString,200,&size);
KdPrint((“InfoFile:size is %d”,size));
RtlStringCchCopyW(PFileRenameInfo->FileName, size+1 ,DestString);

And right at that point, you have trashed your stack, leading to a
crash. Look, YOU AREN’T PAYING ATTENTION. You aren’t THINKING about
your code. You are writing code without understanding what it does. STOP.

Look at the FILE_RENAME_INFORMATION structure:

|typedef struct _FILE_RENAME_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;|

That structure, as defined, contains enough room for exactly ONE
character of the file name. It doesn’t matter that you took a pointer
to that structure; the memory you allocated on the stack for
FileRenameInfo only has room for ONE character. When you copy 10
characters there, you are overwriting whatever follows it on the stack.
The FILE_RENAME_INFORMATION structure must be allocated DYNAMICALLY,
because you don’t know how large it must be until runtime. You CANNOT
allocate one on the stack.

It is painful that I have to do this, since there are lots of examples,
but HERE is the way you have to use this:

WCHAR* DestString = L"config.txt";
PFILE_RENAME_INFORMATION pfri;
size_t StrSize;

RtlStringCbLengthW( DestString, 999, &StrSize );
pfri = ExAllocatePool( PagedPool, sizeof(FILE_RENAME_INFORMATION) +
StrSize );
RtlStringCbCopyW( pfri->FileName, StrSize, DestString );
pfri->FileName = StrSize / sizeof(WCHAR);
// …

Note that I fetched the size in bytes (Cb). You could use the char
count versions (Cch) if you want, as long as you remember to multiply by
sizeof(WCHAR) where necessary.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.