ZwCreateSection and extending the section

Hi,

I have a problem with ZwCreateSection() routine. I’m mapping a data
file.

  1. When I set 6th argument (AllocationAttributes) of ZwCreateSection()
    to 0, the routine fails - I understood that I need to specify (at least)
    either SEC_COMMIT or SEC_RESERVE, but for both attributes, MSDN says
    “This attribute has no effect for file mapping objects that are backed
    by executable image files or data files (the hfile parameter is a handle
    to a file).” Am I missing something?

  2. It seems that I don’t quite understand meaning of SECTION_EXTEND_SIZE
    flag (2nd argument of ZwCreateSection() routine) - this flag, based on
    documentation, allows caller to “Dynamically extend the size of the
    section”. I map a view (using ZwMapViewOfSection(), AllocationType ==
    MEM_RESERVE), ViewSize > actual file size, routine returns successfully.
    Nevertheless, when I try write beyond actual file (when I write to
    address: base address + something, where something is greater than file
    size and smaller than view size), I run into access violation. I thought
    that when I access page that isn’t allocated yet, but is within mapped
    view, such page is allocated on demand, is marked as dirty and is
    written to file that backs this section - but how does this really work?

Thank you,

Robert

What return status do you get?
What value you pass for SectionPageProtection?

Hi,

well, what I get is an exception (not page fault), all routines return
successfully.

This is actual test-code, file is 128 KB long (so ViewSize is
intentionally larger than mapped file):

----cut ----
status = ZwCreateFile
(
& FileHandle,
GENERIC_READ | GENERIC_WRITE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);

if (!NT_SUCCESS(status))
{
VDbgPrint(“ZwCreateFile() returned 0x%x\n”,
status);
return status;
}

status = ZwCreateSection
(
&vcb->SectionHandle,
SECTION_ALL_ACCESS,
NULL,
NULL, // MaximumSize,
PAGE_READWRITE,
SEC_COMMIT, // AllocationAttributes:
for file, this doesn’t make much sense, but with 0 this function doesn’t
succeede
FileHandle
);
if (!NT_SUCCESS(status))
{
VDbgPrint(“ZwCreateSection() returned 0x%x\n”,
status);
return status;
}

SIZE_T ViewSize;
ViewSize = 1500000;

LARGE_INTEGER SectionOffset;
SectionOffset.QuadPart = 0;

status = ZwMapViewOfSection
(
SectionHandle,
ZwCurrentProcess(),
&vcb->BaseAddress,
0L,
// zero bits (don’t care)
0L,
// commit size
&SectionOffset,
// SectionOffset
&ViewSize,
// ViewSize
ViewUnmap,
// InheritDisposition,
MEM_RESERVE, //
AllocationType
PAGE_READWRITE //
protection
);
if (!NT_SUCCESS(status))
{
VDbgPrint(“ZwMapViewOfSection() returned
0x%x\n”, status);
ZwClose(SectionHandle);
return status;
}

__try
{
// -> this is OK (less than 128K)
*((char *) BaseAddress + 130000) = ‘a’;

// -> this isn’t
*((char *) BaseAddress + 1300000) = ‘a’;
}

__except (1)
{
VDbgPrint(“Exception: %d\n”,
GetExceptionCode());
}
----cut ----

Thanks,
Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@broadcom.com
Sent: Monday, May 07, 2012 16:53
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

What return status do you get?
What value you pass for SectionPageProtection?


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

Try to also set FILE_NO_INTERMEDIATE_BUFFERING in ZwFileOpen,

No, that doesn’t help - still getting “classical” exception c0000005,
when I try to write above actual file contents (but within defined
mapped view).

I also tried - just experimentally! - to use directly cache manager and
section object via this code - it “works”, but … I’d like to use safer
route via “extendable” mapping .

----- CUT -----

PFILE_OBJECT FileObject = NULL;
status = ObReferenceObjectByHandle(FileHandle, SYNCHRONIZE, NULL,
KernelMode, (PVOID *)&FileObject, NULL);

if (status == 0 && CcIsFileCached(FileObject))
{
__try
{
LARGE_INTEGER Offset = {0, 0};
PVOID Bcb;
PVOID Buffer = NULL;
LONG Length = 1024;

if (CcMapData(FileObject, &Offset, Length, MAP_WAIT,
&Bcb, &Buffer) != FALSE)
{
// use Buffer here
// …
.
CcUnpinData(Bcb);
}
}

__except (1)
{
VDbgPrint(“Exception: %d\n”, GetExceptionCode());
}
}

ObDereferenceObject(FileObject);

----- CUT -----

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@broadcom.com
Sent: Monday, May 07, 2012 20:39
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

Try to also set FILE_NO_INTERMEDIATE_BUFFERING in ZwFileOpen,


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

  1. Zero attributes are treated as SEC_COMMIT by the win32 CreateFileMapping API, but ZwAllocateVirtualMemory requires specifying either SEC_COMMIT or SEC_RESERVE explicitly. We’ll update documentation to clarify this.

  2. You can ignore the SECTION_EXTEND_SIZE access right, it refers to functionality that is not public (we’ll probably remove it from the documentation to avoid confusion).

If you need to extend a memory mapped file you can do the following instead:

ZwCreateSection(File, SEC_COMMIT)
ZwMapViewOfSection(Section, MEM_RESERVE)
ZwAllocateVirtualMemory(MEM_COMMIT)

ZwAllocateVirtualMemory(MEM_COMMIT) will extend the file when called with a base address that corresponds to an offset beyond the current end-of-file.

Thanks,
Pavel

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Robert Goldwein
Sent: Monday, May 7, 2012 2:13 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] ZwCreateSection and extending the section

Hi,

I have a problem with ZwCreateSection() routine. I’m mapping a data file.

  1. When I set 6th argument (AllocationAttributes) of ZwCreateSection() to 0, the routine fails - I understood that I need to specify (at least) either SEC_COMMIT or SEC_RESERVE, but for both attributes, MSDN says “This attribute has no effect for file mapping objects that are backed by executable image files or data files (the hfile parameter is a handle to a file).” Am I missing something?

  2. It seems that I don’t quite understand meaning of SECTION_EXTEND_SIZE flag (2nd argument of ZwCreateSection() routine) - this flag, based on documentation, allows caller to “Dynamically extend the size of the section”. I map a view (using ZwMapViewOfSection(), AllocationType == MEM_RESERVE), ViewSize > actual file size, routine returns successfully. Nevertheless, when I try write beyond actual file (when I write to address: base address + something, where something is greater than file size and smaller than view size), I run into access violation. I thought that when I access page that isn’t allocated yet, but is within mapped view, such page is allocated on demand, is marked as dirty and is written to file that backs this section - but how does this really work?

> No, that doesn’t help - still getting “classical” exception c0000005,

when I try to write above actual file contents (but within defined
mapped view).
*****
That seems odd, because this is a standard technique at application level,
and I’ve used it successfully for years. It suggests that MapViewOfFile
is doing more than just extending the section.
*****

I also tried - just experimentally! - to use directly cache manager and
section object via this code - it “works”, but … I’d like to use safer
route via “extendable” mapping .

----- CUT -----

PFILE_OBJECT FileObject = NULL;
status = ObReferenceObjectByHandle(FileHandle, SYNCHRONIZE, NULL,
KernelMode, (PVOID *)&FileObject, NULL);

if (status == 0 && CcIsFileCached(FileObject))
{
__try
{
LARGE_INTEGER Offset = {0, 0};
******
Just as a footnote here: at application level the base offset for the
mapping must be an integer multiple of the allocation granularity (which
in Win32, this week, with the current set of service packs and hotfixes,
is 65,536, but you should always ask the OS what it really is–and I don’t
know which DDI call does that). Since 0 is such a multiple, this code
should work, but don’t think you can set it to arbitrary offsets.
******
PVOID Bcb;
PVOID Buffer = NULL;
LONG Length = 1024;

if (CcMapData(FileObject, &Offset, Length, MAP_WAIT,
&Bcb, &Buffer) != FALSE)
{
// use Buffer here
// …
.
CcUnpinData(Bcb);
}
}

__except (1)
****
Surely, you meant to write EXCEPTION_EXECUTE_HANDLER here, not “1”
****
{
VDbgPrint(“Exception: %d\n”, GetExceptionCode());
******
I wonder why: app programmers who display error codes in hex, even though
the reference header files use decimal; and kernel programmers who display
exception codes in decimal, even though their natural representation is
hex. When in doubt, display both:
VDbgPrint(“Exception: %d 0x%08x\n”, GetExceptionCode(),
GetExceptionCode());
joe
******
}
}

ObDereferenceObject(FileObject);

----- CUT -----

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@broadcom.com
Sent: Monday, May 07, 2012 20:39
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

Try to also set FILE_NO_INTERMEDIATE_BUFFERING in ZwFileOpen,


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


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

>> No, that doesn’t help - still getting “classical” exception c0000005,

> when I try to write above actual file contents (but within defined
mapped view).
*****
That seems odd, because this is a standard technique at application
level, and I’ve used it successfully for years. It suggests that
MapViewOfFile is doing more than just extending the section.
*****

Yes, that was confusing. The problem was that reserved memory had to be
allocated, as the previous reply explains.

> PFILE_OBJECT FileObject = NULL;
> status = ObReferenceObjectByHandle(FileHandle, SYNCHRONIZE, NULL,
> KernelMode, (PVOID *)&FileObject, NULL);
>
> if (status == 0 && CcIsFileCached(FileObject)) {
> __try
> {
> LARGE_INTEGER Offset = {0, 0};
******
Just as a footnote here: at application level the base offset for the
mapping must be an integer multiple of the allocation granularity
(which in Win32, this week, with the current set of service packs and
hotfixes, is 65,536, but you should always ask the OS what it
really is–and I don’t know which DDI call does >that). Since 0 is
such a multiple, this code should work, but don’t think you can set it
to arbitrary offsets.
******

So far I know (and use), CcMapData() routine doesn’t have such
limitations - the only limitation is the length of mapped data, and so
VACB_MAPPING_GRANULARITY (256K).

> PVOID Bcb;
> PVOID Buffer = NULL;
> LONG Length = 1024;
>
> if (CcMapData(FileObject, &Offset, Length, MAP_WAIT,
&Bcb, &Buffer)
> != FALSE)
> {
> // use Buffer here
> // …
> .
> CcUnpinData(Bcb);
> }
> }
>
> __except (1)
****
Surely, you meant to write EXCEPTION_EXECUTE_HANDLER here, not “1”
****

Sure, the code was just experimental, so you’re right, it’s ugly and I
don’t do such things in normal life :wink: (EXCEPTION_EXECUTE_HANDLER is
simply defined as 1, so it’s ugly, but correct).

> {
> VDbgPrint(“Exception: %d\n”, GetExceptionCode());
******
I wonder why: app programmers who display error codes in hex, even
though the reference header files use decimal;
and kernel programmers who display exception codes in decimal, even
though their natural representation is hex. When in doubt, display
both:
VDbgPrint(“Exception: %d 0x%08x\n”, GetExceptionCode(),
GetExceptionCode());

Good point - and really good observation. In this case I just wrote
something to see if I’ll end up in the exception handler or not, but
this was an error on my part - I almost exclusively use %x here, %d is
there just by a mistake.

joe
******
}
}

ObDereferenceObject(FileObject);

BTW, this was another problematic line - in this example, this line
should have been in the scope of “if” and that if should have been
divided into status == success and another if with macro
CcIsFileCached() :wink:

Thank you!
Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@broadcom.com
Sent: Monday, May 07, 2012 20:39
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

Try to also set FILE_NO_INTERMEDIATE_BUFFERING in ZwFileOpen,


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


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


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

Thank you Pavel,

this works exactly as I originally thought.

Another question, regarding Cc* - what do you think about following
approach?

  1. I’d open file with ZwCreateFile(), with no sharing, so I’m the only
    user.
  2. I’d get FILE_OBJECT from file handle.
  3. I’d issue read IRP so FS initializes caching.
  4. Using FILE_OBJECT with Section Object pointers initialized, I can
    technically use Cc* methods directly - e.g. CcMapData(), CcPinRead(),
    CcPreparePinWrite(), …

My target is to map arbitrarily large file - what’s more than
problematic on 32bit platform using ZwMapViewOfSection(),
I need to support random R/W access to whole file.

Personally I don’t “feel” it’s safe, but what’s your opinion?

Thanks,
Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel
Lebedynskiy
Sent: Monday, May 07, 2012 23:22
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

  1. Zero attributes are treated as SEC_COMMIT by the win32
    CreateFileMapping API, but ZwAllocateVirtualMemory requires specifying
    either SEC_COMMIT or SEC_RESERVE explicitly. We’ll update documentation
    to clarify this.

  2. You can ignore the SECTION_EXTEND_SIZE access right, it refers to
    functionality that is not public (we’ll probably remove it from the
    documentation to avoid confusion).

If you need to extend a memory mapped file you can do the following
instead:

ZwCreateSection(File, SEC_COMMIT)
ZwMapViewOfSection(Section, MEM_RESERVE)
ZwAllocateVirtualMemory(MEM_COMMIT)

ZwAllocateVirtualMemory(MEM_COMMIT) will extend the file when called
with a base address that corresponds to an offset beyond the current
end-of-file.

Thanks,
Pavel

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Robert Goldwein
Sent: Monday, May 7, 2012 2:13 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] ZwCreateSection and extending the section

Hi,

I have a problem with ZwCreateSection() routine. I’m mapping a data
file.

  1. When I set 6th argument (AllocationAttributes) of ZwCreateSection()
    to 0, the routine fails - I understood that I need to specify (at least)
    either SEC_COMMIT or SEC_RESERVE, but for both attributes, MSDN says
    “This attribute has no effect for file mapping objects that are backed
    by executable image files or data files (the hfile parameter is a handle
    to a file).” Am I missing something?

  2. It seems that I don’t quite understand meaning of SECTION_EXTEND_SIZE
    flag (2nd argument of ZwCreateSection() routine) - this flag, based on
    documentation, allows caller to “Dynamically extend the size of the
    section”. I map a view (using ZwMapViewOfSection(), AllocationType ==
    MEM_RESERVE), ViewSize > actual file size, routine returns successfully.
    Nevertheless, when I try write beyond actual file (when I write to
    address: base address + something, where something is greater than file
    size and smaller than view size), I run into access violation. I thought
    that when I access page that isn’t allocated yet, but is within mapped
    view, such page is allocated on demand, is marked as dirty and is
    written to file that backs this section - but how does this really work?


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

“Robert Goldwein” wrote in message news:xxxxx@ntdev…

  1. I’d issue read IRP so FS initializes caching.
  2. Using FILE_OBJECT with Section Object pointers initialized, I can
    technically use Cc* methods directly - e.g. CcMapData(), CcPinRead(),
    CcPreparePinWrite(), …

You don’t own these data structures, the file system does. If you party on
them like this then you’re not properly serializing yourself with the file
system, so it’s going to eventually lead to disaster. Also, do you really
want this file data taking up the file system cache?

Why can’t you just use the Zw APIs as they’re expected to be used?

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Robert Goldwein” wrote in message news:xxxxx@ntdev…

Thank you Pavel,

this works exactly as I originally thought.

Another question, regarding Cc* - what do you think about following
approach?

  1. I’d open file with ZwCreateFile(), with no sharing, so I’m the only
    user.
  2. I’d get FILE_OBJECT from file handle.
  3. I’d issue read IRP so FS initializes caching.
  4. Using FILE_OBJECT with Section Object pointers initialized, I can
    technically use Cc* methods directly - e.g. CcMapData(), CcPinRead(),
    CcPreparePinWrite(), …

My target is to map arbitrarily large file - what’s more than
problematic on 32bit platform using ZwMapViewOfSection(),
I need to support random R/W access to whole file.

Personally I don’t “feel” it’s safe, but what’s your opinion?

Thanks,
Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel
Lebedynskiy
Sent: Monday, May 07, 2012 23:22
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

  1. Zero attributes are treated as SEC_COMMIT by the win32
    CreateFileMapping API, but ZwAllocateVirtualMemory requires specifying
    either SEC_COMMIT or SEC_RESERVE explicitly. We’ll update documentation
    to clarify this.

  2. You can ignore the SECTION_EXTEND_SIZE access right, it refers to
    functionality that is not public (we’ll probably remove it from the
    documentation to avoid confusion).

If you need to extend a memory mapped file you can do the following
instead:

ZwCreateSection(File, SEC_COMMIT)
ZwMapViewOfSection(Section, MEM_RESERVE)
ZwAllocateVirtualMemory(MEM_COMMIT)

ZwAllocateVirtualMemory(MEM_COMMIT) will extend the file when called
with a base address that corresponds to an offset beyond the current
end-of-file.

Thanks,
Pavel

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Robert Goldwein
Sent: Monday, May 7, 2012 2:13 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] ZwCreateSection and extending the section

Hi,

I have a problem with ZwCreateSection() routine. I’m mapping a data
file.

  1. When I set 6th argument (AllocationAttributes) of ZwCreateSection()
    to 0, the routine fails - I understood that I need to specify (at least)
    either SEC_COMMIT or SEC_RESERVE, but for both attributes, MSDN says
    “This attribute has no effect for file mapping objects that are backed
    by executable image files or data files (the hfile parameter is a handle
    to a file).” Am I missing something?

  2. It seems that I don’t quite understand meaning of SECTION_EXTEND_SIZE
    flag (2nd argument of ZwCreateSection() routine) - this flag, based on
    documentation, allows caller to “Dynamically extend the size of the
    section”. I map a view (using ZwMapViewOfSection(), AllocationType ==
    MEM_RESERVE), ViewSize > actual file size, routine returns successfully.
    Nevertheless, when I try write beyond actual file (when I write to
    address: base address + something, where something is greater than file
    size and smaller than view size), I run into access violation. I thought
    that when I access page that isn’t allocated yet, but is within mapped
    view, such page is allocated on demand, is marked as dirty and is
    written to file that backs this section - but how does this really work?


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

Hi Scott,

Yes, I surely want to use Zw API, that’s why I asked the original
question. Tapping FS’s own structures and playing with Cc and FO that I
don’t own… it’s just theoretical question, I wouldn’t consider doing
that.

And surprisingly also yes, I’d really want this file data taking up the
file system cache - my scenario is that I have a large file (large =
several GBs) with many short random reads, some short random writes.
Usually, these reads are concentrated on a single segment of the file.
Cc API is ideal for that; on the other hand, I can’t map whole file
using ZwMapViewOfSection(), but I’ll have to deal with that.

Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Scott Noone
Sent: Tuesday, May 08, 2012 15:56
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] ZwCreateSection and extending the section

“Robert Goldwein” wrote in message news:xxxxx@ntdev…

  1. I’d issue read IRP so FS initializes caching.
  2. Using FILE_OBJECT with Section Object pointers initialized, I can
    technically use Cc* methods directly - e.g. CcMapData(), CcPinRead(),
    CcPreparePinWrite(), …

You don’t own these data structures, the file system does. If you party
on them like this then you’re not properly serializing yourself with the
file system, so it’s going to eventually lead to disaster. Also, do you
really want this file data taking up the file system cache?

Why can’t you just use the Zw APIs as they’re expected to be used?

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst OSR Open Systems
Resources, Inc.
http://www.osronline.com

“Robert Goldwein” wrote in message news:xxxxx@ntdev…

Thank you Pavel,

this works exactly as I originally thought.

Another question, regarding Cc* - what do you think about following
approach?

  1. I’d open file with ZwCreateFile(), with no sharing, so I’m the only
    user.
  2. I’d get FILE_OBJECT from file handle.
  3. I’d issue read IRP so FS initializes caching.
  4. Using FILE_OBJECT with Section Object pointers initialized, I can
    technically use Cc* methods directly - e.g. CcMapData(), CcPinRead(),
    CcPreparePinWrite(), …

My target is to map arbitrarily large file - what’s more than
problematic on 32bit platform using ZwMapViewOfSection(), I need to
support random R/W access to whole file.

Personally I don’t “feel” it’s safe, but what’s your opinion?

Thanks,
Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel
Lebedynskiy
Sent: Monday, May 07, 2012 23:22
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

  1. Zero attributes are treated as SEC_COMMIT by the win32
    CreateFileMapping API, but ZwAllocateVirtualMemory requires specifying
    either SEC_COMMIT or SEC_RESERVE explicitly. We’ll update documentation
    to clarify this.

  2. You can ignore the SECTION_EXTEND_SIZE access right, it refers to
    functionality that is not public (we’ll probably remove it from the
    documentation to avoid confusion).

If you need to extend a memory mapped file you can do the following
instead:

ZwCreateSection(File, SEC_COMMIT)
ZwMapViewOfSection(Section, MEM_RESERVE)
ZwAllocateVirtualMemory(MEM_COMMIT)

ZwAllocateVirtualMemory(MEM_COMMIT) will extend the file when called
with a base address that corresponds to an offset beyond the current
end-of-file.

Thanks,
Pavel

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Robert Goldwein
Sent: Monday, May 7, 2012 2:13 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] ZwCreateSection and extending the section

Hi,

I have a problem with ZwCreateSection() routine. I’m mapping a data
file.

  1. When I set 6th argument (AllocationAttributes) of ZwCreateSection()
    to 0, the routine fails - I understood that I need to specify (at least)
    either SEC_COMMIT or SEC_RESERVE, but for both attributes, MSDN says
    “This attribute has no effect for file mapping objects that are backed
    by executable image files or data files (the hfile parameter is a handle
    to a file).” Am I missing something?

  2. It seems that I don’t quite understand meaning of SECTION_EXTEND_SIZE
    flag (2nd argument of ZwCreateSection() routine) - this flag, based on
    documentation, allows caller to “Dynamically extend the size of the
    section”. I map a view (using ZwMapViewOfSection(), AllocationType ==
    MEM_RESERVE), ViewSize > actual file size, routine returns successfully.
    Nevertheless, when I try write beyond actual file (when I write to
    address: base address + something, where something is greater than file
    size and smaller than view size), I run into access violation. I thought
    that when I access page that isn’t allocated yet, but is within mapped
    view, such page is allocated on demand, is marked as dirty and is
    written to file that backs this section - but how does this really work?


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


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

Robert,

Simply opening the file in buffered (cached) mode and using ZwReadFile/WriteFile will give you the same performance as using it as memory mapped file. Memory mapping is just a convenience of direct addressing (and you also save one memcopy). The caching policies are still the same.

> It suggests that MapViewOfFile is doing more than just extending the section.

MapViewOfFile actually exposes a subset of what NtMapViewOfSection can do.

Using the NT API, there are two supported ways to extend a file-backed section:

  1. NtCreateSection with a size larger than the current file size.

  2. NtMapViewOfSection(MEM_RESERVE) followed by NtAllocateVirtualMemory(MEM_COMMIT).

MapViewOfFile doesn’t (currently) allow creating MEM_RESERVE views, so #2 is impossible to do using win32 APIs.

Well, I already did this, and the difference in performance was
staggering - I tested 100.000 random reads of 1K blocks from 1 GB file -
and result is that using mapped file is ~ 10 times faster than using
ZwReadFile (on checked Windows 7) - quite frankly I can’t explain this,
I doubt it’s just because of overhead from creating/completing more
IRPs…

Robert

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@broadcom.com
Sent: Tuesday, May 08, 2012 17:39
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwCreateSection and extending the section

Robert,

Simply opening the file in buffered (cached) mode and using
ZwReadFile/WriteFile will give you the same performance as using it as
memory mapped file. Memory mapping is just a convenience of direct
addressing (and you also save one memcopy). The caching policies are
still the same.


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

> My target is to map arbitrarily large file - what’s more than problematic on 32bit platform using ZwMapViewOfSection(), I need to support random R/W access to whole file.

The cache manager also can’t map arbitrarily large files. It only has (at most) 2 GB of available VA space on 32 bits, so for any file that is larger than that the cache manager will have to map/unmap portions of the file to perform IO.

If you really wanted to you could do the same thing manually with ZwMapViewOfSection. But, as others have said, it’s much easier to just use normal read/write APIs and let the cache manager do the caching.

Thank you Pavel, it’s definitely easier, but it seems that ZwReadFile
with caching is really much worse (performance) than file mapping - and
I have no idea why.

But maybe (I’d hope) there’s something wrong with my tests.

Test file (1 GB) is opened this way:

status = ZwCreateFile
(
& FileHandle,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);

The following code takes around 20s to complete, when it’s called
repetitively, it’s takes always the same amout of time.

LARGE_INTEGER beforeTime;
KeQuerySystemTime(&beforeTime);

ULONG seed = 26548894;
char buffer[1024];

for (int i = 0; i < 100 * 1000; i++)
{
ULONG rand = RtlRandomEx(&seed) % (1024 * 256);

LARGE_INTEGER offset;
offset.QuadPart = rand * 1024;

ZwReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock,
buffer, 1024, &offset, NULL);
}

LARGE_INTEGER afterTime;
KeQuerySystemTime(&afterTime);

int length = ((afterTime.QuadPart - beforeTime.QuadPart) / 10 /
1000 / 1000);
DbgPrint(“Length = %d\n”, length);

On the other hand, this code takes around 2s, file is mapped to
BaseAddress:

LARGE_INTEGER beforeTime2;
KeQuerySystemTime(&beforeTime2);

ULONG seed = 26548894;
char buffer2[1024];

for (int j = 0; j < 100 * 1000; j++)
{
ULONG rand = RtlRandomEx(&seed) % (1024 * 256);

memcpy(buffer2, (char *) BaseAddress + (rand * 1024),
1024);
}

LARGE_INTEGER afterTime2;
KeQuerySystemTime(&afterTime2);

int length2 = ((afterTime2.QuadPart - beforeTime2.QuadPart) / 10
/ 1000 / 1000);
DbgPrint(“Length2 = %d\n”, length2);

Important fact - I ran these two tests separately.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel
Lebedynskiy
Sent: Tuesday, May 08, 2012 23:12
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] ZwCreateSection and extending the section

My target is to map arbitrarily large file - what’s more than
problematic on 32bit platform using ZwMapViewOfSection(), I need to
support random R/W access to whole file.

The cache manager also can’t map arbitrarily large files. It only has
(at most) 2 GB of available VA space on 32 bits, so for any file that is
larger than that the cache manager will have to map/unmap portions of
the file to perform IO.

If you really wanted to you could do the same thing manually with
ZwMapViewOfSection. But, as others have said, it’s much easier to just
use normal read/write APIs and let the cache manager do the caching.


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

On 5/8/2012 11:40 PM, Robert Goldwein wrote:

[…] it seems that ZwReadFile
with caching is really much worse (performance) than file mapping - and
I have no idea why.
How about using kernrate to find out where the extra time is spent?

Well, now I know.

I knew that flag FILE_RANDOM_ACCESS serves as a hint for FS how to treat
files; in MSDN, this flag is described as "Access to the file can be
random, so no sequential read-ahead operations should be performed by
file-system drivers or by the system. " Nevertheless, this mere hint
changes everyting - the performance of ZwReadFile and file mapping is
now almost equal, hooray.

Thank you all for your input.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Hagen Patzke
Sent: Wednesday, May 09, 2012 09:30
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] ZwCreateSection and extending the section

On 5/8/2012 11:40 PM, Robert Goldwein wrote:

[…] it seems that ZwReadFile
with caching is really much worse (performance) than file mapping -
and
I have no idea why.
How about using kernrate to find out where the extra time is spent?


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

Excellent! That was going to be my suggestion, glad to hear it had that much
of an impact. Without this flag the Cache Manager assumes sequential access,
so you’ll get read ahead and more aggressive unmapping of areas you’ve
behind your current location. Definitely not what you want in your case.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Robert Goldwein” wrote in message news:xxxxx@ntdev…

Well, now I know.

I knew that flag FILE_RANDOM_ACCESS serves as a hint for FS how to treat
files; in MSDN, this flag is described as "Access to the file can be
random, so no sequential read-ahead operations should be performed by
file-system drivers or by the system. " Nevertheless, this mere hint
changes everyting - the performance of ZwReadFile and file mapping is
now almost equal, hooray.

Thank you all for your input.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Hagen Patzke
Sent: Wednesday, May 09, 2012 09:30
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] ZwCreateSection and extending the section

On 5/8/2012 11:40 PM, Robert Goldwein wrote:

[…] it seems that ZwReadFile
with caching is really much worse (performance) than file mapping -
and
I have no idea why.
How about using kernrate to find out where the extra time is spent?


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

>Cc API is ideal for that

Why not just abandon mapping and use ZwRead/WriteFile for this?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com